;; [[file:init-emacs.org::*Start][Start:1]]
;; -*- mode: emacs-lisp; lexical-binding: t -*-
;;==============================================================================
;; init-emacs.org
;;
;;; Main Emacs Settings File
;;
;; Author: Kyle W T Sherman
;;
;; This file was generated from init-emacs.org and should not be edited
;; manually.
;;
;; init-emacs.org ==> init-emacs.el ==> init-emacs.elc
;;==============================================================================

;;==============================================================================
;;; Start
;;==============================================================================

;; add timestamps to `*Messages*' buffer
(defun message--with-timestamp (format-string &rest args)
  "Add timestamps to `*Messages*' buffer."
  (when (and (> (length format-string) 0)
             (not (string= format-string " ")))
    (let ((deactivate-mark nil))
      (save-excursion
        (with-current-buffer "*Messages*"
          (let ((inhibit-read-only t))
            (goto-char (point-max))
            (when (not (bolp)) (newline))
            (insert (format-time-string "[%T] " (current-time)))))))))
;; advise `message'
(advice-add 'message :before #'message--with-timestamp)

;; init-message (custom message logger for initialization messages)
(defun init-message (level format-string &rest args)
  "Custom version of `message' to log messages during Emacs initialization.
\nLEVEL is the indentation level."
  (let ((file (file-name-sans-extension (file-name-nondirectory (or load-file-name (buffer-file-name) (buffer-name))))))
    (message (concat ";;; " file " " (make-string (* 2 level) ?-) "> " format-string) args)))

(init-message 1 "Start")

;; set load start time
(defvar emacs-load-start-time
  nil
  "Track the time it takes Emacs to start.")
(setq emacs-load-start-time (current-time))

;; prevent compile errors when using cl functions
(eval-when-compile (require 'cl))
;; Start:1 ends here

;; [[file:init-emacs.org::*Key%20Bindings][Key Bindings:1]]
;;==============================================================================
;;; Key Bindings
;;==============================================================================

(init-message 1 "Key Bindings")
;; Key Bindings:1 ends here

;; [[file:init-emacs.org::*Function%20Keys][Function Keys:1]]
;;------------------------------------------------------------------------------
;;; Key Bindings: Function Keys
;;------------------------------------------------------------------------------

(init-message 2 "Key Bindings: Function Keys")

;; function keys
(defun custom-key-bindings-function-keys ()
  "Set custom function key bindings."
  (when (fboundp 'help)
    (global-set-key (kbd "<f1>") 'help))  ; defaults to `help-for-help'
  (when (fboundp 'help-for-help)
    (global-set-key (kbd "S-<f1>") 'help-for-help)) ; defaults to undefined
  (when (fboundp 'help-command)
    (global-set-key (kbd "<f2>") 'help-command)) ; defaults to Prefix Command
  ;; (when (fboundp 'tmm-menubar)
  ;;   (global-set-key (kbd "<f1>") 'tmm-menubar)) ; defaults to `help-for-help'
  ;; (when (fboundp 'help)
  ;;   (global-set-key (kbd "<f2>") 'help))        ; defaults to Prefix Command
  ;; (when (fboundp 'help-for-help)
  ;;   (global-set-key (kbd "S-<f2>") 'help-for-help)) ; defaults to undefined
  (when (fboundp 'kmacro-start-macro-or-insert-counter)
    (global-set-key (kbd "<f3>") 'kmacro-start-macro-or-insert-counter)) ; defaults to `kmacro-start-macro-or-insert-counter'
  (when (fboundp 'kmacro-end-or-call-macro)
    (global-set-key (kbd "<f4>") 'kmacro-end-or-call-macro)) ; defaults to `kmacro-end-or-call-macro'
  ;; (when (fboundp 'kmacro-end-and-call-macro)
  ;;   (global-set-key (kbd "<f5>") 'kmacro-end-and-call-macro)) ; defaults to undefined
  ;; (when (fboundp 'web-query-google-define)
  ;;   (global-set-key (kbd "<f5>") 'web-query-google-define)) ; defaults to undefined
  (when (fboundp 'define-word-at-point)
    (global-set-key (kbd "<f5>") 'define-word-at-point)) ; defaults to undefined
  (when (fboundp 'web-query-word-at-point)
    (global-set-key (kbd "S-<f5>") 'web-query-word-at-point)) ; defaults to undefined
  (when (fboundp 'ispell-word)
    (global-set-key (kbd "<f6>") 'ispell-word)) ; defaults to undefined
  ;; (when (fboundp 'ispell)
  ;;   (global-set-key (kbd "S-<f6>") 'ispell)) ; defaults to undefined
  (when (fboundp 'web-query)
    (global-set-key (kbd "S-<f6>") 'web-query)) ; defaults to undefined
  (when (fboundp 'ispell)
    (global-set-key (kbd "<f7>") 'ispell)) ; defaults to undefined
  ;; (when (fboundp 'mode-compile)
  ;;   (global-set-key (kbd "<f7>") 'mode-compile)) ; defaults to undefined
  (when (fboundp 'web-query-symbol-by-mode-at-point)
    (global-set-key (kbd "<S-f7>") 'web-query-symbol-by-mode-at-point)) ; defaults to undefined
  ;; (when (fboundp 'flymake-goto-next-error)
  ;;   (global-set-key (kbd "<f8>") 'flymake-goto-next-error)) ; defaults to undefined
  ;; (when (fboundp 'web-query-symbol-by-mode-at-point)
  ;;   (global-set-key (kbd "<f8>") 'web-query-symbol-by-mode-at-point)) ; defaults to undefined
  (when (fboundp 'neotree)
    (global-set-key (kbd "<f8>") 'neotree)) ; defaults to undefined
  (when (fboundp 'cycle-buffer-backward)
    (global-set-key (kbd "<f9>") 'cycle-buffer-backward)) ; defaults to undefined
  (when (fboundp 'cycle-buffer-backward-permissive)
    (global-set-key (kbd "S-<f9>") 'cycle-buffer-backward-permissive)) ; defaults to undefined
  (when (fboundp 'cycle-buffer)
    (global-set-key (kbd "<f10>") 'cycle-buffer)) ; defaults to `tmm-menubar'
  (when (fboundp 'cycle-buffer-permissive)
    (global-set-key (kbd "S-<f10>") 'cycle-buffer-permissive)) ; defaults to undefined
  ;; (when (fboundp 'bs-cycle-previous)
  ;;   (global-set-key (kbd "<f9>") 'bs-cycle-previous)) ; defaults to undefined
  ;; (when (fboundp 'bs-cycle-next)
  ;;   (global-set-key (kbd "<f10>") 'bs-cycle-next))) ; defaults to `tmm-menubar'
  )

(init-message 3 "custom-key-bindings-function-keys")
(custom-key-bindings-function-keys)
;; Function Keys:1 ends here

;; [[file:init-emacs.org::*Extended%20Keys][Extended Keys:1]]
;;------------------------------------------------------------------------------
;;; Key Bindings: Extended Keys
;;------------------------------------------------------------------------------

(init-message 2 "Key Bindings: Extended Keys")

;; extended keys
(defun custom-key-bindings-extended-keys ()
  "Set custom extended key bindings."

  ;; ;; control+alt arrow keys do page-up/down and home/end
  ;; (global-set-key (kbd "C-M-<left>") (lookup-key (current-global-map) (kbd "<home>") t))
  ;; (global-set-key (kbd "C-M-<right>") (lookup-key (current-global-map) (kbd "<end>") t))
  ;; (global-set-key (kbd "C-M-<up>") (lookup-key (current-global-map) (kbd "<prior>") t))
  ;; (global-set-key (kbd "C-M-<down>") (lookup-key (current-global-map) (kbd "<next>") t))

  ;; ;; shift arrow keys
  ;; (define-key function-key-map "\eO2A" [S-up])
  ;; (define-key function-key-map "\eO2B" [S-down])
  ;; (define-key function-key-map "\eO2D" [S-left])
  ;; (define-key function-key-map "\eO2C" [S-right])

  ;; ;; buffer switching
  ;; (when (fboundp 'cycle-buffer)
  ;;   ;; control arrow keys
  ;;   ;; these default to undefined
  ;;   ;; (global-set-key (kbd "C-<left>") 'cycle-buffer-backward)
  ;;   ;; (global-set-key (kbd "C-<right>") 'cycle-buffer)
  ;;   ;; (global-set-key (kbd "C-<left>") 'bs-cycle-previous)
  ;;   ;; (global-set-key (kbd "C-<right>") 'bs-cycle-next)
  ;;   ;; (global-set-key (kbd "C-<up>") 'cycle-buffer-backward-permissive)
  ;;   ;; (global-set-key (kbd "C-<down>") 'cycle-buffer-permissive)
  ;;   (global-set-key (kbd "M-O d") 'cycle-buffer-backward)
  ;;   (global-set-key (kbd "M-O c") 'cycle-buffer)
  ;;   (global-set-key (kbd "M-O a") 'cycle-buffer-backward-permissive)
  ;;   (global-set-key (kbd "M-O b") 'cycle-buffer-permissive))

  ;; window move
  (when (fboundp 'windmove-left)
    ;; shift arrow keys
    ;; these default to undefined
    (global-set-key (kbd "S-<left>") 'windmove-left)
    (global-set-key (kbd "S-<right>") 'windmove-right)
    (global-set-key (kbd "S-<up>") 'windmove-up)
    (global-set-key (kbd "S-<down>") 'windmove-down))
    ;;(global-set-key (kbd "M-[ d") 'windmove-left)
    ;;(global-set-key (kbd "M-[ c") 'windmove-right)
    ;;(global-set-key (kbd "M-[ a") 'windmove-up)
    ;;(global-set-key (kbd "M-[ b") 'windmove-down))

  ;; ;; window move
  ;; (when (fboundp 'windmove-left)
  ;;   ;; control arrow keys
  ;;   ;; these default to undefined
  ;;   (global-set-key (kbd "C-<left>") 'windmove-left)
  ;;   (global-set-key (kbd "C-<right>") 'windmove-right)
  ;;   (global-set-key (kbd "C-<up>") 'windmove-up)
  ;;   (global-set-key (kbd "C-<down>") 'windmove-down)
  ;;   (global-set-key (kbd "M-O d") 'windmove-left)
  ;;   (global-set-key (kbd "M-O c") 'windmove-right)
  ;;   (global-set-key (kbd "M-O a") 'windmove-up)
  ;;   (global-set-key (kbd "M-O b") 'windmove-down))

  ;; ;; split move
  ;; (when (and (fboundp 'split-move-up) (fboundp 'split-move-down))
  ;;   ;; these default to undefined
  ;;   (global-set-key (kbd "M-<up>") 'split-move-up)
  ;;   (global-set-key [?\e (up)] 'split-move-up)
  ;;   (global-set-key (kbd "M-<down>") 'split-move-down)
  ;;   (global-set-key [?\e (down)] 'split-move-down))

  ;; beginning of line
  (global-set-key (kbd "<home>") 'beginning-of-line) ; defaults to `move-beginning-of-line'

  ;; end of line
  (global-set-key (kbd "<end>") 'end-of-line) ; defaults to `move-end-of-line'

  ;; beginning of buffer
  (global-set-key (kbd "C-<home>") 'beginning-of-buffer) ; defaults to undefined

  ;; end of buffer
  (global-set-key (kbd "C-<end>") 'end-of-buffer) ; defaults to undefined

  ;; cycle buffer
  ;; (when (fboundp 'bs-cycle-next)
  ;;   (global-set-key (kbd "C-<tab>") 'bs-cycle-next)) ; defaults to undefined
  (when (fboundp 'cycle-buffer)
    (global-set-key (kbd "C-<tab>") 'cycle-buffer)) ; defaults to undefined

  ;; cycle buffer backward
  ;; (when (fboundp 'bs-cycle-previous)
  ;;   (global-set-key (kbd "C-S-<tab>") 'bs-cycle-previous)) ; defaults to undefined
  (when (fboundp 'cycle-buffer-backward)
    (global-set-key (kbd "C-S-<tab>") 'cycle-buffer-backward)) ; defaults to undefined

  ;; ;; undo only
  ;; (global-set-key (kbd "C-<plus>") 'undo-only) ; defaults to undefined
  )

(init-message 3 "custom-key-bindings-extended-keys")
(custom-key-bindings-extended-keys)
;; Extended Keys:1 ends here

;; [[file:init-emacs.org::*Standard%20Keys][Standard Keys:1]]
;;------------------------------------------------------------------------------
;;; Key Bindings: Standard Keys
;;------------------------------------------------------------------------------

(init-message 2 "Key Bindings: Standard Keys")

;; standard keys
(defun custom-key-bindings-standard-keys ()
  "Set custom standard key bindings."

  ;; turn off insert key
  (global-set-key (kbd "<insert>") nil)   ; defaults to `overwrite-mode'

  ;; set C-h to backward delete so the backspace key works (for old laptops)
  ;;(global-set-key (kbd "C-h") 'backward-delete-char) ; defaults to `help-command'
  ;;(global-set-key (kbd "C-h") 'help) ; defaults to `help-command'

  ;; modify backspace
  ;;(global-set-key (kbd "C-h") 'backward-delete-char-untabify) ; defaults to `help-command'

  ;; word/region delete
  ;;(global-set-key (kbd "C-M-h") 'backward-kill-word) ; defaults to `mark-defun'
  ;;(global-set-key (kbd "C-w") 'backward-kill-word) ; defaults to `kill-region'
  ;;(global-set-key (kbd "C-x C-k") 'kill-region) ; defaults to `kmacro-keymap'---
  ;; (when (fboundp 'kill-word-enhanced)
  ;;   (global-set-key (kbd "M-d") 'kill-word-enhanced)) ; defaults to `kill-word'
  (when (fboundp 'kill-region-or-word)
    (global-set-key (kbd "C-w") 'kill-region-or-word)) ; defaults to `kill-region'

  ;; newline
  ;; (when (fboundp 'insert-line-below)
  ;;   (global-unset-key (kbd "<C-return>")) ; defaults to `cua-set-rectangle-mark'
  ;;   (global-set-key (kbd "<C-return>") 'insert-line-below)) ; defaults to `cua-set-rectangle-mark'
  ;; (when (fboundp 'insert-line-above)
  ;;   (global-set-key (kbd "<C-M-return>") 'insert-line-above)) ; defaults to undefined
  (when (fboundp 'insert-line-below)
    (global-set-key (kbd "<C-M-return>") 'insert-line-below)) ; defaults to undefined

  ;; newline and indent
  ;;(global-set-key (kbd "<return>") 'newline-and-indent) ; defaults to `self-insert-command'
  ;;(global-set-key (kbd "C-<return>") 'newline-and-indent) ; defaults to `self-insert-command'
  (global-set-key (kbd "C-m") 'newline-and-indent) ; defaults to `self-insert-command'
  ;;(global-set-key (kbd "\r") 'newline-and-indent) ; defaults to `self-insert-command'

  ;; ;; indent or expand (tab)
  ;; (global-set-key (kbd "<tab>") 'indent-or-expand) ; defaults to `lisp-indent-line'
  ;; ;;(global-set-key (kbd "C-i") 'indent-or-expand) ; defaults to `lisp-indent-line'
  ;; ;;(global-set-key (kbd "TAB") 'indent-or-expand) ; defaults to `lisp-indent-line'

  ;; ;; indent line and next line
  ;; (global-set-key (kbd "C-x t") 'indent-down) ; defaults to undefined

  ;; set mark
  ;; (global-set-key (kbd "M-SPC") 'set-mark-command)) ; defaults to undefined

  ;; set rectangle mark
  (when (fboundp 'cua-set-rectangle-mark)
    (global-set-key (kbd "C-x rm") 'cua-set-rectangle-mark)) ; defaults to undefined

  ;; just one space
  (when (fboundp 'just-one-space)
    (global-set-key (kbd "C-x C-SPC") 'just-one-space)) ; defaults to `pop-global-mark'

  ;; help
  ;;(global-set-key (kbd "C-x C-h") 'help) ; defaults to undefined
  (global-set-key (kbd "C-x C-h") 'help-command) ; defaults to undefined
  ;;(global-set-key (kbd "C-c C-h") 'help-command) ; defaults to undefined
  (global-set-key (kbd "C-x ?") 'help)    ; defaults to undefined

  ;; ;; cursor movement keys (single character)
  ;; (global-set-key (kbd "M-j") 'backward-char)  ; defaults to `indent-new-comment-line'
  ;; (global-set-key (kbd "M-l") 'forward-char)   ; defaults to `downcase-word'
  ;; (global-set-key (kbd "M-i") 'previous-line)  ; defaults to `tab-to-tab-stop'
  ;; (global-set-key (kbd "M-k") 'next-line)      ; defaults to `kill-sentence'
  (global-set-key (kbd "M-n") 'scroll-up) ; defaults to undefined
  (global-set-key (kbd "M-p") 'scroll-down) ; defaults to undefined

  ;; ;; cursor movement keys (multi-character)
  (global-set-key (kbd "C-M-<down>") 'scroll-up) ; defaults to `down-list`
  (global-set-key (kbd "C-M-<up>") 'scroll-down) ; defaults to `backward-up-list`
  (global-set-key (kbd "C-M-<left>") 'beginning-of-line) ; defaults to `backward-sexp-enhanced`
  (global-set-key (kbd "C-M-<right>") 'end-of-line) ; defaults to `forward--sexp-enhanced`
  ;; (global-set-key (kbd "C-M-j") 'backward-word) ; defaults to `indent-new-comment-line'
  ;; (global-set-key (kbd "C-M-l") 'forward-word) ; defaults to `reposition-window'
  ;; ;;(global-unset-key (kbd "M-TAB"))
  ;; ;;(global-set-key (kbd "M-TAB") 'scroll-down) ; defaults to `lisp-complete-symbol'
  ;; ;;(global-unset-key (kbd "C-M-i"))
  ;; (global-set-key (kbd "C-M-i") 'scroll-down) ; defaults to `lisp-complete-symbol'
  ;; (global-set-key (kbd "C-M-k") 'scroll-up) ; defaults to `kill-sexp'
  ;; (global-set-key (kbd "C-M-u") 'beginning-of-line) ; defaults to `backward-up-list'
  ;; (global-set-key (kbd "C-M-o") 'end-of-line) ; defaults to `split-line'

  ;; describe function or variable at point
  (when (fboundp 'describe-function-or-variable-at-point)
    (global-set-key (kbd "C-h z") 'describe-function-or-variable-at-point) ; defaults to undefined
    (global-set-key (kbd "C-x C-h z") 'describe-function-or-variable-at-point)) ; defaults to undefined

  ;; smart M-x
  (when (fboundp 'smex)
    (global-set-key (kbd "M-x") 'smex)) ; defaults to `execute-extended-command'
  (when (fboundp 'smex-major-mode-commands)
    (global-set-key (kbd "M-X") 'smex-major-mode-commands)) ; defaults to `execute-extended-command'
  ;; alternates for M-x
  (global-set-key (kbd "C-x C-m") 'execute-extended-command) ; defaults to Prefix Command
  (global-set-key (kbd "C-c C-m") 'execute-extended-command) ; defaults to undefined
  ;;(global-set-key (kbd "M-a") 'execute-extended-command) ; defaults to `backward-sentence'

  ;; menubar
  (when (fboundp 'tmm-menubar)
    (global-set-key (kbd "C-M-z") 'tmm-menubar)) ; defaults to undefined
  ;;(global-set-key (kbd "M-z") 'tmm-menubar)) ; defaults to `zap-to-char'

  ;; force save maybe
  (when (fboundp 'save-buffer-always-maybe)
    (global-set-key (kbd "C-x C-s") 'save-buffer-always-maybe)) ; defaults to `save-buffer'

  ;; ;; rename buffer and file
  ;; (when (fboundp 'rename-buffer-and-file)
  ;;   (global-set-key (kbd "C-x C-r") 'rename-buffer-and-file)) ; defaults to `find-file-read-only'

  ;; ;; ibuffer
  ;; (when (fboundp 'ibuffer)
  ;;   (global-set-key (kbd "C-x C-b") 'ibuffer)) ; defaults to `list-buffers'

  ;; bs-show (buffer select)
  (when (fboundp 'bs-show)
    (global-set-key (kbd "C-x C-b") 'bs-show)) ; defaults to `list-buffers'

  ;; bury buffer
  (global-set-key (kbd "C-c y") 'bury-buffer) ; defaults to undefined

  ;; revert buffer
  (global-set-key (kbd "C-c r") 'revert-buffer) ; defaults to undefined

  ;; diff buffer
  (global-set-key (kbd "C-c d") 'diff-current-buffer) ; defaults to undefined

  ;; switch to scratch
  ;; (when (fboundp 'switch-to-scratch)
  ;;   (global-set-key (kbd "C-c C-s") 'switch-to-scratch)) ; defaults to undefined

  ;; ;; mark whole buffer
  ;; (global-set-key (kbd "C-x h") 'mark-whole-buffer) ; defaults to `mark-whole-buffer'

  ;; ;; source emacs init file
  ;; (global-set-key (kbd "C-c =") '(load-library "~/.emacs.d/init.el")) ; defaults to undefined

  ;; query replace regexp
  (global-set-key (kbd "M-&") 'query-replace-regexp) ; defaults to `query-replace'

  ;; mark full word
  (when (fboundp 'mark-full-word)
    (global-set-key (kbd "M-@") 'mark-full-word)) ; defaults to `mark-word'

  ;; expand region
  (when (fboundp 'er/expand-region)
    (global-set-key (kbd "M-=") 'er/expand-region) ; defaults to `count-lines-region'
    (global-set-key (kbd "C-=") 'er/contract-region) ; defaults to `count-lines-region'
    (global-set-key (kbd "C-M-SPC") 'er/expand-region) ; defaults to `mark-sexp'
    (global-set-key (kbd "C-M-S-SPC") 'er/contract-region)) ; defaults to undefined

  ;; insert menu prompt
  (when (fboundp 'insert-menu-prompt)
    (global-set-key (kbd "C-x i") 'insert-menu-prompt)) ; defaults to `insert-file'

  ;; goto line
  ;; just use the default "M-g M-g" for `goto-line'
  ;;(global-set-key (kbd "M-g") 'goto-line)
  ;;(global-set-key (kbd "C-c C-g") 'goto-line)
  ;;(global-set-key (kbd "C-x g") 'goto-line) ; defaults to undefined

  ;; switch windows
  (global-set-key (kbd "M-o") 'other-window) ; defaults to `facemenu-keymap'
  (when (fboundp 'ace-window)
    (global-set-key (kbd "C-x o") 'ace-window)) ; defaults to `other-window'

  ;; split windows
  (global-set-key (kbd "M-1") 'delete-other-windows) ; defaults to `digit-argument'
  (global-set-key (kbd "M-2") 'split-window-horizontally) ; defaults to `digit-argument'
  (global-set-key (kbd "M-3") 'split-window-vertically) ; defaults to `digit-argument'
  ;; (when (fboundp 'switch-window-then-delete)
  ;;   (global-set-key (kbd "M-9") 'switch-window-then-delete)) ; defaults to `digit-argument'
  (global-set-key (kbd "M-0") 'delete-window) ; defaults to `digit-argument'

  ;; swap windows
  (when (fboundp 'swap-windows)
    ;;(global-set-key (kbd "M-p") 'swap-windows) ; defaults to undefined
    (global-set-key (kbd "C-x O") 'swap-windows) ; defaults to `other-window'
    (global-set-key (kbd "C-x p") 'swap-windows)) ; defaults to undefined

  ;; toggle window split
  (when (fboundp 'toggle-window-split)
    (global-set-key (kbd "M-P") 'toggle-window-split)) ; defaults to undefined

  ;; kill buffer
  (global-set-key (kbd "C-x C-k") 'kill-this-buffer) ; defaults to `kmacro-keymap'
  ;; (global-set-key (kbd "C-x k") 'kill-or-bury-buffer) ; defaults to `kill-buffer' or `ido-kill-buffer'
  ;; (global-set-key (kbd "C-x C-k" (lambda () (interactive) (kill-or-bury-buffer t))) ; defaults to `kmacro-keymap'
  (when (fboundp 'kill-other-window-buffer)
    (global-set-key (kbd "M-9") 'kill-other-window-buffer)) ; defaults to `digit-argument'

  ;; ;; revert buffer
  ;; (global-set-key (kbd "C-x C-r") 'revert-buffer) ; defaults to `find-file-read-only'

  ;; delete word
  (when (fboundp 'delete-word)
    (global-set-key (kbd "M-d") 'delete-word)) ; defaults to `kill-word'
  (when (fboundp 'backward-delete-word)
    (global-set-key (kbd "C-<backspace>") 'backward-delete-word)) ; defaults to `backward-kill-word'

  ;; copy line
  (when (fboundp 'copy-line)
    (global-set-key (kbd "C-x C-y") 'copy-line)) ; defaults to undefined

  ;; cut line
  (when (fboundp 'cut-line)
    (global-set-key (kbd "C-x M-y") 'cut-line)) ; defaults to undefined

  ;; delete to end of line
  (when (fboundp 'delete-to-end-of-line)
    (global-set-key (kbd "C-k") 'delete-to-end-of-line)) ; defaults to `kill-line'

  ;; delete line
  (when (fboundp 'delete-line)
    ;;(global-set-key (kbd "C-M-d") 'delete-line)) ; defaults to `down-list'
    (global-set-key (kbd "C-M-k") 'delete-line)) ; defaults to `kill-sexp'

  ;; kill-whole-line
  (global-set-key (kbd "C-M-d") 'kill-whole-line) ; defaults to `down-list'

  ;; duplicate line
  (when (fboundp 'duplicate-line)
    (global-set-key (kbd "C-x C-d") 'duplicate-line)) ; defaults to `list-directory'

  ;; ;; duplicate line and comment out original
  ;; (when (fboundp 'duplicate-line)
  ;;   (global-set-key (kbd "C-c C-d" (lambda () (interactive) (duplicate-line nil t)))) ; defaults to undefined

  ;; kill ring browser
  (when (fboundp 'browse-kill-ring)
    (global-set-key (kbd "C-M-y") 'browse-kill-ring)) ; defaults to undefined

  ;; join line
  ;;(global-set-key (kbd "C-x C-j") 'join-line)  ; defaults to undefined
  (global-set-key (kbd "C-M-j") 'join-line)  ; defaults to `comment-indent-new-line'

  ;; join next line
  (when (fboundp 'join-next-line)
    (global-set-key (kbd "M-j") 'join-next-line)) ; defaults to `indent-new-comment-line'

  ;; move line down
  (when (fboundp 'move-line-down)
    (global-set-key (kbd "<M-S-down>") 'move-line-down)) ; defaults to undefined
  ;; (when (fboundp 'move-text-down)
  ;;   (global-set-key (kbd "<M-S-down>") 'move-text-down)) ; defaults to undefined

  ;; move line up
  (when (fboundp 'move-line-up)
    (global-set-key (kbd "<M-S-up>") 'move-line-up)) ; defaults to undefined
  ;; (when (fboundp 'move-text-up)
  ;;   (global-set-key (kbd "<M-S-up>") 'move-text-up)) ; defaults to undefined

  ;; ;; enhanced forward-word
  ;; ;; gets set with `forward-word' defun
  ;; (when (fboundp 'forward-word-enhanced)
  ;;   (global-set-key (kbd "M-f") 'forward-word-enhanced) ; defaults to `forward-word'
  ;;   (global-set-key [?\e (right)] 'forward-word-enhanced)) ; defaults to `forward-word'

  ;; ;; enhanced backward-word
  ;; ;; gets set with `backward-word' defun
  ;; (when (fboundp 'backward-word-enhanced)
  ;;   (global-set-key (kbd "M-b") 'backward-word-enhanced) ; defaults to `backward-word'
  ;;   (global-set-key [?\e (left)] 'backward-word-enhanced)) ; defaults to `backward-word'

  ;; ;; enhanced scroll-up
  ;; ;; gets set with `scroll-up' defun
  ;; (when (fboundp 'scroll-up-enhanced)
  ;;   (global-set-key (kbd "<next>") 'scroll-up-enhanced)) ; defaults to `scroll-up'

  ;; ;; enhanced scroll-down
  ;; ;; gets set with `scroll-down' defun
  ;; (when (fboundp 'scroll-down-enhanced)
  ;;   (global-set-key (kbd "<prior>") 'scroll-down-enhanced)) ; defaults to `scroll-down'

  ;; ;; enhanced downcase-word
  ;; ;; gets set with `downcase-word' defun
  ;; (when (fboundp 'downcase-word-enhanced)
  ;;   (global-set-key (kbd "M-l") 'downcase-word-enhanced)) ; defaults to `downcase-word'
  ;;   ;;(global-set-key (kbd "C-c C-l") 'downcase-word-enhanced)) ; defaults to undefined

  ;; ;; enhanced upcase-word
  ;; ;; gets set with `upcase-word' defun
  ;; (when (fboundp 'upcase-word-enhanced)
  ;;   (global-set-key (kbd "M-u") 'upcase-word-enhanced)) ; defaults to `upcase-word'
  ;;   ;;(global-set-key (kbd "C-c C-u") 'upcase-word-enhanced)) ; defaults to undefined

  ;; ;; enhanced capitalize-word
  ;; ;; gets set with `capitalize-word' defun
  ;; (when (fboundp 'capitalize-word-enhanced)
  ;;   (global-set-key (kbd "M-c") 'capitalize-word-enhanced)) ; defaults to `capitalize-word'

  ;; enhanced titleize-word
  (when (fboundp 'titleize-word-enhanced)
    (global-set-key (kbd "M-t") 'titleize-word-enhanced) ; defaults to `transpose-words'
    (global-set-key (kbd "M-T") 'titleize-line-or-region)) ; defaults to undefined

  ;; enlarge window by 5
  (when (fboundp 'enlarge-window-5)
    (global-set-key (kbd "C-x &") 'enlarge-window-5)) ; defaults to undefined

  ;; shrink window by 5
  (when (fboundp 'shrink-window-5)
    (global-set-key (kbd "C-x %") 'shrink-window-5)) ; defaults to `View-goto-percent'

  ;; describe text properties
  (global-set-key (kbd "C-c C-p") 'describe-text-properties) ; defaults to undefined

  ;; goto last change (undo)
  (when (fboundp 'goto-last-change)
    (global-set-key (kbd "C-x C-_") 'goto-last-change))

  ;; ;; print time stamp
  ;; (when (fboundp 'print-time-stamp)
  ;;   (global-set-key (kbd "C-x a") 'print-time-stamp)) ; defaults to Prefix Command

  ;; ;; insert uui
  ;; (when (fboundp 'uuid)
  ;;   ;;(global-set-key (kbd "C-x u") 'uuid)        ; defaults to `advertised-undo'
  ;;   (global-set-key (kbd "C-c u") 'uuid))       ; defaults to undefined

  ;; ;; insert guid
  ;; (when (fboundp 'guid)
  ;;   (global-set-key (kbd "C-c g") 'guid))       ; defaults to undefined

  ;; jump to matching parenthesis
  (when (fboundp 'match-paren)
    (global-set-key (kbd "M-(") 'match-paren))

  ;; evaluate current sexp
  (global-set-key (kbd "C-x C-e") 'eval-current-sexp) ; defaults to `eval-last-sexp'
  ;; \C-\M-x defaults to `eval-defun'

  ;; evaluate all sexp's in current buffer
  (when (fboundp 'eval-sexp-buffer)
    (global-set-key (kbd "C-x M-e") 'eval-sexp-buffer)) ; defaults to undefined

  ;; indent current sexp
  (global-set-key (kbd "M-C-q") 'indent-current-sexp) ; defaults to `indent-sexp' or `indent-pp-sexp'

  ;; indent all sexp's in current buffer
  (when (fboundp 'indent-sexp-buffer)
    (global-set-key (kbd "C-x M-q") 'indent-sexp-buffer)) ; defaults to undefined

  ;; comment and uncomment sexp's
  (when (fboundp 'comment-or-uncomment-sexp)
    (define-key emacs-lisp-mode-map (kbd "C-M-;") 'comment-or-uncomment-sexp))

  ;; append equal characters up to column 80
  (when (fboundp 'append-equal-to-column-80)
    (global-set-key (kbd "C-c =") 'append-equal-to-column-80)) ; defaults to undefined

  ;; append dash characters up to column 80
  (when (fboundp 'append-dash-to-column-80)
    (global-set-key (kbd "C-c -") 'append-dash-to-column-80)) ; defaults to undefined

  ;; append asterisk characters up to column 80
  (when (fboundp 'append-asterisk-to-column-80)
    (global-set-key (kbd "C-c 8") 'append-asterisk-to-column-80)  ; defaults to undefined
    (global-set-key (kbd "C-c *") 'append-asterisk-to-column-80)) ; defaults to undefined

  ;; add lisp comment block (equal)
  (when (fboundp 'insert-lisp-comment-block-equal)
    (global-set-key (kbd "C-c C-c =") 'insert-lisp-comment-block-equal)) ; defaults to undefined

  ;; add lisp comment block (dash)
  (when (fboundp 'insert-lisp-comment-block-dash)
    (global-set-key (kbd "C-c C-c -") 'insert-lisp-comment-block-dash)) ; defaults to undefined

  ;; ;; add c/c++/java comment block
  ;; (when (fboundp 'insert-c-comment-block)
  ;;   (global-set-key (kbd "C-c *") 'insert-c-comment-block)) ; defaults to undefined

  ;; ;; add db change log template line
  ;; (when (fboundp 'insert-db-change-log-template-line)
  ;;   (global-set-key (kbd "C-c t") 'insert-db-change-log-template-line)) ; defaults to undefined

  ;; ;; add db change log template line legacy
  ;; (when (fboundp 'insert-db-change-log-template-line-legacy)
  ;;   (global-set-key (kbd "C-c T") 'insert-db-change-log-template-line-legacy)) ; defaults to undefined

  ;; ;; add xml header
  ;; (when (fboundp 'insert-xml-header)
  ;;   (global-set-key (kbd "C-c x") 'insert-xml-header)) ; defaults to undefined

  ;; ;; line up assignment commands
  ;; (when (fboundp 'local-lineup-assignment-commands)
  ;;   (global-set-key (kbd "C-c _") 'local-lineup-assignment-commands)) ; defaults to undefined

  ;; ;; line up declaration commands
  ;; (when (fboundp 'local-lineup-declaration-commands)
  ;;   (global-set-key (kbd "C-c|") 'local-lineup-declaration-commands)) ; defaults to undefined

  ;; line up commands
  (global-set-key (kbd "C-c |") 'align-current) ; defaults to undefined

  ;; hippie expand
  (when (fboundp 'hippie-expand)
    (global-set-key (kbd "M-/") 'hippie-expand)) ; defaults to `dabbrev-expand'
  ;;(global-set-key (kbd "S-<tab>") 'hippie-expand)) ; defaults to `lisp-indent-line'

  ;; complete tag
  (when (fboundp 'complete-tag)
    (global-set-key (kbd "M-C-/") 'complete-tag)) ; defaults to undefined

  ;; comment region
  (when (fboundp 'comment-region)
    (global-set-key (kbd "C-c ]") 'comment-region)) ; defaults to undefined

  ;; uncomment region
  (when (fboundp 'uncomment-region)
    (global-set-key (kbd "C-c [") 'uncomment-region)) ; defaults to undefined

  ;; unset set fill column
  (global-unset-key (kbd "C-x f"))        ; defaults to `set-fill-column'

  ;; compare windows
  (when (fboundp 'compare-windows)
    (global-set-key (kbd "C-c C-w") 'compare-windows)) ; defaults to undefined

  ;; unfill-paragraph
  (when (fboundp 'unfill-paragraph)
    (global-set-key (kbd "M-Q") 'unfill-paragraph)) ; defaults to `fill-paragraph'

  ;; double-space punctuation
  (when (fboundp 'double-space-punctuation)
    (global-set-key (kbd "C-M-q") 'double-space-punctuation)) ; defaults to undefined

  ;; next-error with recenter-top-bottom
  (when (fboundp 'next-error-recenter-top-bottom)
    (global-set-key (kbd "M-g M-n") 'next-error-recenter-top-bottom)) ; defaults to `next-error'

  ;; ;; pop-up shell
  ;; (when (fboundp 'pop-up-shell)
  ;;   (global-set-key (kbd "C-c C-]") 'pop-up-shell)) ; defaults to undefined

  ;; ;; toggle side windows
  ;; (global-set-key (kbd "C-c C-[") 'window-toggle-side-windows) ; defaults to undefined

  ;; toggle pop-up shell
  (when (and (fboundp 'pop-up-shell) (fboundp 'pop-up-shell-toggle))
    (global-set-key (kbd "C-c C-]") 'pop-up-shell-toggle))) ; defaults to undefined

(init-message 3 "custom-key-bindings-standard-keys")
(custom-key-bindings-standard-keys)
;; Standard Keys:1 ends here

;; [[file:init-emacs.org::*Modes%20and%20Module%20Keys][Modes and Module Keys:1]]
;;------------------------------------------------------------------------------
;;; Key Bindings: Modes and Module Keys
;;------------------------------------------------------------------------------

(init-message 2 "Key Bindings: Modes and Module Keys")

;; modes and modules keys
(defun custom-key-bindings-modes-and-modules-keys ()
  "Set custom modes and modules key bindings."

  ;; ;; bookmarks
  ;; (when (fboundp 'load-bookmarks)
  ;;   (global-set-key (kbd "C-c C-b") 'load-bookmarks)) ; defaults to undefined

  ;; diary
  (when (fboundp 'diary)
    (global-set-key (kbd "C-x y") 'diary)) ; defaults to undefined

  ;; imenu
  (global-set-key (kbd "C-M-'") 'imenu)   ; defaults to undefined

  ;; isearch
  ;; regular expression searches
  (when (fboundp 'isearch-forward-regexp)
    (global-set-key (kbd "M-s") 'isearch-forward-regexp)) ; defaults to undefined
  (when (fboundp 'isearch-backward-regexp)
    (global-set-key (kbd "M-r") 'isearch-backward-regexp)) ; defaults to `move-to-window-line'
  ;; activate `occur' from isearch
  (define-key isearch-mode-map (kbd "C-o")
    (lambda ()
      (interactive)
      (let ((case-fold-search isearch-case-fold-search))
        (occur (if isearch-regexp isearch-string (regexp-quote isearch-string))))))

  ;; line number mode
  (when (fboundp 'linum-mode)
    (global-set-key (kbd "C-x C-n") 'linum-mode)) ; defaults to `set-goal-column'

  ;; occur
  (when (fboundp 'occur)
    ;;(global-set-key (kbd "C-x u") 'occur) ; defaults to `undo'
    (global-set-key (kbd "C-c o") 'occur)) ; defaults to undefined

  ;; shell
  (global-set-key (kbd "C-x !") 'shell) ; defaults to undefined
  ;;(global-set-key (kbd "C-x !") (lambda () (interactive) (term "bash"))) ; defaults to undefined
  ;;(global-set-key (kbd "C-x !") 'eshell) ; defaults to undefined

  ;; ;; find file as root
  ;; (when (fboundp 'find-file-root)
  ;;   (global-set-key (kbd "C-x C-r") 'find-file-root)) ; defaults to `find-file-read-only'

  ;; ;; find alternative file as root
  ;; (when (fboundp 'find-alternative-file-root)
  ;;   (global-set-key (kbd "C-x C-r") 'find-alternative-file-root)) ; defaults to `find-file-read-only'

  ;; ;; find file as root or find alternative file as root
  ;; (when (fboundp 'find-file-root-or-find-alternative-file-root)
  ;;   (global-set-key (kbd "C-x C-r") 'find-file-root-or-find-alternative-file-root)) ; defaults to `find-file-read-only'
  )

(init-message 3 "custom-key-bindings-modes-and-modules-keys")
(custom-key-bindings-modes-and-modules-keys)
;; Modes and Module Keys:1 ends here

;; [[file:init-emacs.org::*Grouped%20Prefix%20Keys][Grouped Prefix Keys:1]]
;;------------------------------------------------------------------------------
;;; Key Bindings: Grouped Prefix Keys
;;------------------------------------------------------------------------------

(init-message 2 "Key Bindings: Grouped Prefix Keys")

;; grouped prefix keys
(defun custom-key-bindings-grouped-prefix-keys ()
  "Set custom grouped prefix key bindings."

  ;; help commands
  ;; "C-h e" defaults to `view-echo-area-messages'
  (global-unset-key (kbd "C-h e"))
  ;;(global-set-key (kbd "C-h e") 'lisp-find-map)
  (global-set-key (kbd "C-h ee") 'view-echo-area-messages)
  (global-set-key (kbd "C-h ef") 'find-function)
  (global-set-key (kbd "C-h ek") 'find-function-on-key)
  (global-set-key (kbd "C-h el") 'find-library)
  (global-set-key (kbd "C-h ev") 'find-variable)
  (global-set-key (kbd "C-h eV") 'apropos-value)

  ;; functional commands
  ;; "C-c e" defaults to undefined
  (global-unset-key (kbd "C-c e"))
  (global-set-key (kbd "C-c ec") 'emacs-lisp-byte-compile)
  (global-set-key (kbd "C-c ed") 'toggle-debug-on-error)
  (global-set-key (kbd "C-c eeb") 'eval-buffer)
  (global-set-key (kbd "C-c eer") 'eval-region)
  (global-set-key (kbd "C-c efj") 'json-fix-code)
  (global-set-key (kbd "C-c efx") 'xml-format)
  (global-set-key (kbd "C-c em") 'macrostep-mode)
  (global-set-key (kbd "C-c epl") 'package-list-packages-no-fetch)
  (global-set-key (kbd "C-c epL") 'package-list-packages)
  ;; (global-set-key (kbd "C-c epu") 'package-list-update)
  ;; (global-set-key (kbd "C-c epi") 'package-list-install-missing)
  ;; (global-set-key (kbd "C-c epU") 'package-list-unaccounted-packages)
  (when (and (fboundp 'safe-load) (boundp 'emacs-home-dir))
    (global-set-key (kbd "C-c eri") `(safe-load ,(expand-file-name "init.el" emacs-home-dir))))
  (when (fboundp 'switch-to-messages)
    (global-set-key (kbd "C-c esm") 'switch-to-messages))
  (when (fboundp 'new-scratch)
    (global-set-key (kbd "C-c esn") 'new-scratch))
  (when (fboundp 'new-emacs-lisp-scratch)
    (global-set-key (kbd "C-c ese") 'new-emacs-lisp-scratch))
  (when (fboundp 'switch-to-scratch)
    (global-set-key (kbd "C-c ess") 'switch-to-scratch))
  (when (fboundp 'switch-to-scratch-for-current-mode)
    (global-set-key (kbd "C-c esc") 'switch-to-scratch-for-current-mode))
  (global-set-key (kbd "C-c ex") 'regexp-builder)

  ;; grep commands
  (when (fboundp 'grep-bin)
    (global-set-key (kbd "C-c gb") 'grep-bin)) ; defaults to undefined
  (when (fboundp 'grep-clojure)
    (global-set-key (kbd "C-c gc") 'grep-clojure)) ; defaults to undefined
  (when (fboundp 'grep-clisp)
    (global-set-key (kbd "C-c gl") 'grep-clisp)) ; defaults to undefined
  (when (fboundp 'grep-elisp)
    (global-set-key (kbd "C-c ge") 'grep-elisp)) ; defaults to undefined
  (when (fboundp 'grep-elisp-extended)
    (global-set-key (kbd "C-c gE") 'grep-elisp-extended)) ; defaults to undefined
  (when (fboundp 'grep-emacs-init)
    (global-set-key (kbd "C-c gi") 'grep-emacs-init)) ; defaults to undefined
  ;; (when (fboundp 'grep-home)
  ;;   (global-set-key (kbd "C-c gh") 'grep-home)) ; defaults to undefined
  (when (fboundp 'grep-home-init)
    (global-set-key (kbd "C-c gh") 'grep-home-init)) ; defaults to undefined
  (when (fboundp 'grep-org)
    (global-set-key (kbd "C-c go") 'grep-org)) ; defaults to undefined
  (when (fboundp 'grep-web)
    (global-set-key (kbd "C-c gw") 'grep-web)) ; defaults to undefined

  ;; browse-url commands
  (global-set-key (kbd "C-c C-z .") 'browse-url-at-point)
  (global-set-key (kbd "C-c C-z b") 'browse-url-of-buffer)
  (global-set-key (kbd "C-c C-z r") 'browse-url-of-region)
  (global-set-key (kbd "C-c C-z u") 'browse-url)
  (global-set-key (kbd "C-c C-z v") 'browse-url-of-file))

(init-message 3 "custom-key-bindings-grouped-prefix-keys")
(custom-key-bindings-grouped-prefix-keys)
;; Grouped Prefix Keys:1 ends here

;; [[file:init-emacs.org::*Set%20All%20Custom%20Key%20Bindings][Set All Custom Key Bindings:1]]
;;------------------------------------------------------------------------------
;;; Key Bindings: Set All Custom Key Bindings
;;------------------------------------------------------------------------------

(init-message 2 "Key Bindings: Set All Custom Key Bindings")

;; set all custom key bindings
(defun custom-key-bindings-set-all ()
  "Set all custom key bindings."

  (init-message 3 "custom-key-bindings-function-keys")
  (custom-key-bindings-function-keys)

  (init-message 3 "custom-key-bindings-extended-keys")
  (custom-key-bindings-extended-keys)

  (init-message 3 "custom-key-bindings-standard-keys")
  (custom-key-bindings-standard-keys)

  (init-message 3 "custom-key-bindings-modes-and-modules-keys")
  (custom-key-bindings-modes-and-modules-keys)

  (init-message 3 "custom-key-bindings-grouped-prefix-keys")
  (custom-key-bindings-grouped-prefix-keys))
;; Set All Custom Key Bindings:1 ends here

;; [[file:init-emacs.org::*Environment%20Settings][Environment Settings:1]]
;;==============================================================================
;;; Environment Settings
;;==============================================================================

(init-message 1 "Environment Settings")
;; Environment Settings:1 ends here

;; [[file:init-emacs.org::*Debugging][Debugging:1]]
;;------------------------------------------------------------------------------
;;; Environment Settings: Debugging
;;------------------------------------------------------------------------------

(init-message 2 "Environment Settings: Debugging")
;; Debugging:1 ends here

;; [[file:init-emacs.org::*Debugging][Debugging:2]]
;; turn debugging on when errors occur
(setq debug-on-error t)
;; ;; turn debugging on after init completes
;; (defun local-after-init-hook-debug-on-error ()
;;   (setq debug-on-error t))
;; (add-hook 'after-init-hook #'local-after-init-hook-debug-on-error)
;; Debugging:2 ends here

;; [[file:init-emacs.org::*Environment][Environment:1]]
;;------------------------------------------------------------------------------
;;; Environment Settings: Environment
;;------------------------------------------------------------------------------

(init-message 2 "Environment Settings: Environment")
;; Environment:1 ends here

;; [[file:init-emacs.org::*Environment][Environment:2]]
;; set coding system to UTF-8
(setq current-language-environment "UTF-8"
      locale-coding-system 'utf-8)
(set-language-environment 'utf-8)
(set-default-coding-systems 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(prefer-coding-system 'utf-8)
;; Environment:2 ends here

;; [[file:init-emacs.org::*Environment][Environment:3]]
;; set timezone to CST
(setenv "TZ" "CDT+5")
;; Environment:3 ends here

;; [[file:init-emacs.org::*Environment][Environment:4]]
;; set object print depth
(setq print-length nil
      print-level nil
      eval-expression-print-length nil
      eval-expression-print-level nil)
;; Environment:4 ends here

;; [[file:init-emacs.org::*Environment][Environment:5]]
;; determine if running on a Windows system
(defconst w32-system
  (memq system-type '(emx win32 w32 mswindows ms-dos windows-nt))
  "Non-nil if running on a Windows system.")
;; Environment:5 ends here

;; [[file:init-emacs.org::*Environment][Environment:6]]
;; determine if running on a work system
(defconst work-system
  (member (system-name)
          '("kyle-work"
            "kyle-work-media"))
  "Non-nil if running on a work system.")
;; Environment:6 ends here

;; [[file:init-emacs.org::*Environment][Environment:7]]
;; cd to home
(cd "~")
;; Environment:7 ends here

;; [[file:init-emacs.org::*Environment][Environment:8]]
;; shell environment
(setq shell-file-name "bash"
      shell-command-switch "-c"
      ;;explicit-shell-file-name "/usr/bin/env bash"
      explicit-shell-file-name shell-file-name
      explicit-sh-args '("-login" "-i"))
(setenv "SHELL" shell-file-name)

;; quote arguments on windows
(when w32-system
  (defvar w32-quote-process-args
    ?\"
    "Windows quote arguments."))
;; Environment:8 ends here

;; [[file:init-emacs.org::*Global%20Variables][Global Variables:1]]
;;------------------------------------------------------------------------------
;;; Environment Settings: Global Variables
;;------------------------------------------------------------------------------

(init-message 2 "Environment Settings: Global Variables")
;; Global Variables:1 ends here

;; [[file:init-emacs.org::*Global%20Variables][Global Variables:2]]
;; set emacs home directory
(defconst emacs-home-dir
  ;;(file-truename "~/.emacs.d")
  (expand-file-name "~/.emacs.d")
  "Emacs configuration home directory.")
;; Global Variables:2 ends here

;; [[file:init-emacs.org::*Global%20Variables][Global Variables:3]]
(defmacro emacs-home-sub-dir (dir)
  "Return expanded directory name of DIR if found as a
sub-directory of `emacs-home-dir', or just `emacs-home-dir'
otherwise."
  `(or (and (file-exists-p (expand-file-name ,dir emacs-home-dir))
            (expand-file-name ,dir emacs-home-dir))
       emacs-home-dir))
;; Global Variables:3 ends here

;; [[file:init-emacs.org::*Global%20Variables][Global Variables:4]]
;; set emacs modules directory
(defconst emacs-modules-dir
  (emacs-home-sub-dir "modules")
  "Emacs modules directory.")
;; Global Variables:4 ends here

;; [[file:init-emacs.org::*Global%20Variables][Global Variables:5]]
;; set local modules directory
(defconst local-modules-dir
  (emacs-home-sub-dir "local-modules")
  "Emacs local modules directory.")
;; Global Variables:5 ends here

;; [[file:init-emacs.org::*Global%20Variables][Global Variables:6]]
;; set local work modules directory
(defconst local-work-modules-dir
  (emacs-home-sub-dir "local-work-modules")
  "Emacs local work modules directory.")
;; Global Variables:6 ends here

;; [[file:init-emacs.org::*Global%20Variables][Global Variables:7]]
;; set customization file
(defconst customization-file
  (expand-file-name "customization.el" emacs-home-dir)
  "Emacs customization file.")
(setq custom-file customization-file)
;; Global Variables:7 ends here

;; [[file:init-emacs.org::*Global%20Variables][Global Variables:8]]
;; set init-emacs.org true file name
(defconst init-emacs-true-file-name
  (file-truename (expand-file-name "init-emacs.org" emacs-home-dir))
  "The true file name of this buffer.")
;; Global Variables:8 ends here

;; [[file:init-emacs.org::*Global%20Variables][Global Variables:9]]
;; set user name
(defconst user-name "kyle")
(defconst user-full-name "Kyle W T Sherman")
(defconst user-short-name "Kyle Sherman")
(defconst user-first-name "Kyle")
(defconst user-last-name "Sherman")
;; Global Variables:9 ends here

;; [[file:init-emacs.org::*Global%20Variables][Global Variables:10]]
;; set email address
(defconst user-mail-address
  (if (getenv "EMAIL")
      (getenv "EMAIL")
    (concat "kyle" "w" "sherman" "@" "gmail" "." "com"))
  "User email address.")
;; Global Variables:10 ends here

;; [[file:init-emacs.org::*Global%20Variables][Global Variables:11]]
;; set no-spam email address
(defconst user-mail-address-nospam
  (replace-regexp-in-string "\\." " dot "
                            (replace-regexp-in-string "@" " at " user-mail-address))
  "Slightly obfuscated user email address.")
;; Global Variables:11 ends here

;; [[file:init-emacs.org::*Global%20Variables][Global Variables:12]]
;; signature
(defun signature (&optional fortune)
  "Return a signature.
\nA fortune is added if FORTUNE is non-nil."
  (let ((name (or user-short-name user-full-name))
        (mail user-mail-address))
    (let ((sig (if (and name mail)
                   (concat name " <" mail ">")
                 (if name
                     name
                   mail))))
      (concat (if sig sig "")
              (if (and sig fortune) "\n\n" "")
              (if fortune
                  (shell-command-to-string
                   (concat "fortune -a "
                           (shell-quote-argument (expand-file-name "~/quotes"))
                           " | xargs echo -n"))
                "")))))
;; Global Variables:12 ends here

;; [[file:init-emacs.org::*Load%20Path][Load Path:1]]
(init-message 2 "Environment Settings: Load Path")

;; add paths to the head of `load-path' in reverse order.

;; personal elisp projects
(when (file-exists-p local-modules-dir)
  (add-to-list 'load-path local-modules-dir))

;; ;; personal emacs initialization scripts
;; (when (file-exists-p local-init-dir)
;;   (add-to-list 'load-path local-init-dir))

;; ;; emacs home directory
;; (when (file-exists-p emacs-home-dir)
;;   (add-to-list 'load-path emacs-home-dir))

;; emacs modules directory
(when (file-exists-p emacs-modules-dir)
  (add-to-list 'load-path emacs-modules-dir))

;; ;; org-mode directory
;; (when (file-exists-p (expand-file-name "org-mode/contrib/lisp" emacs-modules-dir))
;;   (add-to-list 'load-path (expand-file-name "org-mode/contrib/lisp" emacs-modules-dir)))
;; (when (file-exists-p (expand-file-name "org-mode/lisp" emacs-modules-dir))
;;   (add-to-list 'load-path (expand-file-name "org-mode/lisp" emacs-modules-dir)))
;; Load Path:1 ends here

;; [[file:init-emacs.org::*General][General:1]]
;;------------------------------------------------------------------------------
;;; Environment Settings: General
;;------------------------------------------------------------------------------

(init-message 2 "Environment Settings: General")
;; General:1 ends here

;; [[file:init-emacs.org::*General][General:2]]
(init-message 3 "Disable Splash Screen")

;; disable splash screen
(setq inhibit-startup-screen t)
;; General:2 ends here

;; [[file:init-emacs.org::*General][General:3]]
(init-message 3 "Hide Menu Bar")

;; hide menu-bar (use C-M-z to activate)
(when (and (fboundp 'menu-bar-mode)
           menu-bar-mode)
  (menu-bar-mode -1))
;; General:3 ends here

;; [[file:init-emacs.org::*General][General:4]]
(init-message 3 "Set Default Buffer Mode to `org-mode'")

;; set default buffer mode to `org-mode'
(setq initial-major-mode 'org-mode)
;; General:4 ends here

;; [[file:init-emacs.org::*General][General:5]]
(init-message 3 "Start with Empty Scratch Buffer")

;; clear scratch buffer
(setq initial-scratch-message nil)
;; General:5 ends here

;; [[file:init-emacs.org::*General][General:6]]
(init-message 3 "Ask before Closing Emacs")

;; ask before closing emacs
(setq kill-emacs-query-functions
      (cons (lambda () (yes-or-no-p "Really kill Emacs? "))
            kill-emacs-query-functions))
;; General:6 ends here

;; [[file:init-emacs.org::*General][General:7]]
(init-message 3 "Make Backspace Key Work Correctly")

;; make baskspace key work
(normal-erase-is-backspace-mode 1)
;; General:7 ends here

;; [[file:init-emacs.org::*General][General:8]]
(init-message 3 "Add Some Characters to Word Boundaries")

;; add underscore to word boundaries
(modify-syntax-entry ?_ "w")

;; ;; add dash to word boundaries
;; (modify-syntax-entry ?- "w")
;; General:8 ends here

;; [[file:init-emacs.org::*General][General:9]]
(init-message 3 "Ignore Comments when Parsing S-Expressions")

;; do not parse comments in sexp's
(setq parse-sexp-ignore-comments t)
(setq-default parse-sexp-ignore-comments parse-sexp-ignore-comments)
;; General:9 ends here

;; [[file:init-emacs.org::*General][General:10]]
(init-message 3 "Wrap Lines by Default")

;; wrap lines
(setq truncate-lines nil)
;; General:10 ends here

;; [[file:init-emacs.org::*General][General:11]]
(init-message 3 "Turn Off `auto-fill-mode'")

;; do not automatically break lines by inserting newlines
(turn-off-auto-fill)
;; however, visually break lines that are longer than the screen width
;;(visual-line-mode 1)
;; General:11 ends here

;; [[file:init-emacs.org::*General][General:12]]
(init-message 3 "Prevent `next-line' from Inserting Newlines")

;; stop cursor at the end of the file
(setq next-line-add-newlines nil)
;; General:12 ends here

;; [[file:init-emacs.org::*General][General:13]]
(init-message 3 "Keep the Cursor in the Same Column When Using Page-Up and Page-Down")

;; keep screen position when using page-up and page-down
(setq scroll-preserve-screen-position 'keep)
;; General:13 ends here

;; [[file:init-emacs.org::*General][General:14]]
(init-message 3 "Scroll Conservatively")

;; scroll one line at a time
(setq scroll-step 1)
;; scroll fewer lines
(setq scroll-conservatively 101)
;; turn off vertical auto-scroll
(setq auto-window-vscroll nil)
;; General:14 ends here

;; [[file:init-emacs.org::*General][General:15]]
(init-message 3 "Ignore Case on Search Matches")

;; make searches case-insensitive
(setq case-fold-search t)
;; General:15 ends here

;; [[file:init-emacs.org::*General][General:16]]
(init-message 3 "Highlight Search Matches")

;; highlight search matches
(setq search-highlight t
      ;;isearch-highlight t
      query-replace-highlight t)
;; General:16 ends here

;; [[file:init-emacs.org::*General][General:17]]
(init-message 3 "Hightlight Marked Regions")

;; make current selection visible
(transient-mark-mode 1)
(setq-default transient-mark-mode t)
;; General:17 ends here

;; [[file:init-emacs.org::*General][General:18]]
(init-message 3 "Set Default Tab Indentation to Four Spaces and Turn on Auto-Complete")

;; set tab indentation, width, and convert tabs to spaces
(setq indent-tabs-mode nil              ; do not insert tab characters
      tab-width 4                       ; default tab width is four spaces
      standard-indent 4                 ; default margin-changing functions indent
      tab-always-indent 'complete       ; tab key will try to auto-complete after auto-tabbing line
      tab-stop-list (cl-loop for x from 1 to 40
                             collect (* x 4)))
(setq-default indent-tabs-mode indent-tabs-mode
              tab-width tab-width
              standard-indent standard-indent
              tab-always-indent tab-always-indent
              tab-stop-list tab-stop-list)
;; General:18 ends here

;; [[file:init-emacs.org::*General][General:19]]
(init-message 3 "Set Default Line-Wrapping Column to 78")

;; set default fill column for `auto-fill-mode' mode and `fill-paragraph'
(setq fill-column 78)
(setq-default fill-column fill-column)
;; General:19 ends here

;; [[file:init-emacs.org::*General][General:20]]
(init-message 3 "Set Default Right-Margin Comment Indent Column to 40")

;; set default comment column for in-line comments
(setq comment-column 40)
(setq-default comment-column comment-column)
;; set default comment fill column for in-line comments
(setq comment-fill-column nil)
(setq-default comment-fill-column comment-fill-column)
;; General:20 ends here

;; [[file:init-emacs.org::*General][General:21]]
(init-message 3 "Have Cursor Movements Attempt to Keep Point on Original Column")

;; turn on goal column support
(put 'set-goal-column 'disabled nil)
;; General:21 ends here

;; [[file:init-emacs.org::*General][General:22]]
(init-message 3 "Sentences and Colons Should Have Two Spaces after Them")

;; insert two spaces after a sentence when filling text
(setq sentence-end-double-space t)
;; insert two spaces after a colon when filling text
(setq colon-double-space t)
;; General:22 ends here

;; [[file:init-emacs.org::*General][General:23]]
(init-message 3 "Highlight Matching Parenthesis")

;; highlight matching parenthesis
(show-paren-mode 1)
;; General:23 ends here

;; [[file:init-emacs.org::*General][General:24]]
(init-message 3 "Highlight TABs")

;; highlight tabs
(setq highlight-tabs t)
(setq-default highlight-tabs highlight-tabs)
;; General:24 ends here

;; [[file:init-emacs.org::*General][General:25]]
(init-message 3 "Highlight Trailing Whitespace")

;; highlight trailing white spaces
(setq show-trailing-whitespace t)
(setq-default show-trailing-whitespace show-trailing-whitespace)
;; General:25 ends here

;; [[file:init-emacs.org::*General][General:26]]
(init-message 3 "Set Default Font to Droid Sans Mono-12 or System 9x15")

;; set default font
(ignore-errors
  (condition-case nil
      ;;(set-frame-font"8x13" nil t)
      ;;(set-frame-font "9x15" nil t)
      (set-frame-font "Droid Sans Mono-12" nil t)
    ;;(set-frame-font "Ubuntu Mono-13" nil t)
    ;;(set-frame-font "Inconsolata-15" nil t)
    ;;(set-frame-font "Bitstream Vera Sans Mono-12" nil t)
    ('error
     (set-frame-font "9x15" nil t))))
;; General:26 ends here

;; [[file:init-emacs.org::*General][General:27]]
(init-message 3 "Turn on Syntax Highlighting")

;; turn on global font lock mode and syntax highlighting
(global-font-lock-mode 1)
(setq font-lock-maximum-decoration t)
;; General:27 ends here

;; [[file:init-emacs.org::*General][General:28]]
(init-message 3 "Typing Replaces Highlighted Text")

;; replace highlighted text with typed text
(delete-selection-mode t)
;; General:28 ends here

;; [[file:init-emacs.org::*General][General:29]]
(init-message 3 "Set Commenting Style to Indent")

;; ;; set comment start (default) and padding
;; (setq comment-start "#"
;;       comment-padding " ")
;; set comment style
(setq comment-style 'indent)
;; General:29 ends here

;; [[file:init-emacs.org::*General][General:30]]
(init-message 3 "Have `apropos' Search All Symbols and Order by Relevance")

;; make apropos command search all symbols
(setq apropos-do-all t)

;; make apropos command list results by relevance
(setq apropos-sort-by-scores t
      apropos-documentation-sort-by-scores t)
;; General:30 ends here

;; [[file:init-emacs.org::*General][General:31]]
(init-message 3 "Set Default `grep' Command")

;; set grep command
(setq grep-command "grep -n -H -i -r -e ")
;; General:31 ends here

;; [[file:init-emacs.org::*General][General:32]]
(init-message 3 "Set Email Sources")

;; email settings
(setq mail-sources `((pop :server "pop.gmail.com" :port 995 :user ,user-mail-address
                          :connection ssl :leave t)))
;; General:32 ends here

;; [[file:init-emacs.org::*General][General:33]]
(init-message 3 "Set Default Browser to x-www-browser")

;; set default browser
(setq browse-url-generic-program "x-www-browser")
;;(setq browse-url-generic-program "mozilla")
;;(setq browse-url-generic-program "w3m")
;;(setq browse-url-browser-function 'browse-url-generic)
;;(setq browse-url-browser-function 'w3m-browse-url)
;;(setq browse-url-browser-function 'browse-url-firefox
;;      browse-url-new-window-flag  t
;;      browse-url-firefox-new-window-is-tab t)
;; General:33 ends here

;; [[file:init-emacs.org::*General][General:34]]
(init-message 3 "Single Character Deletion Commands Delete Active Regions Without Saving to the Kill Ring")

;; when deleting an active region via single character deletion command,
;; do not save to kill ring
(setq delete-active-region t)
;; General:34 ends here

;; [[file:init-emacs.org::*General][General:35]]
(init-message 3 "Disable `vc-git'.")

;; disable vc-git
(setq vc-handled-backends nil)
;; General:35 ends here

;; [[file:init-emacs.org::*General][General:36]]
(init-message 3 "Set time zones to use for `display-time-world'.")

;; set display-time-world time zones
(setq display-time-world-list
      '(("Etc/UTC" "UTC")
        ("America/Los_Angeles" "San Diego")
        ("America/Chicago" "Minneapolis")
        ("America/New_York" "New York")
        ("Etc/GMT" "GMT")
        ("Europe/London" "London")
        ("Europe/Paris" "Paris")
        ("Asia/Tokyo" "Tokyo")))
;; General:36 ends here

;; [[file:init-emacs.org::*System][System:1]]
;;------------------------------------------------------------------------------
;;; Environment Settings: System
;;------------------------------------------------------------------------------

(init-message 2 "Environment Settings: System")
;; System:1 ends here

;; [[file:init-emacs.org::*System][System:2]]
;; reduce frequency of garbage collections
(setq gc-cons-threshold 20000000)       ; defaults to 800000
;; System:2 ends here

;; [[file:init-emacs.org::*System][System:3]]
;; set max variable bindings
(setq max-specpdl-size 10000)           ; defaults to 1300
;; System:3 ends here

;; [[file:init-emacs.org::*System][System:4]]
;; set max eval depth
(setq max-lisp-eval-depth 10000)        ; defaults to 600
;; System:4 ends here

;; [[file:init-emacs.org::*System][System:5]]
;; set max message log size
(setq message-log-max 2048)             ; defaults to 1000
;; System:5 ends here

;; [[file:init-emacs.org::*System][System:6]]
;; set max history list size
(setq history-length 250)               ; defaults to 30
;; System:6 ends here

;; [[file:init-emacs.org::*System][System:7]]
;; remove duplicates from history lists
(setq history-delete-duplicates t)      ; defaults to nil
;; System:7 ends here

;; [[file:init-emacs.org::*System][System:8]]
;; change all calls to `yes-or-no-p' to `y-or-n-p'
(fset 'yes-or-no-p 'y-or-n-p)
;; System:8 ends here

;; [[file:init-emacs.org::*System][System:9]]
;; enable upercase region (C-x C-u)
(put 'upcase-region 'disabled nil)

;; enable lowercase region (C-x C-l)
(put 'downcase-region 'disabled nil)

;; enable narrow to region
(put 'narrow-to-region 'disabled nil)

;; turn off the disabling of certain commands
(setq disabled-command-function nil)
;; System:9 ends here

;; [[file:init-emacs.org::*Files][Files:1]]
;;------------------------------------------------------------------------------
;;; Environment Settings: Files
;;------------------------------------------------------------------------------

(init-message 2 "Environment Settings: Files")
;; Files:1 ends here

;; [[file:init-emacs.org::*Files][Files:2]]
;; enable file variables
(setq enable-local-variables t
      enable-local-eval 'maybe)
;; Files:2 ends here

;; [[file:init-emacs.org::*Files][Files:3]]
;; set temporary files dir to '/tmp/'
(setq temporary-file-directory "/tmp/")
;; Files:3 ends here

;; [[file:init-emacs.org::*Files][Files:4]]
;; delete auto-save files
(setq delete-auto-save-files t)

;; do not make auto-save files
(setq auto-save-default nil)
(setq-default auto-save-default nil)
;; (setq auto-save-file-name-transforms `((".*" ,temporary-file-directory t))
;;       auto-save-list-file-prefix temporary-file-directory
;;       auto-save-list-file-name nil
;;       auto-save-default nil)
;; Files:4 ends here

;; [[file:init-emacs.org::*Files][Files:5]]
;; do not make backup files
(setq make-backup-files nil)
(setq-default make-backup-files nil)
;; (setq backup-directory-alist `((".*" . ,temporary-file-directory))
;;       make-backup-files nil
;;       backup-by-copying t
;;       version-control nil
;;       delete-old-versions t)
;; Files:5 ends here

;; [[file:init-emacs.org::*Files][Files:6]]
;; do not make lock files
(setq create-lockfiles nil)
(setq-default create-lockfiles nil)
;; Files:6 ends here

;; [[file:init-emacs.org::*Files][Files:7]]
;; follow symlinks to version control files without asking or warning
(setq vc-follow-symlinks t)
(setq-default vc-follow-symlinks vc-follow-symlinks)
;; Files:7 ends here

;; [[file:init-emacs.org::*Files][Files:8]]
;; handle gzip/zip/jar/tar files
(auto-compression-mode t)
;; Files:8 ends here

;; [[file:init-emacs.org::*Files][Files:9]]
;; reuse existing buffers, following file links
(setq find-file-existing-other-name t)
;; Files:9 ends here

;; [[file:init-emacs.org::*Files][Files:10]]
;; end files with a newline
(setq require-final-newline t)
;; Files:10 ends here

;; [[file:init-emacs.org::*Files][Files:11]]
;; turn on auto buffer revert mode
(global-auto-revert-mode 1)
;; this is currently bugged and will cause the buffer to re-center vertically every couple of seconds
;; (setq global-auto-revert-non-file-buffers t ; auto refresh dired too
;;       auto-revert-verbose nil)              ; but, be quiet about it
;; Files:11 ends here

;; [[file:init-emacs.org::*Files][Files:12]]
;; auto-create directories in path on save
(defun create-directories-on-save ()
  (or (file-exists-p (file-name-directory buffer-file-name))
      (make-directory (file-name-directory buffer-file-name) t)))
(add-hook 'before-save-hook #'create-directories-on-save)
;; Files:12 ends here

;; [[file:init-emacs.org::*Files][Files:13]]
;; remove trailing lines on call to `delete-trailing-whitespace'
(setq delete-trailing-lines t)

;; remove trailing whitespace on file saves
(defun delete-trailing-whitespace-if-not-read-only (&optional start end)
  "Call `delete-trailing-whitespace' if current buffer is not read-only."
  (interactive (if (use-region-p)
                   (list (region-beginning) (region-end))
                 (list nil nil)))
  (when (not buffer-read-only)
    (delete-trailing-whitespace start end)))
(add-hook 'before-save-hook #'delete-trailing-whitespace-if-not-read-only)
;; Files:13 ends here

;; [[file:init-emacs.org::*Files][Files:14]]
;; make shell scripts executable when saving (and reset the buffer mode)
(when (fboundp 'executable-make-buffer-file-executable-if-script-p)
  (add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p))
;; Files:14 ends here

;; [[file:init-emacs.org::*Files][Files:15]]
;; auto-save bookmarks
(setq bookmark-save-flag 1)
;; Files:15 ends here

;; [[file:init-emacs.org::*Files][Files:16]]
;; desktop history
(desktop-save-mode 1)
(setq desktop-save 'ask-if-new
      desktop-load-locked-desktop t
      desktop-restore-eager 0 ; do not restore any buffers until all modules and modes have loaded
      desktop-buffers-not-to-save (concat "\\("
                                          "\\.log\\|(ftp)\\|^tags\\|^TAGS"
                                          "\\.diary\\|\\diary\\|\\.bbdb"
                                          "\\)$"))
(add-to-list 'desktop-globals-to-save 'file-name-history t)
(add-to-list 'desktop-modes-not-to-save 'Info-mode t)
(add-to-list 'desktop-modes-not-to-save 'info-lookup-mode t)
;;(add-to-list 'desktop-modes-not-to-save 'dired-mode t)
;;(add-to-list 'desktop-modes-not-to-save 'fundamental-mode t)
;; Files:16 ends here

;; [[file:init-emacs.org::*Files][Files:17]]
;; save minibuffer history
(when (fboundp 'savehist-mode)
  ;;(setq savehist-file (expand-file-name "history" emacs-home-dir)) ; defaults to ~/.emacs.d/history
  (savehist-mode 1)
  (setq savehist-save-minibuffer-history 1
        savehist-additional-variables '(kill-ring
                                        search-ring
                                        regexp-search-ring)))
;; Files:17 ends here

;; [[file:init-emacs.org::*Files][Files:18]]
;; save place in files
(setq save-place t)
(setq-default save-place save-place)
;; Files:18 ends here

;; [[file:init-emacs.org::*Buffers%20and%20Windows][Buffers and Windows:1]]
;;------------------------------------------------------------------------------
;;; Environment Settings: Buffers and Windows
;;------------------------------------------------------------------------------

(init-message 2 "Environment Settings: Buffers and Windows")
;; Buffers and Windows:1 ends here

;; [[file:init-emacs.org::*Buffers%20and%20Windows][Buffers and Windows:2]]
;; allow undo/redo of window settings
(when (fboundp 'winner-mode)
  (winner-mode 1))
;; Buffers and Windows:2 ends here

;; [[file:init-emacs.org::*Buffers%20and%20Windows][Buffers and Windows:3]]
;; auto scroll compilation buffer
(setq compilation-scroll-output t)
;; Buffers and Windows:3 ends here

;; [[file:init-emacs.org::*Buffers%20and%20Windows][Buffers and Windows:4]]
;; delay buffer fontification to increase scroll speed
(setq jit-lock-defer-time 0.05)
;; Buffers and Windows:4 ends here

;; [[file:init-emacs.org::*Buffers%20and%20Windows][Buffers and Windows:5]]
;; preserve buffer point for each window
(setq switch-to-buffer-preserve-window-point t)
;; Buffers and Windows:5 ends here

;; [[file:init-emacs.org::*Functions][Functions:1]]
;;==============================================================================
;;; Functions
;;==============================================================================

(init-message 1 "Functions")
;; Functions:1 ends here

;; [[file:init-emacs.org::*Initialization%20Functions][Initialization Functions:1]]
;;------------------------------------------------------------------------------
;;; Functions: Initialization Functions
;;------------------------------------------------------------------------------

(init-message 2 "Functions: Initialization Functions")
;; Initialization Functions:1 ends here

;; [[file:init-emacs.org::*No%20heading][No heading:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Initialization Functions: safe-substring
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Initialization Functions: safe-substring")

;; safe substring
(defun safe-substring (string from &optional to)
  "Calls the `substring' function safely.
\nNo errors will be returned for out of range values of FROM and
TO.  Instead an empty string is returned."
  (let* ((len (length string))
         (to (or to len)))
    (when (< from 0)
      (setq from (+ len from)))
    (when (< to 0)
      (setq to (+ len to)))
    (if (or (< from 0) (> from len)
            (< to 0) (> to len)
            (< to from))
        ""
      (substring string from to))))
;; No heading:1 ends here

;; [[file:init-emacs.org::*require-if-available][require-if-available:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Initialization Functions: require-if-available
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Initialization Functions: require-if-available")

;; require if available
;; prevent load errors if a required package does not exist
(defun require-if-available (&rest args)
  "Require symbols and load library strings.
\nFails quietly if some are not available."
  (let (lib)
    (condition-case nil
        (mapc (lambda (e)
                (setq lib e)
                (cond
                 ((stringp e) (load-library e))
                 ((symbolp e) (require e))))
              args)
      ('file-error
       (progn (message "Could not load extension: %s" lib) nil)))))
;; require-if-available:1 ends here

;; [[file:init-emacs.org::*load-file-if-available][load-file-if-available:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Initialization Functions: load-file-if-available
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Initialization Functions: load-file-if-available")

;; load file if available
(defun load-file-if-available (file)
  "Load emacs lisp file, if it exists.
\nFails quietly if file does not exist."
  (when (file-exists-p file)
    (load-file file)))
;; load-file-if-available:1 ends here

;; [[file:init-emacs.org::*compile-file-if-needed][compile-file-if-needed:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Initialization Functions: compile-file-if-needed
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Initialization Functions: compile-file-if-needed")

(when (fboundp 'safe-substring)
  ;; compile expanded file name
  (defun compile-file-if-needed-process-file (file)
    (let* ((file (expand-file-name file))
           (file-comp (concat file "c")))
      (when (or
             (not (file-exists-p file-comp))
             (file-newer-than-file-p file file-comp))
        (byte-compile-file file))))

  ;; compile file if needed
  (defun compile-file-if-needed (file)
    "Compile emacs lisp file if needed."
    ;; add .el if needed
    (unless (string= (safe-substring file -3) ".el")
      (setq file (concat file ".el")))
    ;; find file
    (if (file-exists-p file)
        (compile-file-if-needed-process-file file)
      (dolist (path load-path)
        (let ((file (concat path "/" file)))
          (when (file-exists-p file)
            (compile-file-if-needed-process-file file)))))
    (when (get-buffer "*Compile-Log*")
      ;;(kill-buffer "*Compile-Log*")
      (delete-other-windows))))
;; compile-file-if-needed:1 ends here

;; [[file:init-emacs.org::*with-eval-after-load][with-eval-after-load:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Initialization Functions: with-eval-after-load
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Initialization Functions: with-eval-after-load")

(unless (fboundp 'with-eval-after-load)
  (defmacro with-eval-after-load (file &rest body)
    `(eval-after-load ,file
       `(funcall (function ,(lambda () ,@body))))))
;; with-eval-after-load:1 ends here

;; [[file:init-emacs.org::*eval-after-load-with-byte-compile][eval-after-load-with-byte-compile:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Initialization Functions: eval-after-load-with-byte-compile
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Initialization Functions: eval-after-load-with-byte-compile")

;; byte compiled `eval-after-load'
;; byte compile the body; if the feature is not available, ignore warnings
;; Source: http://www.lunaryorn.com/2013/06/25/introducing-with-eval-after-load.html
;; Source: http://www.lunaryorn.com/2013/05/01/byte-compiling-eval-after-load.html
;; Source: http://lists.gnu.org/archive/html/bug-gnu-emacs/2012-11/msg01262.html
(defmacro eval-after-load-with-byte-compile (file &rest body)
  "After FILE is loaded, evaluate BODY.
\nBODY is byte compiled.
FILE may be a named feature or a file name, see `eval-after-load'
for details."
  (declare (indent 1) (debug t))
  `(,(if (or (not byte-compile-current-file)
             (if (symbolp file)
                 (require file nil :no-error)
               (load file :no-message :no-error)))
         'progn
       (message "eval-after-load-with-byte-compile: cannot find %s" file)
       'with-no-warnings)
    (with-eval-after-load ',file ,@body)))
;; eval-after-load-with-byte-compile:1 ends here

;; [[file:init-emacs.org::*safe-load][safe-load:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Initialization Functions: safe-load
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Initialization Functions: safe-load")

(defvar safe-load-error-list ""
  "List of files that reported errors when loaded with `safe-load'.")

(defun safe-load (file &optional noerror nomessage nosuffix)
  "Load FILE safely.
\nIf an error occurs when loading, report it and add FILE to
`safe-load-error-list'."
  (interactive "f")
  (condition-case nil
      (load file noerror nomessage nosuffix)
    ('error
     (setq safe-load-error-list (concat safe-load-error-list " " file))
     (message "Error loading %s" file)
     ;;(sleep-for 1)
     nil)))

(defun safe-load-check ()
  "Check for any previous `safe-load' loading errors."
  (interactive)
  (unless (string= safe-load-error-list "")
    (message "Error loading: %s" safe-load-error-list)))

(defun safe-load-compile (file &optional noerror nomessage nosuffix)
  "Calls `compile-file-if-needed' followed by `safe-load'."
  (interactive "f")
  (compile-file-if-needed file)
  (safe-load file noerror nomessage nosuffix))
;; safe-load:1 ends here

;; [[file:init-emacs.org::*save-mark-and-excursion][save-mark-and-excursion:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Initialization Functions: save-mark-and-excursion
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Initialization Functions: save-mark-and-excursion")

(unless (fboundp 'save-mark-and-excursion)

  (defun save-mark-and-excursion--save ()
    (cons
     (let ((mark (mark-marker)))
       (and mark (marker-position mark) (copy-marker mark)))
     mark-active))

  (defun save-mark-and-excursion--restore (saved-mark-info)
    (let ((saved-mark (car saved-mark-info))
          (omark (marker-position (mark-marker)))
          (nmark nil)
          (saved-mark-active (cdr saved-mark-info)))
      ;; mark marker
      (if (null saved-mark)
          (set-marker (mark-marker) nil)
        (setf nmark (marker-position saved-mark))
        (set-marker (mark-marker) nmark)
        (set-marker saved-mark nil))
      ;; mark active
      (let ((cur-mark-active mark-active))
        (setf mark-active saved-mark-active)
        ;; if mark is active now, and either was not active or was at a
        ;; different place, run the activate hook
        (if saved-mark-active
            (unless (eq omark nmark)
              (run-hooks 'activate-mark-hook))
          ;; if mark has ceased to be active, run deactivate hook
          (when cur-mark-active
            (run-hooks 'deactivate-mark-hook))))))

  (defmacro save-mark-and-excursion (&rest body)
    "Like `save-excursion', but also save and restore the mark state.
\nThis macro does what `save-excursion' did before Emacs 25.1."
    (let ((saved-marker-sym (make-symbol "saved-marker")))
      `(let ((,saved-marker-sym (save-mark-and-excursion--save)))
         (unwind-protect
             (save-excursion ,@body)
           (save-mark-and-excursion--restore ,saved-marker-sym))))))
;; save-mark-and-excursion:1 ends here

;; [[file:init-emacs.org::*Advice%20Functions][Advice Functions:1]]
;;------------------------------------------------------------------------------
;;; Functions: Advice Functions
;;------------------------------------------------------------------------------

(init-message 2 "Advice Functions")
;; Advice Functions:1 ends here

;; [[file:init-emacs.org::*Compile%20Goto%20Error%20Org][Compile Goto Error Org:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Advice Functions: Compile Goto Error Org
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Advice Functions: Compile Goto Error Org")

;; open compilation bugs in org file for errors in tangled elisp code
(defun compile-goto-error--org (&optional event)
  "Open compilation bugs in org file for errors in tangled elisp code."
  (when (eq major-mode 'emacs-lisp-mode)
    (ignore-errors (org-babel-tangle-jump-to-org))))

;; compilation hook
(defun compilation-mode-hook--compile-goto-error ()
  ;; advise `compile-goto-error'
  (advice-add 'compile-goto-error :after #'compile-goto-error--org))
(add-hook 'compilation-mode-hook #'compilation-mode-hook--compile-goto-error)
;; Compile Goto Error Org:1 ends here

;; [[file:init-emacs.org::*General%20Functions][General Functions:1]]
;;------------------------------------------------------------------------------
;;; Functions: General Functions
;;------------------------------------------------------------------------------

(init-message 2 "Functions: General Functions")
;; General Functions:1 ends here

;; [[file:init-emacs.org::*list-to-string][list-to-string:1]]
;;------------------------------------------------------------------------------
;;;; Functions: General Functions: list-to-string
;;------------------------------------------------------------------------------

(init-message 3 "Functions: General Functions: list-to-string")

;; list to string
(defun list-to-string (list &optional delimiter)
  "Return concatenated characters in LIST using optional DELIMITER."
  (let ((delimiter (or delimiter "")))
    (mapconcat 'string list delimiter)))
;; list-to-string:1 ends here

;; [[file:init-emacs.org::*string-to-list][string-to-list:1]]
;;------------------------------------------------------------------------------
;;;; Functions: General Functions: string-to-list
;;------------------------------------------------------------------------------
;;
;; There are multiple ways to convert a string to a list.
;;
;; You can use `split-string' to return a list of strings:
;;
;;   (split-string STRING "" t)
;;
;; You can use loop to return a list of characters:
;;
;;   (cl-loop for x across STRING collect x)
;;
;; You can also use append to return a list of characters:
;;
;;   (append STRING nil)

(init-message 3 "Functions: General Functions: string-to-list")

;; string to list
(defun string-to-list (string)
  "Return list of characters in STRING."
  (cl-loop for x across string collect x))
;; string-to-list:1 ends here

;; [[file:init-emacs.org::*join-strings][join-strings:1]]
;;------------------------------------------------------------------------------
;;;; Functions: General Functions: join-strings
;;------------------------------------------------------------------------------

(init-message 3 "Functions: General Functions: join-strings")

;; join strings
(defun join-strings (list &optional delim)
  "Convert LIST of strings into a single string.
\nUse optional DELIM as a delimiter."
  (if delim
      (cl-reduce (lambda (x y) (concat x delim y)) list)
    (cl-reduce (lambda (x y) (concat x y)) list)))
;; join-strings:1 ends here

;; [[file:init-emacs.org::*file-to-string][file-to-string:1]]
;;------------------------------------------------------------------------------
;;;; Functions: General Functions: file-to-string
;;------------------------------------------------------------------------------

(init-message 3 "Functions: General Functions: file-to-string")

;; file to string
(defun file-to-string (file)
  "Return the contents of FILE as a string."
  (if (file-exists-p file)
      (with-temp-buffer
        (insert-file-contents file)
        (buffer-string))
    nil))
;; file-to-string:1 ends here

;; [[file:init-emacs.org::*chomp][chomp:1]]
;;------------------------------------------------------------------------------
;;;; Functions: General Functions: chomp
;;------------------------------------------------------------------------------

(init-message 3 "Functions: General Functions: chomp")

;; chomp
(defun chomp (string)
  "Remove trailing carriage returns and new lines from STRING.
\nLike the Perl chomp command."
  (if (and
       (stringp string)
       (string-match "\r?\n$" string))
      (replace-match "" t nil string)
    string))
;; chomp:1 ends here

;; [[file:init-emacs.org::*trim][trim:1]]
;;------------------------------------------------------------------------------
;;;; Functions: General Functions: trim
;;------------------------------------------------------------------------------

(init-message 3 "Functions: General Functions: trim")

;; trim
(defun trim (string)
  "Remove starting and trailing whitespace from STRING."
  (if (stringp string)
      (replace-regexp-in-string "^[ \t\n]*" ""
                                (replace-regexp-in-string "[ \t\n]*$" "" string))
    string))
;; trim:1 ends here

;; [[file:init-emacs.org::*for-each][for-each:1]]
;;------------------------------------------------------------------------------
;;;; Functions: General Functions: for-each
;;------------------------------------------------------------------------------

(init-message 3 "Functions: General Functions: for-each")

;; for each
(defun for-each (fn list)
  "Call FN for each element in list LIST."
  (when list
    (funcall fn (car list))
    (for-each fn (cdr list))))
;; for-each:1 ends here

;; [[file:init-emacs.org::*is-single][is-single:1]]
;;------------------------------------------------------------------------------
;;;; Functions: General Functions: is-single
;;------------------------------------------------------------------------------

(init-message 3 "Functions: General Functions: is-single")

;; is single
(defun is-single (list)
  "Return true if LIST is a list of one element."
  (and (consp list) (null (cdr list))))
;; is-single:1 ends here

;; [[file:init-emacs.org::*append-element][append-element:1]]
;;------------------------------------------------------------------------------
;;;; Functions: General Functions: append-element
;;------------------------------------------------------------------------------

(init-message 3 "Functions: General Functions: append-element")

;; append element
(defun append-element (list elm)
  "Append ELM to end of list LIST."
  (append list (list elm)))
;; append-element:1 ends here

;; [[file:init-emacs.org::*map-integer][map-integer:1]]
;;------------------------------------------------------------------------------
;;;; Functions: General Functions: map-integer
;;------------------------------------------------------------------------------

(init-message 3 "Functions: General Functions: map-integer")

;; map integer
(defun map-integer (fn n)
  "Call function FN once for every number from 0 to N-1."
  (let ((acc nil))
    (dotimes (i n)
      (push (funcall fn i) acc))
    (nreverse acc)))
;; map-integer:1 ends here

;; [[file:init-emacs.org::*filter][filter:1]]
;;------------------------------------------------------------------------------
;;;; Functions: General Functions: filter
;;------------------------------------------------------------------------------

(init-message 3 "Functions: General Functions: filter")

;; filter
(defun filter (fn list)
  "Call function FN for each element in list LIST and return the non-nil results."
  (let (acc)
    (dolist (x list (nreverse acc))
      (let ((val (funcall fn x)))
        (when val (push val acc))))))
;; filter:1 ends here

;; [[file:init-emacs.org::*most][most:1]]
;;------------------------------------------------------------------------------
;;;; Functions: General Functions: most
;;------------------------------------------------------------------------------

(init-message 3 "Functions: General Functions: most")

;; most
(defun most (fn list)
  "Call function FN for each element in LIST and return the highest score.
\nThe function FN must return a number as a score for a given element.
The element with the highest result is returned with its score."
  (if (null list)
      (list nil nil)
    (let* ((wins (car list))
           (max (funcall fn wins)))
      (dolist (x (cdr list))
        (let ((score (funcall fn x)))
          (when (> score max)
            (setq wins x
                  max score))))
      (list wins max))))
;; most:1 ends here

;; [[file:init-emacs.org::*queue][queue:1]]
;;------------------------------------------------------------------------------
;;;; Functions: General Functions: queue
;;------------------------------------------------------------------------------

(init-message 3 "Functions: General Functions: queue")

;; queue
(defun make-queue ()
  "Return FIFO (first-in first-out) queue function.

Then call the queue function with one of the following commands:

  'push X = Add X to the back of the queue
  'pop    = Remove element from the front of the queue and return it
  'peek   = Return the element in the front of the queue
  'show   = Display the queue's contents
  'fb     = Display the front and back queues (for debugging)

Source: http://irreal.org/blog/?p=40"
  (lexical-let (front
                back)
    (lambda (cmd &optional data)
      (cl-labels ((exchange ()
                            (setq front (reverse back))
                            (setq back '())))
        (cl-case cmd
          ((push) (push data back))
          ((pop) (or (pop front)
                     (progn
                       (exchange)
                       (pop front))))
          ((peek) (unless front
                    (exchange))
           (car front))
          ((show) (format "%s" (append front (reverse back))))
          ((fb) (format "front: %s, back: %s" front back))
          (else (error "Illegal command given to queue object: %s" cmd)))))))
;; queue:1 ends here

;; [[file:init-emacs.org::*quicksort][quicksort:1]]
;;------------------------------------------------------------------------------
;;;; Functions: General Functions: quicksort
;;------------------------------------------------------------------------------

(init-message 3 "Functions: General Functions: quicksort")

;; quicksort
(defun quicksort (list)
  "Return sorted LIST (using the Quicksort algorithm)."
  (if (null list) nil
    (let* ((elt (car list))
           (rst (cdr list))
           (left-p (lambda (x) (< x elt))))
      (append (quicksort (cl-remove-if-not left-p rst))
              (list elt)
              (quicksort (cl-remove-if left-p rst))))))
;; quicksort:1 ends here

;; [[file:init-emacs.org::*hash-table-dump][hash-table-dump:1]]
;;------------------------------------------------------------------------------
;;;; Functions: General Functions: hash-table-dump
;;------------------------------------------------------------------------------

(init-message 3 "Functions: General Functions: hash-table-dump")

;; dump hash table contents
(defun hash-table-dump (table)
  "Return contents of TABLE as an association list."
  (let (result)
    (maphash (lambda (k v) (push (cons k v) result)) table)
    (nreverse result)))
;; hash-table-dump:1 ends here

;; [[file:init-emacs.org::*Emacs%20Functions][Emacs Functions:1]]
;;------------------------------------------------------------------------------
;;; Functions: Emacs Functions
;;------------------------------------------------------------------------------

(init-message 2 "Emacs Functions")
;; Emacs Functions:1 ends here

;; [[file:init-emacs.org::*inside-string][inside-string:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: inside-string
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: inside-string")

;; inside-string
(defun inside-string ()
  "Return non-nil if point is inside a string."
  (not (not (nth 3 (syntax-ppss)))))
;; inside-string:1 ends here

;; [[file:init-emacs.org::*inside-comment][inside-comment:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: inside-comment
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: inside-comment")

;; inside-comment
(defun inside-comment ()
  "Return non-nil if point is inside a comment."
  (nth 4 (syntax-ppss)))
;; inside-comment:1 ends here

;; [[file:init-emacs.org::*try-finally][try-finally:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: try-finally
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: try-finally")

;; try/finally code block
(defmacro try-finally (fn &rest finally)
  "Evaluate FN catching and returning any errors after FINALLY is
evaluated."
  `(unwind-protect
       (let (result)
         (condition-case err
             (setq result (progn ,fn))
           ('error
            (message (format "Caught error: %s" err))
            (setq result (cons 'error (list err)))))
         result)
     ,@finally))
;; try-finally:1 ends here

;; [[file:init-emacs.org::*save-buffer-always][save-buffer-always:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: save-buffer-always
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: save-buffer-always")

;; save buffer even if it has not been modified
(defun save-buffer-always ()
  "Save current buffer in visited file even if it has not been modified."
  (interactive)
  (set-buffer-modified-p t)
  (save-buffer))
;; save-buffer-always:1 ends here

;; [[file:init-emacs.org::*save-buffer-always-maybe][save-buffer-always-maybe:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: save-buffer-always-maybe
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: save-buffer-always-maybe")

;; allow prefix to determine if regular save or forced save is used
(defun save-buffer-always-maybe (arg)
  "Call `save-buffer' if no prefix given, otherwise call
`save-buffer-always' to force a save."
  (interactive "P")
  (if arg
      (save-buffer-always)
    (save-buffer)))
;; save-buffer-always-maybe:1 ends here

;; [[file:init-emacs.org::*describe-function-or-variable-at-point][describe-function-or-variable-at-point:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: describe-function-or-variable-at-point
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: describe-function-or-variable-at-point")

;; describe function or variable at point
(defun describe-function-or-variable-at-point (&optional point)
  "Describe function or variable at POINT (or `point' if not given).
\nUse `describe-function' or `describe-variable' as appropriate."
  (interactive)
  (let ((point (or point (point))))
    (save-excursion
      (goto-char point)
      (if (eq (variable-at-point) 0)
          (call-interactively 'describe-function)
        (call-interactively 'describe-variable)))))
;; describe-function-or-variable-at-point:1 ends here

;; [[file:init-emacs.org::*mode-line-add][mode-line-add:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: mode-line-add
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: mode-line-add")

;; add item to mode line
(defun mode-line-add (item)
  "Add ITEM to `global-mode-string' part of the mode line."
  (or global-mode-string (setq global-mode-string '("")))
  (add-to-list 'global-mode-string item t))
;; mode-line-add:1 ends here

;; [[file:init-emacs.org::*insert-line-below][insert-line-below:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: insert-line-below
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: insert-line-below")

;; insert line below
(defun insert-line-below ()
  "Insert a line below current one."
  (interactive)
  (end-of-line)
  (newline)
  (indent-for-tab-command))
;; insert-line-below:1 ends here

;; [[file:init-emacs.org::*insert-line-above][insert-line-above:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: insert-line-above
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: insert-line-above")

;; insert line above
(defun insert-line-above ()
  "Insert a line above current one."
  (interactive)
  (beginning-of-line)
  (newline)
  (forward-line -1)
  (indent-for-tab-command))
;; insert-line-above:1 ends here

;; [[file:init-emacs.org::*move-line-down][move-line-down:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: move-line-down
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: move-line-down")

;; move line down
(defun move-line-down ()
  (interactive)
  (let ((col (current-column)))
    (forward-line)
    (transpose-lines 1)
    (forward-line -1)
    (move-to-column col)))
;; move-line-down:1 ends here

;; [[file:init-emacs.org::*move-line-up][move-line-up:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: move-line-up
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: move-line-up")

;; move line up
(defun move-line-up ()
  (interactive)
  (let ((col (current-column)))
    (forward-line 1)
    (ignore-errors (transpose-lines -1))
    (forward-line -1)
    (move-to-column col)))
;; move-line-up:1 ends here

;; [[file:init-emacs.org::*kill-word-enhanced][kill-word-enhanced:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: kill-word-enhanced
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: kill-word-enhanced")

;; enhanced kill-word
(defun kill-word-enhanced (arg)
  "Kill word at point."
  (interactive "*P")
  (save-excursion
    (let ((p (point)))
      (forward-word 1)
      (when (> (point) p)
        (forward-word -1)))
    (kill-word (or arg 1))
    (when (eq (char-after) ? )
      (delete-char 1))))
;; kill-word-enhanced:1 ends here

;; [[file:init-emacs.org::*kill-region-or-word][kill-region-or-word:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: kill-region-or-word
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: kill-region-or-word")

;; kill region or word
(defun kill-region-or-word ()
  "Call `kill-region' or `backward-kill-word' depending on
whether or not a region is selected."
  (interactive "*")
  (if (use-region-p)
      (kill-region (point) (mark))
    (backward-kill-word 1)))
;; kill-region-or-word:1 ends here

;; [[file:init-emacs.org::*kill-duplicate-lines][kill-duplicate-lines:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: kill-duplicate-lines
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: kill-duplicate-lines")

;; kill duplicate lines in region or buffer
(defun kill-duplicate-lines (&optional beg end)
  "Kill duplicate lines in the pre-sorted selected region or entire buffer (if none)."
  (interactive "*")
  (let ((beg (or beg (if (use-region-p) (region-beginning) (point-min))))
        (end (or end (if (use-region-p) (region-end) (point-max)))))
    (save-excursion
      (save-restriction
        (narrow-to-region beg end)
        (goto-char (point-min))
        (while (not (eobp))
          (kill-line 1)
          (yank)
          (let ((next-line (point)))
            (while (re-search-forward (format "^%s" (regexp-quote (car kill-ring))) nil t)
              (replace-match "" nil nil))
            (goto-char next-line)))))))
;; kill-duplicate-lines:1 ends here

;; [[file:init-emacs.org::*indent-or-expand][indent-or-expand:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: indent-or-expand
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: indent-or-expand")

;; indent or expand based on line position
(defun indent-or-expand ()
  "Either indent according to mode, or expand the word preceding point."
  (interactive "*")
  (if (and
       (not (bobp))
       (not (eobp))
       (= ?w (char-syntax (char-before)))
       (not (= ?w (char-syntax (char-after)))))
      (dabbrev-expand nil)
    (indent-according-to-mode)))
;; indent-or-expand:1 ends here

;; [[file:init-emacs.org::*swap-windows][swap-windows:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: swap-windows
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: swap-windows")

;; swap windows
(defun swap-windows ()
  "If you have two windows, swap them."
  (interactive)
  (if (not (= (count-windows) 2))
      (message "You need exactly two windows to swap them.")
    (let* ((w1 (first (window-list)))
           (w2 (second (window-list)))
           (b1 (window-buffer w1))
           (b2 (window-buffer w2))
           (s1 (window-start w1))
           (s2 (window-start w2)))
      (set-window-buffer w1 b2)
      (set-window-buffer w2 b1)
      (set-window-start w1 s2)
      (set-window-start w2 s1))))
;; swap-windows:1 ends here

;; [[file:init-emacs.org::*toggle-window-split][toggle-window-split:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: toggle-window-split
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: toggle-window-split")

;; toggle split windows
(defun toggle-window-split ()
  "If you have two windows, toggle them between horizontal and vertical layouts."
  (interactive)
  (if (not (= (count-windows) 2))
      (message "You need exactly two windows to toggle them.")
    (let* ((w1 (first (window-list)))
           (w2 (second (window-list)))
           (b1 (window-buffer w1))
           (b2 (window-buffer w2))
           (s1 (window-start w1))
           (s2 (window-start w2))
           (e1 (window-edges w1))
           (e2 (window-edges w2))
           (win-2nd (not (and (<= (car e1) (car e2))
                              (<= (cadr e1) (cadr e2)))))
           (splitter
            (if (= (car e1) (car e2))
                'split-window-horizontally
              'split-window-vertically)))
      (delete-other-windows)
      (funcall splitter)
      (when win-2nd (other-window 1))
      (set-window-buffer (selected-window) b1)
      (set-window-buffer (next-window) b2)
      (select-window w1)
      (when win-2nd (other-window 1)))))
;; toggle-window-split:1 ends here

;; [[file:init-emacs.org::*enlarge-window-5][enlarge-window-5:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: enlarge-window-5
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: enlarge-window-5")

;; enlarge window by 5
(defun enlarge-window-5 (arg)
  "Make current window 5 lines bigger."
  (interactive "P")
  (if arg
      (enlarge-window (* 5 arg))
    (enlarge-window 5)))
;; enlarge-window-5:1 ends here

;; [[file:init-emacs.org::*shrink-window-5][shrink-window-5:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: shrink-window-5
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: shrink-window-5")

;; shrink window by 5
(defun shrink-window-5 (arg)
  "Make current window 5 lines smaller."
  (interactive "P")
  (if arg
      (enlarge-window (* -5 arg))
    (enlarge-window -5)))
;; shrink-window-5:1 ends here

;; [[file:init-emacs.org::*compile-elisp][compile-elisp:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: compile-elisp
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: compile-elisp")

;; byte compile elisp directory
(defun compile-elisp (&optional dir)
  "Byte compile DIR directory.
\nDIR defaults to `emacs-home-dir' or `~/.emacs.d'."
  (interactive)
  (byte-recompile-directory (or dir emacs-home-dir "~/.emacs.d") 0))
;; compile-elisp:1 ends here

;; [[file:init-emacs.org::*join-next-line][join-next-line:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: join-next-line
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: join-next-line")

;; join next line with current
(defun join-next-line (arg)
  (interactive "*P")
  (dotimes (n (or arg 1))
    (join-line -1)))
;; join-next-line:1 ends here

;; [[file:init-emacs.org::*sort-all-lines][sort-all-lines:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: sort-all-lines
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: sort-all-lines")

;; sort all lines in buffer
(defun sort-all-lines ()
  "Sort all lines in current buffer."
  (interactive "*")
  (save-excursion
    (sort-lines nil (point-min) (point-max))))
;; sort-all-lines:1 ends here

;; [[file:init-emacs.org::*delete-word][delete-word:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: delete-word
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: delete-word")

;; delete-word
(defun delete-word (arg)
  "Delete characters forward until encountering the end of the
type of character on point.  Types are: whitespace, alphanumeric,
and symbol/other.
With argument ARG, do this that many times."
  (interactive "p")
  (let ((whitespace-regexp "[ \t\n]")
        (alphanumeric-regexp "[[:alnum:]-_]"))
    (dotimes (x arg)
      (delete-region
       (point)
       (save-excursion
         (let ((type (cond ((looking-at whitespace-regexp) :whitespace)
                           ((looking-at alphanumeric-regexp) :alphanumeric)
                           (t :other)))
               (char (char-after)))
           (forward-char 1)
           (while (case type
                    (:whitespace (looking-at whitespace-regexp))
                    (:alphanumeric (looking-at alphanumeric-regexp))
                    (:other (= char (char-after))))
             (forward-char 1))
           (point)))))))
;; delete-word:1 ends here

;; [[file:init-emacs.org::*backward-delete-word][backward-delete-word:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: backward-delete-word
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: backward-delete-word")

;; backward-delete-word
(defun backward-delete-word (arg)
  "Delete characters backward until encountering the end of the
type of character on point.  Types are: whitespace, alphanumeric,
and symbol/other.
With argument ARG, do this that many times."
  (interactive "p")
  (let ((whitespace-regexp "[ \t\n]")
        (alphanumeric-regexp "[[:alnum:]-_]"))
    (dotimes (x arg)
      (delete-region
       (save-excursion
         (backward-char 1)
         (let ((type (cond ((looking-at whitespace-regexp) :whitespace)
                           ((looking-at alphanumeric-regexp) :alphanumeric)
                           (t :other)))
               (char (char-before)))
           (backward-char 1)
           (while (case type
                    (:whitespace (looking-at whitespace-regexp))
                    (:alphanumeric (looking-at alphanumeric-regexp))
                    (:other (= char (char-after))))
             (backward-char 1))
           (forward-char 1)
           (point)))
       (point)))))
;; backward-delete-word:1 ends here

;; [[file:init-emacs.org::*copy-line][copy-line:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: copy-line
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: copy-line")

;; copy line
(defun copy-line (&optional line)
  "Copy the line containing the point or LINE."
  (interactive)
  (save-excursion
    (when line
      (goto-char (point-min))
      (forward-line (1- line)))
    (goto-char (line-beginning-position))
    (let ((beg (point)))
      (if (eobp)
          (goto-char (line-end-position))
        (forward-line 1))
      (copy-region-as-kill beg (point)))))
;; copy-line:1 ends here

;; [[file:init-emacs.org::*cut-line][cut-line:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: cut-line
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: cut-line")

;; cut line
(defun cut-line (&optional line)
  "Cut the line containing the point or LINE."
  (interactive "*")
  (save-excursion
    (when line
      (goto-char (point-min))
      (forward-line (1- line)))
    (goto-char (line-beginning-position))
    (let ((beg (point)))
      (if (eobp)
          (goto-char (line-end-position))
        (forward-line 1))
      (kill-region beg (point)))))
;; cut-line:1 ends here

;; [[file:init-emacs.org::*delete-line][delete-line:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: delete-line
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: delete-line")

;; delete line
(defun delete-line (&optional line)
  "Delete the line containing the point or LINE."
  (interactive "*")
  (let ((col (- (point) (line-beginning-position))))
    (when line
      (goto-char (point-min))
      (forward-line (1- line)))
    (goto-char (line-beginning-position))
    (delete-region (point)
                   (progn
                     (forward-line 1)
                     (point)))
    (if (<= (+ (point) col) (line-end-position))
        (forward-char col)
      (goto-char (line-end-position)))))
;; delete-line:1 ends here

;; [[file:init-emacs.org::*delete-to-end-of-line][delete-to-end-of-line:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: delete-to-end-of-line
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: delete-to-end-of-line")

;; delete to end of line
(defun delete-to-end-of-line (&optional arg)
  "Delete from the point to the end of the line containing the point."
  (interactive "*P")
  (delete-region (point)
                 (progn
                   (if arg
                       (forward-line (prefix-numeric-value arg))
                     (if (not (eolp))
                         (goto-char (line-end-position))
                       (forward-char 1)))
                   (point))))
;; delete-to-end-of-line:1 ends here

;; [[file:init-emacs.org::*duplicate-line][duplicate-line:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: duplicate-line
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: duplicate-line")

;; duplicate line
(defun duplicate-line (&optional comment line)
  "Duplicate the line containing the point.

If COMMENT is non-nil, also comment out the original line.
If LINE is non-nil, duplicate that line instead.

Handles duplicating `org-table' lines correctly.  Also fixes
closing s-expressions properly.

Cursor is left at current column in newly created line."
  (interactive "*P")
  (let ((col (current-column)))
    (when line
      (goto-char (point-min))
      (forward-line (1- line)))
    (let ((line (buffer-substring (line-beginning-position) (line-end-position))))
      (when comment
        (comment-region (line-beginning-position) (line-end-position)))
      (when (and (fboundp 'org-at-table-p) (org-at-table-p))
        (org-table-insert-row)
        (delete-region (line-beginning-position) (1+ (line-end-position))))
      (goto-char (line-end-position))
      (newline)
      (insert line)
      (move-to-column col)
      (when (or (eq major-mode 'emacs-lisp-mode)
                (eq major-mode 'lisp-mode))
        (save-excursion
          (forward-line -1)
          (goto-char (line-beginning-position))
          (forward-sexp)
          (when (looking-at "\\()+\\)[ \t]*;")
            (replace-match (make-string (length (match-string 1)) ?\s) nil nil nil 1))
          (when (looking-at ")+")
            (replace-match ""))
          (forward-line 1))))))
;; duplicate-line:1 ends here

;; [[file:init-emacs.org::*duplicate-line-inc][duplicate-line-inc:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: duplicate-line-inc
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: duplicate-line-inc")

;; duplicate line with incrementing numbers
(defun duplicate-line-inc (&optional line)
  "Duplicate the line containing the point or LINE and increment any numbers by 1."
  (interactive "*")
  (let ((col (current-column)))
    (save-excursion
      (when line
        (goto-char (point-min))
        (forward-line (1- line)))
      (copy-region-as-kill (line-beginning-position) (line-end-position))
      (goto-char (line-end-position))
      (if (eobp)
          (newline)
        (forward-line 1))
      (open-line 1)
      (yank))
    (forward-line 1)
    (while (re-search-forward "[0-9]+" (line-end-position) t)
      (let ((num (string-to-number
                  (buffer-substring (match-beginning 0) (match-end 0)))))
        (replace-match (int-to-string (1+ num)))))
    (move-to-column col)))
;; duplicate-line-inc:1 ends here

;; [[file:init-emacs.org::*goto-line-enhanced][goto-line-enhanced:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: goto-line-enhanced
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: goto-line-enhanced")

;; enhanced goto-line
(defun goto-line-enhanced ()
  "Show line numbers while prompting for the line number to go to."
  (interactive)
  (if (or
       (and (boundp 'linum-mode) linum-mode)
       current-prefix-arg)
      (call-interactively 'goto-line)
    (unwind-protect
        (progn
          (linum-mode 1)
          (call-interactively 'goto-line))
      (linum-mode -1))))
(global-set-key [remap goto-line] 'goto-line-enhanced)
;; goto-line-enhanced:1 ends here

;; [[file:init-emacs.org::*forward-word-enhanced][forward-word-enhanced:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: forward-word-enhanced
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: forward-word-enhanced")

;; enhanced forward-word
(defun forward-word-enhanced (arg)
  "Move point forward one word or ARG words (backward if ARG is negative)."
  (interactive "P")
  (let ((arg (or arg 1)))
    (if (< arg 0)
        (backward-word-enhanced (- 0 arg))
      (dotimes (n arg)
        (forward-char 1)
        (backward-word 1)
        (forward-word 2)
        (backward-word 1))
      t)))
(global-set-key [remap forward-word] 'forward-word-enhanced)
;; forward-word-enhanced:1 ends here

;; [[file:init-emacs.org::*backword-word-enhanced][backword-word-enhanced:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: backword-word-enhanced
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: backword-word-enhanced")

;; enhanced backward-word
(defun backward-word-enhanced (arg)
  "Move point backward one word or ARG words (forward if ARG is negative)."
  (interactive "P")
  (let ((arg (or arg 1)))
    (if (< arg 0)
        (forward-word-enhanced (- 0 arg))
      (dotimes (n arg)
        (backward-word 1))
      t)))
(global-set-key [remap backward-word] 'backward-word-enhanced)
;; backword-word-enhanced:1 ends here

;; [[file:init-emacs.org::*forward-sexp-enhanced][forward-sexp-enhanced:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: forward-sexp-enhanced
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: forward-sexp-enhanced")

;; enhanced forward-sexp
(defun forward-sexp-enhanced (arg)
  "Move point forward one balanced expression (sexp) or ARG sexp's (backward if ARG is negative)."
  (interactive "P")
  (let ((arg (or arg 1))
        (p (point)))
    (ignore-errors
      (forward-sexp arg))
    (when (= p (point))
      (cond
       ((> arg 0)
        (forward-char 1)
        (when (> arg 1)
          (forward-sexp-enhanced (1- arg))))
       ((< arg 0)
        (forward-char -1)
        (when (< arg -1)
          (forward-sexp-enhanced (1+ arg))))
       (t)))))
(global-set-key [remap forward-sexp] 'forward-sexp-enhanced)
;; forward-sexp-enhanced:1 ends here

;; [[file:init-emacs.org::*backward-sexp-enhanced][backward-sexp-enhanced:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: backward-sexp-enhanced
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: backward-sexp-enhanced")

;; enhanced backward-sexp
(defun backward-sexp-enhanced (arg)
  "Move point backward one balanced expression (sexp) or ARG sexp's (forward if ARG is negative)."
  (interactive "P")
  (let ((arg (or arg 1)))
    (forward-sexp-enhanced (- 0 arg))))
(global-set-key [remap backward-sexp] 'backward-sexp-enhanced)
;; backward-sexp-enhanced:1 ends here

;; [[file:init-emacs.org::*scroll-up-enhanced][scroll-up-enhanced:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: scroll-up-enhanced
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: scroll-up-enhanced")

;; enhanced scroll-up
(defun scroll-up-enhanced (arg)
  "Scroll up one page or ARG amount.
\nIf less than a page away, jump to the end of the buffer."
  (interactive "P")
  (let ((col (current-column)))
    (condition-case nil
        (if arg
            (scroll-up arg)
          (scroll-up))
      ('error
       (goto-char (point-max))))
    (move-to-column col)))
(global-set-key [remap scroll-up] 'scroll-up-enhanced)
;; scroll-up-enhanced:1 ends here

;; [[file:init-emacs.org::*scroll-down-enhanced][scroll-down-enhanced:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: scroll-down-enhanced
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: scroll-down-enhanced")

;; enhanced scroll-down
(defun scroll-down-enhanced (arg)
  "Scroll down one page or ARG amount.
\nIf less than a page away, jump to the beginning of the buffer."
  (interactive "P")
  (let ((col (current-column)))
    (condition-case nil
        (if arg
            (scroll-down arg)
          (scroll-down))
      ('error
       (goto-char (point-min))))
    (move-to-column col)))
(global-set-key [remap scroll-down] 'scroll-down-enhanced)
;; scroll-down-enhanced:1 ends here

;; [[file:init-emacs.org::*scroll-up-command-enhanced][scroll-up-command-enhanced:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: scroll-up-command-enhanced
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: scroll-up-command-enhanced")

;; enhanced scroll-up-command
(defun scroll-up-command-enhanced (arg)
  "Scroll up one page or ARG amount.
\nIf less than a page away, jump to the end of the buffer."
  (interactive "P")
  (let ((col (current-column)))
    (condition-case nil
        (if arg
            (scroll-up-command arg)
          (scroll-up-command))
      ('error
       (goto-char (point-max))))
    (move-to-column col)))
(global-set-key [remap scroll-up-command] 'scroll-up-command-enhanced)
;; scroll-up-command-enhanced:1 ends here

;; [[file:init-emacs.org::*scroll-down-command-enhanced][scroll-down-command-enhanced:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: scroll-down-command-enhanced
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: scroll-down-command-enhanced")

;; enhanced scroll-down-command
(defun scroll-down-command-enhanced (arg)
  "Scroll down one page or ARG amount.
\nIf less than a page away, jump to the beginning of the buffer."
  (interactive "P")
  (let ((col (current-column)))
    (condition-case nil
        (if arg
            (scroll-down-command arg)
          (scroll-down-command))
      ('error
       (goto-char (point-min))))
    (move-to-column col)))
(global-set-key [remap scroll-down-command] 'scroll-down-command-enhanced)
;; scroll-down-command-enhanced:1 ends here

;; [[file:init-emacs.org::*downcase-word-enhanced][downcase-word-enhanced:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: downcase-word-enhanced
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: downcase-word-enhanced")

;; enhanced downcase-word
(defun downcase-word-enhanced (arg)
  "Convert word at point to lower case."
  (interactive "*P")
  (let ((p (point)))
    (forward-word 1)
    (when (> (point) p)
      (forward-word -1)))
  (downcase-word (or arg 1)))
(global-set-key [remap downcase-word] 'downcase-word-enhanced)
;; downcase-word-enhanced:1 ends here

;; [[file:init-emacs.org::*upcase-word-enhanced][upcase-word-enhanced:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: upcase-word-enhanced
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: upcase-word-enhanced")

;; enhanced upcase-word
(defun upcase-word-enhanced (arg)
  "Convert word at point to upper case."
  (interactive "*P")
  (let ((p (point)))
    (forward-word 1)
    (when (> (point) p)
      (forward-word -1)))
  (upcase-word (or arg 1)))
(global-set-key [remap upcase-word] 'upcase-word-enhanced)
;; upcase-word-enhanced:1 ends here

;; [[file:init-emacs.org::*capitalize-word-enhanced][capitalize-word-enhanced:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: capitalize-word-enhanced
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: capitalize-word-enhanced")

;; enhanced capitalize-word
(defun capitalize-word-enhanced (arg)
  "Capitalize word at point."
  (interactive "*P")
  (let ((syntax-table (copy-syntax-table (syntax-table))))
    (modify-syntax-entry ?- "." syntax-table)
    (with-syntax-table syntax-table
      (let ((p (point)))
        (forward-word 1)
        (when (> (point) p)
          (forward-word -1)))
      (capitalize-word (or arg 1)))))
(global-set-key [remap capitalize-word] 'capitalize-word-enhanced)
;; capitalize-word-enhanced:1 ends here

;; [[file:init-emacs.org::*eval-current-sexp][eval-current-sexp:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: eval-current-sexp
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: eval-current-sexp")

;; evaluate current sexp
(defun eval-current-sexp (eval-last-sexp-arg-internal)
  "Evaluate current sexp; print value in minibuffer.
Interactively, with prefix argument, print output into current buffer.
Calls `eval-last-sexp' to handle eval."
  (interactive "P")
  (save-excursion
    (end-of-defun)
    (eval-last-sexp eval-last-sexp-arg-internal)))
;; eval-current-sexp:1 ends here

;; [[file:init-emacs.org::*eval-sexp-buffer][eval-sexp-buffer:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: eval-sexp-buffer
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: eval-sexp-buffer")

;; evaluate all sexp's in buffer
(defun eval-sexp-buffer (&optional buffer)
  "Evaluate all sexp's in BUFFER.
\nBUFFER defaults to the current buffer."
  (interactive)
  (save-excursion
    (when buffer
      (set-buffer buffer))
    (goto-char (point-min))
    (let ((count 0))
      (while (not (eobp))
        (forward-sexp)
        (eval-last-sexp nil)
        (incf count))
      (message (format "Evaluated %d expressions." count)))))
;; eval-sexp-buffer:1 ends here

;; [[file:init-emacs.org::*eval-and-replace-last-sexp][eval-and-replace-last-sexp:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: eval-and-replace-last-sexp
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: eval-and-replace-last-sexp")

;; replace sexp before point with its evaluation
(defun eval-and-replace-last-sexp ()
  "Replace sexp before point with its evaluation."
  (interactive "*")
  (backward-kill-sexp)
  (condition-case nil
      (prin1 (eval (read (current-kill 0)))
             (current-buffer))
    ('error
     (message "Invalid expression")
     (insert (current-kill 0)))))
;; eval-and-replace-last-sexp:1 ends here

;; [[file:init-emacs.org::*eval-and-replace-current-sexp][eval-and-replace-current-sexp:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: eval-and-replace-current-sexp
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: eval-and-replace-current-sexp")

;; replace current sexp with its evaluation
(defun eval-and-replace-current-sexp ()
  "Replace current sexp with its evaluation."
  (interactive "*")
  (save-excursion
    (end-of-defun)
    (eval-and-replace-last-sexp)))
;; eval-and-replace-current-sexp:1 ends here

;; [[file:init-emacs.org::*macroexpand-and-replace][macroexpand-and-replace:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: macroexpand-and-replace
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: macroexpand-and-replace")

;; replace sexp before point with its macroexpand
(defun macroexpand-and-replace ()
  "Replace sexp before point with its macroexpand."
  (interactive "*")
  (backward-kill-sexp)
  (condition-case nil
      (prin1 (macroexpand (read (current-kill 0)))
             (current-buffer))
    ('error
     (message "Invalid expression")
     (insert (current-kill 0)))))
;; macroexpand-and-replace:1 ends here

;; [[file:init-emacs.org::*calc-eval-and-replace-region][calc-eval-and-replace-region:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: calc-eval-and-replace-region
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: calc-eval-and-replace-region")

;; evaluate region using `calc-eval' and replace it with the result
(defun calc-eval-and-replace-region (beg end)
  (interactive "*r")
  (let ((result (calc-eval (buffer-substring-no-properties beg end))))
    (kill-region beg end)
    (insert result)))
;; calc-eval-and-replace-region:1 ends here

;; [[file:init-emacs.org::*calc-eval-and-replace-line][calc-eval-and-replace-line:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: calc-eval-and-replace-line
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: calc-eval-and-replace-line")

;; evaluate line using `calc-eval' and replace it with the result
(defun calc-eval-and-replace-line ()
  (interactive "*")
  (calc-eval-and-replace-region (line-beginning-position) (line-end-position)))
;; calc-eval-and-replace-line:1 ends here

;; [[file:init-emacs.org::*next-error-recenter-top-bottom][next-error-recenter-top-bottom:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: next-error-recenter-top-bottom
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: next-error-recenter-top-bottom")

;; next-error-recenter-top-bottom
(defun next-error-recenter-top-bottom (&optional arg reset)
  "Call `next-error' then `recenter-top-bottom'."
  (interactive "P")
  (next-error arg reset)
  (recenter-top-bottom '(4)))
;; next-error-recenter-top-bottom:1 ends here

;; [[file:init-emacs.org::*indent-current-sexp][indent-current-sexp:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: indent-current-sexp
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: indent-current-sexp")

;; indent current sexp
(defun indent-current-sexp ()
  "Indent current sexp."
  (interactive "*")
  (save-excursion
    (end-of-defun)
    (let ((end (point)))
      (beginning-of-defun)
      ;; indent sexp
      (indent-sexp nil)
      ;; loop through every line checking for eol comments
      (while (< (point) end)
        (goto-char (line-end-position))
        ;; if comment exists, indent it
        (when (eq (get-text-property (point) 'face) 'font-lock-comment-face)
          (comment-indent))
        (forward-line 1)))))
;; indent-current-sexp:1 ends here

;; [[file:init-emacs.org::*indent-sexp-buffer][indent-sexp-buffer:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: indent-sexp-buffer
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: indent-sexp-buffer")

;; indent all sexp's in buffer
(defun indent-sexp-buffer (&optional buffer)
  "Indent all sexp's in BUFFER.
\nBUFFER defaults to the current buffer."
  (interactive "*")
  (save-excursion
    (when buffer
      (set-buffer buffer))
    (goto-char (point-min))
    (let ((count 0))
      (while (not (eobp))
        (forward-sexp 1)
        (indent-current-sexp)
        (incf count))
      (message (format "Indented %d expressions." count)))))
;; indent-sexp-buffer:1 ends here

;; [[file:init-emacs.org::*comment-or-uncomment-sexp][comment-or-uncomment-sexp:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: comment-or-uncomment-sexp
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: comment-or-uncomment-sexp")

;; comment or uncomment sexp's
(defun uncomment-sexp (&optional n)
  "Uncomment an sexp around point."
  (interactive "P")
  (let* ((initial-point (point-marker))
         (p)
         (end (save-excursion
                (when (elt (syntax-ppss) 4)
                  (search-backward-regexp comment-start-skip
                                      (line-beginning-position)
                                      t))
                (setq p (point-marker))
                (comment-forward (point-max))
                (point-marker)))
         (beg (save-excursion
                (forward-line 0)
                (while (= end (save-excursion
                                (comment-forward (point-max))
                                (point)))
                  (forward-line -1))
                (goto-char (line-end-position))
                (search-backward-regexp comment-start-skip
                                    (line-beginning-position)
                                    t)
                (while (looking-at-p comment-start-skip)
                  (forward-char -1))
                (point-marker))))
    (unless (= beg end)
      (uncomment-region beg end)
      (goto-char p)
      ;; identify the top-level sexp inside the comment
      (while (and (ignore-errors (backward-up-list) t)
                  (>= (point) beg))
        (skip-chars-backward (rx (syntax expression-prefix)))
        (setq p (point-marker)))
      ;; re-comment everything before it
      (ignore-errors
        (comment-region beg p))
      ;; and everything after it
      (goto-char p)
      (forward-sexp (or n 1))
      (skip-chars-forward "\r\n[:blank:]")
      (if (< (point) end)
          (ignore-errors
            (comment-region (point) end))
        ;; if this is a closing delimiter, pull it up
        (goto-char end)
        (skip-chars-forward "\r\n[:blank:]")
        (when (= 5 (car (syntax-after (point))))
          (delete-indentation))))
    ;; without a prefix, it's more useful to leave point where it was
    (unless n
      (goto-char initial-point))))

;; (defun comment-sexp--raw ()
;;   "Comment the sexp at point or ahead of point."
;;   (pcase (or (bounds-of-thing-at-point 'sexp)
;;              (save-excursion
;;                (skip-chars-forward "\r\n[:blank:]")
;;                (bounds-of-thing-at-point 'sexp)))
;;     (`(,l . ,r)
;;      (goto-char r)
;;      (skip-chars-forward "\r\n[:blank:]")
;;      (comment-region l r)
;;      (skip-chars-forward "\r\n[:blank:]"))))

(defun comment-or-uncomment-sexp (&optional n)
  "Comment the sexp at point and move past it.
If already inside (or before) a comment, uncomment instead.
With a prefix argument N, (un)comment that many sexps."
  (interactive "P")
  (if (or (elt (syntax-ppss) 4)
          (< (save-excursion
               (skip-chars-forward "\r\n[:blank:]")
               (point))
             (save-excursion
               (comment-forward 1)
               (point))))
      (uncomment-sexp n)
    (dotimes (_ (or n 1))
      (pcase (or (bounds-of-thing-at-point 'sexp)
                 (save-excursion
                   (skip-chars-forward "\r\n[:blank:]")
                   (bounds-of-thing-at-point 'sexp)))
        (`(,l . ,r)
         (goto-char r)
         (skip-chars-forward "\r\n[:blank:]")
         (comment-region l r)
         (skip-chars-forward "\r\n[:blank:]"))))))
;; comment-or-uncomment-sexp:1 ends here

;; [[file:init-emacs.org::*rename-buffer-and-file][rename-buffer-and-file:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: rename-buffer-and-file
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: rename-buffer-and-file")

;; rename buffer and file
(defun rename-buffer-and-file (file-name &optional confirm)
 "Rename current buffer and file to FILE-NAME."
 (interactive
  (list (if buffer-file-name
            (read-file-name "Rename buffer to: " default-directory)
          (error "Current buffer is not visiting a file"))
        (not current-prefix-arg)))
 (or (not file-name) (string-equal file-name "")
     (let ((source-file-name (buffer-file-name)))
       (if (not source-file-name)
           (error "Buffer '%s' is not visiting a file" (buffer-name))
         (progn
           (write-file file-name confirm)
           (when (file-exists-p file-name)
             (delete-file source-file-name)))))))
;; rename-buffer-and-file:1 ends here

;; [[file:init-emacs.org::*move-buffer-and-file][move-buffer-and-file:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: move-buffer-and-file
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: move-buffer-and-file")

;; move buffer and file
(defun move-buffer-and-file (dir &optional confirm)
 "Move current buffer and file to DIR."
 (interactive
  (list (if buffer-file-name
            (read-directory-name "Move to directory: " default-directory
                                 (file-name-directory (buffer-file-name)))
          (error "Current buffer is not visiting a file"))
        (not current-prefix-arg)))
 (let* ((source-file-name (buffer-file-name))
        (dir (if (or (string= dir "")
                     (not (string= (substring dir -1) "/")))
                 (concat dir "/")
               dir))
        (file-name (concat dir (file-name-nondirectory source-file-name))))
   (if (not source-file-name)
       (message "Buffer '%s' is not visiting a file" (buffer-name))
     (progn
       (unless (and confirm
                    (file-exists-p file-name)
                    (not (yes-or-no-p (format "File `%s' exists; overwrite? " file-name)))
                    (message "Canceled"))
         (copy-file source-file-name file-name t)
         (delete-file source-file-name)
         (set-visited-file-name file-name)
         (set-buffer-modified-p nil)
         (vc-refresh-state))))))
;; move-buffer-and-file:1 ends here

;; [[file:init-emacs.org::*delete-buffer-and-file][delete-buffer-and-file:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: delete-buffer-and-file
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: delete-buffer-and-file")

;; delete buffer and file
(defun delete-buffer-and-file (&optional buffer)
  "Delete BUFFER and file associated with it.
\nBUFFER defaults to the current buffer."
  (interactive)
  (let* ((buffer-name (or buffer (current-buffer)))
         (file-name (buffer-file-name buffer-name)))
    (if (not (and file-name (file-exists-p file-name)))
        (if (fboundp 'ido-kill-buffer)
            (ido-kill-buffer)
          (kill-buffer))
      (unless (and
               (not (yes-or-no-p (format "Are you sure you want to delete '%s'? " file-name)))
               (message "Canceled"))
        (delete-file file-name)
        (kill-buffer buffer-name)
        (message "File '%s' successfully deleted" file-name)))))
;; delete-buffer-and-file:1 ends here

;; [[file:init-emacs.org::*expand-relative-file-name][expand-relative-file-name:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: expand-relative-file-name
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: expand-relative-file-name")

;; expand relative file name
(defun expand-relative-file-name (file-name)
  "Expand FILE-NAME found in current directory."
  (expand-file-name file-name (file-name-directory (or load-file-name buffer-file-name))))
;; expand-relative-file-name:1 ends here

;; [[file:init-emacs.org::*remove-trailing-blanks][remove-trailing-blanks:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: remove-trailing-blanks
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: remove-trailing-blanks")

;; remove trailing blanks and newlines before saving a buffer
;; mode hooks are added in their sections
(defun remove-trailing-blanks (&optional ask)
  "Remove trailing spaces and tabs from every line in the current buffer.
\nAlso remove trailing newlines from the end of the buffer, apart
from one.
\nIf ASK is non-nil, ask for confirmation."
  (when (and (not (zerop (buffer-size)))
             (char-equal (char-after (buffer-size)) ?\n)
             (save-excursion
               (save-restriction
                 (save-match-data
                   (widen)
                   (goto-char (point-min))
                   (or (search-forward " \n" nil t)
                       (search-forward "\t\n" nil t)
                       (re-search-forward "\n\n\\'" nil t)))))
             (if ask
                 (yes-or-no-p "Remove trailing spaces and newlines before saving? ")
               (message "Removing trailing spaces and newlines...")
               t))
    (save-excursion
      (save-restriction
        (save-match-data
          (widen)
          (goto-char (point-min))
          (while (re-search-forward "[ \t]+$" nil 'move)
            (replace-match ""))
          (when (bolp)
            (skip-chars-backward "\n")
            (delete-region (1+ (point)) (point-max)))))))
  nil)

(defun remove-trailing-blanks-ask ()
  (remove-trailing-blanks t))

(defun install-remove-trailing-blanks ()
  (add-hook 'write-contents-functions #'remove-trailing-blanks))

(defun install-remove-trailing-blanks-ask ()
  (add-hook 'write-contents-functions #'remove-trailing-blanks-ask))

;; remove trailing blanks
;;(add-hook 'fundamental-mode-hook #'install-remove-trailing-blanks)

;; remove trailing blanks from all save files
;;(add-hook 'write-contents-functions #'remove-trailing-blanks)
;; remove-trailing-blanks:1 ends here

;; [[file:init-emacs.org::*remove-tabs][remove-tabs:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: remove-tabs
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: remove-tabs")

;; remove tabs before saving a buffer
;; mode hooks are added in their sections
(defun remove-tabs (&optional ask)
  "Remove tabs from every line in the current buffer.
\nIf ASK is non-nil, ask for confirmation.
\nIf buffer is read-only quietly do nothing."
  (when (not buffer-read-only)
    (when (and (not (zerop (buffer-size)))
               (char-equal (char-after (buffer-size)) ?\n)
               (save-excursion
                 (save-restriction
                   (save-match-data
                     (widen)
                     (goto-char (point-min))
                     (search-forward "\t" nil t))))
               (if ask
                   (yes-or-no-p "Remove tabs before saving? ")
                 (message "Removing tabs...")
                 t))
      (save-excursion
        (save-restriction
          (save-match-data
            (goto-char (point-min))
            (while (re-search-forward "[ \t]+$" nil t)
              (delete-region (match-beginning 0) (match-end 0)))
            (goto-char (point-min))
            (when (search-forward "\t" nil t)
              (untabify (1- (point)) (point-max))))))))
  nil)

(defcustom remove-tabs-exceptions
  '((:file . "\.tsv$")
    (:mode . "Makefile")
    (:file . "Makefile"))

  "List of mode name and file name regexp patterns to exclude
from tab removal on file save."
  :type 'list
  :group 'files)

(defun remove-tabs-with-exceptions (&optional ask)
  (let ((file-name (file-name-nondirectory (buffer-file-name))))
    (unless
        (cl-remove-if (lambda (x)
                        (let ((type (car x))
                              (name (cdr x)))
                          (and
                           (not (and (eq type :mode)
                                     (stringp mode-name)
                                     (string= mode-name name)))
                           (not (and (eq type :file)
                                     (string-match name file-name))))))
                      remove-tabs-exceptions)
      (remove-tabs ask))))

(defun remove-tabs-ask ()
  (remove-tabs t))

(defun remove-tabs-with-exceptions-ask ()
  (remove-tabs-with-exceptions t))

(defun install-remove-tabs ()
  (add-hook 'write-contents-functions #'remove-tabs-with-exceptions))

(defun install-remove-tabs-ask ()
  (add-hook 'write-contents-functions #'remove-tabs-with-exceptions-ask))

;; remove tabs
;;(add-hook 'fundamental-mode-hook #'install-remove-tabs)

;; remove tabs from all saved files (with exceptions)
(add-hook 'write-contents-functions #'remove-tabs-with-exceptions)
;; remove-tabs:1 ends here

;; [[file:init-emacs.org::*indent-down][indent-down:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: indent-down
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: indent-down")

;; indent line and next line
(defun indent-down ()
  "Indent current line via `lisp-indent-line' then go down one line via `next-line'."
  (interactive "*")
  (lisp-indent-line)
  (forward-line 1))
;; indent-down:1 ends here

;; [[file:init-emacs.org::*server-start-maybe][server-start-maybe:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: server-start-maybe
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: server-start-maybe")

;; emacs server start
(defun server-start-maybe ()
  "Safe way to start an emacs server."
  (unless w32-system
    (server-start t)
    (server-start)))
;; server-start-maybe:1 ends here

;; [[file:init-emacs.org::*load-bookmarks][load-bookmarks:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: load-bookmarks
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: load-bookmarks")

;; load bookmarks
(defun load-bookmarks (&optional file)
  "Load bookmarks html FILE.
\nFILE defaults to `~/lynx_bookmarks.html'."
  (interactive)
  (let ((file (or file "~/lynx_bookmarks.html")))
    (w3m-browse-url (expand-file-name file))))
;; load-bookmarks:1 ends here

;; [[file:init-emacs.org::*find-file-updir][find-file-updir:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: find-file-updir
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: find-file-updir")

;; find file in current or any parent directory
(defun find-file-updir (name &optional directory)
  "Return the absolute file name of NAME if it is found in the
current buffer's default directory or in any parent directory.
\nIf DIRECTORY is non-nil, then it is used instead of the current
buffer's default directory."
  (let ((name (expand-file-name name directory)))
    (while (and
            (not (file-exists-p name))
            (not (string= name (concat "/" (file-name-nondirectory name)))))
      (setq name (expand-file-name (concat
                                    (file-name-directory name)
                                    "../"
                                    (file-name-nondirectory name)))))
    (when (file-exists-p name) name)))
;; find-file-updir:1 ends here

;; [[file:init-emacs.org::*find-file-eof][find-file-eof:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: find-file-eof
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: find-file-eof")

;; find file, then move to EOF
(defun find-file-eof (file)
  "Run `find-file' with FILE, then move the point to the end of buffer."
  (find-file file)
  (goto-char (point-max)))
;; find-file-eof:1 ends here

;; [[file:init-emacs.org::*mark-full-word][mark-full-word:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: mark-full-word
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: mark-full-word")

;; mark full word
(defun mark-full-word (&optional arg allow-extend)
  "Set mark ARG words away from start of word at point.
\nPoint is moved to the beginning of the word at point, then
`mark-word' is called with the given arguments."
  (interactive "P\np")
  (beginning-of-thing 'word)
  (mark-word arg allow-extend))
;; mark-full-word:1 ends here

;; [[file:init-emacs.org::*term-buffer][term-buffer:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: term-buffer
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: term-buffer")

;; open persistent terminal buffer
(defun term-buffer ()
  "Create or visit a persistent terminal buffer."
  (interactive)
  (let ((name "*ansi-term*"))
    (if (not (get-buffer name))
        (progn
          (split-window-sensibly (selected-window))
          (other-window 1)
          (ansi-term (getenv "SHELL")))
      (switch-to-buffer-other-window name))))
;; term-buffer:1 ends here

;; [[file:init-emacs.org::*term-ansi][term-ansi:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: term-ansi
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: term-ansi")

;; run an application in an ansi-term window
(when (fboundp 'term-ansi-make-term)
  (defun term-ansi (name cmd &rest switches)
    (let ((buffer (apply #'term-ansi-make-term
                         (generate-new-buffer-name (concat "*" name "*"))
                         cmd nil switches)))
      (set-buffer buffer)
      (when (fboundp 'term-mode) (term-mode))
      (when (fboundp 'term-char-mode) (term-char-mode))
      (when (fboundp 'term-set-escape-char) (term-set-escape-char ?\C-x))
      (switch-to-buffer buffer))))
;; term-ansi:1 ends here

;; [[file:init-emacs.org::*pop-up-shell][pop-up-shell:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: pop-up-shell
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: pop-up-shell")

;; open pop-up terminal window
(defun pop-up-shell (arg)
  "Pop-up a shell in a side window passing ARG."
  (interactive "P")
  (select-window
   (display-buffer-in-side-window
    (save-window-excursion
      (let ((prefix-arg arg))
        (call-interactively #'shell))
      (current-buffer))
    '((side . bottom)))))
;; pop-up-shell:1 ends here

;; [[file:init-emacs.org::*pop-up-shell-toggle][pop-up-shell-toggle:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: pop-up-shell-toggle
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: pop-up-shell-toggle")

;; open pop-up terminal window
(defun pop-up-shell-toggle (arg)
  "Toggle visibility of `pop-up-shell'.
ARG is passed along if shell is being toggled on."
  (interactive "P")
  (let ((buffer-window (get-buffer-window "*shell*")))
    (if buffer-window
        (delete-window buffer-window)
      (pop-up-shell arg))))
;; pop-up-shell-toggle:1 ends here

;; [[file:init-emacs.org::*switch-to-scratch][switch-to-scratch:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: switch-to-scratch
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: switch-to-scratch")

;; switch to scratch buffer
(defun switch-to-scratch ()
  "Switch to `*scratch*' buffer, creating it if needed."
  (interactive)
  (switch-to-buffer "*scratch*"))
;; switch-to-scratch:1 ends here

;; [[file:init-emacs.org::*switch-to-scratch-for-current-mode][switch-to-scratch-for-current-mode:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: switch-to-scratch-for-current-mode
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: switch-to-scratch-for-current-mode")

;; switch to scratch buffer for curent mode
(defun switch-to-scratch-for-current-mode ()
  "Switch to `*scratch-MODE*' buffer, creating it if needed."
  (interactive)
  (let* ((mode major-mode)
         (buffer-name (concat "*scratch-" (symbol-name mode) "*")))
    (switch-to-buffer buffer-name)
    (funcall mode)))
;; switch-to-scratch-for-current-mode:1 ends here

;; [[file:init-emacs.org::*new-scratch][new-scratch:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: new-scratch
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: new-scratch")

;; create a new scratch buffer
(defun new-scratch ()
  "Create a new scratch buffer."
  (interactive)
  (switch-to-buffer (generate-new-buffer-name "*scratch*")))
;; new-scratch:1 ends here

;; [[file:init-emacs.org::*new-emacs-lisp-scratch][new-emacs-lisp-scratch:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: new-emacs-lisp-scratch
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: new-emacs-lisp-scratch")

;; create a new scratch buffer
(defun new-emacs-lisp-scratch ()
  "Create a new scratch buffer with `emacs-lisp-mode'."
  (interactive)
  (switch-to-buffer (generate-new-buffer-name "*scratch-emacs-lisp-mode*"))
  (emacs-lisp-mode))
;; new-emacs-lisp-scratch:1 ends here

;; [[file:init-emacs.org::*recreate-scratch-when-killed][recreate-scratch-when-killed:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: recreate-scratch-when-killed
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: recreate-scratch-when-killed")

;; recreate scratch buffer when killed
(defun recreate-scratch-when-killed ()
  "Recreate scratch buffer, when it is killed.

Add the following to your init.el file for this to work:

  \(add-hook 'kill-buffer-query-functions #'recreate-scratch-when-killed)"
  (interactive)
  (if (string= (buffer-name (current-buffer)) "*scratch*")
      (let ((kill-buffer-query-functions kill-buffer-query-functions))
        (remove-hook 'kill-buffer-query-functions 'recreate-scratch-when-killed)
        (kill-buffer (current-buffer))
        (set-buffer (get-buffer-create "*scratch*"))
        nil)
    t))

(add-hook 'kill-buffer-query-functions #'recreate-scratch-when-killed)
;; recreate-scratch-when-killed:1 ends here

;; [[file:init-emacs.org::*switch-to-messages][switch-to-messages:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: switch-to-messages
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: switch-to-messages")

;; switch to messages buffer
(defun switch-to-messages ()
  "Switch to `*Messages*' buffer, creating it if needed."
  (interactive)
  (switch-to-buffer "*Messages*"))
;; switch-to-messages:1 ends here

;; [[file:init-emacs.org::*diff-current-buffer][diff-current-buffer:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: diff-current-buffer
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: diff-current-buffer")

;; show a diff of the current buffer with its file contents
(defun diff-current-buffer ()
  "Show a diff of the current buffer with its file contents."
  (interactive)
  (diff-buffer-with-file (current-buffer)))
;; diff-current-buffer:1 ends here

;; [[file:init-emacs.org::*get-char-property-here][get-char-property-here:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: get-char-property-here
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: get-char-property-here")

;; get character property at current point
(defun get-char-property-here ()
  (interactive)
  (let (face)
    (setq face (get-char-property (point) 'face))
    (when (called-interactively-p 'any)
      (message "%s" face))
    face))
;; get-char-property-here:1 ends here

;; [[file:init-emacs.org::*comments-in-buffer][comments-in-buffer:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: comments-in-buffer
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: comments-in-buffer")

(defun comments-in-buffer (&optional beg end)
  "Return a list of all the comments in the current buffer.
\nOptional START and END parameters will limit the search to a region."
  (interactive)
  (let ((beg (or beg (if (use-region-p) (region-beginning) (point-min))))
        (end (or end (if (use-region-p) (region-end) (point-max))))
        comments)
    (save-excursion
      (save-restriction
        (narrow-to-region beg end)
        (goto-char (point-min))
        (while (comment-search-forward (point-max) t)
          (push (buffer-substring-no-properties (point) (line-end-position)) comments))))
    (nreverse comments)))
;; comments-in-buffer:1 ends here

;; [[file:init-emacs.org::*count-words][count-words:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: count-words
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: count-words")

;; count number of words in region or buffer
(defun count-words (&optional beg end)
  "Count the number of words in the selected region or entire buffer (if none)."
  (interactive)
  (let* ((beg (or beg (if (use-region-p) (region-beginning) (point-min))))
         (end (or end (if (use-region-p) (region-end) (point-max))))
         (count (how-many "\\w+" beg end)))
    (when (called-interactively-p 'any)
      (message "%s" count))
    count))
;; count-words:1 ends here

;; [[file:init-emacs.org::*count-words-paragraph][count-words-paragraph:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: count-words-paragraph
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: count-words-paragraph")

;; count number of words in current paragraph
(defun count-words-paragraph ()
  "Count the number of words in the current paragraph."
  (interactive)
  (save-excursion
    (let (end
          (count 0))
      (forward-paragraph 1)
      (setq end (point))
      (backward-paragraph 1)
      (setq count (how-many "\\w+" (point) end))
      (when (called-interactively-p 'any)
        (message "%s" count))
      count)))
;; count-words-paragraph:1 ends here

;; [[file:init-emacs.org::*date-offset][date-offset:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: date-offset
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: date-offset")

;; date offset
(defun date-offset (&optional offset timezone format)
  "Return current date/time plus OFFSET seconds.
\nOFFSET is the number of seconds to add to the current
time (defaults to 0).
\nTIMEZONE changes the timezone (defaults to local system setting).
\nFORMAT is a 'date' format string (defaults to
'+%Y-%m-%dT%H:%M:%SZ')."
  (interactive)
  (let* ((offset (or offset 0))
         (format (or format (setq format "+%Y-%m-%dT%H:%M:%SZ")))
         (date (replace-regexp-in-string
                "^ +\\|[ \n]+$" ""
                (shell-command-to-string
                 (concat
                  (if timezone
                      (concat "TZ=" (shell-quote-argument timezone) " ")
                    "")
                  "date -d \"" (shell-quote-argument (number-to-string offset))
                  " sec\" " (shell-quote-argument format))))))
    (when (called-interactively-p 'any)
      (message "%s" date))
    date))
;; date-offset:1 ends here

;; [[file:init-emacs.org::*ascii-table][ascii-table:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: ascii-table
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: ascii-table")

;; print an ascii table
;; (defun ascii-table ()
;;   "Print the ASCII characters from 0 to 254 in a buffer."
;;   (interactive)
;;   (switch-to-buffer "*ASCII Table*")
;;   (erase-buffer)
;;   (dotimes (x 255)
;;     (insert (format "%4d %c\n" x x)))
;;   (goto-char (point-min)))

;; print an ascii table
(defun ascii-table ()
  "Print the ASCII characters from 0 to 254 in a buffer."
  (interactive)
  ;; thanks to David Jolley for the special-chars list
  (let ((special-chars ["NUL " "SOH " "STX " "ETX " "EOT "
                        "ENQ " "ACK " "BEL " "BS  " "HT  "
                        "LF  " "VT  " "FF  " "CR  " "SO  "
                        "SI  " "DLE " "DC1 " "DC2 " "DC3 "
                        "DC4 " "NAK " "SYN " "ETB " "CAN "
                        "EM  " "SUB " "ESC " "FS  " "GS  "
                        "RS  " "US  "]))
    (switch-to-buffer "*ASCII Table*")
    (erase-buffer)
    (dotimes (y 32)
      (dotimes (x 8)
        (when (and (> y 0) (zerop (mod x 8)))
          (newline))
        (let ((c (+ y (* x 32))))
          (insert (format "%4d " c)
                  (cond
                   ((< c 32)
                    (aref special-chars c))
                   ((= c 127)
                    "DEL ")
                   ((or (< c 127) (> c 159))
                    (format "%-4c" c))
                   (t "    "))))))
    (goto-char (point-min))))
;; ascii-table:1 ends here

;; [[file:init-emacs.org::*memory-use-counts-pretty][memory-use-counts-pretty:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: memory-use-counts-pretty
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: memory-use-counts-pretty")

;; pretty print version of `memory-use-counts'
(defun memory-use-counts-pretty ()
  "Pretty print version of `memory-use-counts'."
  (interactive)
  (let ((tags '(Conses Floats Vector-Cells Symbols String-Chars Miscs Intervals Strings))
        (muc (memory-use-counts))
        (str ""))
    (dotimes (n (length tags))
      (setq str (concat str (if (zerop (length str)) "" ", ")
                        (symbol-name (nth n tags)) ": " (number-to-string (nth n muc)))))
    str))
;; memory-use-counts-pretty:1 ends here

;; [[file:init-emacs.org::*git-paste-cleanup][git-paste-cleanup:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: git-paste-cleanup
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: git-paste-cleanup")

;; clean up git paste
(defun git-paste-cleanup (beg end)
  "Remove `+' characters from the start of lines in region."
  (interactive "*r")
  (save-excursion
    (goto-char beg)
    (when (> (point) (line-beginning-position))
      (forward-line 1)
      (goto-char (line-beginning-position)))
    (while (< (point) end)
      (when (looking-at "^+")
        (delete-char 1))
      (forward-line 1))))
;; git-paste-cleanup:1 ends here

;; [[file:init-emacs.org::*execute-buffer][execute-buffer:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: execute-buffer
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: execute-buffer")

;; execute buffer
;; TODO: need to test
(defun execute-buffer ()
  "Execute or compile current file."
  (interactive)
  (let* ((file-name (shell-quote-argument (buffer-file-name)))
         (file-type (substring (shell-command-to-string (concat "file " file-name)) 0 -1))
         (type-map '(("Lisp" . "clisp")
                     ("bash" . "bash")
                     ("perl" . "perl")
                     ("python" . "python")
                     ("java" . "javac")
                     ("kotlin" . "kotlinc")
                     ("php" . "php")
                     (" c " . "gcc")))
         cmd)
    (delete-other-windows)
    (do ((type type-map (cdr type)))
        ((or (not type) cmd))
      (when (cl-search (car type) file-type)
        (setq cmd (cdr type))))
    (shell-command (concat cmd " " file-name))))
;; execute-buffer:1 ends here

;; [[file:init-emacs.org::*file-in-exec-path][file-in-exec-path:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: file-in-exec-path
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: file-in-exec-path")

;; file in exec path
(defun file-in-exec-path (name)
  "Return non-nil if NAME is a file found in `exec-path'."
  (catch 'done
    (dolist (dir exec-path)
      (when (file-exists-p (concat (file-name-as-directory dir) name))
        (throw 'done t)))
    nil))
;; file-in-exec-path:1 ends here

;; [[file:init-emacs.org::*unicode-shell][unicode-shell:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Functions: unicode-shell
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Functions: unicode-shell")

;; unicode shell
(defun unicode-shell ()
  "Execute the shell buffer in UTF-8 encoding.
\nNote that you need to set the environment variable LANG and
others appropriately."
  (interactive)
  (let ((coding-system-for-read 'utf-8)
        (coding-system-for-write 'utf-8)
        (coding-system-require-warning t))
    (call-interactively 'shell)))
;; unicode-shell:1 ends here

;; [[file:init-emacs.org::*Emacs%20Grouped%20Functions][Emacs Grouped Functions:1]]
;;------------------------------------------------------------------------------
;;; Functions: Emacs Grouped Functions
;;------------------------------------------------------------------------------

(init-message 2 "Emacs Grouped Functions")
;; Emacs Grouped Functions:1 ends here

;; [[file:init-emacs.org::*Buffer%20Kill][Buffer Kill:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Grouped Functions: Buffer Kill
;;------------------------------------------------------------------------------

(init-message 3 "Buffer Kill")
;; Buffer Kill:1 ends here

;; [[file:init-emacs.org::*kill-buffer-query-functions-maybe-bury][kill-buffer-query-functions-maybe-bury:1]]
;;------------------------------------------------------------------------------
;;;;; Functions: Emacs Grouped Functions: Buffer Kill: kill-buffer-query-functions-maybe-bury
;;------------------------------------------------------------------------------

(init-message 4 "kill-buffer-query-functions-maybe-bury")

;; kill or bury buffer
;;(defconst bury-buffer-names '("*scratch*" "*Messages*"))
(defconst bury-buffer-names '("*Messages*"))
(defun kill-buffer-query-functions-maybe-bury ()
  "Bury certain buffers instead of killing them.
\nReturn nil if buffer should be buried instead of killed.
Used as a `kill-buffer-query-functions' hook."
  (if (member (buffer-name (current-buffer)) bury-buffer-names)
      (progn
        (kill-region (point-min) (point-max))
        (bury-buffer)
        nil)
    t))
(add-hook 'kill-buffer-query-functions #'kill-buffer-query-functions-maybe-bury)
;; kill-buffer-query-functions-maybe-bury:1 ends here

;; [[file:init-emacs.org::*kill-other-window-buffer][kill-other-window-buffer:1]]
;;------------------------------------------------------------------------------
;;;;; Functions: Emacs Grouped Functions: Buffer Kill: kill-other-window-buffer
;;------------------------------------------------------------------------------

(init-message 4 "Functions: Emacs Grouped Functions: Buffer Kill: kill-other-window-buffer")

;; kill other window buffer
(defun kill-other-window-buffer ()
  "Kill buffer in other window, prompting user to select a window
if there are more than two."
  (interactive)
  (let ((orig-window (selected-window)))
    (cond
     ((and (fboundp 'switch-window)
           (> (length (window-list)) 1))
      (switch-window)
      (kill-buffer (current-buffer))
      (select-window orig-window))
     ((= (length (window-list)) 2)
      (other-window 1)
      (kill-buffer (current-buffer))
      (select-window orig-window))
     (t
      (message "No other window to kill")))))
;; kill-other-window-buffer:1 ends here

;; [[file:init-emacs.org::*Clipboard][Clipboard:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Emacs Grouped Functions: Clipboard
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Emacs Grouped Functions: Clipboard")

;; Modified versions of the similarly named functions `clipboard-kill-region',
;; `clipboard-kill-ring-save', and `clipboard-yank'.  These functions use the
;; Linux command line tool `xsel' (which must be installed) to get the same
;; functionality when running Emacs in command line mode.
;; In Ubuntu/Debian run:
;;   sudo apt-get install xsel

;; only load if xsel command is available on system
(if (executable-find "xsel")
    (progn
      (init-message 4 "xclipboard-kill-region")

      ;; kill region and save to clipboard
      (defun xclipboard-kill-region (beg end)
        "Kill the region, and save it in the X clipboard."
        (interactive "*r")
        (shell-command (concat
                        "echo "
                        (shell-quote-argument (buffer-substring-no-properties beg end))
                        " | xsel -i"))
        (kill-region beg end))

      (init-message 4 "xclipboard-kill-ring-save")

      ;; copy region and save to clipboard
      (defun xclipboard-kill-ring-save (beg end)
        "Copy region to kill ring, and save in the X clipboard."
        (interactive "r")
        (shell-command (concat
                        "echo "
                        (shell-quote-argument (buffer-substring-no-properties beg end))
                        " | xsel -i"))
        (kill-ring-save beg end))

      (init-message 4 "xclipboard-yank")

      ;; paste from clipboard
      (defun xclipboard-yank ()
        "Insert the clipboard contents, or the last stretch of killed text."
        (interactive "*")
        (insert (shell-command-to-string "xsel -o"))))
  (message "Warning: Could not find xsel command (X-Clipboard interaction not enabled)"))
;; Clipboard:1 ends here

;; [[file:init-emacs.org::*Text%20Conversion%20Functions][Text Conversion Functions:1]]
;;------------------------------------------------------------------------------
;;; Functions: Text Conversion Functions
;;------------------------------------------------------------------------------

(init-message 2 "Functions: Text Conversion Functions")
;; Text Conversion Functions:1 ends here

;; [[file:init-emacs.org::*escape-xml][escape-xml:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Conversion Functions: escape-xml
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Conversion Functions: escape-xml")

;; escape xml
(defun escape-xml (string)
  "Escape XML in STRING."
  ;; & => &amp;
  (setq string (replace-regexp-in-string "&" "&amp;" string))
  ;; ' => &apos;
  (setq string (replace-regexp-in-string "'" "&apos;" string))
  ;; ! => &bang;
  ;;(setq string (replace-regexp-in-string "!" "&bang;" string))
  ;; = => &eq;
  ;;(setq string (replace-regexp-in-string "=" "&eq;" string))
  ;; > => &gt;
  (setq string (replace-regexp-in-string ">" "&gt;" string))
  ;; < => &lt;
  (setq string (replace-regexp-in-string "<" "&lt;" string))
  ;; ? => &quest;
  ;;(setq string (replace-regexp-in-string "\?" "&quest;" string))
  ;; " => &quot;
  (setq string (replace-regexp-in-string "\"" "&quot;" string))
  ;; / => &slash;
  ;;(setq string (replace-regexp-in-string "/" "&slash;" string))
  ;; return result
  string)
;; escape-xml:1 ends here

;; [[file:init-emacs.org::*unescape-xml][unescape-xml:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Conversion Functions: unescape-xml
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Conversion Functions: unescape-xml")

;; unescape xml
(defun unescape-xml (string)
  "Unescape XML in STRING."
  ;; &apos; => '
  (setq string (replace-regexp-in-string "&apos;" "'" string))
  ;; &bang; => !
  ;;(setq string (replace-regexp-in-string "&bang;" "!" string))
  ;; &eq; => =
  ;;(setq string (replace-regexp-in-string "&eq;" "=" string))
  ;; &gt; => >
  (setq string (replace-regexp-in-string "&gt;" ">" string))
  ;; &lt; => <
  (setq string (replace-regexp-in-string "&lt;" "<" string))
  ;; &quest; => ?
  ;;(setq string (replace-regexp-in-string "&quest;" "\?" string))
  ;; &quot; => "
  (setq string (replace-regexp-in-string "&quot;" "\"" string))
  ;; &slash; => /
  ;;(setq string (replace-regexp-in-string "&slash;" "/" string))
  ;; &amp; => &
  (setq string (replace-regexp-in-string "&amp;" "&" string))
  ;; return result
  string)
;; unescape-xml:1 ends here

;; [[file:init-emacs.org::*titleize][titleize:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Conversion Functions: titleize
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Conversion Functions: titleize")

;; titleize
;; (used the rules found here: http://titlecapitalization.com/)
(defun titleize (string &optional do-not-cap-ends)
  "Capitalize STRING according to titling conventions.

If a word should be capitalized, `capitalize-word' is called,
otherwise `downcase-word' is called.

If DO-NOT-CAP-ENDS is non-nil, the first and last words will not
be automatically capitalized."
  ;; TODO: Do not change words that are mixed case or all caps
  (interactive "*")
  (let ((words-single
         '(;; conjunctions
           "and" "as" "be" "into" "is" "it" "nor" "or" "so" "the" "that" "yet"
           ;; prepositions (single words)
           "a" "abaft" "aboard" "about" "above" "absent" "across" "afore"
           "after" "against" "along" "alongside" "amid" "amidst" "among"
           "amongst" "an" "anenst" "apropos" "apud" "around" "as" "aside"
           "astride" "at" "athwart" "atop" "barring" "before" "behind" "below"
           "beneath" "beside" "besides" "between" "beyond" "but" "by" "circa"
           "concerning" "despite" "down" "during" "except" "excluding"
           "failing" "following" "for" "forenenst" "from" "given" "in"
           "including" "inside" "into" "like" "mid" "midst" "minus" "modulo"
           "near" "next" "notwithstanding" "o'" "of" "off" "on" "onto"
           "opposite" "out" "outside" "over" "pace" "past" "per" "plus" "pro"
           "qua" "regarding" "round" "sans" "save" "since" "than" "through"
           "thru" "throughout" "thruout" "till" "times" "to" "toward" "towards"
           "under" "underneath" "unlike" "until" "unto" "up" "upon" "versus"
           "vs" "via" "vice" "vis-à-vis" "vis-a-vis" "whereas" "with" "within"
           "without" "worth"))
        (words-double
         '(;; prepositions (double words)
           "according to" "ahead of" "apart from" "as for" "as of" "as per"
           "as regards" "aside from" "back to" "because of" "close to"
           "due to" "except for" "far from" "in to" "inside of" "instead of"
           "left of" "near to" "next to" "on to" "out from" "out of"
           "outside of" "owing to" "prior to" "pursuant to" "rather than"
           "regardless of" "right of" "subsequent to" "such as" "thanks to"
           "that of" "up to"))
        (words-triple
         '(;; prepositions (triple words)
           "as far as" "as long as" "as opposed to" "as well as" "as soon as"
           "at the behest of" "by means of" "by virtue of" "for the sake of"
           "in accordance with" "in addition to" "in case of" "in front of"
           "in lieu of" "in order to" "in place of" "in point of"
           "in spite of" "on account of" "on behalf of" "on top of"
           "with regard to" "with respect to" "with a view to")))
    (let ((words-single-regexp (regexp-opt (mapcar #'capitalize words-single) 'words))
          (words-double-regexp (regexp-opt (mapcar #'capitalize words-double) 'words))
          (words-triple-regexp (regexp-opt (mapcar #'capitalize words-triple) 'words))
          (punctuation-word-regexp "\\([^[:blank:]][.?!]['\"”]?[[:blank:]]*\\w+\\)")
          (first-word-regexp "^\\(\\w+\\)")
          (last-word-regexp "\\(\\w+\\)$"))
      (if do-not-cap-ends
          (replace-regexp-in-string
           punctuation-word-regexp 'capitalize
           (replace-regexp-in-string
            words-single-regexp 'downcase
            (replace-regexp-in-string
             words-double-regexp 'downcase
             (replace-regexp-in-string
              words-triple-regexp 'downcase
              (capitalize string) t t) t t) t t) t t)
        (replace-regexp-in-string
         first-word-regexp 'capitalize
         (replace-regexp-in-string
          last-word-regexp 'capitalize
          (replace-regexp-in-string
           punctuation-word-regexp 'capitalize
           (replace-regexp-in-string
            words-single-regexp 'downcase
            (replace-regexp-in-string
             words-double-regexp 'downcase
             (replace-regexp-in-string
              words-triple-regexp 'downcase
              (capitalize string) t t) t t) t t) t t) t t) t t)))))
;; titleize:1 ends here

;; [[file:init-emacs.org::*titleize-word-enhanced][titleize-word-enhanced:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Conversion Functions: titleize-word-enhanced
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Conversion Functions: titleize-word-enhanced")

;; enhanced titleize-word
(defun titleize-word-enhanced (arg)
  "Titleize word at point."
  (interactive "*p")
  (let ((syntax-table (copy-syntax-table (syntax-table))))
    (modify-syntax-entry ?- "." syntax-table)
    (with-syntax-table syntax-table
      (dotimes (x (or arg 1))
        (let ((p (point)))
          (forward-word 1)
          (forward-word -1)
          (when (< (point) p)
            (forward-word 1)))
        (let ((bounds (bounds-of-thing-at-point 'word)))
          (when bounds
            (goto-char (car bounds)))
          (when (re-search-forward "\\(\\w+\\)" nil t)
            (replace-match (titleize (match-string 0) t) t)))))))
;; titleize-word-enhanced:1 ends here

;; [[file:init-emacs.org::*titleize-line-or-region][titleize-line-or-region:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Conversion Functions: titleize-line-or-region
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Conversion Functions: titleize-line-or-region")

;; titleize line or selected region
(defun titleize-line-or-region (&optional beg end)
  "Capitalize the current line or selected region according to
titling conventions.

If a word should be capitalized, `capitalize-word' is called,
otherwise `downcase-word' is called."
  (interactive "*")
  (let* ((pt (point))
         (beg (or beg (if (use-region-p) (region-beginning) (progn (beginning-of-line-text) (point)))))
         (end (or end (if (use-region-p) (region-end) (line-end-position))))
         (col (- pt beg)))
    (let ((syntax-table (copy-syntax-table (syntax-table)))
          (str (buffer-substring-no-properties beg end)))
      (modify-syntax-entry ?- "." syntax-table)
      (with-syntax-table syntax-table
        (kill-region beg end)
        (goto-char beg)
        (insert (titleize str))
        (goto-char (+ beg col))))))
;; titleize-line-or-region:1 ends here

;; [[file:init-emacs.org::*unfill-paragraph][unfill-paragraph:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Conversion Functions: unfill-paragraph
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Conversion Functions: unfill-paragraph")

;; reverse of `fill-paragraph'
(defun unfill-paragraph ()
  "Convert a multi-line paragraph into a single line of text."
  (interactive)
  (let ((fill-column (point-max)))
    (fill-paragraph nil)))
;; unfill-paragraph:1 ends here

;; [[file:init-emacs.org::*double-space-punctuation][double-space-punctuation:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Conversion Functions: double-space-punctuation
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Conversion Functions: double-space-punctuation")

;; replace single-space sentence ends with double-space ends
(defun double-space-punctuation (&optional beg end)
  "Double-space sentence ending punctuation in the current
paragraph or selected region."
  (interactive "*")
  (save-excursion
    (let ((beg (or beg (and (use-region-p) (region-beginning))))
          (end (or end (and (use-region-p) (region-end)))))
      (unless (and beg end)
        (mark-paragraph)
        (setq beg (point)
              end (mark-marker)))
      (goto-char beg)
      (while (and (< (point) end)
                  (re-search-forward "\\([^[:blank:]][.?!]['\"”]?\\)[[:blank:]]\\([^[:blank:]]\\)" end t))
        (replace-match "\\1  \\2")))))
;; double-space-punctuation:1 ends here

;; [[file:init-emacs.org::*single-space-punctuation][single-space-punctuation:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Conversion Functions: single-space-punctuation
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Conversion Functions: single-space-punctuation")

;; replace double-space sentence ends with single-space ends
(defun single-space-punctuation (&optional beg end)
  "Single-space sentence ending punctuation in the current
paragraph or selected region."
  (interactive "*")
  (save-excursion
    (let ((beg (or beg (and (use-region-p) (region-beginning))))
          (end (or end (and (use-region-p) (region-end)))))
      (unless (and beg end)
        (mark-paragraph)
        (setq beg (point)
              end (mark-marker)))
      (goto-char beg)
      (while (and (< (point) end)
                  (re-search-forward "\\([^[:blank:]][.?!]['\"”]?\\)[[:blank:]]\\([^[:blank:]]\\)" end t))
        (replace-match "\\1 \\2")))))
;; single-space-punctuation:1 ends here

;; [[file:init-emacs.org::*Text%20Inserting%20Functions][Text Inserting Functions:1]]
;;------------------------------------------------------------------------------
;;; Functions: Text Inserting Functions
;;------------------------------------------------------------------------------

(init-message 2 "Text Inserting Functions")
;; Text Inserting Functions:1 ends here

;; [[file:init-emacs.org::*insert-timestamp][insert-timestamp:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: insert-timestamp
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: insert-timestamp")

;; insert timestamp
(defun insert-timestamp (&optional pos)
  "Insert a timestamp at point or POS."
  (interactive "*")
  (if pos
      (save-excursion
        (goto-char pos)
        (insert (format-time-string "%Y-%m-%d %H:%M:%S")))
    (insert (format-time-string "%Y-%m-%d %H:%M:%S"))))
;; insert-timestamp:1 ends here

;; [[file:init-emacs.org::*insert-path][insert-path:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: insert-path
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: insert-path")

;; insert path
(defun insert-path (path)
  "Insert path."
  (interactive "*FPath: ")
  (insert (expand-file-name path)))
;; insert-path:1 ends here

;; [[file:init-emacs.org::*uuid][uuid:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: uuid
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: uuid")

;; uuid
(defmacro uuid ()
  "Return a UUID.
\nExample: 5ac55464-24e6-419c-99cf-5e1682bb3819"
  (cond
   ;; use uuid script if found
   ((executable-find "uuid")
    `(replace-regexp-in-string
      "^ +\\|[ \n]+$" ""
      (shell-command-to-string "uuid")))
   ;; otherwise, use linux mcookie command if found
   ((executable-find "mcookie")
    `(let ((uuid (replace-regexp-in-string
                  "^ +\\|[ \n]+$" ""
                  (shell-command-to-string "mcookie"))))
       (concat (substring uuid 0 8)
               "-" (substring uuid 8 12)
               "-" (substring uuid 12 16)
               "-" (substring uuid 16 20)
               "-" (substring uuid 20 32))))
   ;; else error
   (t
    `(error "Could not find a suitable system command to produce a UUID"))))
(defalias 'guid 'uuid)

;; old versions

;; (defun uuid ()
;;   "Insert a UUID at point.
;; \nExample: 5ac55464-24e6-419c-99cf-5e1682bb3819"
;;   (interactive "*")
;;   (insert (substring (shell-command-to-string "${HOME}/bin/uuid") 0 -1)))

;; (defun uuid ()
;;   "Insert a UUID at point.
;; Example: 4524044b2c41310701d09e8678bbc64e"
;;   (interactive "*")
;;   (insert (substring (shell-command-to-string "mcookie") 0 -1)))

;; (defun guid ()
;;   "Insert a GUID at point.
;;
;; Example: ed812ddb-87c5-a1e0-3377-ed40a632e6ed"
;;   (interactive "*")
;;   (let ((uuid (substring (shell-command-to-string "mcookie") 0 -1)))
;;     (insert (substring uuid 0 8)
;;             "-" (substring uuid 8 12)
;;             "-" (substring uuid 12 16)
;;             "-" (substring uuid 16 20)
;;             "-" (substring uuid 20 32))))
;; uuid:1 ends here

;; [[file:init-emacs.org::*insert-uuid][insert-uuid:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: insert-uuid
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: insert-uuid")

;; insert uuid
(defun insert-uuid ()
  "Insert a UUID at point.
\nExample: 5ac55464-24e6-419c-99cf-5e1682bb3819"
  (interactive "*")
  (insert (uuid)))
(defalias 'insert-guid 'insert-uuid)
;; insert-uuid:1 ends here

;; [[file:init-emacs.org::*uuid-xml][uuid-xml:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: uuid-xml
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: uuid-xml")

;; uuid-xml
(defmacro uuid-xml ()
  "Return a Java UUID serialized for XML.
\nExample:
\n  <java.util.UUID>
    <default>
      <leastSigBits>-8689645201391190588</leastSigBits>
      <mostSigBits>-4837091181110474279</mostSigBits>
    </default>
  </java.util.UUID>"
  (let ((cmd "uuid-xml"))
    ;; use uuid script if found
    (if (executable-find cmd)
        `(shell-command-to-string (concat ,cmd " | tail -n +2"))
      ;; else error
      `(error "Could not find %s command" ,cmd))))
;; uuid-xml:1 ends here

;; [[file:init-emacs.org::*insert-uuid-xml][insert-uuid-xml:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: insert-uuid-xml
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: insert-uuid-xml")

;; insert uuid-xml
(defun insert-uuid-xml ()
  "Insert a Java UUID serialized for XML at point.
\nExample:
\n  <java.util.UUID>
    <default>
      <leastSigBits>-8689645201391190588</leastSigBits>
      <mostSigBits>-4837091181110474279</mostSigBits>
    </default>
  </java.util.UUID>"
  (interactive "*")
  (insert (uuid-xml)))
;; insert-uuid-xml:1 ends here

;; [[file:init-emacs.org::*insert-incrementing-vertical-numbers][insert-incrementing-vertical-numbers:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: insert-incrementing-vertical-numbers
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: insert-incrementing-vertical-numbers")

;; insert incrementing numbers in a vertical column
(defun insert-incrementing-vertical-numbers (end &optional start)
  "Insert incrementing numbers vertically in the current column.
\nStart with 1 or START (if non-nil) up to and including END."
  (interactive "*nMax integer: ")
  (let ((start (or start 1))
        (col (- (point) (line-beginning-position))))
    (do ((x start (1+ x)))
        ((> x end))
      (insert (number-to-string x))
      (when (< x end)
        (or (zerop (forward-line 1))
            (progn
              (goto-char (line-end-position))
              (newline)))
        (let ((pos (+ (line-beginning-position) col)))
          (while (< (point) pos)
            (if (eobp)
                (insert " ")
              (forward-char 1))))))))
;; insert-incrementing-vertical-numbers:1 ends here

;; [[file:init-emacs.org::*append-char-to-column][append-char-to-column:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: append-char-to-column
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: append-char-to-column")

;; append a character up to a column
(defun append-char-to-column (char col)
  "Append character CHAR up to column COL and delete any past that point."
  (save-excursion
    (goto-char (line-end-position))
    (while (< (- (point) (line-beginning-position)) col)
      (insert char))
    (goto-char (+ (line-beginning-position) col))
    (while (and
            (char-after)
            (char-equal (char-after) (string-to-char char)))
      (delete-char 1))))
;; append-char-to-column:1 ends here

;; [[file:init-emacs.org::*append-equal-to-column-80][append-equal-to-column-80:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: append-equal-to-column-80
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: append-equal-to-column-80")

;; append equal characters up to column 80
(defun append-equal-to-column-80 ()
  "Insert equal characters up to column 80."
  (interactive "*")
  (append-char-to-column "=" 80))
;; append-equal-to-column-80:1 ends here

;; [[file:init-emacs.org::*append-dash-to-column-80][append-dash-to-column-80:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: append-dash-to-column-80
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: append-dash-to-column-80")

;; append dash characters up to column 80
(defun append-dash-to-column-80 ()
  "Insert dash characters up to column 80."
  (interactive "*")
  (append-char-to-column "-" 80))
;; append-dash-to-column-80:1 ends here

;; [[file:init-emacs.org::*append-asterisk-to-column-80][append-asterisk-to-column-80:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: append-asterisk-to-column-80
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: append-asterisk-to-column-80")

;; append asterisk characters up to column 80
(defun append-asterisk-to-column-80 ()
  "Insert asterisk characters up to column 80."
  (interactive "*")
  (append-char-to-column "*" 80))
;; append-asterisk-to-column-80:1 ends here

;; [[file:init-emacs.org::*insert-lisp-comment-block-equal][insert-lisp-comment-block-equal:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: insert-lisp-comment-block-equal
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: insert-lisp-comment-block-equal")

;; insert lisp comment block (equal)
(defun insert-lisp-comment-block-equal ()
  "Insert lisp comment block (equal)."
  (interactive "*")
  (indent-according-to-mode)
  (insert ";;")
  (append-equal-to-column-80)
  (end-of-line)
  (newline-and-indent)
  (insert ";;")
  (newline-and-indent)
  (insert ";;")
  (append-equal-to-column-80)
  (end-of-line)
  (newline)
  (forward-line -2)
  (end-of-line)
  (insert " "))
;; insert-lisp-comment-block-equal:1 ends here

;; [[file:init-emacs.org::*insert-lisp-comment-block-dash][insert-lisp-comment-block-dash:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: insert-lisp-comment-block-dash
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: insert-lisp-comment-block-dash")

;; insert lisp comment block (dash)
(defun insert-lisp-comment-block-dash ()
  "Insert lisp comment block (dash)."
  (interactive "*")
  (indent-according-to-mode)
  (insert ";;")
  (append-dash-to-column-80)
  (end-of-line)
  (newline-and-indent)
  (insert ";;")
  (newline-and-indent)
  (insert ";;")
  (append-dash-to-column-80)
  (end-of-line)
  (newline)
  (forward-line -2)
  (end-of-line)
  (insert " "))
;; insert-lisp-comment-block-dash:1 ends here

;; [[file:init-emacs.org::*insert-center-lisp-comment][insert-center-lisp-comment:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: insert-center-lisp-comment
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: insert-center-lisp-comment")

;; insert center lisp comment
(defun insert-center-lisp-comment ()
  "Insert center lisp comment (in comment block)."
  (interactive "*")
  (save-excursion
    (goto-char (line-beginning-position))
    (while (looking-at " +") (forward-char 1))
    (while (looking-at ";+") (forward-char 1))
    (let ((start (point)))
      (forward-line -1)
      (let ((len (- (line-end-position) (line-beginning-position)))
            (spacer (char-before (line-end-position))))
        (forward-line 1)
        (while (search-forward (char-to-string spacer) (line-end-position) t)
          (replace-match ""))
        (goto-char start)
        (while (looking-at " ")
          (delete-char 1 t))
        (goto-char (line-end-position))
        (while (eq (char-before (point)) ? )
          (delete-char -1 t))
        (let ((spacers (- (floor (/ (- len (- (point) start)) 2)) 4)))
          (goto-char start)
          (insert " " (make-string spacers spacer) " ")
          (goto-char (line-end-position))
          (insert " ")
          (insert (make-string (- len (- (point) (line-beginning-position))) ?=)))))))
;; insert-center-lisp-comment:1 ends here

;; [[file:init-emacs.org::*insert-c-comment-block][insert-c-comment-block:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: insert-c-comment-block
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: insert-c-comment-block")

;; insert c/c++/java comment block
(defun insert-c-comment-block ()
  "Insert c/c++/java comment block."
  (interactive "*")
  (indent-according-to-mode)
  (insert "/")
  (append-asterisk-to-column-80)
  (end-of-line)
  (newline-and-indent)
  (insert "*")
  (indent-according-to-mode)
  (newline-and-indent)
  (insert "*")
  (indent-according-to-mode)
  (append-asterisk-to-column-80)
  (end-of-line)
  (delete-char -1)
  (insert "/")
  (newline)
  (forward-line -2)
  (end-of-line)
  (insert " "))
;; insert-c-comment-block:1 ends here

;; [[file:init-emacs.org::*insert-c-comment-stub][insert-c-comment-stub:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: insert-c-comment-stub
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: insert-c-comment-stub")

;; insert c/c++/java comment stub
(defun insert-c-comment-stub ()
  "Insert c/c++/java comment stub."
  (interactive "*")
  (end-of-line)
  (indent-according-to-mode)
  (insert "/**")
  (newline-and-indent)
  (insert "*")
  (indent-according-to-mode)
  (newline-and-indent)
  (insert "*/")
  (indent-according-to-mode)
  (newline)
  (forward-line -2)
  (end-of-line)
  (insert " "))
;; insert-c-comment-stub:1 ends here

;; [[file:init-emacs.org::*insert-db-change-log-template-line][insert-db-change-log-template-line:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: insert-db-change-log-template-line
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: insert-db-change-log-template-line")

;; insert db change log template line
(defun insert-db-change-log-template-line ()
  "Insert Everest DB Change Log template line at point."
  (interactive "*")
  ;;(insert (cons '(format-time-string "%m/%d" (current-time)) " | | | E_ | .D.Q.S.T.P. | yes\n"))
  (insert (format-time-string "%m/%d" (current-time)))
  (insert " |  |  | E_ | .D.Q.S.T.P. | yes")
  (newline)
  (forward-line -1)
  (forward-char 8))
;; insert-db-change-log-template-line:1 ends here

;; [[file:init-emacs.org::*insert-db-change-log-template-line-legacy][insert-db-change-log-template-line-legacy:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: insert-db-change-log-template-line-legacy
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: insert-db-change-log-template-line-legacy")

;; insert db change log template line legacy
(defun insert-db-change-log-template-line-legacy ()
  "Insert Legacy DB Change Log template line at point."
  (interactive "*")
  (insert (format-time-string "%m/%d" (current-time)))
  (insert " |  |  | AwardCafe_Client | .D.S.P. | yes")
  (newline)
  (forward-line -1)
  (forward-char 8))
;; insert-db-change-log-template-line-legacy:1 ends here

;; [[file:init-emacs.org::*insert-xml-header][insert-xml-header:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: insert-xml-header
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: insert-xml-header")

;; insert xml header
(defun insert-xml-header ()
  "Insert standard XML header.
\nSpecifically: <?xml version=\"1.0\" encoding=\"utf-8\"?>"
  (interactive "*")
  (insert "<?xml version=\"1.0\" encoding=\"utf-8\"?>"))
;; insert-xml-header:1 ends here

;; [[file:init-emacs.org::*insert-lexical-binding][insert-lexical-binding:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: insert-lexical-binding
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: insert-lexical-binding")

;; insert lexical-binding file local variable
(defun insert-lexical-binding ()
  "Insert file local variable `lexical-binding' in the first line
of the current buffer."
  (interactive "*")
  (save-excursion
    (goto-char (point-min))
    (if (looking-at ";; -\\*-.*-\\*-")
        (unless (looking-at ";; -\\*-.*lexical-binding:.*-\\*-")
          (goto-char (line-end-position))
          (forward-char -4)
          (when (looking-at " -\\*-")
            (forward-char -1)
            (if (looking-at ";")
                (forward-char 1)
              (progn
                (forward-char 1)
                (insert ";")))
            (insert " lexical-binding: t;")))
      (insert ";; -*- lexical-binding: t; -*-\n;;\n"))))
;; insert-lexical-binding:1 ends here

;; [[file:init-emacs.org::*insert-figlet][insert-figlet:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Text Inserting Functions: insert-figlet
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Text Inserting Functions: insert-figlet")

;; insert figlet version of text
(defun insert-figlet (text)
  "Insert figlet version of TEXT, if figlet is installed."
  (interactive "*sText: ")
  (if (executable-find "figlet")
      (insert (shell-command-to-string (concat "figlet " text)))
    (error "Could not find figlet command")))
;; insert-figlet:1 ends here

;; [[file:init-emacs.org::*External%20Program%20Functions][External Program Functions:1]]
;;------------------------------------------------------------------------------
;;; Functions: External Program Functions
;;------------------------------------------------------------------------------

(init-message 2 "External Program Functions")
;; External Program Functions:1 ends here

;; [[file:init-emacs.org::*insert-date][insert-date:1]]
;;------------------------------------------------------------------------------
;;;; Functions: External Program Functions: insert-date
;;------------------------------------------------------------------------------

(init-message 3 "Functions: External Program Functions: insert-date")

;; insert date
(defun insert-date ()
  "Insert current date in YYYY-MM-DD format."
  (interactive "*")
  (call-process "date" nil t nil "+%Y-%m-%d")
  (delete-char -1))
;; insert-date:1 ends here

;; [[file:init-emacs.org::*insert-datetime][insert-datetime:1]]
;;------------------------------------------------------------------------------
;;;; Functions: External Program Functions: insert-datetime
;;------------------------------------------------------------------------------

(init-message 3 "Functions: External Program Functions: insert-datetime")

;; insert datetime
(defun insert-datetime ()
  "Insert current date and time in YYYY-MM-DD HH:MM:SS format."
  (interactive "*")
  (call-process "date" nil t nil "+%Y-%m-%d %H:%M:%S")
  (delete-char -1))
;; insert-datetime:1 ends here

;; [[file:init-emacs.org::*insert-time][insert-time:1]]
;;------------------------------------------------------------------------------
;;;; Functions: External Program Functions: insert-time
;;------------------------------------------------------------------------------

(init-message 3 "Functions: External Program Functions: insert-time")

;; insert time
(defun insert-time ()
  "Insert current time in HH:MM:SS format."
  (interactive "*")
  (call-process "date" nil t nil "+%H:%M:%S")
  (delete-char -1))
;; insert-time:1 ends here

;; [[file:init-emacs.org::*insert-date-stamp][insert-date-stamp:1]]
;;------------------------------------------------------------------------------
;;;; Functions: External Program Functions: insert-date-stamp
;;------------------------------------------------------------------------------

(init-message 3 "Functions: External Program Functions: insert-date-stamp")

;; insert date stamp
(defun insert-date-stamp ()
  "Insert current date in YYYYMMDD format."
  (interactive "*")
  (call-process "date" nil t nil "+%Y%m%d")
  (delete-char -1))
;; insert-date-stamp:1 ends here

;; [[file:init-emacs.org::*insert-fortune][insert-fortune:1]]
;;------------------------------------------------------------------------------
;;;; Functions: External Program Functions: insert-fortune
;;------------------------------------------------------------------------------

(init-message 3 "Functions: External Program Functions: insert-fortune")

;; insert fortune
(defun insert-fortune (&optional file)
  "Insert a random fortune.
\nIf FILE is non-nil, use that fortune file."
  (interactive "*")
  (call-process "fortune" nil t nil "-a" (if file (shell-quote-argument file) "")))
;; insert-fortune:1 ends here

;; [[file:init-emacs.org::*insert-quote][insert-quote:1]]
;;------------------------------------------------------------------------------
;;;; Functions: External Program Functions: insert-quote
;;------------------------------------------------------------------------------

(init-message 3 "Functions: External Program Functions: insert-quote")

;; insert quote
(defun insert-quote ()
  "Insert a random quote."
  (interactive "*")
  (insert-fortune (expand-file-name "~/quotes")))
;; insert-quote:1 ends here

;; [[file:init-emacs.org::*Newer%20Emacs%20Functionality%20Functions][Newer Emacs Functionality Functions:1]]
;;------------------------------------------------------------------------------
;;; Functions: Newer Emacs Functionality Functions
;;------------------------------------------------------------------------------

(init-message 2 "New Emacs Functionality Functions")
;; Newer Emacs Functionality Functions:1 ends here

;; [[file:init-emacs.org::*line-number-at-pos][line-number-at-pos:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Newer Emacs Functionality Functions: line-number-at-pos
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Newer Emacs Functionality Functions: line-number-at-pos")

;; line-number-at-pos
(unless (fboundp 'line-number-at-pos)
  (defun line-number-at-pos (&optional pos)
    "Return (narrowed) buffer line number at position POS.
  \nIf POS is nil, use current buffer location."
    (save-excursion
      (when pos
        (goto-char pos))
      (1+ (count-lines (point-min) (line-beginning-position))))))
;; line-number-at-pos:1 ends here

;; [[file:init-emacs.org::*Grep%20Search%20Functions][Grep Search Functions:1]]
;;------------------------------------------------------------------------------
;;; Functions: Grep Search Functions
;;------------------------------------------------------------------------------

(init-message 2 "Grep Searches")
;; Grep Search Functions:1 ends here

;; [[file:init-emacs.org::*grep-elisp][grep-elisp:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Grep Search Functions: grep-elisp
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Grep Search Functions: grep-elisp")

;; grep custom elisp files
(defun grep-elisp (query &optional extended)
  "Grep custom elisp directories for QUERY.

Run `grep' COMMAND, where COMMAND is:

  `grep-default-command' QUERY FILES

FILES is a list of files generated from the following
files/directories:

  `emacs-home-dir' or ~/.emacs.d (if EXTENDED is t)
  `local-init-dir' if it exists
  `local-modules-dir' if it exists

A file matching pattern of `*.el$' is used."
  (interactive "sGrep custom elisp files: ")
  (let (paths
        path
        files)
    (if extended
        (if (and (boundp 'emacs-home-dir)
                 (file-exists-p emacs-home-dir))
            (push emacs-home-dir paths)
          "~/.emacs.d")
      (progn
        (when (and (boundp 'local-init-dir)
                   local-init-dir
                   (file-exists-p local-init-dir))
          (push local-init-dir paths))
        (when (and (boundp 'local-modules-dir)
                   local-modules-dir
                   (file-exists-p local-modules-dir))
          (push local-modules-dir paths))))
    ;; loop through paths
    (while paths
      (setq path (expand-file-name (car paths)))
      (setq paths (cdr paths))
      ;; traverse directories
      (if (file-directory-p path)
          ;; loop through files
          (dolist (file (nreverse (directory-files path t)))
            ;; ignore `.' and `..'
            (unless (string-match "^\\.\\.?$" (file-name-nondirectory file))
              ;; add directories to paths
              (if (file-directory-p file)
                  (push file paths)
                ;; add elisp file
                (when (string-match "\\.el$" file)
                  (push file files)))))
        ;; add file
        (push path files)))
    ;; build command
    (let ((cmd (or grep-command "grep -n -H -i -r -e ")))
      ;; add query
      (setq cmd (concat cmd " \"" query "\""))
      ;; add files
      (dolist (file files)
        (setq cmd (concat cmd " \"" file "\"")))
      ;; execute command using `grep' command
      (grep cmd))))
;; grep-elisp:1 ends here

;; [[file:init-emacs.org::*grep-elisp-extended][grep-elisp-extended:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Grep Search Functions: grep-elisp-extended
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Grep Search Functions: grep-elisp-extended")

;; grep extended custom elisp files (everything in ~/.emacs.d)
(defun grep-elisp-extended (query)
  "Call `grep-elisp' with QUERY and EXTENDED set to t."
  (interactive "sGrep custom elisp files (extended): ")
  (grep-elisp query t))
;; grep-elisp-extended:1 ends here

;; [[file:init-emacs.org::*grep-custom][grep-custom:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Grep Search Functions: grep-custom
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Grep Search Functions: grep-custom")

;; grep custom macro
(defmacro grep-custom (dirs match)
  "Return a custom grep function.
DIRS is a list of the directories to search.
MATCH is the file pattern to match."
  `(lambda (query)
     (let ((paths (reverse (quote ,dirs)))
           (match ,match)
           path
           files)
       ;; loop through paths
       (while paths
         (setq path (expand-file-name (car paths)))
         (setq paths (cdr paths))
         ;; traverse directories
         (if (file-directory-p path)
             ;; loop through files
             (dolist (file (nreverse (directory-files path t)))
               ;; ignore `.' and `..' and svn directories
               (unless (or (string-match "^\\.\\.?$" (file-name-nondirectory file))
                           (string-match "\\.svn" (file-name-nondirectory file)))
                 ;; add directories to paths
                 (if (file-directory-p file)
                     (push file paths)
                   ;; add files in directories to files
                   (when (or (not match)
                             (string-match match file))
                     (push file files)))))
           ;; add file
           (push path files)))
       ;; build command
       (let ((cmd (or grep-command "grep -n -H -i -e")))
         ;; add query
         (setq cmd (concat cmd " \"" query "\""))
         ;; add files
         (dolist (file files)
           (setq cmd (concat cmd " \"" file "\"")))
         ;; execute command using `grep' command
         (grep cmd)))))
;; examples:
;; (funcall (grep-custom ("~/.profile") ".*") "path")
;; grep-custom:1 ends here

;; [[file:init-emacs.org::*grep-custom-generate][grep-custom-generate:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Grep Search Functions: grep-custom-generate
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Grep Search Functions: grep-custom-generate")

;; grep custom generate macro
(defmacro grep-custom-generate (name prompt dirs match)
  "Generate a custom grep function.
\nNAME is the function name.
PROMPT is displayed if no query is given.
DIRS is a list of the directories to search.
MATCH is the file pattern to match."
  (let ((dirs dirs)
        (match match))
    `(defun ,name (query)
       ,(concat "Grep custom directories for QUERY.\n\n"
                "Run `grep' COMMAND, where COMMAND is:\n\n"
                "`grep-default-command' QUERY FILES\n\n"
                "FILES is a list of files generated from the following\n"
                "files/directories:\n\n"
                (concat "  " (cl-reduce (lambda (x y) (concat x "\n  " y)) dirs) "\n\n")
                "A file matching pattern of `" match "' is used.")
       (interactive ,(concat "s" prompt))
       (funcall (grep-custom ,dirs ,match) query))))
;; grep-custom-generate:1 ends here

;; [[file:init-emacs.org::*grep-bin][grep-bin:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Grep Search Functions: grep-bin
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Grep Search Functions: grep-bin")

;; grep bin
(grep-custom-generate grep-bin "Grep HOME bin files: " ("~/bin") nil)
;; grep-bin:1 ends here

;; [[file:init-emacs.org::*grep-clojure][grep-clojure:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Grep Search Functions: grep-clojure
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Grep Search Functions: grep-clojure")

;; grep clojure
(grep-custom-generate grep-clojure "Grep Clojure files: " ("~/clojure") "\\.clj$")
;; grep-clojure:1 ends here

;; [[file:init-emacs.org::*grep-clisp][grep-clisp:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Grep Search Functions: grep-clisp
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Grep Search Functions: grep-clisp")

;; grep clisp
(grep-custom-generate grep-clisp "Grep CLISP files: " ("~/clisp") "\\.lisp$")
;; grep-clisp:1 ends here

;; [[file:init-emacs.org::*grep-emacs-init][grep-emacs-init:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Grep Search Functions: grep-emacs-init
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Grep Search Functions: grep-emacs-init")

;; grep emacs initialization
(grep-custom-generate grep-emacs-init "Grep Emacs Initialization files: "
                      ("~/.emacs.d/init.el"
                       "~/.emacs.d/init-emacs.org"
                       "~/.emacs.d/customization.el")
                      "\\(\\.el$\\|\\.org$\\)")
;; grep-emacs-init:1 ends here

;; [[file:init-emacs.org::*grep-home-init][grep-home-init:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Grep Search Functions: grep-home-init
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Grep Search Functions: grep-home-init")

;; grep home
(grep-custom-generate grep-home-init "Grep Home Initialization files: "
                      ("~/org/init-home.org") "\\.org$")
;; grep-home-init:1 ends here

;; [[file:init-emacs.org::*grep-org][grep-org:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Grep Search Functions: grep-org
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Grep Search Functions: grep-org")

;; grep org
(grep-custom-generate grep-org "Grep org files: " ("~/org") "\\.org$")
;; grep-org:1 ends here

;; [[file:init-emacs.org::*grep-web][grep-web:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Grep Search Functions: grep-web
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Grep Search Functions: grep-web")

;; grep web
(grep-custom-generate grep-web "Grep web files: " ("~/web/org") "\\.org$")
;; grep-web:1 ends here

;; [[file:init-emacs.org::*TAGS%20File%20Functions][TAGS File Functions:1]]
;;------------------------------------------------------------------------------
;;; Functions: TAGS File Functions
;;------------------------------------------------------------------------------

(init-message 2 "TAGS Files")
;; TAGS File Functions:1 ends here

;; [[file:init-emacs.org::*etags-create][etags-create:1]]
;;------------------------------------------------------------------------------
;;;; Functions: TAGS File Functions: etags-create
;;------------------------------------------------------------------------------

(init-message 3 "Functions: TAGS File Functions: etags-create")

;; create TAGS file
(defun etags-create (&optional local)
  "Create local TAGS file.
\nIf LOCAL is non-nil, visit the new TAGS file locally only.
\nFirst an existing TAGS file is searched for going up the
directory path.  If none is found, a \"src\" directory is
searched for and, if found, its parent directory is used.
Failing that the user is prompted for the location."
  (interactive)
  (let ((file (or (find-file-updir "TAGS")
                  (when (find-file-updir "src")
                    (expand-file-name (concat (find-file-updir "src") "/../TAGS")))
                  ;; ask for TAGS directory if not found
                  (concat (read-directory-name "Top of source tree: " default-directory) "/TAGS")))
        (extension (or (file-name-extension (buffer-file-name))
                       ;; extension defaults to `el'
                       "el"))
        query)
    ;; generate find command parameters
    ;; for c/c++ files, add extra extensions
    (if (member extension '("h" "c" "hpp" "cpp"))
        (setq query "-name \"*.h\" -o -name \"*.c\" -o -name \"*.hpp\" -o -name \"*.cpp\"")
      (setq query (concat "-name \"*." extension "\"")))
    (let ((cmd (concat "find " (file-name-directory file) " " query " -print0 | "
                       "grep -zZv \"/.svn/\" | "
                       "xargs -0 etags -o " file " && "
                       "echo 'Created TAGS file'")))
      (message (format "Running command: %s" cmd))
      ;; create tags file
      (shell-command cmd)
      ;; kill TAGS buffer
      (when (get-buffer "TAGS")
        (kill-buffer "TAGS"))
      ;; set tags file
      (visit-tags-table file local))))
;; etags-create:1 ends here

;; [[file:init-emacs.org::*Code%20Formatting%20Functions][Code Formatting Functions:1]]
;;------------------------------------------------------------------------------
;;; Functions: Code Formatting Functions
;;------------------------------------------------------------------------------

(init-message 2 "Code Formatting Functions")
;; Code Formatting Functions:1 ends here

;; [[file:init-emacs.org::*indent-region-or-sexp][indent-region-or-sexp:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: indent-region-or-sexp
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: indent-region-or-sexp")


;; indent-region-or-sexp:1 ends here

;; [[file:init-emacs.org::*find-code-block][find-code-block:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: find-code-block
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: find-code-block")

;; find begin and end of current code block
(defun find-code-block (&optional regexp indent)
  "Find the begin and end of code block containing point.

When run interactively, then begin and end points of the block
are printed in the minibuffer.  Otherwise, a list containing them
is returned.

A code block is defined as contiguous lines of text having the
same indentation.  So a code block ends when either the
indentation changes or a blank line is reached.

The begin point will be at the start of a line and the end point
will be at the end of a line, unless point is not in a code block
in which case nil is returned for both.

The optional parameter REGEXP is an additional regular expression
to match on.  If non-nil, every line in the code block must also
match REGEXP.

If optional parameter INDENT is non-nil then each line will be
indented via `indent-according-to-mode'."
  (interactive "*")
  (let (beg
        end
        (ind 0)
        (blank-line-regexp "^[ \t]*$"))
    (save-excursion
      ;; indent if INDENT is t
      ;;(when indent
      ;;  (indent-according-to-mode))
      (setq ind (current-indentation))
      (goto-char (line-beginning-position))
      ;; continue if we are in a code block
      (unless (or
               (looking-at blank-line-regexp)
               (if regexp
                   (not (looking-at regexp))
                 nil))
        ;; move up to first line in block
        (while (and
                (not (bobp))
                (not (looking-at blank-line-regexp))
                (= ind (current-indentation))
                (if regexp
                    (looking-at regexp)
                  t))
          (forward-line -1)
          ;; indent if INDENT is t
          ;;(when indent
          ;;  (indent-according-to-mode))
          (goto-char (line-beginning-position)))
        ;; if current line is not part of range, then move down
        (unless (and
                 (not (looking-at blank-line-regexp))
                 (= ind (current-indentation))
                 (if regexp
                     (looking-at regexp)
                   t))
          (forward-line 1))
        (goto-char (line-beginning-position))
        (setq beg (point))
        ;; indent if INDENT is t
        (when indent
          (indent-according-to-mode))
        (setq ind (current-indentation))
        ;; move down to last line in block
        (while (and
                (not (eobp))
                (not (looking-at blank-line-regexp))
                (= ind (current-indentation))
                (if regexp
                    (looking-at regexp)
                  t))
          (forward-line 1)
          ;; indent if INDENT is t
          (when indent
            (indent-according-to-mode))
          (goto-char (line-beginning-position)))
        (unless (and
                 (not (looking-at blank-line-regexp))
                 (= ind (current-indentation))
                 (if regexp
                     (looking-at regexp)
                   t))
          (forward-line -1))
        (end-of-line)
        (setq end (point))))
    (if (called-interactively-p 'any)
        (message "%s %s" beg end)
      (list beg end))))
;; find-code-block:1 ends here

;; [[file:init-emacs.org::*lineup-assignment-commands][lineup-assignment-commands:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: lineup-assignment-commands
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: lineup-assignment-commands")

;; line up assignment commands
;; TODO: look at `align' and `align-regexp' functions to help with this
(defun lineup-assignment-commands (&optional indent)
  "Line up a block of variable assignment commands.

Match any contiguous block of code (presumably assignment
commands) and line up the equal signs.

If optional parameter INDENT is non-nil then each line will be
indented via `indent-according-to-mode'.

Example:

  // assignments
  var1 = value1; // var1
  variable2 = value2; // var2

Becomes:

  // assignments
  var1      = value1;             // var1
  variable2 = value2;             // var2"
  (interactive "*")
  (let* ((range (find-code-block nil indent)) ; range
         (beg (car range))                    ; beginning of range
         (end (cadr range))                   ; end of range
         (pos 0)
         (equal-regexp "[ \t]*=[ \t]*"))
    (save-excursion
      ;; if there are lines in range, continue
      (when (> end beg)
        ;; preserve block range
        (save-restriction
          (narrow-to-region beg end)
          ;; preserve search data
          (save-match-data
            ;; move down code block
            (goto-char (point-min))
            (while (< (point) (point-max))
              ;; store farthest equal sign that is not in a comment
              (when (and
                     (re-search-forward equal-regexp (line-end-position) t)
                     (not (equal (get-char-property (point) 'face)
                                 'font-lock-comment-face)))
                ;; remove extra whitespace
                (goto-char (line-beginning-position))
                (re-search-forward equal-regexp (line-end-position))
                (replace-match " = ")
                ;; put point before the equal sign
                (backward-char 2)
                ;; store point if larger than others
                (when (> (- (point) (line-beginning-position)) pos)
                  (setq pos (- (point) (line-beginning-position)))))
              (goto-char (line-beginning-position))
              (forward-line 1))
            ;; move through the block, padding as needed
            (goto-char (point-min))
            (while (< (point) (point-max))
              (when (and
                     (re-search-forward equal-regexp (line-end-position) t)
                     (not (equal (get-char-property (point) 'face)
                                 'font-lock-comment-face)))
                (backward-char 2)
                ;; pad as needed
                (while (< (- (point) (line-beginning-position)) pos)
                  (insert " ")))
              (goto-char (line-beginning-position))
              (forward-line 1))
            ;; handle lines that ends in a comment
            (goto-char (point-min))
            (while (< (point) (point-max))
              (goto-char (line-beginning-position))
              (forward-char (current-indentation))
              ;; if line is not a comment line and line ends in a comment, then
              ;; call comment-indent
              (when (and
                     (not (equal (get-char-property (line-end-position) 'face)
                                 'font-lock-comment-face))
                     (equal (get-char-property (line-end-position) 'face)
                            'font-lock-comment-face))
                (comment-indent))
              (forward-line 1))))))))
;; lineup-assignment-commands:1 ends here

;; [[file:init-emacs.org::*lineup-assignment-commands-indent][lineup-assignment-commands-indent:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: lineup-assignment-commands-indent
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: lineup-assignment-commands-indent")

;; line up assignment commands indent
(defun lineup-assignment-commands-indent ()
  (interactive "*")
  (lineup-assignment-commands t))
;; lineup-assignment-commands-indent:1 ends here

;; [[file:init-emacs.org::*lineup-declaration-commands][lineup-declaration-commands:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: lineup-declaration-commands
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: lineup-declaration-commands")

;; line up declaration commands
;; TODO: fix removal of extra whitespace in block
;; TODO: fix adding whitespace where needed in block
(defun lineup-declaration-commands (&optional indent)
  "Line up a block of variable declaration commands.

If optional parameter INDENT is non-nil then each line will be
indented via `indent-according-to-mode'.

Example:

  // variables
  public Integer i; // int example
  public String s; // string example
  private Integer i2; // int 2
  private String s2; // string 2
  protected Date dte; // date example

Becomes:

  // variables
  public    Integer i;            // int example
  public    String  s;            // string example
  private   Integer i2;           // int 2
  private   String  s2;           // string 2
  protected Date    dte;          // date example"
  (interactive "*")
  (let* ((range (find-code-block nil indent)) ; range
         (beg (car range))                    ; beginning of range
         (end (cadr range))                   ; end of range
         face                                 ; current font face
         face-prev                            ; previous font face
         face-change                          ; has face changed
         (change -1)                          ; current column to line up on
         (change-prev -2)                     ; previous column to line up on
         (whitespace-regexp "[ \t]+"))        ; regexp to match whitespace
    (save-excursion
      ;; if there are lines in range, continue
      (when (> end beg)
        ;; preserve block range
        (save-restriction
          (narrow-to-region beg end)
          ;; preserve search data
          (save-match-data
            ;; remove extra whitespace
            (goto-char (point-min))
            (while (< (point) (point-max))
              (forward-char (current-indentation))
              (while (re-search-forward whitespace-regexp (line-end-position) t)
                (replace-match " "))
              (goto-char (line-beginning-position))
              (forward-line 1))
            ;; loop until all face changes have been analyzed
            (while (> change change-prev)
              ;; update change-prev
              (setq change-prev change)
              ;; set change-prev to indent on first pass
              (when (< change-prev 0)
                (setq change-prev (current-indentation)))
              ;; clear face
              (setq face nil)
              ;; clear face-prev
              (setq face-prev nil)
              ;; goto start of range
              (goto-char (point-min))
              ;; loop through all lines in range
              (while (< (point) (point-max))
                ;; goto start of line + indentation
                (goto-char (line-beginning-position))
                (forward-char (current-indentation))
                ;; ignore comment lines
                (unless (member (get-char-property (point) 'face)
                                (list 'font-lock-comment-face
                                      'nxml-comment-delimiter-face
                                      'nxml-comment-content-face))
                  ;; goto start of line + change-prev
                  (goto-char (line-beginning-position))
                  (forward-char change-prev)
                  ;; get face-prev of first non-whitespace character
                  (unless face-prev
                    (save-excursion
                      (while (and (< (point) (line-end-position))
                                  (looking-at whitespace-regexp))
                        (forward-char 1))
                      (when (< (point) (line-end-position))
                        (setq face-prev (get-char-property (point) 'face)))))
                  ;; move forward until we hit whitespace, tracking any face change
                  (setq face-change nil)
                  (while (and (< (point) (line-end-position))
                              (not (looking-at whitespace-regexp)))
                    (when (not (equal face-prev (get-char-property (point) 'face)))
                      (setq face-change t))
                    (forward-char 1))
                  ;; move forward until a non-whitespace character is reached that
                  ;; changes the face
                  (while (and (< (point) (line-end-position))
                              (or
                               (looking-at whitespace-regexp)
                               (and (not face-change)
                                    (equal face-prev (get-char-property (point) 'face)))))
                    (forward-char 1))
                  ;; if the face changed and it is farther than the current
                  ;; change, set the face and change value; face is set on the
                  ;; first pass after which a match is expected
                  (when (and (< (point) (line-end-position))
                             (< change (- (point) (line-beginning-position)))
                             (if face
                                 (equal face (get-char-property (point) 'face))
                               t))
                    ;; only set face on first pass
                    (unless face
                      (setq face (get-char-property (point) 'face)))
                    (setq change (- (point) (line-beginning-position)))))
                ;; move to next line and continue
                (forward-line 1))
              ;; if a face change is found, lineup lines
              (when (> change change-prev)
                ;; goto start of range
                (goto-char (point-min))
                ;; loop through all lines in range
                (while (< (point) (point-max))
                  ;; goto start of line + indentation
                  (goto-char (line-beginning-position))
                  (forward-char (current-indentation))
                  ;; ignore comment lines
                  (unless (member (get-char-property (point) 'face)
                                  (list 'font-lock-comment-face
                                        'nxml-comment-delimiter-face
                                        'nxml-comment-content-face))
                    ;; goto start of line + change-prev
                    (goto-char (line-beginning-position))
                    (forward-char change-prev)
                    ;; find start of face change
                    ;; move forward until whitespace is reached
                    (while (and (< (point) (line-end-position))
                                (not (looking-at whitespace-regexp)))
                      (forward-char 1))
                    ;; move forward until a non-whitespace character is reached
                    ;; that matches the face change
                    (while (and (< (point) (line-end-position))
                                (or
                                 (looking-at whitespace-regexp)
                                 (not (equal face (get-char-property (point) 'face)))))
                      (forward-char 1))
                    ;; space as needed
                    (while (< (- (point) (line-beginning-position)) change)
                      ;; TODO: as a precaution check that previous character is
                      ;; whitespace
                      (insert " ")))
                  ;; move to next line and continue
                  (forward-line 1))))
            ;; handle lines that ends in a comment
            (goto-char (point-min))
            (while (< (point) (point-max))
              (goto-char (line-beginning-position))
              (forward-char (current-indentation))
              ;; if line is not a comment line and line ends in a comment, then
              ;; call comment-indent
              (when (and
                     (not (equal (get-char-property (line-end-position) 'face)
                                 'font-lock-comment-face))
                     (equal (get-char-property (line-end-position) 'face)
                            'font-lock-comment-face))
                (comment-indent))
              (forward-line 1))))))))
;; lineup-declaration-commands:1 ends here

;; [[file:init-emacs.org::*lineup-declaration-commands-indent][lineup-declaration-commands-indent:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: lineup-declaration-commands-indent
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: lineup-declaration-commands-indent")

;; line up declaration commands indent
(defun lineup-declaration-commands-indent ()
  (interactive "*")
  (lineup-declaration-commands t))
;; lineup-declaration-commands-indent:1 ends here

;; [[file:init-emacs.org::*lineup-comments][lineup-comments:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: lineup-comments
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: lineup-comments")

;; line up a block of lines with comments
(defun lineup-comments (beg end)
  "Line up a block of commented lines.

Example:

  // variables
  public Integer i; // int example
  public String s; // string example
  private Integer i2; // int 2
  private String s2; // string 2
  protected Date dte; // date example

Becomes:

  // variables
  public Integer i;             // int example
  public String s;              // string example
  private Integer i2;           // int 2
  private String s2;            // string 2
  protected Date dte;           // date example"
  (interactive "*r")
  (align-regexp beg end comment-start))
;; lineup-comments:1 ends here

;; [[file:init-emacs.org::*java-toggle-comment-type][java-toggle-comment-type:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: java-toggle-comment-type
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: java-toggle-comment-type")

;; toggle between single and multi-line java/c comments
(defun java-toggle-comment-type ()
  "Toggle between single and multi-line Java/C comments.

Examples:

                   /*
  // comment  ==>   * comment
                    */

  /*
   * comment  ==>  // comment
   */"
  (interactive "*")
  (let ((indentation-regexp "^[ \t]*")
        (empty-line-regexp "^[ \t]*$")
        (single-line-comment-regexp "^[ \t]*// ")
        (multi-line-comment-regexp "^[ \t]*\\* ")
        (multi-line-comment-begin-regexp "^[ \t]*/\\*")
        (multi-line-comment-end-regexp "^[ \t]*\\*/")
        (class-regexp "\\bclass\\b"))
    (save-excursion
      (goto-char (line-beginning-position))
      (if (looking-at single-line-comment-regexp)
          ;; convert single line comments into a multi-line comment
          (let ((beg (progn
                         (while (and (not (bobp))
                                     (looking-at single-line-comment-regexp))
                           (forward-line -1))
                         (when (not (looking-at single-line-comment-regexp))
                           (forward-line 1))
                         (line-beginning-position)))
                (end (progn
                       (while (and (not (eobp))
                                   (looking-at single-line-comment-regexp))
                         (forward-line 1))
                       (when (not (looking-at single-line-comment-regexp))
                         (forward-line -1))
                       (line-end-position)))
                (space (make-string (- (re-search-forward indentation-regexp) (line-beginning-position)) ? ))
                (class (progn
                         (goto-char (line-beginning-position))
                         (forward-line 1)
                         (while (looking-at empty-line-regexp)
                           (forward-line 1))
                         (looking-at class-regexp))))
            (goto-char beg)
            ;;(insert (concat space "/*" (if class "*" "")))
            (insert (concat space "/*"))
            (newline)
            (while (re-search-forward single-line-comment-regexp end t)
              (replace-match (concat space " * ")))
            (goto-char (line-end-position))
            (newline)
            (insert (concat space " */")))
        ;; convert multi-line comment to single line comments
        (let ((beg (progn
                       (while (and (not (bobp))
                                   (or (looking-at multi-line-comment-regexp)
                                       (looking-at multi-line-comment-end-regexp)))
                         (forward-line -1))
                       (if (looking-at multi-line-comment-begin-regexp)
                           (line-beginning-position)
                         nil)))
              (end (progn
                     (while (and (not (eobp))
                                 (or (looking-at multi-line-comment-regexp)
                                     (looking-at multi-line-comment-begin-regexp)))
                       (forward-line 1))
                     (if (looking-at multi-line-comment-end-regexp)
                         (line-end-position)
                       nil)))
              (space (make-string (- (re-search-forward indentation-regexp) (line-beginning-position) 1) ? )))
          (when (and beg end)
            (goto-char beg)
            (delete-region (point) (progn (forward-line 1) (point)))
            (while (re-search-forward multi-line-comment-regexp end t)
              (replace-match (concat space "// ")))
            (goto-char (line-end-position))
            (delete-region (point) (progn (forward-line 1) (goto-char (line-end-position)) (point)))))))))

(init-message 3 "Functions: Code Formatting Functions: c-toggle-comment-type")

(defalias 'c-toggle-comment-type 'java-toggle-comment-type)
;; java-toggle-comment-type:1 ends here

;; [[file:init-emacs.org::*java-remove-comments][java-remove-comments:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: java-remove-comments
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: java-remove-comments")

;; remove all java comments
(defun java-remove-comments (&optional beg end)
  "Remove all Java comments from buffer or region."
  (interactive "*")
  (let ((beg (or beg (if (use-region-p) (region-beginning) (point-min))))
        (end (or end (if (use-region-p) (region-end) (point-max)))))
    (save-excursion
      (save-restriction
        (narrow-to-region beg end)
        (let (quote                     ; whether inside a quote
              escape                    ; whether inside an escape
              comment)                  ; whether inside a block comment
          (goto-char (point-min))
          (while (not (eobp))
            (forward-char 1)
            (let ((char (preceding-char))
                  (next-char (following-char)))
              (case char
                (?\"                    ; quote
                 (unless (or comment escape)
                   (setq quote (not quote))))
                (?\\                    ; escape
                 (unless comment
                   (setq escape (not escape))))
                (t
                 (if comment            ; inside block comment
                     (when (and (char-equal char ?*) (char-equal next-char ?/)) ; check for comment end
                       (forward-char 1)
                       (when (and (eolp) (not (eobp)))
                         (forward-char 1))
                       (delete-region comment (point))
                       (setq comment nil))
                   (unless (or quote escape) ; check for comment start
                     (cond
                      ;; inline comment
                      ((and (char-equal char ?/) (char-equal next-char ?/))
                       (forward-char -1)
                       (while (and (not (bolp))
                                   (or (char-equal (preceding-char) ? )
                                       (char-equal (preceding-char) ?\t)))
                         (forward-char -1))
                       (let ((mark (point)))
                         (goto-char (line-end-position))
                         (when (not (eobp))
                           (forward-char 1))
                         (delete-region mark (point))))
                      ;; block comment
                      ((and (char-equal char ?/) (char-equal next-char ?*))
                       (setq comment (1- (point))))))))))))))))
;; java-remove-comments:1 ends here

;; [[file:init-emacs.org::*+java-remove-comments+][+java-remove-comments+:1]]
;; ;;------------------------------------------------------------------------------
;; ;;;; Functions: Code Formatting Functions: java-remove-comments
;; ;;------------------------------------------------------------------------------

;; (init-message 3 "Functions: Code Formatting Functions: java-remove-comments")

;; ;; remove all java comments from string
;; (defun java-remove-comments (string)
;;   "Return code STRING with all Java comments removed."
;;   (loop with result = ()                ; result character list
;;         with quote = nil                ; whether inside of a quote
;;         with escape = nil               ; whether inside of an escape
;;         with comment = 0                ; whether inside of a comment (0 = none, 1 = inline, 2 = block, 3 = ending block)
;;         for pc = nil then c             ; previous character
;;         for c across string             ; current character
;;         for r = pc                      ; character to collect
;;         do (case c
;;              (?\"                       ; quote
;;               (unless escape
;;                 (setq quote (not quote))))
;;              (?\\                       ; escape
;;               (setq escape (not escape)))
;;              (t
;;               (when pc
;;                 (case comment
;;                   (0                         ; not inside a comment
;;                    (unless (or quote escape) ; check for comment start
;;                      (cond
;;                       ((and (= pc ?/) (= c ?/)) ; inline comment start
;;                        (setq comment 1))
;;                       ((and (= pc ?/) (= c ?*)) ; block comment start
;;                        (setq comment 2)))))
;;                   (1                      ; inside an inline comment
;;                    (when (= c ?\n)        ; inline comment ends with newline
;;                      (setq comment 0
;;                            r nil
;;                            quote nil))) ; quotes cannot go past EOL for inline comments
;;                   (2                    ; inside a block comment
;;                    (when (and (not (or quote escape)) (= pc ?*) (= c ?/)) ; check for comment end
;;                      (setq comment 3
;;                            r nil)))
;;                   (3
;;                    (setq comment 0
;;                          r nil))))))
;;         do (when (and escape (/= c ?\\)) ; escape only lasts for next character
;;              (setq escape nil))
;;         do (when (and r (= comment 0))  ; add r to result
;;              (push r result))
;;         finally return (progn ; add last character to result and return string
;;                          (when (= comment 0)
;;                            (push c result))
;;                          (message "=====> %S" (mapconcat 'string (nreverse result) ""))
;;                          (mapconcat 'string (nreverse result) ""))))

;; +java-remove-comments+:1 ends here

;; [[file:init-emacs.org::*lisp-to-camel-case][lisp-to-camel-case:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: lisp-to-camel-case
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: lisp-to-camel-case")

;; lisp to camel case
(defun lisp-to-camel-case ()
  "Convert word under point from lisp notation to camel case notation."
  (interactive "*")
  (let* ((bounds (bounds-of-thing-at-point 'word))
         (beg (car bounds))
         (end (cdr bounds)))
    (save-excursion
      (save-restriction
        (narrow-to-region beg end)
        (goto-char (point-min))
        (while (re-search-forward "-" nil t)
          (let ((p (point)))
            (capitalize-word 1)
            (goto-char p)))
        (goto-char (point-min))
        (while (re-search-forward "-" nil t)
          (replace-match ""))))))
;; lisp-to-camel-case:1 ends here

;; [[file:init-emacs.org::*camel-case-to-lisp][camel-case-to-lisp:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: camel-case-to-lisp
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: camel-case-to-lisp")

;; camel case to lisp
(defun camel-case-to-lisp ()
  "Convert word under point from camel case notation to lisp notation."
  (interactive "*")
  (let* ((bounds (bounds-of-thing-at-point 'word))
         (beg (car bounds))
         (end (cdr bounds))
         (case-fold-search nil))
    (save-excursion
      (save-restriction
        (narrow-to-region beg end)
        (goto-char (point-min))
        (while (re-search-forward "[A-Z]" nil t)
          (forward-char -1)
          (insert "-")
          (forward-char 1))
        (goto-char (point-min))
        (downcase-word 1)))))
;; camel-case-to-lisp:1 ends here

;; [[file:init-emacs.org::*c-fix-code][c-fix-code:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: c-fix-code
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: c-fix-code")

;; c fix code
(defun c-fix-code (&optional beg end)
  "Clean up c/c++ code."
  (interactive "*")
  (let ((beg (or beg (if (use-region-p) (region-beginning) (point-min))))
        (end (or end (if (use-region-p) (region-end) (point-max)))))
    (save-excursion
      (save-restriction
        (narrow-to-region beg end)
        ;; remove tabs
        (remove-tabs)
        ;; remove trailing blanks
        (remove-trailing-blanks)
        ;; remove extra spaces from functions
        (goto-char (point-min))
        (while (re-search-forward "([ \t]*" nil t)
          (replace-match "("))
        (goto-char (point-min))
        (while (re-search-forward "[ \t]*)" nil t)
          (replace-match ")"))
        ;; remove extra spaces from template references
        ;;(goto-char (point-min))
        ;;(while (re-search-forward "<[ \t]*\\(.*?\\)[ \t]*>" nil t)
        ;;  (replace-match "<\\1>"))
        ;; add spaces after commas
        (goto-char (point-min))
        (while (re-search-forward "\\,\\([^ ]\\)" nil t)
          (replace-match ", \\1"))
        ;; remove double or more spaces
        (goto-char (point-min))
        (while (re-search-forward "\\([^ \.]\\)  +" nil t)
          (replace-match "\\1 "))
        ;; remove double or more blank lines
        (goto-char (point-min))
        (while (re-search-forward "\n\n\n+" nil t)
          (replace-match "\n\n"))
        ;; remove blank line before block start
        (goto-char (point-min))
        (while (re-search-forward "\n\n[ \t]*{" nil t)
          (replace-match "\n{")
          (indent-according-to-mode))
        ;; indent buffer
        (indent-region (point-min) (point-max) nil)))))
;; c-fix-code:1 ends here

;; [[file:init-emacs.org::*ruby-fix-code][ruby-fix-code:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: ruby-fix-code
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: ruby-fix-code")

;; ruby fix code
(defun ruby-fix-code (&optional beg end)
  "Clean up ruby code."
  (interactive "*")
  (let ((beg (or beg (if (use-region-p) (region-beginning) (point-min))))
        (end (or end (if (use-region-p) (region-end) (point-max)))))
    (save-excursion
      (save-restriction
        (narrow-to-region beg end)
        ;; remove tabs
        (remove-tabs)
        ;; remove trailing blanks
        (remove-trailing-blanks)
        ;; remove extra spaces from functions
        (goto-char (point-min))
        (while (re-search-forward "([ \t]*\\(.*?\\)[ \t]*)" nil t)
          (replace-match "(\\1)"))
        ;; remove extra spaces from variable references
        (goto-char (point-min))
        (while (re-search-forward "#{[ \t]*\\(.*?\\)[ \t]*}" nil t)
          (replace-match "#{\\1}"))
        ;; remove extra spaces from hash references
        (goto-char (point-min))
        (while (re-search-forward "\\[[ \t]*\\(.*?\\)[ \t]*\\]" nil t)
          (replace-match "[\\1]"))
        ;; remove extra spaces from each clauses
        (goto-char (point-min))
        (while (re-search-forward "|[ \t]*\\(.*?\\)[ \t]*|" nil t)
          (replace-match "|\\1|"))
        ;; add spaces after commas
        (goto-char (point-min))
        (while (re-search-forward "\\,\\([^ ]\\)" nil t)
          (replace-match ", \\1"))
        ;; remove double or more spaces
        (goto-char (point-min))
        (while (re-search-forward "\\([^ \.]\\)  +" nil t)
          (replace-match "\\1 "))
        ;; remove double or more blank lines
        (goto-char (point-min))
        (while (re-search-forward "\n\n\n+" nil t)
          (replace-match "\n\n"))
        ;; indent buffer
        (indent-region (point-min) (point-max) nil)))))
;; ruby-fix-code:1 ends here

;; [[file:init-emacs.org::*java-fix-code][java-fix-code:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: java-fix-code
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: java-fix-code")

;; java fix code
(defun java-fix-code (&optional beg end)
  "Clean up Java code."
  (interactive "*")
  (let ((beg (or beg (if (use-region-p) (region-beginning) (point-min))))
        (end (or end (if (use-region-p) (region-end) (point-max)))))
    (save-excursion
      (save-restriction
        (narrow-to-region beg end)
        ;; remove tabs
        (remove-tabs)
        ;; remove trailing blanks
        (remove-trailing-blanks)
        ;; remove extra spaces from functions
        (goto-char (point-min))
        (while (re-search-forward "([ \t]*" nil t)
          (replace-match "("))
        (goto-char (point-min))
        (while (re-search-forward "[ \t]*)" nil t)
          (replace-match ")"))
        ;; add spaces after commas
        (goto-char (point-min))
        (while (re-search-forward "\\,\\([^ ]\\)" nil t)
          (replace-match ", \\1"))
        ;; add spaces after special forms keywords names
        (dolist (name '("catch" "else" "for" "if" "return" "switch" "while"))
          (goto-char (point-min))
          (while (re-search-forward (concat name "(") nil t)
            (replace-match (concat name " ("))))
        ;; join "} CONNECTOR {" into one line
        (dolist (name '("catch" "else"))
          (goto-char (point-min))
          (while (re-search-forward (concat "}[ \t\n]*" name) nil t)
            (replace-match (concat "} " name))
            (indent-according-to-mode)))
        ;; remove double or more spaces
        (goto-char (point-min))
        (while (re-search-forward "\\([^ \.]\\)  +" nil t)
          (replace-match "\\1 "))
        ;; remove double or more blank lines
        (goto-char (point-min))
        (while (re-search-forward "\n\n\n+" nil t)
          (replace-match "\n\n"))
        ;; remove blank line before block start
        (goto-char (point-min))
        (while (re-search-forward "\n\n[ \t]*{" nil t)
          (replace-match "\n{")
          (indent-according-to-mode))
        ;; indent buffer
        (indent-region (point-min) (point-max) nil)))))
;; java-fix-code:1 ends here

;; [[file:init-emacs.org::*json-fix-code][json-fix-code:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: json-fix-code
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: json-fix-code")

;; json fix code
;; Source: http://stefan.arentz.ca/beautify-json-in-emacs.html
(defun json-fix-code (&optional beg end)
  "Clean up JSON block."
  (interactive "*")
  (save-excursion
    (let ((beg (or beg (if (use-region-p) (region-beginning) (point-min))))
          (end (or end (if (use-region-p) (region-end) (point-max)))))
      ;; first convert json to one line to prevent issues with newlines in strings
      (goto-char beg)
      (forward-line 1)
      (while (< (point) end)
        (delete-char -1)
        (insert ? )
        (goto-char (line-beginning-position))
        (forward-line 1))
      ;; finally use the python json.tool to format the json string
      (shell-command-on-region beg end "python -mjson.tool" (current-buffer) t))))
;; json-fix-code:1 ends here

;; [[file:init-emacs.org::*xml-format][xml-format:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: xml-format
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: xml-format")

;; xml format
(defun xml-format (&optional beg end)
  "Format XML buffer.
\nConvert poorly formatted XML into something better."
  (interactive "*")
  (let ((beg (or beg (if (use-region-p) (region-beginning) (point-min))))
        (end (or end (if (use-region-p) (region-end) (point-max))))
        (mode major-mode))
    (save-excursion
      (save-restriction
        (narrow-to-region beg end)
        (xml-mode)
        (let ((xml-eol "[ \t]*\n[ \t]*")
              (xml-tag-end-regexp ">")
              (xml-close-tag-regexp "</")
              (xml-block-regexp "<[^>]*>[^<]*</[^>]*>"))
          (save-excursion
            ;; preserve search data
            (save-match-data
              ;; remove all existing EOL characters
              (goto-char (point-min))
              (while (re-search-forward xml-eol nil t)
                (replace-match ""))
              ;; move down code adding newlines were needed
              (goto-char (point-min))
              (while (re-search-forward xml-tag-end-regexp nil t)
                (insert "\n")
                (when (and
                       (looking-at xml-block-regexp)
                       (not (looking-at xml-close-tag-regexp)))
                  (re-search-forward xml-block-regexp nil t)
                  (forward-char -1)))
              ;; indent buffer
              (indent-region (point-min) (point-max)))))
        (funcall mode)))))
;; xml-format:1 ends here

;; [[file:init-emacs.org::*Code%20Inserting%20Functions][Code Inserting Functions:1]]
;;------------------------------------------------------------------------------
;;; Functions: Code Inserting Functions
;;------------------------------------------------------------------------------

(init-message 2 "Code Inserting Functions")
;; Code Inserting Functions:1 ends here

;; [[file:init-emacs.org::*project-euler-insert-template][project-euler-insert-template:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Inserting Functions: project-euler-insert-template
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Inserting Functions: project-euler-insert-template")

;; insert project euler template
(defun project-euler-insert-template (num &optional count)
  "Insert a Project Euler template for NUM.
\nIf optional COUNT is given, repeat up to NUM+COUNT-1."
  (if (string= (buffer-name) "project-euler.lisp")
      (dotimes (x (or count 1))
        (let ((strnum (format "%03d" (+ num x))))
          (save-excursion
            (goto-char (point-min))
            (re-search-forward "^;;; Template")
            (goto-char (line-beginning-position))
            (forward-line 3)
            (let ((beg (point)))
              (forward-sexp 2)
              (goto-char (line-beginning-position))
              (forward-line 2)
              (let ((template (replace-regexp-in-string
                               "\\?" strnum
                               (buffer-substring-no-properties beg (point)))))
                (search-backward-regexp "^;;; New Problems")
                (forward-line -1)
                (insert template))))))
    (error "Buffer is not 'project-euler.lisp'")))
;; project-euler-insert-template:1 ends here

;; [[file:init-emacs.org::*insert-tree][insert-tree:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Code Inserting Functions: insert-tree
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Inserting Functions: insert-tree")

;; insert tree
(defun insert-tree (leaves padding)
  "Insert binary tree with LEAVES at the bottom and PADDING on the left."
  (let ((size (* 3 (expt 2 leaves)))
        (pad (do* ((l 1 (1+ l))
                   (pad 0 (+ pad (* 3 (expt 2 l)))))
                 ((> l leaves) pad))))
    (do ((s size (1- s)))
        ((zerop s))
      (let ((i ""))
        (dotimes (x (+ padding s))
          (setq i (concat i " ")))
        (setq i (concat i "/"))
        (dotimes (x (* (- size s) 2))
          (setq i (concat i " ")))
        (setq i (concat i "\\"))
        (insert i)
        (newline)))))

   ;;                                              /\
   ;;                                             /  \
   ;;                                            /    \
   ;;                                           /      \
   ;;                                          /        \
   ;;                                         /          \
   ;;                                        /            \
   ;;                                       /              \
   ;;                                      /                \
   ;;                                     /                  \
   ;;                                    /                    \
   ;;                                 1 /                      \ 1
   ;;                                  /                        \
   ;;                                 /                          \
   ;;                                /                            \
   ;;                               /                              \
   ;;                              /                                \
   ;;                             /                                  \
   ;;                            /                                    \
   ;;                           /                                      \
   ;;                          /                                        \
   ;;                         /                                          \
   ;;                        /                                            \
   ;;                       /                                              \
   ;;                      /\                                              /\
   ;;                     /  \                                            /  \
   ;;                    /    \                                          /    \
   ;;                   /      \                                        /      \
   ;;                  /        \                                      /        \
   ;;               1 /          \ 2                                1 /          \ 2
   ;;                /            \                                  /            \
   ;;               /              \                                /              \
   ;;              /                \                              /                \
   ;;             /                  \                            /                  \
   ;;            /                    \                          /                    \
   ;;           /                      \                        /                      \
   ;;          /\                      /\                      /\                      /\
   ;;         /  \                    /  \                    /  \                    /  \
   ;;      1 /    \ 3              2 /    \ 6              1 /    \ 3              2 /    \ 6
   ;;       /      \                /      \                /      \                /      \
   ;;      /        \              /        \              /        \              /        \
   ;;     /          \            /          \            /          \            /          \
   ;;    /\          /\          /\          /\          /\          /\          /\          /\
   ;; 1 /  \ 4    3 /  \ 12   2 /  \ 8    6 /  \ 24   1 /  \ 4    3 /  \ 12   2 /  \ 8    6 /  \ 24
   ;;  /    \      /    \      /    \      /    \      /    \      /    \      /    \      /    \
;; insert-tree:1 ends here

;; [[file:init-emacs.org::*Esoteric%20Functions][Esoteric Functions:1]]
;;------------------------------------------------------------------------------
;;; Functions: Esoteric Functions
;;------------------------------------------------------------------------------

(init-message 2 "Functions: Esoteric Functions")
;; Esoteric Functions:1 ends here

;; [[file:init-emacs.org::*Fahrenheit/Celsius%20Conversions][Fahrenheit/Celsius Conversions:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Esoteric Functions: Fahrenheit/Celsius Conversions
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Esoteric Functions: Fahrenheit/Celsius Conversions")
;; Fahrenheit/Celsius Conversions:1 ends here

;; [[file:init-emacs.org::*fahrenheit-to-celsius][fahrenheit-to-celsius:1]]
;;------------------------------------------------------------------------------
;;;;; Functions: Esoteric Functions: Fahrenheit/Celsius Conversions: fahrenheit-to-celsius
;;------------------------------------------------------------------------------

(init-message 4 "Functions: Esoteric Functions: Fahrenheit/Celsius Conversions: fahrenheit-to-celsius")

;; convert fahrenheit to celsius
(defun fahrenheit-to-celsius (deg)
  "Convert fahrenheit degrees to celsius."
  (/ (* (- deg 32.0) 5.0) 9.0))
;; fahrenheit-to-celsius:1 ends here

;; [[file:init-emacs.org::*fahrenheit-to-celsius-query][fahrenheit-to-celsius-query:1]]
;;------------------------------------------------------------------------------
;;;;; Functions: Esoteric Functions: Fahrenheit/Celsius Conversions: fahrenheit-to-celsius-query
;;------------------------------------------------------------------------------

(init-message 4 "Functions: Esoteric Functions: Fahrenheit/Celsius Conversions: fahrenheit-to-celsius-query")

;; convert fahrenheit to celsius with user query
(defun fahrenheit-to-celsius-query (deg)
  "Prompt user for fahrenheit degrees to convert to celsius."
  (interactive "nFahrenheit degrees: ")
  (let ((cel (fahrenheit-to-celsius deg)))
    (when (called-interactively-p 'any)
      (message "Celsius degrees: %s" cel))
    cel))
;; fahrenheit-to-celsius-query:1 ends here

;; [[file:init-emacs.org::*celsius-to-fahrenheit][celsius-to-fahrenheit:1]]
;;------------------------------------------------------------------------------
;;;;; Functions: Esoteric Functions: Fahrenheit/Celsius Conversions: celsius-to-fahrenheit
;;------------------------------------------------------------------------------

(init-message 4 "Functions: Esoteric Functions: Fahrenheit/Celsius Conversions: celsius-to-fahrenheit")

;; convert celsius to fahrenheit
(defun celsius-to-fahrenheit (deg)
  "Convert celsius degrees to fahrenheit."
  (+ (* (/ deg 5.0) 9.0) 32.0))
;; celsius-to-fahrenheit:1 ends here

;; [[file:init-emacs.org::*celsius-to-fahrenheit-query][celsius-to-fahrenheit-query:1]]
;;------------------------------------------------------------------------------
;;;;; Functions: Esoteric Functions: Fahrenheit/Celsius Conversions: celsius-to-fahrenheit-query
;;------------------------------------------------------------------------------

(init-message 4 "Functions: Esoteric Functions: Fahrenheit/Celsius Conversions: celsius-to-fahrenheit-query")

;; convert celsius to fahrenheit with user query
(defun celsius-to-fahrenheit-query (deg)
  "Prompt user for celsius degrees to convert to fahrenheit."
  (interactive "nCelsius degrees: ")
  (let ((cel (celsius-to-fahrenheit deg)))
    (when (called-interactively-p 'any)
      (message "Fahrenheit degrees: %s" cel))
    cel))
;; celsius-to-fahrenheit-query:1 ends here

;; [[file:init-emacs.org::*base-conversion][base-conversion:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Esoteric Functions: base-conversion
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Esoteric Functions: base-conversion")

;; base conversion
(defun base-conversion (base-from base-to num)
  "Convert NUM from BASE-FROM to BASE-TO."
  (interactive)
  ;; first get base 10 number
  (let ((num
         (do* ((n (mod num 10) (mod num 10))
               (num (/ num 10) (/ num 10))
               (pos 1 (* pos base-from))
               (result (* pos n) (+ result (* pos n))))
             ((zerop num) result))))
    ;; now convert to base-to
    (do* ((n (mod num base-to) (mod num base-to))
          (num (/ num base-to) (/ num base-to))
          (pos 1 (* pos base-to))
          (result (* pos n) (+ result (* pos n))))
        ((zerop num) result))))
;; base-conversion:1 ends here

;; [[file:init-emacs.org::*ldif-update-xml][ldif-update-xml:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Esoteric Functions: ldif-update-xml
;;------------------------------------------------------------------------------

;; lidf update xml
(init-message 3 "Functions: Esoteric Functions: ldif-update-xml")
(defun ldif-update-xml ()
  "Update an LDIF node with the base64 encoded value of an XML block.
\nMust be run from the attribute being updated, which must be in
the form of `attribute::'."
  (interactive "*")
  (let (beg
        end
        attr
        block
        (blank-line-regexp "^[ \t]*$"))
    (save-excursion
      (save-match-data
        ;; save attr position
        (goto-char (line-beginning-position))
        (when (search-forward "::" (line-end-position) t)
          (setq attr (point))
          ;; find xml block
          (when (search-forward "<?xml" nil t)
            ;; get xml block range (fron starting <?xml to first blank line)
            ;; TODO: make this better by search for starting and ending xml
            ;; nodes
            (setq beg (line-beginning-position))
            (while (and
                    (not (eobp))
                    (not (looking-at blank-line-regexp)))
              (forward-line 1))
            (forward-line -1)
            (end-of-line)
            (setq end (point))
            ;; copy block to temp buffer
            (setq block (buffer-substring beg end))
            ;; following two lines used for debugging
            ;;(save-current-buffer
            ;;  (set-buffer (get-buffer-create "*temp*"))
            (with-temp-buffer
              (insert block)
              (goto-char (point-min))
              ;; if block is commented out, then uncomment
              (search-forward "<?xml")
              (goto-char (line-beginning-position))
              (when (char-equal (char-after (point)) ?#)
                (while (char-equal (char-after (point)) ?#)
                  ;; remove leading #
                  (delete-char 1)
                  ;; remove single space if exists
                  (when (char-equal (char-after (point)) ? )
                    (delete-char 1))
                  (forward-line 1)
                  (goto-char (line-beginning-position))))
              ;; remove comment lines
              (goto-char (point-min))
              (while (re-search-forward "^#" (point-max) t)
                (delete-region (line-beginning-position) (line-end-position))
                (unless (eobp)
                  (delete-char 1)))
              ;; base64 encode block
              (base64-encode-region (point-min) (point-max))
              ;; append every line with a space
              (goto-char (point-min))
              (while (not (eobp))
                (goto-char (line-beginning-position))
                (insert " ")
                (forward-line 1))
              ;; copy encoded block
              (setq block (buffer-substring (point-min) (point-max))))
            ;; delete attr data
            (goto-char attr)
            (delete-region (point) (line-end-position))
            (forward-line 1)
            (goto-char (line-beginning-position))
            (while (char-equal (char-after (point)) ? )
              (delete-region (line-beginning-position) (line-end-position))
              (delete-char 1))
            ;; paste encoded block
            (goto-char attr)
            (insert block)))))))
;; ldif-update-xml:1 ends here

;; [[file:init-emacs.org::*Programs][Programs:1]]
;;------------------------------------------------------------------------------
;;; Functions: Programs
;;------------------------------------------------------------------------------

(init-message 2 "Functions: Programs")
;; Programs:1 ends here

;; [[file:init-emacs.org::*National%20Debt][National Debt:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Programs: National Debt
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Programs: National Debt")

;; national dept
;; (defun national-debt ()
;;   "Return the current US national debt."
;;   (interactive)
;;   (save-current-buffer
;;     (url-retrieve
;;      "http://www.brillig.com/debt_clock"
;;      (lambda (x)
;;        (re-search-forward "debtiv\.gif.*alt=\"\\([^\"]*\\)" nil t)
;;        (message
;;         (replace-regexp-in-string
;;          "\s+" ""
;;          (buffer-substring-no-properties (match-beginning 1) (match-end 1))))))))
(defun national-debt ()
  "Return the current US national debt."
  (interactive)
  (save-current-buffer
    (let ((buffer (url-retrieve-synchronously "http://brillig.com/debt_clock/"))
          result)
      (when buffer
        (with-current-buffer buffer
          (goto-char (point-min))
          (when (re-search-forward "debtiv\.gif.*[Aa][Ll][Tt]=\"\\([^\"]*\\)" nil t)
            (setq result
                  (replace-regexp-in-string
                   "\s+" ""
                   (buffer-substring-no-properties (match-beginning 1) (match-end 1)))))))
      (if result
          (if (called-interactively-p 'any)
              (message result)
            (string-to-number
             (replace-regexp-in-string "," ""
                                       (replace-regexp-in-string "\\$" "" result))))
        (message "Error fetching the national debt")))))
;; National Debt:1 ends here

;; [[file:init-emacs.org::*Flesch%20Readability%20Index][Flesch Readability Index:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Programs: Flesch Readability Index
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Programs: Flesch Readability Index")

;; flesch readability index
(defun flesch-readability-index (&optional beg end)
  "Compute the Flesch Readability Index of the current region or entire buffer.

The Flesch Readability Index is defined on wikipedia here:

  http://en.wikipedia.org/wiki/Flesch-Kincaid_Readability_Test

This function provides that index following the guidelines presented here:

  http://cs.boisestate.edu/~amit/teaching/125/lab/p4.html

Guidelines:

  - Count all words in the text.  A word is any sequence of
    characters delimited by white space, whether or not it is an
    actual English word.

  - Count all syllables in each word.  To make this simple, use
    the following rules.  Each group of adjacent
    vowels (a,e,i,o,u,y) counts as one syllable (for example, the
    \"ea\" in \"real\" contributes one syllable, but the \"e..a\"
    in \"regal\" count as two syllables).  However, an \"e\" at
    the end of a word doesn't count as a syllable.  For example,
    the word \"eagle\" would be one syllable by Flesch's rules.
    However, the word \"intrigue\" is three syllables (since the
    e is preceded by a vowel).  Also, each word has at least one
    syllable, even if the previous rules give a count of zero.

  - Count all sentences.  A sentence is ended by a period, colon,
    semicolon, questions mark, or exclamation mark.

  - The index is computed by:

    index = 206.835  - (1.015 * words / sentences) - (84.6 * syllables / words)

  - Index should be rounded to the nearest integer.

The index is a number, usually between 0 and 100, indicating how
difficult the text is to read."
  (interactive)
  (cl-labels ((count-words (beg end)
                           (how-many "\\w+" beg end))
              (count-sentences (beg end)
                               (how-many "[\.\:\;\?\!]\\W" beg end))
              ;; (count-sentences (beg end)
              ;;                  (save-excursion
              ;;                    (let ((count 0))
              ;;                      (goto-char beg)
              ;;                      (while (< (point) end)
              ;;                        (forward-sentence 1)
              ;;                        (setq count (1+ count))))))
              (count-syllables (beg end)
                               (let ((letter-regexp "[A-Za-z]")
                                     (vowel-regexp "[AEIOUYaeiouy]")
                                     (e-end-regexp "[Ee]\\W"))
                                 (save-excursion
                                   (let ((count 0))
                                     (goto-char beg)
                                     (while (< (point) end)
                                       (while (and (< (point) end)
                                                   (not (looking-at letter-regexp)))
                                         (forward-char 1))
                                       (let ((state (if (looking-at vowel-regexp) 2 1)))
                                         (when (= state 2)
                                           (setq count (1+ count)))
                                         (while (looking-at letter-regexp)
                                           (if (and (= state 1)
                                                    (looking-at vowel-regexp)
                                                    (not (looking-at e-end-regexp)))
                                               (setq state 2
                                                     count (1+ count))
                                             (if (and (= state 2)
                                                      (not (looking-at vowel-regexp)))
                                                 (setq state 1)))
                                           (forward-char 1))))
                                     count)))))
    (let* ((beg (or beg (if (use-region-p) (region-beginning) (point-min))))
           (end (or end (if (use-region-p) (region-end) (point-max))))
           (words (count-words beg end))
           (sentences (count-sentences beg end))
           (syllables (count-syllables beg end))
           (index (round (- 206.835
                            (/ (* 1.015 words) (if (> sentences 0) sentences 1))
                            (/ (* 84.6 syllables) (if (> words 0) words 1)))))
           (index-desc
            (cond
             ((> index 90) "5th grader")
             ((> index 80) "6th grader")
             ((> index 70) "7th grader")
             ((> index 65) "8th grader")
             ((> index 60) "9th grader")
             ((> index 50) "High school student")
             ((> index 30) "College student")
             ((>= index 0) "College graduate")
             (t "Law school graduate"))))
      (message "Words: %s, Sentences: %s, Syllables %s, Flesch Readability Index: %s (%s)"
               words sentences syllables index index-desc)
      index)))
;; Flesch Readability Index:1 ends here

;; [[file:init-emacs.org::*Phone%20Number%20Words][Phone Number Words:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Programs: Phone Number Words
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Programs: Phone Number Words")

;; phone number to words
;; TODO: finish this
(defun phone-number-words (num &optional word-file)
  "Convert phone number NUM into word strings that may be used instead.
\nSingle digits may appear between words.
WORD-FILE defaults to `/usr/share/dict/words'."
  (interactive "sPhone number: ")
  (let ((word-file (or word-file "/usr/share/dict/words")))
    (defun file-to-string (file)
      (with-temp-buffer
        (insert-file-contents file)
        (buffer-string)))
    (defun string-to-list (string)
      (cl-loop for x across string collect x))
    (defun list-to-string (list)
      (mapconcat 'string list ""))
    ;;(setq word-file "~/tw")
    (unless (file-exists-p word-file)
      (error "Word file `%s' does not exist" word-file))
    ;; load word file
    (let* ((words (split-string (file-to-string word-file))) ; word list
           (word-hash (make-hash-table :size (length words))) ; number to word hash
           (letter-digit '((?A . ?2) (?B . ?2) (?C . ?2)
                           (?D . ?3) (?E . ?3) (?F . ?3)
                           (?G . ?4) (?H . ?4) (?I . ?4)
                           (?J . ?5) (?K . ?5) (?L . ?5)
                           (?M . ?6) (?N . ?6) (?O . ?6)
                           (?P . ?7) (?Q . ?7) (?R . ?7) (?S . ?7)
                           (?T . ?8) (?U . ?8) (?V . ?8)
                           (?W . ?9) (?X . ?9) (?Y . ?9) (?Z . ?9)))) ; letter to digit mappings
      ;; build word hash
      (dolist (word words)
        (let* ((letters (string-to-list (upcase word)))
               (number (list-to-string (mapcar (lambda (x) (char-to-string (cdr (assoc x letter-digit)))) letters))))
          ;;(message "letters: %S, number: %S" letters number)
          (setf (gethash number word-hash) word))))))
;; Phone Number Words:1 ends here

;; [[file:init-emacs.org::*Keyboard%20Cat%20Mode][Keyboard Cat Mode:1]]
;;------------------------------------------------------------------------------
;; Keyboard Cat Mode (buffer types out as you hit keyboard buttons)
;;
;; Author: http://www.reddit.com/user/zk_phi
;; Source: http://www.reddit.com/r/emacs/comments/1orlrr/anyone_familiar_with_something_like_this_for/ccuxj9w
;; Based on: https://github.com/natw/keyboard_cat.vim
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Programs: Keyboard Cat Mode")

(defvar keyboard-cat-overlay nil)

(defun keyboard-cat-next ()
  (interactive)
  (move-overlay keyboard-cat-overlay
                (goto-char (min (1+ (overlay-start keyboard-cat-overlay))
                                (point-max)))
                (overlay-end keyboard-cat-overlay)))

(defvar keyboard-cat-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map [remap self-insert-command] 'keyboard-cat-next)
    (define-key map [remap keyboard-quit] 'keyboard-cat-mode)
    map))

(define-minor-mode keyboard-cat-mode
  "Minor mode that slowly exposes current buffer as keys are pressed."
  :init nil
  :keymap keyboard-cat-mode-map
  (if keyboard-cat-mode
      (overlay-put
       (setq-local keyboard-cat-overlay
                   (make-overlay (point-min) (point-max)))
       'invisible t)
    (delete-overlay keyboard-cat-overlay)))
;; Keyboard Cat Mode:1 ends here

;; [[file:init-emacs.org::*Keyboard%20Display%20Mode][Keyboard Display Mode:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Programs: Keyboard Display Mode
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Programs: Keyboard Display Mode")

(defvar keyboard-display-process-name "gxmessage")

(defvar keyboard-display-key-log nil)

(defvar keyboard-display-key-log-width 0)

(defvar keyboard-display-key-log-size
  10
  "Maximum number of key presses to keep in the log.")

(defvar keyboard-display-key-log-duration
  5
  "Number of seconds to keep key presses in the key log.")

(defvar keyboard-display-message-duration
  5
  "Number of seconds to keep key press display showing.")

(defvar keyboard-display-last-key "")
(defvar keyboard-display-last-key-count 1)

(defun keyboard-display-key-press ()
  "Display current key press using gxmessage."
  (let ((key (concat (if current-prefix-arg
                         (concat current-prefix-arg " ")
                       "")
                     (symbol-name this-command))))
    (when keyboard-display-key-log
      (if (< (caar (reverse keyboard-display-key-log))
             (- (float-time (current-time)) keyboard-display-key-log-duration))
          (setq keyboard-display-key-log nil
                keyboard-display-key-log-width 0
                keyboard-display-last-key ""
                keyboard-display-last-key-count 1)
        (when (>= (length keyboard-display-key-log) keyboard-display-key-log-size)
          (pop keyboard-display-key-log))))
    (if (string= keyboard-display-last-key key)
        (setq key (concat key " x " (number-to-string (incf keyboard-display-last-key-count))))
      (setq keyboard-display-last-key key
            keyboard-display-last-key-count 1))
    (when (> (length key) keyboard-display-key-log-width)
      (setq keyboard-display-key-log-width (length key)))
    (setq key (substring (concat key (make-string keyboard-display-key-log-width ? ))
                         0 keyboard-display-key-log-width))
    (if (> keyboard-display-last-key-count 1)
        (setcdr (car (last keyboard-display-key-log)) key)
      (setq keyboard-display-key-log (append keyboard-display-key-log
                                             (list (cons (float-time (current-time)) key)))))
    (let ((msg (mapconcat (lambda (x) (cdr x)) keyboard-display-key-log "\n")))
      (start-process keyboard-display-process-name nil
                     "gxmessage" "-borderless" "-nofocus" "-center"
                     "-timeout" (int-to-string keyboard-display-message-duration)
                     "-buttons" "" "-fn" "mono 32" msg))))

(defvar keyboard-display-mode-map
  (let ((map (make-sparse-keymap)))
    map))

(define-minor-mode keyboard-display-mode
  "Minor mode that displays every key press in a pop-up message."
  :init nil
  :keymap keyboard-display-mode-map
  (if keyboard-display-mode
      (add-hook 'pre-command-hook #'keyboard-display-key-press)
    (remove-hook 'pre-command-hook 'keyboard-display-key-press)))
;; Keyboard Display Mode:1 ends here

;; [[file:init-emacs.org::*Star%20Wars%20Scroll][Star Wars Scroll:1]]
;;------------------------------------------------------------------------------
;; Star Wars Scroll (scroll current text buffer like Star Wars opening text)
;;
;; http://mbork.pl/2015-12-18_Star_Wars_crawl_in_Emacs
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Programs: Star Wars Scroll")

(defvar star-wars-scroll-substitution-list
  '(("." . 0)
    (" " . 0)
    ("[.,;:!?] " . 1)
    ("\\B[aeiou]\\B" . 0)
    ("\\B[bcdfghjklmnpqrstvwxyz]\\B" . 0)
    ("\\w\\b" . 0)
    ("[.,;:!?]" . 0)
    ("[^.,;:!?] " . 1)
    ("\\b\\w" . 0)
    (".$" . 0)
    ("^." . 0))
  "A list of dotted pairs with car equal to the regex matching
the character we want to delete and cdr equal to how many
characters we want to move the point forward before actually
deleting a character (useful in the case of space after a
punctuation).  We begin with the substitutions we want to perform
first.  If more than one regex matches, the last one is valid, so
it is probably a good idea to begin with \".\".")

(defun star-wars-scroll-center-line-no-tabs ()
  "A simplified version of center-line, using no tabs (and not
taking into account leading/trailing whitespace."
  (save-excursion
    (let ((length (progn (end-of-line)
                         (current-column))))
      (goto-char (line-beginning-position))
      (insert (make-string (max 0 (/ (- fill-column length) 2)) ?\s)))))

(defun star-wars-scroll-scroll-prepare-marker-list ()
  "Prepare (and return) a list of markers pointing at characters
to delete from the current line, in the \"right\" order."
  (save-excursion
    (let ((limit (progn
                   (star-wars-scroll-center-line-no-tabs) ; this may use tabs
                   (back-to-indentation)
                   (point)))
          (subst-list star-wars-scroll-substitution-list)
          (marker-list nil))
      (while subst-list
        (end-of-line)
        (while (search-backward-regexp (caar subst-list) limit t)
          (forward-char (cdar subst-list))
          (push (point-marker) marker-list))
        (setq subst-list (cdr subst-list)))
      (delete-dups marker-list)
      (setq marker-list (nreverse marker-list)))))

(defvar star-wars-scroll-untouched-lines 3
  "Number of lines at the bottom of the window which should not
be touched by character deletion.")

(defvar star-wars-scroll-delay .5
  "Delay (in seconds) between frames of animation.")

(defun star-wars-scroll-scroll-current-buffer ()
  "Actually do SW-like scroll in the current buffer."
  (let (marker-list-list)
    (goto-char (point-min))
    (open-line (window-height))
    (goto-char (point-max))
    (move-beginning-of-line 0)
    (while (progn
             (push (star-wars-scroll-scroll-prepare-marker-list) marker-list-list)
             (> (point) (+ (point-min) (window-height))))
      (forward-line -1))
    (while (< (point-min) (point-max)) ; here the actual scroll begins
      (goto-char (point-min))
      (kill-line 1)
      (redisplay t)
      (sleep-for star-wars-scroll-delay)
      (let ((walker marker-list-list))
        (while (progn
                 (goto-char (or (caar walker) (point-min)))
                 (and walker (< (line-number-at-pos) (- (window-height) star-wars-scroll-untouched-lines))))
          (when (car walker)
            (goto-char (caar walker))
            (delete-char 1)
            (setf (car walker) (cdar walker)))
          (when (car walker)
            (goto-char (caar walker))
            (delete-char 1)
            (setf (car walker) (cdar walker))
            (goto-char (line-beginning-position))
            (insert " "))
          (setq walker (cdr walker)))))))

(defun star-wars-scroll ()
  "Do Star-Wars-like scroll of the region, or the whole buffer if
  no region is active, in a temporary buffer, and delete it
  afterwards.  Special care is taken to make the lines more or
  less legible as long as possible, for example spaces after
  punctuation are deleted before vowels, vowels are deleted
  before consonants etc."
  (interactive)
  (save-excursion
    (let ((begin (point-min)) (end (point-max)))
      (when (region-active-p)
        (setq begin (region-beginning))
        (setq end (region-end)))
      (copy-region-as-kill begin end)
      (with-temp-buffer
        (switch-to-buffer (current-buffer))
        (rename-buffer "*Star Wars Scroll*")
        (buffer-disable-undo (current-buffer))
        (untabify (point-min) (point-max))
        (save-window-excursion
          (delete-other-windows)
          (yank)
          (star-wars-scroll-scroll-current-buffer))))))
;; Star Wars Scroll:1 ends here

;; [[file:init-emacs.org::*Games][Games:1]]
;;------------------------------------------------------------------------------
;;; Functions: Games
;;------------------------------------------------------------------------------

(init-message 2 "Functions: Games")
;; Games:1 ends here

;; [[file:init-emacs.org::*Towers%20of%20Hanoi][Towers of Hanoi:1]]
;;------------------------------------------------------------------------------
;;;; Functions: Games: Towers of Hanoi
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Games: Towers of Hanoi")

;; towers of hanoi solution
(defun towers (n)
  "Solve the clasical Towers of Hanoi problem for N levels."
  (interactive "NNumber of disks: ")
  (let ((buffer "*Towers*"))
    ;; setup buffer
    (get-buffer-create buffer)
    (set-buffer buffer)
    (setq buffer-read-only nil)
    (erase-buffer)
    ;; print header
    (insert (format "Towers of Hanio puzzle with %d disks" n))
    (newline)
    (newline)
    ;; make initial call to towers move
    ;; move from peg 1 to 3 using 2
    (towers-move n 1 3 2)
    ;; set buffer to read-only
    (setq buffer-read-only t)
    ;; switch to buffer
    (switch-to-buffer buffer)
    (goto-char (point-min)))
  ;; no return value
  (values))

;; towers of hanoi function to handle a move
(defun towers-move (n from to using)
  "Make one Towers of Hanoi move.
\nN is the number of disks to move.
FROM is the source peg.
TO is the target peg.
USING is the remaining peg."
  (when (> n 0)
    ;; in order to move N disks FROM one peg TO another, we first move N-1
    ;; disks FROM one peg to a USING peg
    (towers-move (1- n) from using to)
    ;; then we move the one remaining peg FROM the starting peg TO the
    ;; finishing peg
    (insert (format "move %d --> %d" from to))
    (newline)
    ;; finally we move the N-1 disks now on the USING peg to the TO peg using
    ;; FROM
    (towers-move (1- n) using to from)))
;; Towers of Hanoi:1 ends here

;; [[file:init-emacs.org::*Package%20Manager][Package Manager:1]]
;;==============================================================================
;;; Package Manager
;;==============================================================================

(init-message 1 "Package Manager")
;; Package Manager:1 ends here

;; [[file:init-emacs.org::*ELPA%20(Emacs%20Lisp%20Package%20Archive)][ELPA (Emacs Lisp Package Archive):1]]
;;------------------------------------------------------------------------------
;;; Package Manager: ELPA (Emacs Lisp Package Archive)
;;------------------------------------------------------------------------------

(init-message 2 "Package Manager: ELPA (Emacs Lisp Package Archive)")

;; elpa (emacs lisp package archive)
(defconst emacs-package-dir
  (expand-file-name "elpa" emacs-home-dir)
  "ELPA (Emacs Lisp Package Archive) packages directory.")
(add-to-list 'load-path emacs-package-dir t)

;; if package is not installed, install it
(unless (require-if-available 'package)
  (let ((buffer (url-retrieve-synchronously "http://tromey.com/elpa/package-install.el")))
    (with-current-buffer buffer
      (goto-char (point-min))
      (re-search-forward "^$" nil 'move)
      (eval-region (point) (point-max))
      (kill-buffer (current-buffer))))
  ;; remove code that gets added to ~/.emacs.d/init.el
  (let ((buffer (find-file-noselect (expand-file-name "~/.emacs.d/init.el"))))
    (with-current-buffer buffer
      (when (re-search-forward ";;; init.el ends here" nil t)
        (goto-char (line-beginning-position))
        (forward-line 2)
        (kill-region (point) (point-max))
        (save-buffer)
        (kill-buffer (current-buffer))))))

;; initialize package system
(require 'package)
(setq package-enable-at-startup nil
      package-archives '(
                         ("org" . "http://orgmode.org/elpa/")
                         ("gnu" . "http://elpa.gnu.org/packages/")
                         ("melpa" . "http://melpa.org/packages/"))
      package-user-dir emacs-package-dir)
(package-initialize)

;; refresh package archive contents if empty
(when (not package-archive-contents)
  (package-refresh-contents))

;; install `use-package' to load packages
(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))
;; install `diminish' to diminish package names on the mode-line in use-package blocks
(unless (package-installed-p 'diminish)
  (package-install 'diminish))
;; install `bind-key' to help with binding keys in use-package blocks
(unless (package-installed-p 'bind-key)
  (package-install 'bind-key))
;; require above packages
(eval-when-compile
  (require 'use-package)
  (setq use-package-verbose t))         ; verbose reporting
(require 'diminish)
(require 'bind-key)
;; ELPA (Emacs Lisp Package Archive):1 ends here

;; [[file:init-emacs.org::*Paradox][Paradox:1]]
;;------------------------------------------------------------------------------
;;; Package Manager: Paradox
;;------------------------------------------------------------------------------

(init-message 2 "Package Manager: Paradox")

;; paradox package menu
(use-package paradox
  :ensure t
  :commands (paradox-enable)
  :config (paradox-enable))
;; Paradox:1 ends here

;; [[file:init-emacs.org::*General%20Settings][General Settings:1]]
;;==============================================================================
;;; General Settings
;;==============================================================================

(init-message 1 "General Settings")
;; General Settings:1 ends here

;; [[file:init-emacs.org::*Mode%20Line][Mode Line:1]]
;;------------------------------------------------------------------------------
;;; General Settings: Mode Line
;;------------------------------------------------------------------------------

(init-message 2 "General Settings: Mode Line")
;; Mode Line:1 ends here

;; [[file:init-emacs.org::*Mode%20Line][Mode Line:2]]
;; turn on date and time in mode line
(setq display-time-day-and-date t)
(if (< emacs-major-version 26)
    (setq display-time-string-forms
          '(" " (format-time-string "%a %Y-%m-%d %H:%M") " "))
  (setq display-time-string-forms
        '(" " (format-time-string "%a %Y-%m-%d %H:%M" nil (current-time-zone)) " ")))
(display-time-mode 1)
;; ;; right-align date and time
;; (display-time-mode 0)
;; (setq global-mode-string (remove 'display-time-string global-mode-string))
;; (setq mode-line-end-spaces
;;       (list (propertize " " 'display '(space :align-to (- right 12)))
;;             'display-time-string))
;; Mode Line:2 ends here

;; [[file:init-emacs.org::*Mode%20Line][Mode Line:3]]
;; show line number in mode line
(line-number-mode 1)
;; Mode Line:3 ends here

;; [[file:init-emacs.org::*Mode%20Line][Mode Line:4]]
;; show column number in mode line
(column-number-mode 1)
;; Mode Line:4 ends here

;; [[file:init-emacs.org::*Mode%20Line][Mode Line:5]]
;; set `mode-line-format'
(setq mode-line-format
      '("%e"
        mode-line-front-space
        #("-" 0 1 (help-echo "mouse-1: select (drag to resize), mouse-2 = C-x 1, mouse-3 = C-x 0"))
        mode-line-mule-info             ; coding system, eol style, read-only status
        mode-line-modified              ; buffer modified status
        mode-line-frame-identification  ; frame name
        mode-line-buffer-identification ; buffer name
        #("  " 0 2 (help-echo "mouse-1: select (drag to resize), mouse-2 = C-x 1, mouse-3 = C-x 0"))
        mode-line-position              ; position in buffer as a percentage, line number, column number
        ;; #(" w:" 0 3 (help-echo "mouse-1: select (drag to resize), mouse-2 = C-x 1, mouse-3 = C-x 0"))
        ;; (count-words-paragraph count-words-paragraph) ; words in current paragraph
        mode-line-projectile            ; project information
        (vc-mode vc-mode)               ; version control information
        #("  " 0 2 (help-echo "mouse-1: select (drag to resize), mouse-2 = C-x 1, mouse-3 = C-x 0"))
        mode-line-modes                 ; major and minor modes
        ;; (which-func-mode
        ;;  ("" which-func-format
        ;;   #("--" 0 2 (help-echo "mouse-1: select (drag to resize), mouse-2 = C-x 1, mouse-3 = C-x 0"))))
        ;; (global-mode-string
        ;;  (#("--" 0 2 (help-echo "mouse-1: select (drag to resize), mouse-2 = C-x 1, mouse-3 = C-x 0"))
        ;;   global-mode-string))
        (global-mode-string
         (#(" " 0 1 (help-echo "mouse-1: select (drag to resize), mouse-2 = C-x 1, mouse-3 = C-x 0"))
          global-mode-string))          ; day, date, time
        #("-%-" 0 3 (help-echo "mouse-1: select (drag to resize), mouse-2 = C-x 1, mouse-3 = C-x 0"))
        mode-line-end-spaces))
(set-default 'mode-line-format mode-line-format)
;; Mode Line:5 ends here

;; [[file:init-emacs.org::*Mode%20Line][Mode Line:6]]
;; set mode line for `projectile-mode'
(defvar mode-line-projectile
  '(:eval (when (ignore-errors (projectile-project-root))
            (concat " " (projectile-project-name))))
  "Mode line format for `projectile'.")
(put 'mode-line-projectile 'risky-local-variable t)
;; Mode Line:6 ends here

;; [[file:init-emacs.org::*Mode%20Line][Mode Line:7]]
;; set mode line for `vc-mode'
;; strip backend name from the version control status information
(defvar mode-line-vc-mode
  '(" " (:eval (let ((backend (symbol-name (vc-backend (or (buffer-file-name) (buffer-name))))))
                 (substring vc-mode (+ (length backend) 2)))))
  "Mode line format for `vc-mode'.")
(put 'mode-line-vc-mode 'risky-local-variable t)
;; Mode Line:7 ends here

;; [[file:init-emacs.org::*Mode%20Line][Mode Line:8]]
;; set `mode-line-modes'
(setq mode-line-modes
      '((#("%[(" 0 3 (help-echo "mouse-1: select (drag to resize), mouse-2 = C-x 1, mouse-3 = C-x 0"))
         (:propertize
          ("" mode-name)
          help-echo "mouse-1: major mode, mouse-2: major mode help, mouse-3: toggle minor modes"
          mouse-face mode-line-highlight local-map
          (keymap
           (mode-line keymap
                      (down-mouse-3 . mode-line-mode-menu-1)
                      (mouse-2 . describe-mode)
                      (down-mouse-1 . mouse-major-mode-menu))))
         ("" mode-line-process)
         (:propertize
          ("" minor-mode-alist)
          mouse-face mode-line-highlight
          help-echo "mouse-2: minor mode help, mouse-3: toggle minor modes"
          local-map
          (keymap
           (header-line keymap
                        (down-mouse-3 . mode-line-mode-menu-1))
           (mode-line keymap
                      (down-mouse-3 . mode-line-mode-menu-1)
                      (mouse-2 . mode-line-minor-mode-help))))
         #("%n" 0 2
           (help-echo "mouse-2: widen" mouse-face mode-line-highlight local-map
                      (keymap
                       (mode-line keymap
                                  (mouse-2 . mode-line-widen)))))
         #(")%]" 0 3
           (help-echo "mouse-1: select (drag to resize), mouse-2 = C-x 1, mouse-3 = C-x 0")))))
(set-default 'mode-line-modes mode-line-modes)

;; (setcar (last (car mode-line-modes))
;;         '#(")%]" 0 3 (help-echo "mouse-1: select (drag to resize), mouse-2 = C-x 1, mouse-3 = C-x 0")))
;; Mode Line:8 ends here

;; [[file:init-emacs.org::*Calendar%20and%20Diary][Calendar and Diary:1]]
;;------------------------------------------------------------------------------
;;; General Settings: Calendar and Diary
;;------------------------------------------------------------------------------

(init-message 2 "General Settings: Calendar and Diary")
;; Calendar and Diary:1 ends here

;; [[file:init-emacs.org::*Calendar%20and%20Diary][Calendar and Diary:2]]
;; turn off diary entries view when calendar is run
(setq calendar-view-diary-initially-flag nil)
;; Calendar and Diary:2 ends here

;; [[file:init-emacs.org::*GUI][GUI:1]]
;;------------------------------------------------------------------------------
;;; General Settings: GUI
;;------------------------------------------------------------------------------

(when window-system

  (init-message 2 "General Settings: GUI")

  ;; clipboard
  (setq select-enable-clipboard t                                    ; cutting and pasting uses clipboard
        select-enable-primary t                                      ; cutting and pasting uses primary selection
        x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING) ; data-type request for X selection
        save-interprogram-paste-before-kill t                          ; save clipboard strings into kill ring before replacing them
        interprogram-paste-function 'x-cut-buffer-or-selection-value   ; function to call to get text cut from other programs
        mouse-yank-at-point t)                                         ; mouse yank commands yank at point

  ;; inverse video on
  (setq inverse-video t)

  ;; turn off bell
  (setq ring-bell-function 'ignore)

  ;; turn off cursor blinking
  (blink-cursor-mode 0)

  ;; ;; scroll bar on right
  ;; (setq scroll-bar-mode 'right)
  ;; (scroll-bar-mode -1)
  ;; (scroll-bar-mode 1)

  ;; turn off scroll bar
  (when (and (fboundp 'scroll-bar-mode)
             scroll-bar-mode)
    (scroll-bar-mode -1))

  ;; turn off toolbar
  (when (and (fboundp 'tool-bar-mode)
             tool-bar-mode)
    (tool-bar-mode -1))

  ;; visible bell
  (setq visible-bell t)

  ;; make default frame size fullscreen
  (add-to-list 'default-frame-alist '(fullscreen . maximized))

  ;; put current buffer name in title bar
  (setq frame-title-format "%b")

  ;; mouse button one drags the scroll bar
  (global-set-key [vertical-scroll-bar down-mouse-1] 'scroll-bar-drag)

  ;; scroll mouse settings
  (setq mouse-wheel-scroll-amount '(1 ((shift) . 1))
        mouse-wheel-progressive-speed t)

  ;; ;; font
  ;; (set-frame-font "-Misc-Fixed-Normal-R-Normal--15-140-75-75-C-90-ISO8859-1")
  ;; ;;(set-frame-font "-Misc-Fixed-Bold-R-Normal--15-140-75-75-C-90-ISO8859-1")
  ;; ;;(set-frame-font "-Misc-Fixed-Bold-R-Normal--15-140-75-75-C-90-UTF-8")
  ;; ;;(set-frame-font "-outline-Bitstream Vera Sans Mono-normal-r-normal-normal-12-90-96-96-c-*-iso8859-1")

  ;; faces
  ;; green foreground on black background with green cursor
  (custom-set-faces
   '(default ((t (:foreground "green" :background "black"))))
   '(cursor ((t (:background "green"))))
   '(org-block ((t (:inherit shadow :foreground "green"))))
   '(org-level-1 ((t (:foreground "orange"))))
   '(org-level-2 ((t (:foreground "deep sky blue"))))
   '(org-level-3 ((t (:foreground "yellow green"))))
   '(org-level-4 ((t (:foreground "salmon"))))
   '(org-level-5 ((t (:foreground "orchid"))))
   '(org-level-6 ((t (:foreground "cyan"))))
   '(org-level-7 ((t (:foreground "spring green"))))
   '(org-level-8 ((t (:foreground "tomato")))))

  ;; flatland theme
  ;; https://github.com/gchp/flatland-emacs
  (use-package flatland-theme
    :ensure t
    :init (load-theme 'flatland t)))
;; GUI:1 ends here

;; [[file:init-emacs.org::*Modes][Modes:1]]
;;==============================================================================
;;; Modes
;;==============================================================================

(init-message 1 "Modes")
;; Modes:1 ends here

;; [[file:init-emacs.org::*Setup][Setup:1]]
;;------------------------------------------------------------------------------
;;; Modes: Setup
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Setup")

;; turn off electric mode for all cc modes
(setq-default c-electric-flag nil)
;; Setup:1 ends here

;; [[file:init-emacs.org::*Brainfuck%20Mode][Brainfuck Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Brainfuck Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Brainfuck Mode")

;; brainfuck-mode
(use-package brainfuck-mode
  :ensure t
  :mode ("\\.bf\\'" . brainfuck-mode))
;; Brainfuck Mode:1 ends here

;; [[file:init-emacs.org::*BASIC%20Mode][BASIC Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: BASIC Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: BASIC Mode")

;; basic-mode
(use-package basic
  :mode ("\\.bas\\'" . basic-mode))
;; BASIC Mode:1 ends here

;; [[file:init-emacs.org::*C%20Mode][C Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: C Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: C Mode")

;; c-mode
(use-package cc-mode
  :ensure t
  :after (flyspell eldoc)
  :mode (("\\.c\\'" . c-mode)
         ("\\.h\\'" . c-mode)
         ("\\.ice\\'" . c-mode)
         ("\\.cpp\\'" . c++-mode)
         ("\\.hpp\\'" . c++-mode)
         ("\\.c++\\'" . c++-mode)
         ("\\.h++\\'" . c++-mode))
  :commands (c-skip-comments-and-strings)
  :config (progn
            ;; c style
            (defconst local-c-style
              '((c-tab-always-indent . 'complete)
                (c-basic-offset . 4)
                (c-comment-only-line-offset . 0)
                (c-hanging-braces-alist . ((substatement-open after)
                                           (brace-list-open)))
                (c-hanging-colons-alist . ((member-init-intro before)
                                           (inher-intro)
                                           (case-label after)
                                           (label after)
                                           (access-label after)))
                (c-cleanup-list . (scope-operator
                                   empty-defun-braces
                                   defun-close-semi))
                (c-offsets-alist . ((arglist-close . c-lineup-arglist)
                                    (substatement-open . 0)
                                    (substatement-label . 0)
                                    (label . 0)
                                    (case-label . +)
                                    (block-open . 0)
                                    (defun-block-intro . +)
                                    (statement-block-intro . +)
                                    (substatement . +)
                                    (knr-argdecl-intro . -)
                                    (inline-open . 0)
                                    (defun-block-intro . 4)))
                (c-echo-syntactic-information-p . nil)))

            ;; customizations for c-mode, c++-mode, objc-mode, java-mode, and idl-mode
            (defun local-c-mode-common-hook ()
              ;; add my personal style and set it for the current buffer
              (c-add-style "local" local-c-style t)
              ;;(c-set-style 'stroustrup)

              ;; electric indention turned off
              (when (fboundp 'c-toggle-electric-state) (c-toggle-electric-state -1))

              ;; auto-newline and hungry-delete turned off
              (when (fboundp 'c-toggle-auto-hungry-state) (c-toggle-auto-hungry-state -1))

              ;; ;; keybindings for all supported languages
              ;; ;; can put these in c-mode-base-map because c-mode-map, c++-mode-map,
              ;; ;; objc-mode-map, java-mode-map, and idl-mode-map inherit from it
              ;; (define-key c-mode-base-map (kbd "C-<return>") 'newline-and-indent)
              ;; (define-key c-mode-base-map (kbd "C-c c") 'mode-compile)
              ;; (define-key c-mode-base-map (kbd "C-c k") 'mode-compile-kill)
              ;; (define-key c-mode-base-map (kbd "<f7>") 'mode-compile)

              ;; ;; hide/show mode and keys
              ;; (define-key c-mode-base-map (kbd "C-c <right>") 'hs-show-block)
              ;; (define-key c-mode-base-map (kbd "C-c <left>") 'hs-hide-block)
              ;; (define-key c-mode-base-map (kbd "C-c <up>") 'hs-hide-all)
              ;; (define-key c-mode-base-map (kbd "C-c <down>") 'hs-show-all)
              ;; (hs-minor-mode 1)

              ;; ;; toggle between header files and code files
              ;; (define-key c-mode-base-map (kbd "C-c o") 'ff-find-other-file)

              ;; set default fill column for auto-fill mode and fill-paragraph
              (setq fill-column 78)

              ;; turn on auto-fill
              ;;(turn-on-auto-fill)

              ;; ;; turn off auto newlines
              ;; (setq c-auto-newline nil)

              ;; turn on flyspell
              (flyspell-prog-mode)

              ;; initialize eldoc
              (eldoc-mode 1)

              ;; compilation settings
              (setq compile-command "make -k"
                    compilation-window-height 10
                    compilation-ask-about-save nil
                    ;;compilation-scroll-output t
                    )

              ;; (defun compile-internal--scroll ()
              ;;   "Forces compile buffer to scroll."
              ;;   (let* ((ob (current-buffer))
              ;;          (obw (get-buffer-window ob t))
              ;;          win)
              ;;     (save-excursion
              ;;       (unless (and (setq win (get-buffer-window ad-return-value t))
              ;;                    obw)
              ;;         (select-window win)
              ;;         (goto-char (point-max))
              ;;         (select-window obw)))))
              ;; ;; advise `compile-internal'
              ;; (advice-add 'compile-internal :after #'compile-internal--scroll)

              ;; turn on else minor mode
              ;;(else-mode)
              )
            (add-hook 'c-mode-common-hook #'local-c-mode-common-hook)

            ;; remove trailing blanks
            ;;(add-hook 'c-mode-hook #'install-remove-trailing-blanks)
            ;;(add-hook 'c++-mode-hook #'install-remove-trailing-blanks)
            ;;(add-hook 'c-mode-common-hook #'install-remove-trailing-blanks)

            ;; remove tabs
            ;;(add-hook 'c-mode-hook #'install-remove-tabs)
            ;;(add-hook 'c++-mode-hook #'install-remove-tabs)
            ;;(add-hook 'c-mode-common-hook #'install-remove-tabs)
            ))
;; C Mode:1 ends here

;; [[file:init-emacs.org::*Calendar%20Mode][Calendar Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Calendar Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Calendar Mode")

(use-package calendar
  :ensure t
  :bind* ("C-x c" . calendar)           ; defaults to undefined
  :config (progn
            ;; calendar hook
            (defun local-calendar-load-hook ()
              ;; star current date
              (setq calendar-today-visible-hook 'calendar-star-date)
              ;; star today's date
              (setq calendar-today-visible-hook 'calendar-mark-today)
              ;; mark holidays
              (setq calendar-mark-holidays-flag t)
              ;; keybindings
              (bind-keys :map calendar-mode-map
                         ;; scrolling keys
                         (">" . calendar-scroll-left)
                         ("<" . calendar-scroll-right)
                         ("C-x >" . calendar-scroll-left)
                         ("C-x <" . calendar-scroll-right)))
            (add-hook 'calendar-load-hook #'local-calendar-load-hook)))

;; calendar remind
(use-package calendar-remind
  :commands (calendar-remind-lookup
             calendar-remind-visit
             calendar-remind-visit-insert)
  :config (progn
            (defun local-calendar-remind-load-hook ()
              ;; keybindings
              (bind-keys :map calendar-mode-map
                         ;; remind lookup
                         ("<return>" . calendar-remind-lookup)
                         ("r" . calendar-remind-lookup)
                         ;;("SPC" . calendar-remind-lookup)
                         ;; remind visit
                         ("v" . calendar-remind-visit)
                         ("V" . calendar-remind-visit-insert)))
            (add-hook 'calendar-load-hook #'local-calendar-remind-load-hook)))
;; Calendar Mode:1 ends here

;; [[file:init-emacs.org::*Dired][Dired:1]]
;;------------------------------------------------------------------------------
;;; Modes: Dired
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Dired")

(use-package dired
  :after (dired-single)
  :commands (dired dired-next-line)
  :config (progn
            ;; only prompt once for recursive deletes
            (setq dired-recursive-deletes 'top)

            ;; dired hook for more settings
            (defun local-dired-mode-hook ()
              ;; ;; edit file names within dired
              ;; (define-key dired-mode-map (kbd "e") 'wdired-change-to-wdired-mode)

              ;; RET and mouse click use same buffer
              (when (fboundp 'dired-single-buffer)
                (define-key dired-mode-map (kbd "<return>") 'dired-single-buffer)
                (define-key dired-mode-map (kbd "^")
                  (lambda () (interactive) (dired-single-buffer ".."))))
              (when (fboundp 'joc-dired-single-buffer)
                (define-key dired-mode-map (kbd "<return>") 'joc-dired-single-buffer)
                (define-key dired-mode-map (kbd "^")
                  (lambda () (interactive) (joc-dired-single-buffer ".."))))
              (when (fboundp 'dired-single-buffer-mouse)
                (define-key dired-mode-map (kbd "<mouse-1>") 'dired-single-buffer-mouse))
              (when (fboundp 'joc-dired-single-buffer-mouse)
                (define-key dired-mode-map (kbd "<mouse-1>") 'joc-dired-single-buffer-mouse))
              ;; reset M-o
              (define-key dired-mode-map (kbd "M-o") 'other-window)
              (define-key dired-mode-map (kbd "C-c C-z f") 'browse-url-of-dired-file))

            ;; add hook to dired mode
            (add-hook 'dired-mode-hook #'local-dired-mode-hook)

            ;; goto first file
            (defun dired-back-to-top ()
              (interactive)
              (goto-char (point-min))
              (dired-next-line 4))
            (define-key dired-mode-map (vector 'remap 'beginning-of-buffer) 'dired-back-to-top)

            ;; goto last file
            (defun dired-jump-to-bottom ()
              (interactive)
              (goto-char (point-max))
              (dired-next-line -1))
            (define-key dired-mode-map (vector 'remap 'end-of-buffer) 'dired-jump-to-bottom)))

;;------------------------------------------------------------------------------
;;;; dired-single
;;------------------------------------------------------------------------------

(init-message 3 "dired-single")

;; dired-single (make dired use a single buffer)
(use-package dired-single
  :ensure t)

;;------------------------------------------------------------------------------
;;;; dired-details
;;------------------------------------------------------------------------------

(init-message 3 "dired-details")

;; dired-details (make file details hide-able in dired)
(use-package dired-details
  :disabled t
  :ensure t
  :config (progn
            (setq-default dired-details-hidden-string "... ")
            (dired-details-install)))
;; Dired:1 ends here

;; [[file:init-emacs.org::*Ediff%20Mode][Ediff Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Ediff Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Ediff Mode")

;; ediff-mode
(use-package ediff
  :ensure t
  :config (progn
            ;; split windows horizontally
            (setq ediff-split-window-function 'split-window-horizontally)

            ;; only highlight current diff
            (setq-default ediff-highlight-all-diffs nil)

            ;; turn off whitespace checking
            (setq ediff-diff-options "-w")

            ;; place control window in same frame
            (setq ediff-window-setup-function 'ediff-setup-windows-plain)

            ;; place control window in separate frame
            ;;(setq ediff-window-setup-function 'ediff-setup-windows-multiframe)

            ;; highlight changes to characters rather than words
            ;;(setq ediff-forward-word-function 'forward-char)
            ))
;; Ediff Mode:1 ends here

;; [[file:init-emacs.org::*Erlang%20Mode][Erlang Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Erlang Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Erlang Mode")

;; erlang-mode
(use-package erlang
  :ensure t
  :after (flyspell)
  :mode ("\\.erl\\'" . erlang-mode)
  :interpreter ("erlang" . erlang-mode)
  :commands (erlang-start)
  ;;:load-path "/usr/lib/erlang/lib/tools-2.5.4/emacs/"
  :init (progn
          (add-to-list 'exec-path "/usr/lib/erlang/bin" t)
          (setq erlang-root-dir "/usr/lib/erlang"
                erlang-electric-commands nil))
  :config (progn
            ;; erlang hook
            (defun local-erlang-hook ()
              ;; turn on flyspell
              (flyspell-prog-mode))
            (add-hook 'erlang-hook #'local-erlang-hook)

            ;; remove trailing blanks
            ;;(add-hook 'erlang-mode-hook #'install-remove-trailing-blanks)

            ;; remove tabs
            ;;(add-hook 'erlang-mode-hook #'install-remove-tabs)
            ))
;; Erlang Mode:1 ends here

;; [[file:init-emacs.org::*Flymake%20Cursor][Flymake Cursor:1]]
;;------------------------------------------------------------------------------
;;; Modes: Flymake Cursor
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Flymake Cursor")

;; flymake-cursor
;; flymake-mode has been replace by flymake-cursor
;; flymake-cursor will cause errors and warnings to appear in the minibuffer
(use-package flymake-cursor
  :ensure t)
;; Flymake Cursor:1 ends here

;; [[file:init-emacs.org::*Fundamental%20Mode][Fundamental Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Fundamental Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Fundamental Mode")

;; fundamental-mode

;; remove trailing blanks
;;(add-hook 'fundamental-mode-hook #'install-remove-trailing-blanks)

;; remove tabs
;;(add-hook 'fundamental-mode-hook #'install-remove-tabs)
;; Fundamental Mode:1 ends here

;; [[file:init-emacs.org::*Geiser%20Mode%20(Racket%20Scheme%20Mode)][Geiser Mode (Racket Scheme Mode):1]]
;;------------------------------------------------------------------------------
;;; Modes: Geiser Mode (Racket Scheme Mode)
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Geiser Mode (Racket Scheme Mode)")

;; geiser-mode
(use-package geiser
  :ensure t
  :commands (geiser-mode
             run-geiser
             run-gracket
             run-racket)
  :init (progn
          ;; set default scheme program to racket
          ;;(setq scheme-program-name "racket")
          ;; set default scheme mode to geiser-mode
          ;;(add-hook 'scheme-mode-hook #'geiser-mode)
          )
  :config (progn
            ;; set default geiser implementation to racket
            (setq geiser-default-implementation 'racket)
            ;; set active implementations list to just racket
            (setq geiser-active-implementations '(racket))

            ;; define `insert-char' functions to insert unicode chars
            (defun geiser-insert-sigma ()
              "Insert ∑ character."
              (interactive "*")
              ;;(insert-char ?Σ))
              (insert-char ?∑))

            ;; geiser hook
            (defun local-geiser-mode-hook ()
              ;; keybindings
              (local-set-key (kbd "C-c \\") 'geiser-insert-lambda)
              (local-set-key (kbd "C-c C-\\") 'geiser-insert-lambda)
              (local-set-key (kbd "C-c s") 'geiser-insert-sigma)
              (local-set-key (kbd "C-c C-s") 'geiser-insert-sigma))
            (add-hook 'geiser-mode-hook #'local-geiser-mode-hook)
            (add-hook 'geiser-repl-mode-hook #'local-geiser-mode-hook)))
;; Geiser Mode (Racket Scheme Mode):1 ends here

;; [[file:init-emacs.org::*GNU%20Plot%20Mode][GNU Plot Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: GNU Plot Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: GNU Plot Mode")

;; gnuplot-mode
(use-package gnuplot
  :ensure t
  :mode ("\\.gp\\'" . gnuplot-mode)
  :commands (gnuplot-mode gnuplot-make-buffer gnuplot-send-string-to-gnuplot))
;; GNU Plot Mode:1 ends here

;; [[file:init-emacs.org::*+Go%20Mode+][+Go Mode+:1]]
;; ;;------------------------------------------------------------------------------
;; ;;; Modes: Go Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: Go Mode")

;; ;; go-mode
;; (use-package go-mode
;;   :disabled t
;;   :ensure t
;;   :mode (("\\.go$" . go-mode))
;;   :config (progn
;;             ;; go hook
;;             (defun local-go-mode-hook ()
;;               ;; use goimports instead of gofmt
;;               (setq gofmt-command "goimports")

;;               ;; call gofmt before saving
;;               (add-hook 'before-save-hook #'gofmt-before-save)

;;               ;; customize compile command to run go build
;;               (when (not (string-match "go" compile-command))
;;                 (setq-local compile-command "go build -v && go test -v && go vet"))

;;               ;; oracle
;;               (load-file "${GOPATH}/src/golang.org/x/tools/cmd/oracle/oracle.el")

;;               ;; keybindings
;;               (local-set-key (kbd "M-.") 'godef-jump))
;;             (add-hook 'go-mode-hook #'local-go-mode-hook)))
;; +Go Mode+:1 ends here

;; [[file:init-emacs.org::*Javascript:%20js2%20Mode][Javascript: js2 Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Javascript: js2 Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Javascript: js2 Mode")

;; js2-mode
(use-package js2-mode
  :ensure t
  :mode (("\\.js\\#'" . js2-mode)
         ("\\.gradle\\'" . js-mode))    ; use js-mode for gradle files
  :interpreter ("node" . js2-mode)
  :config (progn
            ;; turn on auto indent
            (setq js2-auto-indent-p t
                  js2-cleanup-whitespace t
                  js2-enter-indents-newline t
                  js2-indent-on-enter-key t
                  js2-bounce-indent-p nil
                  js2-mirror-mode nil
                  js2-mode-escape-quotes nil)
                  ;;js2-electric-keys (quote nil))

            ;; ;; ac-js2 (auto-complete source for js2-mode)
            ;; (use-package ac-js2
            ;;   :config (add-hook 'js2-mode-hook #'ac-js2-mode))
            ))

;;------------------------------------------------------------------------------
;;;; js-comint
;;------------------------------------------------------------------------------

(init-message 3 "js-comint")

;; js-comint (javascript interpreter in window)
(use-package js-comint
  :ensure t
  :after (js2-mode)
  :commands (js-send-buffer
             js-send-buffer-and-go
             js-send-last-sexp
             js-send-last-sexp-and-go
             js-load-file-and-go)
  :config (progn
            ;;(setq inferior-js-program-command "/usr/bin/java org.mozilla.javascript.tools.shell.Main")
            ;;(setq inferior-js-program-command "/usr/bin/rhino")

            ;; keybindings
            (bind-keys :map js2-mode-map
                       ("C-c C-c" . js-eval-sexp-and-go)
                       ("C-x C-e" . js-send-last-sexp)
                       ("C-M-x" . js-eval-sexp-and-go)
                       ("C-c b" . js-send-buffer)
                       ("C-c C-b" . js-send-buffer-and-go)
                       ("C-c C-k" . js-send-buffer-and-go)
                       ("C-c l" . js-load-file-and-go))

            ;; evaluate current sexp
            (defun js-eval-sexp ()
              "js-comint evaluate current sexp."
              (interactive)
              (save-excursion
                (end-of-defun)
                (js-send-last-sexp)))

            ;; evaluate current sexp and switch to js buffer
            (defun js-eval-sexp-and-go ()
              "js-comint evaluate current sexp and switch to js buffer."
              (interactive)
              (save-excursion
                (end-of-defun)
                (js-send-last-sexp-and-go)))

            ;; js2 mode hook
            (defun local-js2-mode-hook ()
              ;; (local-set-key (kbd "C-c C-c") 'js-eval-sexp-and-go)
              ;; (local-set-key (kbd "C-x C-e") 'js-send-last-sexp)
              ;; (local-set-key (kbd "C-M-x") 'js-eval-sexp-and-go)
              ;; (local-set-key (kbd "C-c b") 'js-send-buffer)
              ;; (local-set-key (kbd "C-c C-b") 'js-send-buffer-and-go)
              ;; (local-set-key (kbd "C-c C-k") 'js-send-buffer-and-go)
              ;; (local-set-key (kbd "C-c l") 'js-load-file-and-go)
              ;; disable skewer-mode as it uses similar key bindings
              (when (fboundp 'skewer-mode)
                (skewer-mode -1)))
            (add-hook 'js2-mode-hook #'local-js2-mode-hook)))
;; Javascript: js2 Mode:1 ends here

;; [[file:init-emacs.org::*Kotlin%20Mode][Kotlin Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Kotlin Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Kotlin Mode")

;; kotlin-mode
(use-package kotlin-mode
  :ensure t
  :mode (("\\.kt$" . kotlin-mode)
         ("\\.kts$" . kotlin-mode))
  :commands (java-mode
             kotlin-mode--syntax-propertize-function)
  :functions (kotlin-send-buffer)
  :config (progn
            ;; add style for kotlin-mode
            (add-to-list 'c-default-style '(kotlin-mode . "java"))

            ;; redefine kotlin-mode so that indentation works
            ;; base it off of `java-mode'
            (define-derived-mode kotlin-mode java-mode "Kotlin"
              "Major mode for editing Kotlin."

              (setq font-lock-defaults '((kotlin-mode--font-lock-keywords) nil nil))
              (setq-local syntax-propertize-function #'kotlin-mode--syntax-propertize-function)
              (set (make-local-variable 'comment-start) "//")
              (set (make-local-variable 'comment-padding) 1)
              (set (make-local-variable 'comment-start-skip) "\\(//+\\|/\\*+\\)\\s *")
              (set (make-local-variable 'comment-end) "")
              (set (make-local-variable 'c-comment-start-regexp) "//")
              (set (make-local-variable 'c-block-comment-start-regexp) "/\\*")
              (set (make-local-variable 'indent-line-function) 'kotlin-mode--indent-line)

              :group 'kotlin
              :syntax-table kotlin-mode-syntax-table)

            ;; redefine send region to remove comments before sending
            ;; (kotlinc REPL does not current support comments)
            (defun kotlin-send-region (start end)
              "Send current region to Kotlin interpreter."
              (interactive "r")
              (let ((buffer (current-buffer)))
                (with-temp-buffer
                  (insert-buffer-substring-no-properties buffer start end)
                  (java-remove-comments)
                  (comint-send-region kotlin-repl-buffer (point-min) (point-max))
                  (comint-send-string kotlin-repl-buffer "\n"))))

;;             ;; custom input sender that removes comments
;;             (defun kotlin-input-sender (proc string)
;;               "Custom `kotlin-mode' function for sending to PROC input STRING.
;; This removes comments from the input STRING then forwards the result to
;; `comint-simple-send'."
;;               (comint-simple-send proc (java-remove-comments string)))
;;             (set (make-local-variable 'comint-input-sender) '(kotlin-input-sender))

            ;; ;; redefine kotlin-repl to filter out comments (which are not currently supported by kotlinc)
            ;; (defun kotlin-repl ()
            ;;   "Launch a Kotlin REPL using `kotlin-command' as an inferior mode."
            ;;   (interactive)
            ;;   (unless (comint-check-proc kotlin-repl-buffer)
            ;;     (set-buffer
            ;;      (apply 'make-comint "KotlinREPL"
            ;;             "env"
            ;;             nil
            ;;             "NODE_NO_READLINE=1"
            ;;             kotlin-command
            ;;             kotlin-args-repl))
            ;;     (set (make-local-variable 'comint-preoutput-filter-functions)
            ;;          (list (lambda (string)
            ;;                  (replace-regexp-in-string "\x1b\\[.[GJK]" "" string))))
            ;;     (set (make-local-variable 'comint-input-filter-functions)
            ;;          '(java-remove-comments)))
            ;;   (pop-to-buffer kotlin-repl-buffer))

            ;; ;; modify `kotlin-send-region' so it sends one line at a time
            ;; (defun kotlin-send-region (beg end)
            ;;   "Send current region to Kotlin interpreter."
            ;;   (interactive "r")
            ;;   (save-excursion
            ;;     (goto-char beg)
            ;;     (while (< (point) end)
            ;;       (let ((s (point))
            ;;             (e (if (> (line-end-position) end) end (line-end-position))))
            ;;         (comint-send-region kotlin-repl-buffer s e)
            ;;         (comint-send-string kotlin-repl-buffer "\n")
            ;;         (goto-char e)
            ;;         (when (< (point) end)
            ;;           (forward-char 1))))))
            ))
  ;; :config (progn
  ;;           ;; customizations
  ;;           (defun local-kotlin-mode-hook ()
  ;;             ;; set comment start values to prevent indention errors
  ;;             (setq c-comment-start-regexp "//"
  ;;                   c-block-comment-start-regexp "/\*"))
  ;;           (add-hook 'kotlin-mode-hook #'local-kotlin-mode-hook)))
;; Kotlin Mode:1 ends here

;; [[file:init-emacs.org::*Ledger%20Mode][Ledger Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Ledger Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Ledger Mode")

;; ledger-mode
(use-package ledger-mode
  :ensure t
  :functions (ledger-align-amounts)
  :config (progn
            ;; ledger-align-amounts for entire buffer
            (defun local-ledger-align-amounts ()
              (save-excursion
                (goto-char (point-min))
                (ledger-align-amounts 52)))

            ;; ledger hook
            (defun local-ledger-mode-hook ()
              ;; align amounts on save
              (make-local-variable 'before-save-hook)
              (add-hook 'before-save-hook #'local-ledger-align-amounts))
            (add-hook 'ledger-mode-hook #'local-ledger-mode-hook)))
;; Ledger Mode:1 ends here

;; [[file:init-emacs.org::*Lisp%20Mode][Lisp Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Lisp Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Lisp Mode")

;; lisp-mode
(use-package lisp-mode
  :after (flyspell eldoc info-look)
  :commands (emacs-lisp-mode)
  :functions (local-lisp-mode-hook)
  :mode (("\\.el\\'" . emacs-lisp-mode)
         ("\\.lisp\\'" . lisp-mode)
         ("\\.clisp\\'" . lisp-mode))
  :config (progn
            ;; lisp hook for more settings
            (defun local-lisp-mode-hook ()
              ;; clear input method
              ;;(set-input-method nil)

              ;; set indent function for lisp-mode to `lisp-indent-function'
              ;; (it defaults to `clisp-indent-function')
              (when (equal major-mode 'lisp-mode)
                (setq-local lisp-indent-function 'lisp-indent-function))

              ;; set indent to 2 spaces
              ;;(setq lisp-indent-offset 2)

              ;; add underscore and dash to word boundaries
              (modify-syntax-entry ?_ "w" lisp-mode-syntax-table)
              (modify-syntax-entry ?- "w" lisp-mode-syntax-table)

              ;; define keys
              (local-set-key [(ret)] 'newline-and-indent)
              (local-set-key [(s-tab)] 'lisp-complete-symbol)

              ;; turn on flyspell
              (flyspell-prog-mode)

              ;; initialize eldoc
              (eldoc-mode 1)

              ;; ;; turn on abbreviation mode
              ;; (abbrev-mode 1)

              ;; turn on else minor mode
              ;;(else-mode)

              ;; ;; initialize elisp slime nav mode
              ;; (when (fboundp 'elisp-slime-nav-mode)
              ;;   (elisp-slime-nav-mode)
              ;;   (when (fboundp 'diminish)
              ;;     (with-eval-after-load "elisp-slime-nav"
              ;;       (diminish 'elisp-slime-nav-mode))))

              ;; ;; check parenthesis after file save
              ;; (add-hook 'after-save-hook #'check-parens nil t)

              ;; ;; turn on aggressive indent mode
              ;; (use-package aggressive-indent
              ;;   :ensure t
              ;;   :config (aggressive-indent-mode 1))

              ;; set outline header regexp
              (setq-local outline-regexp "\\(;; [*]\\{1,8\\} \\|;;[;]\\{1,8\\} \\)")
              (setq-local outline-level 'lisp-outline-level))

            ;; add hook to emacs-lisp and lisp modes
            (add-hook 'emacs-lisp-mode-hook 'local-lisp-mode-hook)
            (add-hook 'lisp-mode-hook 'local-lisp-mode-hook)
            (add-hook 'common-lisp-mode-hook 'local-lisp-mode-hook)
            (add-hook 'ielm-mode-hook 'local-lisp-mode-hook)

            ;; remove trailing blanks
            ;;(add-hook 'emacs-lisp-mode-hook #'install-remove-trailing-blanks)
            ;;(add-hook 'lisp-mode-hook #'install-remove-trailing-blanks)
            ;;(add-hook 'common-lisp-mode-hook #'install-remove-trailing-blanks)

            ;; remove tabs
            ;;(add-hook 'emacs-lisp-mode-hook #'install-remove-tabs)
            ;;(add-hook 'lisp-mode-hook #'install-remove-tabs)
            ;;(add-hook 'common-lisp-mode-hook #'install-remove-tabs)
            ))
;; Lisp Mode:1 ends here

;; [[file:init-emacs.org::*Lisp:%20Slime%20Mode][Lisp: Slime Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Lisp: Slime Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Lisp: Slime Mode")

;; slime-mode (superior lisp interaction mode for emacs)
;; if loading slime errors out because swank-loader.lisp is not found, do:
;;   # cd /usr/share/emacs22/site-lisp/slime
;;   # for i in $(ls -1 /usr/share/common-lisp/source/slime/) ; do ln -s /usr/share/common-lisp/source/slime/$i ; done
(use-package slime
  :ensure t
  :load-path (;;(lambda () (expand-file-name "slime" emacs-modules-dir))
              ;;(lambda () (expand-file-name "slime/contrib" emacs-modules-dir))
              (lambda () (expand-file-name "swank-clojure" emacs-modules-dir)))
  :commands (slime-autoloads
             slime
             slime-eval-buffer
             slime-eval-last-expression
             slime-interactive-eval
             slime-last-expression
             slime-mode
             slime-setup
             clisp
             clojure
             swank-clojure-init
             swank-clojure-slime-mode-hook
             swank-clojure-cmd
             swank-clojure-project)
  :config (progn
            ;; clojure swank paths
            (setq swank-clojure-jar-path (expand-file-name "~/.clojure/clojure.jar")
                  swank-clojure-binary (expand-file-name "~/bin/clojure")
                  swank-clojure-extra-classpaths (list (expand-file-name "~/.clojure/clojure.jar")
                                                       (expand-file-name "~/.clojure/jline.jar")
                                                       (expand-file-name "~/.clojure/clojure-contrib.jar")))

            ;; slime setup
            (slime-setup)

            ;; set lisp program to clisp
            ;;(setq inferior-lisp-program "clisp -K full")

            ;; evaluate current sexp
            (defun slime-eval-sexp ()
              "Slime evaluate current sexp."
              (interactive)
              (save-excursion
                (end-of-defun)
                (slime-interactive-eval (slime-last-expression))))

            ;; run slime setup (this does too much)
            ;;(slime-setup)

            ;; redefine `slime-lisp-mode-hook'
            ;; set indent function for lisp-mode to `lisp-indent-function'
            ;; (it defaults to `common-lisp-indent-function')
            (defun slime-lisp-mode-hook ()
              (slime-mode 1)
              (setq-local lisp-indent-function 'lisp-indent-function))

            ;; run custom version of slime setup to preserve lisp-indent-function
            (defun local-slime-lisp-mode-hook ()
              ;; ;; set lisp program
              ;; (setq inferior-lisp-program "clisp -K full")
              ;; (setq inferior-lisp-program "clisp -K base")

              ;; turn on slime mode
              (slime-mode 1)

              ;; typeout frame
              ;;(add-hook 'slime-connected-hook #'slime-ensure-typeout-frame)
              ;; highlight edits
              ;;(add-hook 'slime-mode-hook #'slime-highlight-edits-mode)

              ;; keybindings
              (bind-keys :map slime-mode-map
                         ("C-c C-c" . slime-eval-sexp)
                         ("C-x C-e" . slime-eval-last-expression)
                         ("M-C-x" . slime-eval-sexp)
                         ("C-c C-k" . slime-eval-buffer))

              ;; start inferior lisp job
              ;;(unless (comint-check-proc "*inferior-lisp*")
              ;;  (let ((buffer (current-buffer)))
              ;;    (slime)
              ;;    (switch-to-buffer buffer)))

              ;; ;; auto connect to slime
              ;; (unless (slime-connected-p)
              ;;   (save-excursion (slime)))
              )
            (add-hook 'lisp-mode-hook #'local-slime-lisp-mode-hook)
            (add-hook 'common-lisp-mode-hook #'local-slime-lisp-mode-hook)
            (add-hook 'clojure-mode-hook #'local-slime-lisp-mode-hook)

            ;; cldoc (common lisp info in minibuffer)
            (autoload 'turn-on-cldoc-mode "cldoc" nil t)
            (add-hook 'common-lisp-mode-hook #'turn-on-cldoc-mode)
            ;; wait 3 seconds before showing minibuffer docs
            (setq cldoc-idle-delay 3)

            ;; ;; slime-cl-pitfalls (slime motd warnings)
            ;; (use-package slime-cl-pitfalls
            ;;   :ensure t)

            ;; add clisp to slime implementations
            (add-to-list 'slime-lisp-implementations '(clisp ("/usr/bin/clisp" "-K" "base")) t)

            ;; start clisp function
            (defun clisp ()
              "Start Common Lisp in Slime"
              (interactive)
              (slime 'clisp))

            ;; initialize clisp: quicklisp
            ;; $ clisp --load quicklisp.lisp
            ;; (quicklisp-quickstart:install)
            ;; (ql:add-to-init-file)
            ;; (ql:quickload 'restas)

            ;; add sbcl to slime implementations
            (add-to-list 'slime-lisp-implementations '(sbcl ("/usr/bin/sbcl")) t)

            ;; start sbcl function
            (defun sbcl ()
              "Start Steel Bank Common Lisp in Slime"
              (interactive)
              (slime 'sbcl))

            ;; initialize sbcl: quicklisp
            ;; $ sbcl --load quicklisp.lisp
            ;; (quicklisp-quickstart:install)
            ;; (ql:add-to-init-file)
            ;; (ql:quickload 'restas)

            ;; add clojure to slime implementation
            ;; (add-to-list 'slime-lisp-implementations
            ;;              `(clojure (,(expand-file-name "~/bin/clojure"))
            ;;                        :init swank-clojure-init
            ;;                        :coding-system utf-8-unix) t)
            (add-to-list 'slime-lisp-implementations `(clojure ("/usr/bin/clojure")) t)

            ;; start clojure function
            (defun clojure ()
              "Start Clojure in Slime"
              (interactive)
              (slime 'clojure))

            ;; load slime-mode when lisp-mode is loaded
            (defun local-lisp-mode-hook-slime-mode ()
              (slime-mode 1))
            (add-hook 'lisp-mode-hook #'local-lisp-mode-hook-slime-mode)
            ;; (defun local-inferior-lisp-mode-hook-inferior-slime-mode ()
            ;;   (inferior-slime-mode 1))
            ;; (add-hook 'inferior-lisp-mode-hook #'local-inferior-lisp-mode-hook-inferior-slime-mode)
            ))

;;------------------------------------------------------------------------------
;;;; ac-slime
;;------------------------------------------------------------------------------

(init-message 3 "ac-slime")

;; ac-slime (auto-complete source for slime)
(use-package ac-slime
  :disabled t
  :ensure t
  :after (slime)
  :config (progn
            (add-hook 'slime-mode-hook #'set-up-slime-ac)
            (add-hook 'slime-repl-mode-hook #'set-up-slime-ac)
            (add-to-list 'ac-modes 'slime-repl-mode t)))

;;------------------------------------------------------------------------------
;;;; elisp-slime-nav-mode
;;------------------------------------------------------------------------------

(init-message 3 "elisp-slime-nav-mode")

;; elisp-slime-nav-mode
(use-package elisp-slime-nav
  :ensure t
  :after (slime)
  :diminish elisp-slime-nav-mode
  :commands (elisp-slime-nav-mode)
  :config (elisp-slime-nav-mode))
;; Lisp: Slime Mode:1 ends here

;; [[file:init-emacs.org::*Makefile%20Mode][Makefile Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Makefile Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Makefile Mode")

;; make-mode
(use-package make-mode
  :ensure t
  :mode ("Makefile" . makefile-mode)
  :commands (make-mode)
  ;; :config (progn
  ;;           ;; remove trailing blanks
  ;;           (add-hook 'auto-mode-hook #'install-remove-trailing-blanks))
  )
;; Makefile Mode:1 ends here

;; [[file:init-emacs.org::*Markdown%20Mode][Markdown Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Markdown Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Markdown Mode")

;; markdown-mode
(use-package markdown-mode
  :ensure t
  :mode (("\\.text\\'" . markdown-mode)
         ("\\.markdown\\'" . markdown-mode)
         ("\\.md\\'" . markdown-mode)))

;;------------------------------------------------------------------------------
;;; Convert Org Tables to Markdown
;;------------------------------------------------------------------------------

(init-message 3 "Convert Org Tables to Markdown")

;; convert org tables to markdown
(use-package markdown-mode
  :after (org-table)
  :functions (markdown-mode-fix-org-tables)
  :config (progn
            ;; use org table mode for markdown tables
            (add-hook 'markdown-mode-hook #'orgtbl-mode)

            ;; hook to fix org table format on save
            (defun markdown-mode-fix-org-tables ()
              (save-excursion
                (goto-char (point-min))
                (while (search-forward "-+-" nil t) (replace-match "-|-"))))
            (add-hook 'markdown-mode-hook
                      (lambda()
                        (add-hook 'before-save-hook #'markdown-mode-fix-org-tables nil 'make-it-local)))))
;; Markdown Mode:1 ends here

;; [[file:init-emacs.org::*Muse%20Mode][Muse Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Muse Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Muse Mode")

;; authoring and publishing environment
(use-package muse-mode
  :disabled t
  :load-path (lambda () (expand-file-name "muse/lisp" emacs-modules-dir))
  :mode ("\\.muse\\'" . muse-mode)
  :init (defconst muse-init-file (expand-file-name "~/web/bin/muse-init.el"))
  :config (progn
            ;; call external muse initialization script in web project
            (when (file-exists-p muse-init-file)
              (safe-load muse-init-file))))
;; Muse Mode:1 ends here

;; [[file:init-emacs.org::*Perl%20Mode][Perl Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Perl Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Perl Mode")

;; cperl-mode
(use-package cperl-mode
  :ensure t
  :after (flyspell)
  :mode (("\\.\\([pP][Llm]\\|al\\|t\\)\\'" . cperl-mode)
         ("perl" . cperl-mode)
         ("perl5" . cperl-mode))
  :interpreter ("miniperl" . cperl-mode)
  :config (progn
            ;; perl hook
            (defun local-cperl-mode-hook ()
              ;; configure some options
              (setq cperl-indent-level 4)
              (setq cperl-continued-statement-offset 0)

              ;; turn on flyspell
              (flyspell-prog-mode))
            (add-hook 'cperl-mode-hook #'local-cperl-mode-hook)

            ;; determine if file is a perl script and switch to cperl-mode if it is
            (defun cperl-mode-maybe ()
              (interactive)
              (save-excursion
                (save-match-data
                  (goto-char (point-min))
                  (when (or
                         (search-forward "#!/usr/bin/perl" (line-end-position) t)
                         (search-forward "#!/usr/bin/env perl" (line-end-position) t))
                    (cperl-mode)))))

            ;; run when a file is loaded
            (add-hook 'find-file-hooks #'cperl-mode-maybe)

            ;; remove trailing blanks
            ;;(add-hook 'cperl-mode-hook #'install-remove-trailing-blanks)

            ;; remove tabs
            ;;(add-hook 'cperl-mode-hook #'install-remove-tabs)
            ))
;; Perl Mode:1 ends here

;; [[file:init-emacs.org::*Python%20Mode][Python Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Python Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Python Mode")

;; python-mode
(use-package python-mode
  :ensure t
  :mode (("\\.py$" . python-mode)
         ("\\.python$" . python-mode))
  :commands (py--buffer-filename-remote-maybe)
  :functions (local-python-mode-hook)
  :config (progn
            ;; use ipython
            (setq-default py-shell-name "ipython")
            (setq py-force-py-shell-name-p t)
            (setq-default py-which-bufname "IPython")

            ;; use wx backend, for both mayavi and matplotlib
            (setq py-python-command-args '("--gui=wx" "--pylab=wx" "-colors" "Linux"))

            ;; switch to interpreter after executing code
            ;;(setq py-switch-buffers-on-execute-p t)

            ;; split windows
            ;;(setq py-split-windows-on-execute t)
            (setq py-keep-windows-configuration 'force)

            ;; try to automatically figure out indentation
            (setq py-smart-indentation t)

            ;; python hook
            (defun local-python-mode-hook ()
              ;; ;; set indent
              ;; (setq py-indent-offset 4)

              ;; set outline header regexp
              (setq-local outline-regexp " *\\(def \\|clas\\|#hea\\)")
              ;;(hide-sublevels 1)
              )
            (add-hook 'python-mode-hook 'local-python-mode-hook)

            ;; ;; elpy
            ;; (use-package elpy
            ;;   :ensure t
            ;;   :config (progn
            ;;             ;; turn on elpy mode
            ;;             (elpy-enable)))
            ))

;;------------------------------------------------------------------------------
;;;; jedi
;;------------------------------------------------------------------------------

(init-message 3 "jedi")

;; python auto-completion (jedi)
(use-package jedi
  :ensure t
  :after (python-mode)
  :config (progn
            ;; add jedi completions to auto-complete sources
            (add-to-list 'ac-sources 'ac-source-jedi-direct t)
            ;; enable with python mode
            (add-hook 'python-mode-hook #'jedi:setup)))
;; Python Mode:1 ends here

;; [[file:init-emacs.org::*Racket%20Mode][Racket Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Racket Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Racket Mode")

;; racket-mode
;; (use-package racket-mode
;;   :ensure t
;;   :mode ("\\.rkt\\'" . racket-mode)
;;   :interpreter ("racket" . racket-mode)
;;   :commands (racket-mode
;;              racket-repl)
;;   :config (progn
;;             ;; customizations
;;             (defun local-racket-mode-hook ()
;;               ;; do not auto-complete on tab
;;               (setq tab-always-indent t))
;;             (add-hook 'racket-mode-hook #'local-racket-mode-hook)

;;             ;; turn on support for unicode input
;;             (add-hook 'racket-mode-hook #'racket-unicode-input-method-enable)
;;             (add-hook 'racket-repl-mode-hook #'racket-unicode-input-method-enable)))

(use-package scheme
  :ensure t
  :mode ("\\.rkt\\'" . racket-mode)
  :interpreter ("racket" . racket-mode)
  :commands (racket-mode
             scheme-mode)
  :config (progn
            ;; create racket mode based on scheme mode
            (define-derived-mode racket-mode scheme-mode "Scheme"
              "Major mode for editing Racket Scheme code.  Editing commands
are similar to those of `lisp-mode'.

In addition, if an inferior Racket Scheme process is running, some additional
commands will be defined, for evaluating expressions and controlling the
interpreter, and the state of the process will be displayed in the mode line
of all Scheme buffers.  The names of commands that interact with the Scheme
process start with \"xscheme-\" if you use the MIT Scheme-specific `xscheme'
package; for more information see the documentation for
`xscheme-interaction-mode'.  Use \\[run-scheme] to start an inferior Scheme
using the more general `cmuscheme' package.

Commands:
Delete converts tabs to spaces as it moves back.
Blank lines separate paragraphs.  Semicolons start comments.
\\{scheme-mode-map}"
              ;; turn on geiser-mode
              (when (fboundp 'geiser-mode)
                (geiser-mode t)))

            ;; ;; racket files should use racket-mode
            ;; (add-to-list 'auto-mode-alist '("\\.rkt\\'" . racket-mode))
            ))
;; Racket Mode:1 ends here

;; [[file:init-emacs.org::*Ruby%20Mode][Ruby Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Ruby Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Ruby Mode")

;; ruby-mode
(use-package ruby-mode
  :after (flyspell)
  :mode ("\\.rb$" . ruby-mode)
  :config (progn
            ;; ruby hook
            (defun local-ruby-mode-hook ()
              ;; set indent level
              ;;(setq ruby-indent-level 4)
              (setq ruby-indent-level 2)

              ;; define keys
              (define-key ruby-mode-map (kbd "<return>") 'reindent-then-newline-and-indent)
              ;; undefine electric keys
              (define-key ruby-mode-map (kbd "{") 'self-insert-command)
              (define-key ruby-mode-map (kbd "}") 'self-insert-command)

              ;; turn on flyspell
              (when (boundp 'flyspell-prog-mode)
                (flyspell-prog-mode)))
            (add-hook 'ruby-mode-hook #'local-ruby-mode-hook t)

            ;; turn on flyspell
            (flyspell-prog-mode)

            ;; ;; flymake
            ;; FIXME: No longer works
            ;; (use-package flymake
            ;;   :ensure t
            ;;   :config (progn
            ;;             (defun flymake-ruby-init ()
            ;;               (let* ((temp-file (flymake-init-create-temp-buffer-copy 'flymake-create-temp-inplace))
            ;;                      (local-file (file-relative-name temp-file (file-name-directory buffer-file-name))))
            ;;                 (list "ruby" (list "-c" local-file))))

            ;;             (defun flymake-ruby-enable ()
            ;;               (when (and buffer-file-name
            ;;                          (file-writable-p (file-name-directory buffer-file-name))
            ;;                          (file-writable-p buffer-file-name)
            ;;                          (if (fboundp 'tramp-list-remote-buffers)
            ;;                              (not (cl-subsetp (list (current-buffer)) (tramp-list-remote-buffers)))
            ;;                            t))
            ;;                 (local-set-key (kbd "C-c d") 'flymake-display-err-menu-for-current-line)
            ;;                 (flymake-mode t)))

            ;;             (add-to-list 'flymake-allowed-file-name-masks '(".+\\.rb$" flymake-ruby-init) t)
            ;;             (add-to-list 'flymake-allowed-file-name-masks '("Rakefile$" flymake-ruby-init) t)
            ;;             (add-to-list 'flymake-err-line-patterns '("^\\(.*\\):\\([0-9]+\\): \\(.*\\)$" 1 2 nil 3) t)
            ;;             (add-hook 'ruby-mode-hook #'flymake-ruby-enable)))

            ;; ;; turn on syntax highlighting (actually turns off syntax highlighting)
            ;; (add-hook 'ruby-mode-hook #'turn-on-font-lock)

            ;; ;; turn on abbreviation mode
            ;; (abbrev-mode 1)

            ;; determine if file is a ruby script and switch to ruby-mode if it is
            (defun ruby-mode-maybe ()
              (interactive)
              (save-excursion
                (save-match-data
                  (goto-char (point-min))
                  (when (or
                         (search-forward "#!/usr/bin/ruby" (line-end-position) t)
                         (search-forward "#!/usr/bin/env ruby" (line-end-position) t))
                    (ruby-mode)))))

            ;; run when a file is loaded
            (add-hook 'find-file-hooks #'ruby-mode-maybe)

            ;; remove trailing blanks
            ;;(add-hook 'ruby-mode-hook #'install-remove-trailing-blanks)

            ;; remove tabs
            ;;(add-hook 'ruby-mode-hook #'install-remove-tabs)
            ))

;;------------------------------------------------------------------------------
;;;; robe
;;------------------------------------------------------------------------------

(init-message 3 "robe")

;; robe (Code navigation, documentation lookup and completion for Ruby)
(use-package robe
  :ensure t
  :after (ruby-mode)
  :commands (robe-mode)
  :config (add-hook 'ruby-mode-hook #'robe-mode))

;; ;;------------------------------------------------------------------------------
;; ;;;; inf-ruby
;; ;;------------------------------------------------------------------------------

;; (init-message 3 "inf-ruby")

;; ;; inf-ruby
;; (use-package inf-ruby
;;   :disabled t
;;   :ensure t
;;   :after (ruby-mode)
;;   :interpreter ("ruby" . ruby-mode)
;;   :commands (run-ruby inf-ruby-keys)
;;   :config (progn
;;             (defun local-ruby-mode-hook-inf-ruby-keys ()
;;               (inf-ruby-keys))
;;             (add-hook 'ruby-mode-hook #'local-ruby-mode-hook-inf-ruby-keys)

;;             ;; use ruby-robe with inf-ruby
;;             (defadvice inf-ruby-console-auto (before activate-rvm-for-robe activate)
;;               (rvm-activate-corresponding-ruby))))

;; ;;------------------------------------------------------------------------------
;; ;;;; ac-inf-ruby
;; ;;------------------------------------------------------------------------------

;; (init-message 3 "ac-inf-ruby")

;; ;; ac-inf-ruby (auto-complete source for interactive ruby)
;; (use-package ac-inf-ruby
;;   :ensure t
;;   :config (progn
;;             (add-to-list 'ac-modes 'inf-ruby-mode t)
;;             (add-hook 'inf-ruby-mode-hook #'ac-inf-ruby-enable)
;;             ;; ;; make TAB auto-complete
;;             ;; (define-key inf-ruby-mode-map (kbd "TAB") 'auto-complete)
;;             ))))
;; Ruby Mode:1 ends here

;; [[file:init-emacs.org::*SH%20Mode][SH Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: SH Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: SH Mode")

;; sh-mode
(use-package sh-script
  :ensure t
  :mode (("\\.sh\\'" . sh-mode)
         ("\\.shell\\'" . sh-mode)
         ("\\.bash\\'" . sh-mode)
         ;; use sh-mode for ldif and schema files
         ("\\.ldif\\'" . sh-mode)
         ("\\.schema\\'" . sh-mode)
         ;; use sh-mode for remind files
         ("\\.reminders\\'" . sh-mode)
         ("^reminders_" . sh-mode))
  :config (progn
            ;; make comment lines indent
            (setq sh-indent-comment t)

            ;; determine if file is a shell script and switch to sh-mode if it is
            (defun sh-mode-maybe ()
              (interactive)
              (save-excursion
                (save-match-data
                  (goto-char (point-min))
                  (when (or
                         (search-forward "#!/bin/sh" (line-end-position) t)
                         (search-forward "#!/bin/bash" (line-end-position) t)
                         (search-forward "#!/bin/csh" (line-end-position) t)
                         (search-forward "#!/bin/tsh" (line-end-position) t)
                         (search-forward "#!/bin/zsh" (line-end-position) t)
                         (search-forward "#!/usr/bin/env sh" (line-end-position) t)
                         (search-forward "#!/usr/bin/env bash" (line-end-position) t)
                         (search-forward "#!/usr/bin/env csh" (line-end-position) t)
                         (search-forward "#!/usr/bin/env tsh" (line-end-position) t)
                         (search-forward "#!/usr/bin/env zsh" (line-end-position) t)
                         (search-forward "#=========" (line-end-position) t)
                         (search-forward "#---------" (line-end-position) t))
                    (sh-mode)))))

            ;; run when a file is loaded
            (add-hook 'find-file-hooks #'sh-mode-maybe)

            ;; remove trailing blanks
            ;;(add-hook 'sh-mode-hook #'install-remove-trailing-blanks)

            ;; remove tabs
            ;;(add-hook 'sh-mode-hook #'install-remove-tabs)
            ))
;; SH Mode:1 ends here

;; [[file:init-emacs.org::*Shell%20Mode][Shell Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Shell Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Shell Mode")

;; shell-mode
(use-package shell
  :ensure t
  :commands (shell-mode)
  :config (progn
            ;; set prompt to read only ???
            (setq comint-prompt-read-only t)

            ;; start a shell
            ;;(shell)
            ))

;;------------------------------------------------------------------------------
;;;; ansi-color
;;------------------------------------------------------------------------------

(init-message 3 "ansi-color")

;; ansi-color (use color)
(use-package ansi-color
  :ensure t
  :after shell
  :commands (ansi-color-for-comint-mode-on)
  :config (add-hook 'shell-mode-hook #'ansi-color-for-comint-mode-on))
;; Shell Mode:1 ends here

;; [[file:init-emacs.org::*SQL%20Mode][SQL Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: SQL Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: SQL Mode")

;; sql-mode
(use-package sql
  :ensure t
  :mode (("\\.sql\\'" . sql-mode)
         ("\\.tbl\\'" . sql-mode)
         ("\\.sp\\'" . sql-mode))
  :config (progn
            ;; ;; sql-transform
            ;; (use-package sql-transform
            ;;   :config (progn
            ;;             (defun local-sql-mode-hook ()
            ;;               ;; keybindings
            ;;               (bind-keys :map sql-mode-map
            ;;                          ("C-c s" . sql-to-select)
            ;;                          ("C-c i" . sql-to-insert)
            ;;                          ("C-c u" . sql-to-update)
            ;;                          ("C-c d" . sql-to-delete)))
            ;;             (add-hook 'sql-mode-hook #'local-sql-mode-hook)))

            ;; ;; turn on abbreviation mode
            ;; (abbrev-mode 1)

            ;; remove trailing blanks
            ;;(add-hook 'sql-mode-hook #'install-remove-trailing-blanks)

            ;; remove tabs
            ;;(add-hook 'sql-mode-hook #'install-remove-tabs)

            ;; add databases
            ))

;; ;;------------------------------------------------------------------------------
;; ;;;; mysql
;; ;;------------------------------------------------------------------------------

;; (init-message 3 "mysql")

;; ;; mysql
;; (use-package mysql
;;   :ensure t
;;   :after sql
;;   :config (setq sql-product 'mysql))
;; SQL Mode:1 ends here

;; [[file:init-emacs.org::*Text%20Mode][Text Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Text Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Text Mode")

;; text-mode
(use-package text-mode
  :after (flyspell)
  :mode (("\\.txt\\'" . text-mode)
         ("\\.text\\'" . text-mode)
         ("README" . text-mode)
         ("INSTALL" . text-mode)
         ("CHANGELOG" . text-mode))
  :config (progn
            (defun local-text-mode-hook ()
              ;; set tab
              (setq tab-width 4)
              (setq tab-stop-list '(4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76))
              ;; (setq tab-width 8)
              ;; (setq tab-stop-list '(8 16 24 32 40 48 56 64 72 76))
              (setq indent-tabs-mode t)             ; can insert TAB characters
              (bind-key "<tab>" 'indent-relative text-mode-map)

              ;; set default fill column for auto-fill mode
              (setq fill-column 78)

              ;; turn on word wrap
              (turn-on-auto-fill)

              ;; add underscore and dash to word boundaries
              (modify-syntax-entry ?_ "w" text-mode-syntax-table)
              (modify-syntax-entry ?- "w" text-mode-syntax-table)

              ;; turn on flyspell
              (flyspell-mode 1)

              ;; ;; turn on abbreviation mode
              ;; (abbrev-mode 1)

              ;; turn on pabbrev mode
              ;;(pabbrev-mode)

              ;; insert two spaces after a sentence
              (setq sentence-end-double-space t)

              ;; insert two spaces after a colon
              (setq colon-double-space t))
            (add-hook 'text-mode-hook #'local-text-mode-hook)

            ;; remove trailing blanks
            ;;(add-hook 'text-mode-hook #'install-remove-trailing-blanks)

            ;; remove tabs
            ;;(add-hook 'text-mode-hook #'install-remove-tabs)
            ))
;; Text Mode:1 ends here

;; [[file:init-emacs.org::*XML%20Mode][XML Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: XML Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: XML Mode")

;; nxml-mode
(use-package nxml-mode
  :after (flyspell)
  :load-path (lambda () (expand-file-name "nxml-mode" emacs-modules-dir))
  :mode (("\\.dtd\\'" . nxml-mode)
         ("\\.htm\\'" . nxml-mode)
         ("\\.html\\'" . nxml-mode)
         ("\\.rdf\\'" . nxml-mode)
         ("\\.rhtml\\'" . nxml-mode)
         ("\\.rss\\'" . nxml-mode)
         ("\\.sgml\\'" . nxml-mode)
         ("\\.svg\\'" . nxml-mode)
         ("\\.xhtml\\'" . nxml-mode)
         ("\\.xml\\'" . nxml-mode)
         ("\\.xsd\\'" . nxml-mode)
         ("\\.xsl\\'" . nxml-mode)
         ("\\.tt\\'" . nxml-mode))
  :config (progn
            ;; set magic modes
            ;;(load "rng-auto")
            ;;(unify-8859-on-decoding-mode)
            (add-to-list 'magic-mode-alist '("<\\?xml " . nxml-mode) t)

            ;; nxml hook
            (defun local-nxml-mode-hook ()
              ;; do not use `indent-relative' for tab indenting
              (bind-key "<tab>" 'indent-for-tab-command nxml-mode-map)

              ;; turn off auto-fill mode
              (turn-off-auto-fill)

              ;; turn on flyspell
              (flyspell-prog-mode)

              ;; turn on auto-completion
              (setq nxml-slash-auto-complete-flag t)

              ;; turn on org minor mode
              ;; (when (string-match "\\.\\(x?html\\|php[34]?\\)$"
              ;;                     (file-name-sans-versions (buffer-file-name)))
              ;;   (local-nxml-mode-org))
              ;;(local-nxml-mode-org)

              ;; set outline header regexp
              ;;(setq-local outline-regexp " *<[^/]")
              (setq-local outline-regexp "\\s *<\\([h][1-6]\\|html\\|body\\|head\\)\\b")
              ;;(hide-sublevels 1)
              )
            (add-hook 'nxml-mode-hook #'local-nxml-mode-hook)

            ;; ;;
            ;; (defun local-nxml-mode-org ()
            ;;
            ;;   ;;(setq-local outline-regexp "\\s *<\\([h][1-6]\\|html\\|body\\|head\\)\\b")
            ;;   (setq-local outline-regexp "\\s *<")
            ;;   (setq-local outline-level 'local-nxml-mode-outline-level)
            ;;   (outline-minor-mode 1)
            ;;   (hs-minor-mode 1))

            ;; (defun local-nxml-mode-outline-level ()
            ;;   (save-excursion (re-search-forward html-outline-level))
            ;;   (let ((tag (buffer-substring (match-beginning 1) (match-end 1))))
            ;;     (if (eq (length tag) 2)
            ;;         (- (aref tag 1) ?0)
            ;;       0)))

            ;; (add-to-list 'hs-special-modes-alist
            ;;              '(nxml-mode
            ;;                "<!--\\|<[^/>]>\\|<[^/][^>]*[^/]>"
            ;;                ""
            ;;                "<!--" ;; won't work on its own; uses syntax table
            ;;                (lambda (arg) (local-nxml-mode-forward-element))
            ;;                nil) t)

            ;; (defun local-nxml-mode-forward-element ()
            ;;   (let ((nxml-sexp-element-flag))
            ;;     (setq nxml-sexp-element-flag (not (looking-at "<!--")))
            ;;     (unless (looking-at outline-regexp)
            ;;       (ignore-errors
            ;;         (nxml-forward-balanced-item 1)))))

            ;; remove trailing blanks
            ;;(add-hook 'nxml-mode-hook #'install-remove-trailing-blanks)

            ;; remove tabs
            ;;(add-hook 'nxml-mode-hook #'install-remove-tabs)

            ;; ;; flymake-mode for html
            ;; (use-package flymake
            ;;   :disabled t
            ;;   :ensure t
            ;;   :config (progn
            ;;             (defun flymake-html-init ()
            ;;               (let* ((temp-file (flymake-init-create-temp-buffer-copy 'flymake-create-temp-inplace))
            ;;                      (local-file (file-relative-name temp-file (file-name-directory buffer-file-name))))
            ;;                 (list "tidy" (list local-file))))

            ;;             (add-to-list 'flymake-allowed-file-name-masks '("\\.html$\\|\\.ctp" flymake-html-init) t)
            ;;             (add-to-list 'flymake-err-line-patterns '("line \\([0-9]+\\) column \\([0-9]+\\) - \\(Warning\\|Error\\): \\(.*\\)" nil 1 2 4) t)))

            ;; derive xml-mode and html-mode from nxml-mode
            ;;(defalias 'xml-mode 'nxml-mode)
            ;;(defalias 'html-mode 'nxml-mode)
            (fset 'xml-mode 'nxml-mode)
            (fset 'html-mode 'nxml-mode)))
;; XML Mode:1 ends here

;; [[file:init-emacs.org::*Modules][Modules:1]]
;;==============================================================================
;;; Modules
;;==============================================================================

(init-message 1 "Modules")
;; Modules:1 ends here

;; [[file:init-emacs.org::*abbrev-mode][abbrev-mode:1]]
;;------------------------------------------------------------------------------
;;; Modules: abbrev-mode
;;------------------------------------------------------------------------------

(init-message 2 "Modules: abbrev-mode")

(use-package abbrev
  :diminish abbrev-mode
  :commands (abbrev-mode
             quietly-read-abbrev-file
             write-abbrev-file)
  :init (defconst abbrev-file
          (expand-file-name "~/.abbrev_defs")
          "Abbreviations file used by `abbrev-mode'.")
  :config (progn
            (call-process "touch" nil nil nil abbrev-file)
            (abbrev-mode 1)
            (setq dabbrev-case-replace nil) ; preserve case when replacing abbreviations
            (quietly-read-abbrev-file abbrev-file)
            (setq save-abbrevs 'silently)
            (defun local-kill-emacs-hook-write-abbrev-file ()
              (write-abbrev-file abbrev-file))
            (add-hook 'kill-emacs-hook #'local-kill-emacs-hook-write-abbrev-file)))
;; abbrev-mode:1 ends here

;; [[file:init-emacs.org::*ag][ag:1]]
;;------------------------------------------------------------------------------
;;; Modules: ag
;;------------------------------------------------------------------------------

(init-message 2 "Modules: ag")

(use-package ag
  :ensure t
  :commands (ag))
;; ag:1 ends here

;; [[file:init-emacs.org::*alert][alert:1]]
;;------------------------------------------------------------------------------
;;; Modules: alert
;;------------------------------------------------------------------------------

(init-message 2 "Modules: alert")

(use-package alert
  :ensure t
  :commands (alert)
  :config (setq alert-default-style 'libnotify))
;; alert:1 ends here

;; [[file:init-emacs.org::*analog-clock][analog-clock:1]]
;;------------------------------------------------------------------------------
;;; Modules: analog-clock
;;------------------------------------------------------------------------------

(init-message 2 "Modules: analog-clock")

(use-package analog-clock
  :commands (analog-clock analog-clock-draw-analog)
  :config (progn
            ;; draw an analog clock
            (setq analog-clock-draw-function #'analog-clock-draw-analog)

            ;; draw a digital clock
            ;;(setq analog-clock-draw-function #'analog-clock-draw-ssd)

            ;; screen saver mode (sort of)
            ;;(run-with-idle-timer 600 t #'analog-clock)
            ))
;; analog-clock:1 ends here

;; [[file:init-emacs.org::*anzu][anzu:1]]
;;------------------------------------------------------------------------------
;;; Modules: anzu
;;------------------------------------------------------------------------------

(init-message 2 "Modules: anzu")

(use-package anzu
  :ensure t
  :diminish anzu-mode
  :commands (anzu-mode
             anzu-query-replace
             anzu-query-replace-regexp
             global-anzu-mode)
  :config (progn
            ;; turn on anzu mode
            (anzu-mode +1)

            ;; turn on anzu mode globally
            (global-anzu-mode +1)

            ;; keybindings
            (bind-keys ("M-%" . anzu-query-replace)
                       ("C-M-%" . anzu-query-replace-regexp))))
;; anzu:1 ends here

;; [[file:init-emacs.org::*auto-compile][auto-compile:1]]
;;------------------------------------------------------------------------------
;;; Modules: auto-compile
;;------------------------------------------------------------------------------

(init-message 2 "Modules: auto-compile")

(use-package auto-compile
  :ensure t
  :commands (auto-compile-on-load-mode
             auto-compile-on-save-mode)
  :config (progn
            (setq load-prefer-newer t)
            ;; turn on auto-compile
            (auto-compile-on-load-mode 1)
            (auto-compile-on-save-mode 1)))
;; auto-compile:1 ends here

;; [[file:init-emacs.org::*avy][avy:1]]
;;------------------------------------------------------------------------------
;;; Modules: avy
;;------------------------------------------------------------------------------

(init-message 2 "Modules: avy")

(use-package avy
  :ensure t
  :commands (avy-goto-char avy-goto-char-in-line avy-goto-word-or-subword-1)
  :bind* (("C-;" . avy-goto-char) ; defaults to `flyspell-auto-correct-previous-word'
          ("C-M-;" . pop-to-mark-command)            ; defaults to undefined
          ("C-x ." . avy-goto-word-or-subword-1)     ; defaults to undefined
          ("C-x C-." . avy-goto-word-or-subword-1))) ; defaults to undefined
;; avy:1 ends here

;; [[file:init-emacs.org::*bash-completion][bash-completion:1]]
;;------------------------------------------------------------------------------
;;; Modules: bash-completion
;;------------------------------------------------------------------------------

(init-message 2 "Modules: bash-completion")

(use-package bash-completion
  :ensure t
  :commands (bash-completion-setup)
  :config (bash-completion-setup))
;; bash-completion:1 ends here

;; [[file:init-emacs.org::*bbdb][bbdb:1]]
;;------------------------------------------------------------------------------
;;; Modules: bbdb
;;------------------------------------------------------------------------------

(init-message 2 "Modules: bbdb")

(use-package bbdb
  :ensure t
  :commands (bbdb
             bbdb-initialize)
  :config (progn
            ;;(bbdb-initialize)
            ;;(bbdb-initialize 'gnus 'message 'sc 'w3)
            (bbdb-initialize 'gnus 'message 'sc)

            ;; the following settings were copied from here:
            ;; http://emacs-fu.blogspot.com/2009/08/managing-e-mail-addresses-with-bbdb.html
            ;; TODO: look at these settings
            (setq bbdb-offer-save 1 ;; 1 means save-without-asking

                  bbdb-use-pop-up t      ;; allow popups for addresses
                  bbdb-electric-p t      ;; be disposable with SPC
                  bbdb-popup-target-lines 1 ;; very small

                  bbdb-dwim-net-address-allow-redundancy t ;; always use full name
                  bbdb-quiet-about-name-mismatches 2 ;; show name-mismatches 2 secs

                  bbdb-always-add-address t ;; add new addresses to existing contacts automatically
                  bbdb-canonicalize-redundant-nets-p t ;; x@foo.bar.cx => x@bar.cx

                  bbdb-completion-type nil ;; complete on anything

                  bbdb-complete-name-allow-cycling t ;; cycle through matches (only partially works)

                  bbbd-message-caching-enabled t ;; be fast
                  bbdb-use-alternate-names t     ;; use AKA

                  bbdb-elided-display t ;; single-line addresses

                  ;; auto-create addresses from mail
                  bbdb/mail-auto-create-p 'bbdb-ignore-some-messages-hook
                  bbdb-ignore-some-messages-alist ;; don't ask about fake addresses
                  ;; NOTE: there can be only one entry per header (such as To, From)
                  ;; http://flex.ee.uec.ac.jp/texi/bbdb/bbdb_11.html

                  '(("From" . "no.?reply\\|DAEMON\\|daemon\\|facebookmail\\|twitter")))))

;; ;;------------------------------------------------------------------------------
;; ;;;; lookout
;; ;;------------------------------------------------------------------------------

;; (init-message 3 "lookout")

;; ;; setup lookout for CSV import/export
;; (use-package lookout
;;   :ensure t
;;   :after (bbdb)
;;   :config
;;   (progn
;;     ;; Thunderbird CSV fields:
;;     ;;
;;     ;; First Name, Last Name, Display Name, Nickname, Primary Email, Secondary
;;     ;; Email, Work Phone, Home Phone, Fax Number, Pager Number, Mobile Number,
;;     ;; Home Address, Home Address 2, Home City, Home State, Home ZipCode, Home
;;     ;; Country, Work Address, Work Address 2, Work City, Work State, Work
;;     ;; ZipCode, Work Country, Job Title, Department, Organization, Web Page 1,
;;     ;; Web Page 2, Birth Year, Birth Month, Birth Day, Custom 1, Custom 2,
;;     ;; Custom 3, Custom 4, Notes

;;     (defconst lookout-bbdb-mapping-table-thunderbird-english
;;       '(("lastname" "Last Name")
;;         ("firstname" "First Name")
;;         ("company" "Organization" "Department" "Job Title")
;;         ("net" "Primary Email" "Secondary Email")
;;         ("phones" "Mobile Number" "Work Phone" "Home Phone")
;;         ("addr1" "Home Address" "Home Address 2" "Home City" "Home State" "Home ZipCode" "Home Country")
;;         ("addr2" "Work Address" "Work Address 2" "Work City" "Work State" "Work ZipCode" "Work Country")
;;         ("addr3" "addr3")
;;         ("notes" "Notes")
;;         ("otherfields" "" ""))
;;       ;; ("otherfields"
;;       ;;  "group" "group"))
;;       "Mapping table, usable for input from Thunderbird CSV export.")
;;     (setq lookout-bbdb-mapping-table 'lookout-bbdb-mapping-table-thunderbird-english)

;;     ;; Outlook CSV fields:
;;     ;;
;;     ;; Title, First Name, Middle Name, Last Name, Suffix, Company, Department,
;;     ;; Job Title, Business Street, Business Street 2, Business Street 3,
;;     ;; Business City, Business State, Business Postal Code, Business Country,
;;     ;; Home Street, Home Street 2, Home Street 3, Home City, Home State, Home
;;     ;; Postal Code, Home Country, Other Street, Other Street 2, Other Street
;;     ;; 3, Other City, Other State, Other Postal Code, Other Country,
;;     ;; Assistant's Phone, Business Fax, Business Phone, Business Phone 2,
;;     ;; Callback, Car Phone, Company Main Phone, Home Fax, Home Phone, Home
;;     ;; Phone 2, ISDN, Mobile Phone, Other Fax, Other Phone, Pager, Primary
;;     ;; Phone, Radio Phone, TTY/TDD Phone, Telex, Account, Anniversary,
;;     ;; Assistant's Name, Billing Information, Birthday, Business Address PO
;;     ;; Box, Categories, Children, Directory Server, E-mail Address, E-mail
;;     ;; Type, E-mail Display Name, E-mail 2 Address, E-mail 2 Type, E-mail 2
;;     ;; Display Name, E-mail 3 Address, E-mail 3 Type, E-mail 3 Display Name,
;;     ;; Gender, Government ID Number, Hobby, Home Address PO Box, Initials,
;;     ;; Internet Free Busy, Keywords, Language, Location, Manager's Name,
;;     ;; Mileage, Notes, Office Location, Organizational ID Number, Other
;;     ;; Address PO Box, Priority, Private, Profession, Referred By,
;;     ;; Sensitivity, Spouse, User 1, User 2, User 3, User 4, Web Page

;;     (defconst lookout-bbdb-mapping-table-outlook-english
;;       '(("lastname" "Last Name" "Suffix")
;;         ("firstname" "Title" "First Name" "Middle Name")
;;         ("company" "Company" "Department" "Job Title")
;;         ("net" "E-mail Address" "E-mail 2 Address" "E-mail 3 Address")
;;         ("phones" "Business Phone" "Business Phone 2"
;;          "Home Phone" "Home Phone 2" "Mobile Phone" "Other Phone"
;;          "Assistant's Phone" "Business Fax" "Car Phone" "Callback"
;;          "Home Fax" "Other Fax" "Pager" "Primary Phone" "Radio Phone"
;;          "TTY/TDD Phone" "Telex")
;;         ("addr1" "Business Street" "Business Address PO Box" "Business Street 2" "Business Street 3"
;;          "Business City" "Business State" "Business Postal Code" "Business Country")
;;         ("addr2" "Home Street" "Home Address PO Box" "Home Street 2" "Home Street 3"
;;          "Home City" "Home State" "Home Postal Code" "Home Country")
;;         ("addr3" "Other Street" "Other Address PO Box" "Other Street 2" "Other Street 3"
;;          "Other City" "Other State" "Other Postal Code" "Other Country")
;;         ("notes" "Notes")
;;         ("otherfields" "" ""))
;;       ;; ("otherfields"
;;       ;;  "Account" "Anniversary" "Assistant's Name" "Billing Information"
;;       ;;  "Birthday" "Categories" "Children" "Directory Server" "Gender"
;;       ;;  "Government ID Number" "Hobby" "Initials" "Internet Free Busy"
;;       ;;  "Keywords" "Language" "Location" "Manager's Name" "Mileage"
;;       ;;  "Office Location" "Organizational ID Number" "Priority" "Private"
;;       ;;  "Profession" "Referred By" "Sensitivity" "Spouse"
;;       ;;  "User 1" "User 2" "User 3" "User 4" "Web Page"))
;;       "Mapping table, usable for input from Outlook CSV export.")
;;     (setq lookout-bbdb-mapping-table 'lookout-bbdb-mapping-table-outlook-english)

;;     ;; (defconst lookout-bbdb-mapping-table-outlook-german
;;     ;;   '(("lastname" "Nachname" "Suffix")
;;     ;;     ("firstname" "Vorname" "Weitere Vornamen")
;;     ;;     ("company" "Firma" "Abteilung" "Position")
;;     ;;     ("net" "E-Mail-Adresse" "E-Mail 2: Adresse" "E-Mail 3: Adresse")
;;     ;;     ("phones" "Telefon geschäftlich" "Telefon geschäftlich 2"
;;     ;;      "Telefon privat" "Telefon privat 2" "Mobiltelefon" "Weiteres Telefon"
;;     ;;      "Telefon Assistent" "Fax geschäftlich" "Autotelefon" "Telefon Firma"
;;     ;;      "Fax privat" "Weiteres Fax" "Pager" "Haupttelefon" "Mobiltelefon 2"
;;     ;;      "Telefon für Hörbehinderte" "Telex")
;;     ;;     ("addr1" "Straße geschäftlich" "Straße geschäftlich 2"
;;     ;;      "Straße geschäftlich 3" "Postleitzahl geschäftlich" "Ort geschäftlich"
;;     ;;      "Region geschäftlich" "Land geschäftlich")
;;     ;;     ("addr2" "Straße privat" "Straße privat 2" "Straße privat 3"
;;     ;;      "Postleitzahl privat" "Ort privat" "Region privat" "Land privat")
;;     ;;     ("addr3" "Weitere Straße" "Weitere Straße 2" "Weitere Straße 3"
;;     ;;      "Weitere Postleitzahl" "Weiterer Ort" "Weitere Region" "Weiteres Land")
;;     ;;     ("aka" "FIXME")
;;     ;;     ("notes" "Notizen")
;;     ;;     ("otherfields"
;;     ;;      "Rückmeldung" "Abrechnungsinformation" "Benutzer 1"
;;     ;;      "Benutzer 2" "Benutzer 3" "Benutzer 4" "Beruf" "Büro"
;;     ;;      "Empfohlen von" "Geburtstag" "Geschlecht" "Hobby" "Initialen"
;;     ;;      "Internet-Frei/Gebucht" "Jahrestag" "Kategorien" "Kinder" "Konto"
;;     ;;      "Name Assistent" "Name des/der Vorgesetzten"
;;     ;;      "Organisations-Nr." "Ort" "Partner" "Postfach" "Priorität" "Privat"
;;     ;;      "Regierungs-Nr." "Reisekilometer" "Sprache" "Stichwörter"
;;     ;;      "Vertraulichkeit" "Verzeichnisserver" "Webseite"))
;;     ;;   "Sample mapping table, usable for input from German M$ Outlook.")

;;     ;; alias for compatibility
;;     ;;(defalias 'bbdb-add-new-field 'bbdb-insert-new-field)
;;     ))
;; bbdb:1 ends here

;; [[file:init-emacs.org::*boxquote][boxquote:1]]
;;------------------------------------------------------------------------------
;;; Modules: boxquote
;;------------------------------------------------------------------------------

(init-message 2 "Modules: boxquote")

(use-package boxquote
  :ensure t
  :commands (boxquote-buffer
             boxquote-describe-function
             boxquote-describe-key
             boxquote-describe-variable
             boxquote-insert-file
             boxquote-kill
             boxquote-narrow-to-boxquote
             boxquote-paragraph
             boxquote-region
             boxquote-shell-command
             boxquote-title
             boxquote-unbox-region
             boxquote-where-is
             boxquote-yank)
  :config (progn
            ;; keybindings
            (global-unset-key (kbd "C-c b")) ; defaults to undefined
            (bind-keys ("C-c by" . boxquote-yank)
                       ("C-c br" . boxquote-region)
                       ("C-c bu" . boxquote-unbox-region)
                       ("C-c bt" . boxquote-title)
                       ("C-c bi" . boxquote-insert-file)
                       ("C-c bk" . boxquote-kill)
                       ("C-c bs" . boxquote-shell-command)
                       ("C-c bb" . boxquote-buffer)
                       ("C-c bp" . boxquote-paragraph)
                       ("C-c bn" . boxquote-narrow-to-boxquote)
                       ("C-c bw" . boxquote-where-is)
                       ("C-c bdf" . boxquote-describe-function)
                       ("C-c bdk" . boxquote-describe-key)
                       ("C-c bdv" . boxquote-describe-variable))))
;; boxquote:1 ends here

;; [[file:init-emacs.org::*browse-kill-ring][browse-kill-ring:1]]
;;------------------------------------------------------------------------------
;;; Modules: browse-kill-ring
;;------------------------------------------------------------------------------

(init-message 2 "Modules: browse-kill-ring")

(use-package browse-kill-ring
  :ensure t
  :commands (browse-kill-ring))
;; browse-kill-ring:1 ends here

;; [[file:init-emacs.org::*bs][bs:1]]
;;------------------------------------------------------------------------------
;;; Modules: bs
;;------------------------------------------------------------------------------

(init-message 2 "Modules: bs")

;; original code by Scott Frazer
(use-package bs
  :ensure t
  :config (progn
            ;; buffers to always show
            (defvar local-bs-always-show-regexps '("\\*\\(scratch\\|info\\|grep\\)\\*")
              "*Buffer regexps to always show when buffer switching.")
            ;; buffers to never show
            (defvar local-bs-never-show-regexps '("^\\s-" "^\\*" "TAGS$" "^Map_Sym.txt$" "^% magit")
              "*Buffer regexps to never show when buffer switching.")
            ;; whether or not to ignore dired buffers
            (defvar local-ido-ignore-dired-buffers nil
              "*If non-nil, buffer switching should ignore dired buffers.")

            ;; is string in regexp list
            (defun local-bs-string-in-regexps (string regexps)
              "Return non-nil if STRING matches anything in REGEXPS list."
              (let ((case-fold-search nil))
                (catch 'done
                  (dolist (regexp regexps)
                    (when (string-match regexp string)
                      (throw 'done t))))))

            ;; should buffer be ignored
            (defun local-bs-ignore-buffer (buffer)
              "Return non-nil if BUFFER should be ignored."
              (or (and (not (local-bs-string-in-regexps buffer local-bs-always-show-regexps))
                       (local-bs-string-in-regexps buffer local-bs-never-show-regexps))
                  (and local-ido-ignore-dired-buffers
                       (with-current-buffer buffer
                         (equal major-mode 'dired-mode)))))

            ;; switch between most recently visited buffers
            (defun bs-toggle-recent ()
              "Toggle most recently visited buffers, ignoring certain ones."
              (interactive)
              (catch 'done
                (dolist (buffer (buffer-list))
                  (unless (or (equal (current-buffer) buffer)
                              (and (fboundp 'my-bs-ignore-buffer)
                                   (my-bs-ignore-buffer (buffer-name buffer))))
                    (switch-to-buffer buffer)
                    (throw 'done t)))))

            ;; config bs
            (setq bs-configurations
                  '(("all" nil nil nil nil nil)
                    ("files" nil nil nil (lambda (buffer) (local-bs-ignore-buffer (buffer-name buffer))) nil))
                  bs-cycle-configuration-name "files")))

;;------------------------------------------------------------------------------
;;;; ido
;;------------------------------------------------------------------------------

(init-message 3 "ido")


;; add ignore rules to ido
(use-package ido
  :ensure t
  :after (bs)
  :config (progn
            (setq ido-ignore-buffers '(local-bs-ignore-buffer))))

;;------------------------------------------------------------------------------
;;;; cycle-buffer
;;------------------------------------------------------------------------------

(init-message 3 "cycle-buffer")

;; add ignore rules to cycle-buffer
(use-package cycle-buffer
  :after (bs)
  :config (progn
            (defun local-bs-cycle-buffer-filter-extra ()
              (not (local-bs-ignore-buffer (buffer-name))))
            (add-to-list 'cycle-buffer-filter-extra '(local-bs-cycle-buffer-filter-extra) t)))
;; bs:1 ends here

;; [[file:init-emacs.org::*calc][calc:1]]
;;------------------------------------------------------------------------------
;;; Modules: calc
;;------------------------------------------------------------------------------

(init-message 2 "Modules: calc")

(use-package calc
  :ensure t
  :commands (calc calc-dispatch)
  :config (progn
            ;; keybindings
            (bind-keys ("M-#" . calc-dispatch)))) ; defaults to ???
;; calc:1 ends here

;; [[file:init-emacs.org::*cedet][cedet:1]]
;;------------------------------------------------------------------------------
;;; Modules: cedet
;;------------------------------------------------------------------------------

(init-message 2 "Modules: cedet")

;; (use-package cedet
;;   :ensure t
;;   :commands (cedet)
;;   :config (progn
;;             ;; create sematic cache dir
;;             (defconst semanticdb-dir "~/.semanticdb")
;;             (make-directory (expand-file-name semanticdb-dir) t)))

;;------------------------------------------------------------------------------
;;;; semantic
;;------------------------------------------------------------------------------

(init-message 3 "semantic")

;; (use-package semantic
;;   :ensure t
;;   :commands (semantic)
;;   :init (progn
;;           ;; create sematic cache dir
;;           (defconst semanticdb-dir "~/.semanticdb")
;;           (make-directory (expand-file-name semanticdb-dir) t))
;;   :config (progn
;;             ;; semantic code completion
;;             (setq semantic-load-turn-useful-things-on t)
;;             ;;(setq semantic-load-turn-everything-on t)
;;             (setq semanticdb-default-save-directory semanticdb-dir)
;;             (semantic-load-enable-code-helpers)
;;             ;;(semantic-load-enable-guady-code-helpers)
;;             ;;(semantic-load-enable-excessive-code-helpers)
;;             ;;(semantic-load-enable-semantic-debugging-helpers)
;;             (semantic-idle-summary-mode 1)))

(semantic-mode 1)
;; cedet:1 ends here

;; [[file:init-emacs.org::*centered-cursor-mode][centered-cursor-mode:1]]
;;------------------------------------------------------------------------------
;;; Modules: centered-cursor-mode
;;------------------------------------------------------------------------------

(init-message 2 "Modules: centered-cursor-mode")

(use-package centered-cursor-mode
  :ensure t
  :commands (centered-cursor-mode))
;; centered-cursor-mode:1 ends here

;; [[file:init-emacs.org::*company-mode][company-mode:1]]
;;------------------------------------------------------------------------------
;;; Modules: company-mode
;;------------------------------------------------------------------------------

(init-message 2 "Modules: company-mode")

(use-package company
  :ensure t
  :diminish company-mode
  :commands (company-mode
             company-select-next
             company-select-previous
             global-company-mode)
  :config (progn
            (add-hook 'after-init-hook #'global-company-mode)
            (global-company-mode 1)
            (setq company-auto-complete nil
                  company-idle-delay 2.0)

            ;; keybindings
            (bind-keys :map company-active-map
                       ("C-n" . company-select-next)
                       ("C-p" . company-select-previous))

            ;; backends
            (when (fboundp 'company-dabbrev)
              (add-to-list 'company-backends 'company-dabbrev t))
            ;; (when (fboundp 'company-emacs-eclim)
            ;;   (add-to-list 'company-backends 'company-emacs-eclim t))
            (when (fboundp 'company-elisp)
              (add-to-list 'company-backends 'company-elisp t))
            (when (fboundp 'company-files)
              (add-to-list 'company-backends 'company-files t))
            (when (fboundp 'company-ispell)
              (add-to-list 'company-backends 'company-ispell t))
            (when (fboundp 'company-robe)
              (add-to-list 'company-backends 'company-robe t))))

;;------------------------------------------------------------------------------
;;;; color
;;------------------------------------------------------------------------------

(init-message 3 "color")

;; set colors for a dark background
(use-package color
  :ensure t
  :after (company)
  :commands (color-lighten-name)
  :config (let ((bg (face-attribute 'default :background)))
            (custom-set-faces
             `(company-tooltip ((t (:inherit default :background ,(color-lighten-name bg 10)))))
             `(company-scrollbar-bg ((t (:background ,(color-lighten-name bg 15)))))
             `(company-scrollbar-fg ((t (:background ,(color-lighten-name bg 20)))))
             `(company-tooltip-selection ((t (:inherit font-lock-function-name-face))))
             `(company-tooltip-common ((t (:inherit font-lock-constant-face)))))))
;; company-mode:1 ends here

;; [[file:init-emacs.org::*cycle-buffer][cycle-buffer:1]]
;;------------------------------------------------------------------------------
;;; Modules: cycle-buffer
;;------------------------------------------------------------------------------

(init-message 2 "Modules: cycle-buffer")

(use-package cycle-buffer
  :commands (cycle-buffer
             cycle-buffer-backward
             cycle-buffer-permissive
             cycle-buffer-backward-permissive
             cycle-buffer-toggle-interesting)
  :config (progn
            ;; ignore errors when cycling buffers
            (defun cycle-buffer--ignore-errors (orig-fun &rest args)
              "Ignore errors when calling `cycle-buffer'."
              (ignore-errors
                (apply orig-fun args)))
            ;; advise `cycle-buffer`
            (advice-add 'cycle-buffer :around #'cycle-buffer--ignore-errors)))
;; cycle-buffer:1 ends here

;; [[file:init-emacs.org::*css-mode][css-mode:1]]
;;------------------------------------------------------------------------------
;;; Modules: css-mode
;;------------------------------------------------------------------------------

(init-message 2 "Modules: css-mode")

(use-package css-mode
  :ensure t
  :mode ("\\.css\\'" . css-mode)
  :commands (css-mode cssm-c-style-indenter)
  :config (setq cssm-indent-function #'cssm-c-style-indenter))
;; css-mode:1 ends here

;; [[file:init-emacs.org::*decimation][decimation:1]]
;;------------------------------------------------------------------------------
;;; Modules: decimation
;;------------------------------------------------------------------------------

(init-message 2 "Modules: decimation")

(use-package decimation
  :commands (decimation))
;; decimation:1 ends here

;; [[file:init-emacs.org::*define-word][define-word:1]]
;;------------------------------------------------------------------------------
;;; Modules: define-word
;;------------------------------------------------------------------------------

(init-message 2 "Modules: define-word")

(use-package define-word
  :ensure t
  :commands (define-word define-word-at-point))
;; define-word:1 ends here

;; [[file:init-emacs.org::*demo-it][demo-it:1]]
;;------------------------------------------------------------------------------
;;; Modules: demo-it
;;------------------------------------------------------------------------------

(init-message 2 "Modules: demo-it")

(use-package demo-it
  :ensure t)
;; demo-it:1 ends here

;; [[file:init-emacs.org::*e-blog][e-blog:1]]
;;------------------------------------------------------------------------------
;;; Modules: e-blog
;;------------------------------------------------------------------------------

(init-message 2 "Modules: e-blog")

(let ((file (expand-file-name "e-blog" emacs-modules-dir)))
  (when (file-exists-p file)
    (load file)))
;; e-blog:1 ends here

;; [[file:init-emacs.org::*easy-kill][easy-kill:1]]
;;------------------------------------------------------------------------------
;;; Modules: easy-kill
;;------------------------------------------------------------------------------

(init-message 2 "Modules: easy-kill")

(use-package easy-kill
  :ensure t
  :commands (easy-kill
             easy-mark)
  :config (progn
            (global-set-key [remap kill-ring-save] #'easy-kill)
            (global-set-key [remap mark-sexp] #'easy-mark)))
;; easy-kill:1 ends here

;; [[file:init-emacs.org::*eldoc][eldoc:1]]
;;------------------------------------------------------------------------------
;;; Modules: eldoc
;;------------------------------------------------------------------------------

(init-message 2 "Modules: eldoc")

(use-package eldoc
  :ensure t
  :commands (eldoc-mode)
  :config (progn
            (setq eldoc-idle-delay 0)))
;; eldoc:1 ends here

;; [[file:init-emacs.org::*elfeed][elfeed:1]]
;;------------------------------------------------------------------------------
;;; Modules: elfeed
;;------------------------------------------------------------------------------

(init-message 2 "Modules: elfeed")

(use-package elfeed
  :ensure t
  :config (progn
            (setq-default elfeed-search-filter "-junk +unread")
            (setq elfeed-feeds
                  '(
                    ;; Emacs
                    ("http://www.reddit.com/r/emacs.rss" emacs) ; Reddit Emacs Channel
                    ("http://www.reddit.com/r/linux.rss" linux) ; Reddit Linux Channel
                    ("http://rss.gmane.org/messages/excerpts/gmane.emacs.devel" emacs) ; Emacs Development Newsgroup
                    ("http://planet.emacsen.org/atom.xml" emacs) ; Planet Emacs
                    ("http://emacsredux.com/atom.xml" emacs)     ; Emacs Redux
                    ("http://whattheemacsd.com/atom.xml" emacs)  ; What the .emacs.d?
                    ("http://www.lunaryorn.com/feed.atom" emacs) ; Lunarsite Emacs
                    ("http://endlessparentheses.com/atom.xml" emacs) ; Endless Parentheses
                    ("http://nullprogram.com/feed/" emacs)           ; Null Program
                    ("http://www.masteringemacs.org/feed/" emacs)    ; Mastering Emacs
                    ("http://sachachua.com/blog/feed/" emacs)        ; Sacha Chua
                    ("http://kitchingroup.cheme.cmu.edu/blog/feed/index.xml" emacs) ; Kitchin Group
                    ;; Computers / Technical
                    ("http://slashdot.org/slashdot.rss" dev)               ; Slashdot
                    ("http://planet.ubuntu.com/rss20.xml" dev)             ; Planet Ubuntu
                    ("http://feeds.feedburner.com/codinghorror?format=xml" dev) ; Planet Gnome
                    ("http://feeds.twit.tv/twit_video_hd.xml" dev) ; TWIT
                    ("http://feeds.feedburner.com/codinghorror?format=xml" dev) ; Coding Horror
                    ;; Games
                    ;;("https://robertsspaceindustries.com/comm-link/rss" game) ; Star Citizen
                    ("http://bitemyapp.com/atom.xml" dev) ; bitemyapp
                    ;; Other
                    ("http://open.blogs.nytimes.com/feed/" blog) ; New York Times OPEN Blogs
                    ;;("http://www.tjmaynes.com/atom.xml" blog) ; TJ Maynes
                    ("https://xkcd.com/atom.xml" comic)   ; XKCD Comic
                    ;; Personal
                    ("http://nulldot.net/index.rss" dev) ; Nulldot Blog
                    ))

            ;; function to make it easy to edit the elfeed-feeds
            (defun elfeed-feeds-edit ()
              "Open `init-emacs.org' and move point to `elfeed-feeds' variable for easy editing."
              (interactive)
              (find-file (expand-file-name "init-emacs.org" emacs-home-dir))
              (goto-char (point-min))
              (search-forward "(setq elfeed-feeds")
              (org-show-entry))

            ;; search mode help
            (defun elfeed-search-mode-help ()
              "Display `elfeed-search-mode' commands in mini-buffer."
              (interactive)
              (message (concat "RET show entry, "
                               "+ tag all, "
                               "- untag all, "
                               "G fetch, "
                               "S set filter, "
                               "b browse url, "
                               "g update, "
                               "n next line, "
                               "p prev line, "
                               "q quit, "
                               "r untag unread, "
                               "s live filter, "
                               "u tag unread, "
                               "y yank")))

            ;; show mode help
            (defun elfeed-show-mode-help ()
              "Display `elfeed-show-mode' commands in mini-buffer."
              (interactive)
              (message (concat "TAB next link, "
                               "BACKTAB previous link, "
                               "SPC scroll down, "
                               "BACKSPACE scroll up,"
                               "+ tag, "
                               "- untag, "
                               "P play enclosure, "
                               "b visit, "
                               "d save enclosure, "
                               "g refresh, "
                               "n next, "
                               "p prev, "
                               "q kill buffer, "
                               "s new live search, "
                               "u copy url, "
                               "y yank")))

            ;; keybindings
            (bind-keys :map elfeed-search-mode-map
                       ("h" . elfeed-search-mode-help)
                       ("?" . elfeed-search-mode-help))
            (bind-keys :map elfeed-show-mode-map
                       ("h" . elfeed-show-mode-help)
                       ("?" . elfeed-show-mode-help))))
;; elfeed:1 ends here

;; [[file:init-emacs.org::*elnode][elnode:1]]
;;------------------------------------------------------------------------------
;;; Modules: elnode
;;------------------------------------------------------------------------------

(init-message 2 "Modules: elnode")

(use-package elnode
  :ensure t
  :commands (elnode))
;; elnode:1 ends here

;; [[file:init-emacs.org::*emacs-w3m][emacs-w3m:1]]
;;------------------------------------------------------------------------------
;;; Modules: w3m
;;------------------------------------------------------------------------------

(init-message 2 "Modules: w3m")

;; only use if w3m command is available on system
(if (executable-find "w3m")
    (progn
      ;; w3m
      (use-package w3m
        :ensure t
        :commands (w3m
                   w3m-antenna
                   w3m-browse-url
                   w3m-find-file
                   w3m-namazu
                   w3m-next-buffer
                   w3m-previous-buffer
                   w3m-region
                   w3m-search
                   w3m-weather)
        :config (progn
                  (setq w3m-icon-directory "/usr/share/emacs-w3m/icon")

                  ;; turn on cookies
                  (setq w3m-use-cookies t)

                  ;; keybindings
                  (bind-keys :map w3m-mode-map
                             ("," . w3m-previous-buffer)
                             ("." . w3m-next-buffer))

                  ;;     ;; add new functionality not in this version
                  ;;     (defun w3m-buffer (&optional url charset)
                  ;;       "Render the current buffer.
                  ;; See `w3m-region' for the optional arguments."
                  ;;       (interactive (list (w3m-expand-file-name-as-url (or (buffer-file-name)
                  ;;                                                           default-directory))))
                  ;;       (w3m-region (point-min) (point-max) url charset))

                  ;; add new functionality not in this version
                  (defun w3m-buffer (&optional buffer)
                    "Render the current buffer or BUFFER if given."
                    (interactive)
                    (when buffer
                      (switch-to-buffer buffer))
                    (w3m-region (point-min) (point-max)))

                  ;; auto-rename buffers to page title or url
                  (defun w3m-display-local-hook (url)
                    (rename-buffer
                     (format "*w3m: %s*" (or w3m-current-title w3m-current-url)) t))
                  (add-hook 'w3m-display-hook #'w3m-display-local-hook)))

      ;;------------------------------------------------------------------------------
      ;;;; Modules: w3m-session
      ;;------------------------------------------------------------------------------

      (init-message 3 "w3m-session")

      ;; w3m-session (persistent sessions)
      (use-package w3m-session
        :commands (w3m-session-load
                   w3m-session-load-always
                   w3m-session-save
                   w3m-session-save-always)
        :config (progn
                  (defun w3m-session-local-hook ()
                    ;; keybindings
                    (bind-keys :map w3m-mode-map
                               ("S" . w3m-session-save)
                               ("L" . w3m-session-load)))
                  (add-hook 'w3m-mode-hook #'w3m-session-local-hook)
                  ;;(setq w3m-session-file "~/.w3m-session")
                  ;;(setq w3m-session-save-always nil)
                  ;;(setq w3m-session-load-always nil)
                  ;;(setq w3m-session-show-titles t)
                  ;;(setq w3m-session-duplicate-tabs 'ask) ; 'never, 'always, 'ask
                  )))

  (message "Warning: Could not find w3m command"))
;; emacs-w3m:1 ends here

;; [[file:init-emacs.org::*eperiodic][eperiodic:1]]
;;------------------------------------------------------------------------------
;;; Modules: eperiodic
;;------------------------------------------------------------------------------

(init-message 2 "Modules: eperiodic")

(use-package eperiodic
  :load-path (lambda () (expand-file-name "eperiodic" emacs-modules-dir))
  :commands (eperiodic))
;; eperiodic:1 ends here

;; [[file:init-emacs.org::*epoch][epoch:1]]
;;------------------------------------------------------------------------------
;;; Modules: epoch
;;------------------------------------------------------------------------------

(init-message 2 "Modules: epoch")

(use-package epoch
  :commands (epoch-menu time-to-epoch epoch-to-time))
;; epoch:1 ends here

;; [[file:init-emacs.org::*ert][ert:1]]
;;------------------------------------------------------------------------------
;;; Modules: ert
;;------------------------------------------------------------------------------

(init-message 2 "Modules: ert")

(use-package ert
  :ensure t)
;; ert:1 ends here

;; [[file:init-emacs.org::*expand-region][expand-region:1]]
;;------------------------------------------------------------------------------
;;; Modules: expand-region
;;------------------------------------------------------------------------------

(init-message 2 "Modules: expand-region")

(use-package expand-region
  :ensure t)
;; expand-region:1 ends here

;; [[file:init-emacs.org::*flycheck][flycheck:1]]
;;------------------------------------------------------------------------------
;;; Modules: flycheck
;;------------------------------------------------------------------------------

(init-message 2 "Modules: flycheck")

(use-package flycheck
  :ensure t
  :commands (flycheck-mod global-flycheck-mode)
  :config (progn
            ;; ;; initialize globally
            ;; (add-hook 'after-init-hook #'global-flycheck-mode)
            ))
;; flycheck:1 ends here

;; [[file:init-emacs.org::*flyspell][flyspell:1]]
;;------------------------------------------------------------------------------
;;; Modules: flyspell
;;------------------------------------------------------------------------------

(init-message 2 "Modules: flyspell")

(use-package flyspell
  :ensure t
  :commands (flyspell-mode
             flyspell-mode-off
             flyspell-prog-mode)
  :config (progn
            (setq flyspell-issue-welcome-flag nil ; this fixes the "enabling flyspell mode gave an error" bug
                  flyspell-sort-corrections nil
                  flyspell-use-meta-tab nil)))
;; flyspell:1 ends here

;; [[file:init-emacs.org::*fuzzy][fuzzy:1]]
;;------------------------------------------------------------------------------
;;; fuzzy (fuzzy matching utilities)
;; adds a fuzzy pattern search to isearch if no exact match is found
;;------------------------------------------------------------------------------

(init-message 2 "Modules: fuzzy")

(use-package fuzzy
  :ensure t
  :config (progn
            (when (fboundp 'turn-on-fuzzy-isearch)
              (turn-on-fuzzy-isearch))))
;; fuzzy:1 ends here

;; [[file:init-emacs.org::*g-client][g-client:1]]
;;------------------------------------------------------------------------------
;;; Modules: g-client
;;------------------------------------------------------------------------------

(init-message 2 "Modules: g-client")

(use-package g
  :disabled t
  :ensure t
  :commands (g)
  :config (progn
            ;; set email address
            (when user-mail-address
              (setq g-user-email user-mail-address))
            ;; set html handler
            (setq g-html-handler 'w3m-buffer)
            ;; set curl proxy
            ;;(setq g-curl-program "curl -x mwmspproxy.dowjones.net:80")
            ))
;; g-client:1 ends here

;; [[file:init-emacs.org::*+git-gutter+][+git-gutter+:1]]
;; ;;------------------------------------------------------------------------------
;; ;; Modules: git-gutter
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modules: git-gutter")

;; (use-package git-gutter
;;   :disabled t
;;   :ensure t
;;   :diminish (git-gutter-mode . "GG")
;;   :commands (git-gutter
;;              global-git-gutter-mode)
;;   :config (progn
;;             ;; turn on globally
;;             ;;(global-git-gutter-mode 1)

;;             ;; turn off globally
;;             (global-git-gutter-mode -1)

;;             ;; keybindings
;;             (bind-keys ("C-x C-g" . git-gutter)
;;                        ;; ("C-x v =" . git-gutter:popup-hunk)
;;                        ;; ("C-x p" . git-gutter:previous-hunk)
;;                        ;; ("C-x n" . git-gutter:next-hunk)
;;                        ;; ("C-x v s" . git-gutter:stage-hunk)
;;                        ;; ("C-x v r" . git-gutter:revert-hunk)
;;                        ;; ("C-x v SPC" . git-gutter:mark-hunk)
;;                        )

;;             ;; periodically update
;;             (setq git-gutter:update-interval 2)

;;             ;; set symbols
;;             (setq git-gutter:modified-sign "="
;;                   git-gutter:added-sign "+"
;;                   git-gutter:deleted-sign "-")

;;             ;; set colors
;;             ;; (set-face-foreground 'git-gutter:modified "gray")
;;             ;; (set-face-foreground 'git-gutter:added "gray")
;;             ;; (set-face-foreground 'git-gutter:deleted "gray")
;;             (set-face-background 'git-gutter:modified "purple")
;;             (set-face-background 'git-gutter:added "green")
;;             (set-face-background 'git-gutter:deleted "red")))
;; +git-gutter+:1 ends here

;; [[file:init-emacs.org::*hippie-exp][hippie-exp:1]]
;;------------------------------------------------------------------------------
;;; Modules: hippie-exp
;;------------------------------------------------------------------------------

(init-message 2 "Modules: hippie-exp")

(use-package hippie-exp
  :ensure t
  :config (setq hippie-expand-try-functions-list
                '(try-expand-dabbrev
                  try-expand-dabbrev-all-buffers
                  try-expand-dabbrev-from-kill
                  try-complete-file-name-partially
                  try-complete-file-name
                  try-expand-all-abbrevs
                  try-expand-list
                  try-expand-line
                  try-complete-lisp-symbol-partially
                  try-complete-lisp-symbol)))
;; hippie-exp:1 ends here

;; [[file:init-emacs.org::*htmlize][htmlize:1]]
;;------------------------------------------------------------------------------
;;; Modules: htmlize
;;------------------------------------------------------------------------------

(init-message 2 "Modules: htmlize")

(use-package htmlize
  :ensure t
  :commands (htmlize-buffer
             htmlize-region
             htmlize-file
             htmlize-many-file
             htmlize-many-files-dired))
;; htmlize:1 ends here

;; [[file:init-emacs.org::*hungry-delete][hungry-delete:1]]
;;------------------------------------------------------------------------------
;;; Modules: hungry-delete
;;------------------------------------------------------------------------------

(init-message 2 "Modules: hungry-delete")

(use-package hungry-delete
  :ensure t
  :commands (global-hungry-delete-mode
             hungry-delete-skip-ws-forward
             hungry-delete-skip-ws-backward)
  :config (progn
            (global-hungry-delete-mode -1)

            ;; custom versions of hungry delete functions that do not delete the space
            ;; at point unless it is the last one

            (defun hungry-delete-forward ()
              "Delete the following character or all following whitespace up
to the next non-whitespace character.  See
\\[c-hungry-delete-backward]."
              (interactive)
              (let ((here (point)))
                (hungry-delete-skip-ws-forward)
                (when (> (point) here)
                  (forward-char -1))
                (if (/= (point) here)
                    (delete-region (point) here)
                  (let ((hungry-delete-mode nil))
                    (delete-char 1)))))

            (defun hungry-delete-backward ()
              "Delete the preceding character or all preceding whitespace
back to the previous non-whitespace character.  See also
\\[c-hungry-delete-forward]."
              (interactive)
              (let ((here (point)))
                (hungry-delete-skip-ws-backward)
                (when (< (point) here)
                  (forward-char 1))
                (if (/= (point) here)
                    (delete-region (point) here)
                  (let ((hungry-delete-mode nil))
                    (delete-char -1)))))))
;; hungry-delete:1 ends here

;; [[file:init-emacs.org::*ibuffer][ibuffer:1]]
;;------------------------------------------------------------------------------
;;; Modules: ibuffer
;;------------------------------------------------------------------------------

(init-message 2 "Modules: ibuffer")

(use-package ibuffer
  :ensure t
  :commands (ibuffer)
  :config (progn
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*Apropos\\*$" t)
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*Compile-Log\\*$" t)
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*Completions\\*$" t)
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*ftp .*\\*$" t)
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*grep\\*$" t)
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*Help\\*$" t)
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*IBuffer\\*$" t)
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*inferior-lisp\\*$" t)
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*JDEE bsh\\*$" t)
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*Messages\\*$" t)
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*Occur\\*$" t)
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*RE-Builder\\*$" t)
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*Shell Command Output\\*$" t)
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*slime-events\\*$" t)
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*tramp/.*\\*$" t)
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*WoMan-Log*\\*$" t)

            ;; default groups for ibuffer
            (setq ibuffer-saved-filters
                  '(("default"
                     ("dired" (mode . dired-mode))
                     ("org" (mode . org-mode))
                     ("elisp" (mode . emacs-lisp-mode))
                     ("lisp" (mode . lisp-mode))
                     ("c" (mode . c-mode))
                     ("java" (or
                              (mode . java-mode)
                              (mode . jde-mode)))
                     ("ruby" (mode . ruby-mode))
                     ("python" (mode . python-mode))
                     ("perl" (mode . cperl-mode))
                     ("erc" (mode . erc-mode))
                     ("emacs" (or
                               (name . "^\\*scratch\\*$")
                               (name . "^\\*Messages\\*$")))
                     ("calendar" (or
                                  (name . "^\\*Calendar\\*$")
                                  (name . "^\\*Remind\\*$")
                                  (name . "^diary$")))
                     ("gnus" (or
                              (mode . message-mode)
                              (mode . bbdb-mode)
                              (mode . mail-mode)
                              (mode . gnus-group-mode)
                              (mode . gnus-summary-mode)
                              (mode . gnus-article-mode)
                              (name . "^\\.bbdb$")
                              (name . "^\\.newsrc-dribble"))))))

            ;; ;; keybindings
            ;; (bind-keys ("M-o" . other-window))

            ;; local hook
            (defun local-ibuffer-mode-hook ()
              (ibuffer-switch-to-saved-filter-groups "default"))
              ;;(local-set-key (kbd "M-o") 'other-window))

            ;; add hook
            (add-hook 'ibuffer-mode-hook #'local-ibuffer-mode-hook)))
;; ibuffer:1 ends here

;; [[file:init-emacs.org::*iedit][iedit:1]]
;;------------------------------------------------------------------------------
;;; Modules: iedit
;;------------------------------------------------------------------------------

(init-message 2 "Modules: iedit")

(use-package iedit
  :ensure t
  :commands (iedit-mode)
  :bind* ("C-x ;" . iedit-mode)
  :config (progn
            ;; (defun iedit ()
            ;;   "Run `iedit-mode' on entire buffer."
            ;;   (interactive)
            ;;   (if iedit-mode
            ;;       (iedit-done)
            ;;     (iedit-mode (point-min) (point-max))))
            (defun iedit-mode-current-defun ()
              "Run `iedit-mode' on current defun."
              (interactive)
              (save-excursion
                (save-restriction
                  (widen)
                  (narrow-to-defun)
                  (if (and (boundp 'iedit-mode)
                           iedit-mode)
                      (when (fboundp 'iedit-done) (iedit-done))
                    (when (fboundp 'iedit-start) (iedit-start (current-word) (point-min) (point-max)))))))))
;; iedit:1 ends here

;; [[file:init-emacs.org::*+imdb+][+imdb+:1]]
;; ;;------------------------------------------------------------------------------
;; ;;; Modules: imdb
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modules: imdb")

;; (use-package imdb
;;   :disabled t
;;   :ensure t)
;; +imdb+:1 ends here

;; [[file:init-emacs.org::*info-look][info-look:1]]
;;------------------------------------------------------------------------------
;;; Modules: info-look
;;------------------------------------------------------------------------------

(init-message 2 "Modules: info-look")

;; add info look-up of keywords
;; to add the info files do:
;;   git clone https://github.com/RobBlackwell/dpans2texi.git
;;   ./configure
;;   make wget
;;   make && make install

(use-package info-look
  :ensure t
  :commands (info-lookup-add-help)
  :config (info-lookup-add-help
           :mode 'lisp-mode
           :regexp "[^][()'\" \t\n]+"
           :ignore-case t
           :doc-spec '(("(ansicl)Symbol Index" nil nil nil))))
;; info-look:1 ends here

;; [[file:init-emacs.org::*ispell][ispell:1]]
;;------------------------------------------------------------------------------
;;; Modules: ispell
;;------------------------------------------------------------------------------

(init-message 2 "Modules: ispell")

(use-package ispell
  :ensure t
  :commands (ispell-buffer
             ispell-change-dictionary
             ispell-complete-word
             ispell-message
             ispell-region
             ispell-word)
  :config (progn
            ;; ;; add spell check key to text modes
            ;; (defun local-ispell-complete-word ()
            ;;   (local-set-key (kbd "M-t") 'ispell-complete-word))
            ;; (add-hook 'text-mode-hook #'local-ispell-complete-word)
            ;; (add-hook 'tex-mode-hook #'local-ispell-complete-word)
            ;; (add-hook 'latex-mode-hook #'local-ispell-complete-word)
            (setq ispell-enable-tex-parser t)))
;; ispell:1 ends here

;; [[file:init-emacs.org::*ivy%20(swiper)][ivy (swiper):1]]
;;------------------------------------------------------------------------------
;;; Modules: ivy (swiper)
;;
;; Adds wildcard name completion to common tasks.
;; Replaces `completing-read-function' with `ivy-completing-read'.
;;------------------------------------------------------------------------------

(init-message 2 "Modules: ivy (swiper)")

(use-package swiper
  :ensure t
  :diminish ivy-mode
  :commands (swiper)
  :config (progn
            (ivy-mode 1)
            (setq ivy-use-virtual-buffers t)

            ;; keybindings
            (bind-keys* ("C-M-s" . swiper) ; defaults to `isearch-forward-regexp'
                        ("C-M-r" . ivy-resume)) ; defaults to `isearch-backward-regexp'

            ;; ivy mode breaks tmm-menubar
            ;; force tmm-menubar to use `completing-read-default' instead
            (defun tmm-prompt--force-completing-read-default (orig-fun &rest args)
              "Force `tmm-menubar' to use `completing-read-default'."
              (let ((completing-read-function 'completing-read-default))
                (apply orig-fun args)))
            ;; advise `tmm-prompt'
            (advice-add 'tmm-prompt :around #'tmm-prompt--force-completing-read-default)))

;; ;;------------------------------------------------------------------------------
;; ;;;; counsel
;; ;;------------------------------------------------------------------------------

;; (init-message 3 "counsel")

;; ;; counsel (various completion functions using ivy)
;; (use-package counsel
;;   :disabled t
;;   :ensure t
;;   :after (swiper)
;;   :config (progn
;;             ;; keybindings
;;             (bind-keys* ("M-x" . counsel-M-x)
;;                         ("C-x C-f" . counsel-find-file)
;;                         ("C-h f" . counsel-describe-function)
;;                         ("C-h v" . counsel-describe-variable))))

;; TODO:

;; (use-package counsel
;;   :after ivy
;;   :bind (("C-x C-f" . counsel-find-file)
;;          ("M-x" . counsel-M-x)
;;          ("M-y" . counsel-yank-pop)))

;; (use-package ivy
;;   :defer 0.1
;;   :diminish
;;   :bind (("C-c C-r" . ivy-resume)
;;          ("C-x b" . ivy-switch-buffer)
;;          ("C-x B" . ivy-switch-buffer-other-window))
;;   :custom (ivy-count-format "(%d/%d) ")
;;   (ivy-display-style 'fancy)
;;   (ivy-use-virtual-buffers t)
;;   :config (ivy-mode))

;; (use-package ivy-rich
;;   :after ivy
;;   :custom (ivy-virtual-abbreviate 'full ivy-rich-switch-buffer-align-virtual-buffer t ivy-rich-path-style 'abbrev)
;;   :config (ivy-set-display-transformer 'ivy-switch-buffer 'ivy-rich-switch-buffer-transformer))

;; (use-package swiper
;;   :after ivy
;;   :bind (("C-s" . swiper)
;;          ("C-r" . swiper)))
;; ivy (swiper):1 ends here

;; [[file:init-emacs.org::*json][json:1]]
;;------------------------------------------------------------------------------
;;; Modules: json
;;------------------------------------------------------------------------------

(init-message 2 "Modules: json")

(use-package json
  :ensure t)
;; json:1 ends here

;; [[file:init-emacs.org::*key-chord][key-chord:1]]
;;------------------------------------------------------------------------------
;;; Modules: key-chord
;;------------------------------------------------------------------------------

(init-message 2 "Modules: key-chord")

(use-package key-chord
  :ensure t
  :commands (key-chord-define-global
             key-chord-mode)
  :config (progn
            (key-chord-mode 1)
            ;; key chords
            (key-chord-define-global ",." "<>\C-b")
            (key-chord-define-global "hj" 'undo)
            (key-chord-define-global "jk" 'dabbrev-expand)
            (key-chord-define-global "cv" 'reindent-then-newline-and-indent)
            (key-chord-define-global "4r" "$")))
;; key-chord:1 ends here

;; [[file:init-emacs.org::*keyfreq][keyfreq:1]]
;;------------------------------------------------------------------------------
;;; Modules: keyfreq
;;------------------------------------------------------------------------------

(init-message 2 "Modules: keyfreq")

(use-package keyfreq
  :ensure t
  :commands (keyfreq-autosave-mode
             keyfreq-mode)
  :config (progn
            (keyfreq-mode 1)
            (keyfreq-autosave-mode 1)))
;; keyfreq:1 ends here

;; [[file:init-emacs.org::*lusty-explorer][lusty-explorer:1]]
;;------------------------------------------------------------------------------
;;; Modules: lusty-explorer
;;------------------------------------------------------------------------------

(init-message 2 "Modules: lusty-explorer")

(use-package lusty-explorer)
;; lusty-explorer:1 ends here

;; [[file:init-emacs.org::*magit][magit:1]]
;;------------------------------------------------------------------------------
;;; Modules: magit
;;------------------------------------------------------------------------------

(init-message 2 "Modules: magit")

(use-package magit
  :ensure t
  :diminish magit-auto-revert-mode
  :commands (magit-dispatch-popup
             magit-get
             magit-get-push-branch
             magit-get-remote
             magit-refresh)
  :bind* (("C-x g" . magit-status)            ; defaults to undefined
          ("C-x M-g" . magit-dispatch-popup)) ; defaults to undefined
  :init (setq magit-last-seen-setup-instructions "1.4.0")
  :config (progn
            ;; toggle whitespace ignoring
            (defun magit-toggle-whitespace ()
              (interactive)
              (let ((ws "--ignore-all-space"))
                (if (member ws magit-diff-arguments)
                    (setq magit-diff-arguments (remove ws magit-diff-arguments))
                  (add-to-list 'magit-diff-arguments ws t))
                (magit-refresh)))

            ;; amend without any prompt
            (defun magit-commit-amend-without-prompt ()
              (interactive)
              (save-window-excursion
                (shell-command "git --no-pager commit --amend --reuse-message=HEAD")
                (magit-refresh)))

            ;; visit pull request url
            ;; Author: http://endlessparentheses.com/create-github-prs-from-emacs-with-magit.html
            (defun magit-visit-pull-request-url ()
              "Visit the current branch's pull request on Github."
              (interactive)
              (browse-url
               (format "https://github.com/%s/pull/new/%s"
                       (replace-regexp-in-string
                        "\\`.+github\\.com:\\(.+\\)\\.git\\'" "\\1"
                        (magit-get "remote"
                                   (magit-get-remote nil)
                                   "url"))
                       (cdr (magit-get-push-branch)))))

            ;; keybindings
            (bind-keys :map magit-status-mode-map
                       ("W" . magit-toggle-whitespace)
                       ("C-c C-a" . magit-commit-amend-without-prompt))
            (bind-keys :map magit-mode-map
                       ("v" . magit-visit-pull-request-url))
            ;; use ivy
            (setq magit-completing-read-function 'ivy-completing-read)))
;; magit:1 ends here

;; [[file:init-emacs.org::*mingus][mingus:1]]
;;------------------------------------------------------------------------------
;;; Modules: mingus
;;------------------------------------------------------------------------------

(init-message 2 "Modules: mingus")

(use-package mingus
  :load-path (lambda () (expand-file-name "mingus" emacs-modules-dir))
  :commands (mingus
             mingus-create-NP-mark
             mingus-get-details-for-song
             mingus-get-insertion-number
             mingus-get-new-playlist-version
             mingus-goto-line
             mingus-insertion-point-set-p
             mingus-move
             mingus-move-NP-mark
             mingus-playlist-length
             mingus-set-song-pos
             mingus-switch-to-playlist
             mpd-execute-command
             mpd-get-status)
  :bind* ("C-c m" . mingus-switch-to-buffer) ; defaults to undefined
  :config (progn
            ;; add hook to set custom key bindings
            (defun local-mingus-hook-custom-keybindings ()
              (local-set-key (kbd "<left>") 'backward-char)
              (local-set-key (kbd "<right>") 'forward-char)
              (local-set-key (kbd "C-c C-u") 'mingus-mpc-update))
            (add-hook 'mingus-playlist-hook #'local-mingus-hook-custom-keybindings)
            (add-hook 'mingus-browse-hook #'local-mingus-hook-custom-keybindings)

            ;; set playlist separator
            (setq mingus-playlist-separator
                  (if window-system
                      " ● "
                    " - "))

            ;; set current song marker
            (setq mingus-current-song-marker
                  (if window-system
                      "‣‣‣ "
                    ">>> ")))

            ;; start mingus or switch to it if already running
            (defun mingus-switch-to-buffer ()
              (interactive)
              (if (get-buffer "*Mingus*")
                  (switch-to-buffer "*Mingus*")
                (mingus))))

;; fix bug where `mpd-get-status` no longer returns a value for xfade
(defun mingus-make-status-string--xfade (orig-fun &rest args)
  "Fix xfade bug."
  (let ((xfade 0))
    (apply orig-fun args)))
;; advise `mingus-make-status-string`
(advice-add 'mingus-make-status-string :around #'mingus-make-status-string--xfade)

;; recenter screen after moving to current song
(defun mingus-goto-current-song--recenter ()
  "Recenter screen after moving to current song."
  (recenter))
;; advise `mingus-goto-current-song'
(advice-add 'mingus-goto-current-song :after #'mingus-goto-current-song--recenter)

(defun mingus-display-song-rating (highlight)
  "Display song rating of currently selected mingus song.
\nIf HIGHLIGHT is non-nil, highlight song."
  (if (string= (buffer-name) "*Mingus*")
      (let ((pos (point)))
        (goto-char (line-beginning-position))
        (when (re-search-forward " \\[[0-9]\\]$" (line-end-position) t)
          (replace-match ""))
        (goto-char (line-end-position))
        (let ((rating (mingus-get-song-rating)))
          (when rating
            (insert (concat " ["
                            (number-to-string (mingus-get-song-rating))
                            "]"))))
        (when highlight
          (put-text-property (line-beginning-position) (line-end-position) 'face 'font-lock-keyword-face))
        (goto-char pos))
    (error "Not in `*Mingus*' buffer")))

;; custom highlight of current song
(defun mingus-set-NP-mark--highlight-current-song (orig-fun &rest args)
  "Mark entire line of currently playing song.
\nUse text properties to mark the line then call `mingus-set-NP-mark'."
  (ignore-errors
    (let ((pos (or (and (> (length args) 1) (cadr args))
                   (cl-getf (mpd-get-status mpd-inter-conn) 'song))))
      (when pos
        (save-excursion
          (save-window-excursion
            (mingus-switch-to-playlist)
            (let ((prev-pos (line-number-at-pos (overlay-start *mingus-NP-mark*)))
                  buffer-read-only)
              (buffer-disable-undo)
              (mingus-goto-line prev-pos)
              (remove-text-properties (line-beginning-position) (line-end-position) '(face nil))
              (mingus-goto-line (1+ pos))
              (mingus-display-song-rating t)))))))
  (apply orig-fun args))
;; advise `mingus-set-NP-mark'
(advice-add 'mingus-set-NP-mark :around #'mingus-set-NP-mark--highlight-current-song)

;; load ratings into hash tables
(defun mingus-get-all-song-ratings ()
  "Return all song ratings as a hash table of songs to ratings."
  (let ((ratings (make-hash-table :test 'equal)))
    (dotimes (x 5)
      (let* ((rating (1+ x))
             (file (expand-file-name
                    (concat mingus-ratings-prefix (number-to-string rating))
                    mingus-ratings-directory)))
        (with-temp-buffer
          (insert-file-contents file)
          (goto-char (point-min))
          (while (not (eobp))
            (puthash (buffer-substring-no-properties (line-beginning-position) (line-end-position)) rating ratings)
            (forward-line 1)))))
    ratings))

;; background task to display all song ratings
(defun mingus-display-all-song-ratings ()
  "Display all song ratings in mingus playlist buffer."
  (save-excursion
    (save-window-excursion
      (mingus-switch-to-playlist)
      (let ((ratings (mingus-get-all-song-ratings))
            buffer-read-only)
        (buffer-disable-undo)
        (goto-char (point-min))
        (while (not (eobp))
          (ignore-errors
            (let ((rating (get-byte (- (line-end-position) 2))))
              (unless (and (= (get-byte (- (line-end-position) 1)) 93)
                           (= (get-byte (- (line-end-position) 3)) 91)
                           (>= rating 48)
                           (<= rating 53))
                (let ((details (car (mingus-get-details-for-song))))
                  (when details
                    (let* ((file (plist-get details 'file))
                           (rating (gethash file ratings)))
                      (goto-char (line-end-position))
                      (if rating
                          (insert (concat " [" (number-to-string rating) "]"))
                        (insert " [0]"))))))))
          (forward-line 1))))))

;; advise `mingus'
(advice-add 'mingus :after #'mingus-display-all-song-ratings)

;; update mpc
(defun mingus-mpc-update ()
  "Update (refresh) mpc (Music Player Client)"
  (interactive)
  (message "Updating mpc (Music Player Client)...")
  (shell-command "mpc --wait update > /dev/null 2>&1"))

;;-----------------------------------------------------------------------
;;;; Mingus Fetch Lyrics Commands
;;-----------------------------------------------------------------------

(init-message 3 "Mingus Fetch Lyrics Commands")

;; ;; get lyrics (original non-api version)
;; ;; TODO: add ability to query multiple lyric sites when a result is not found on one
;; (defun mingus-get-lyrics ()
;;   (interactive)
;;   (let ((details (car (mingus-get-details-for-song))))
;;     (when details
;;       (let ((artist (plist-get details 'Artist))
;;             (title (plist-get details 'Title))
;;             (site "azlyrics.com")
;;             ;;(site "allthelyrics.com")
;;             ;;(site "lyricwiki.org")
;;             ;;(site "lyrics.wikia.com")
;;             (user-agent "Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)")
;;             (referer "http://www.google.com/")
;;             (file (shell-command-to-string "echo -n /tmp/mingus-lyrics-$$.html")))
;;         ;; remove ", The" from artist
;;         (setq artist (replace-regexp-in-string artist ", The$" ""))
;;         ;; remove anything in parenthesis from title
;;         (setq title (replace-regexp-in-string title " ?([^)]*)" ""))
;;         (let ((query (concat "http://www.google.com/search?q="
;;                              "lyrics "
;;                              "\"" artist "\" "
;;                              "\"" title "\" "
;;                              "site:" site
;;                              "&btnI=Search")))
;;           (call-process "wget" nil nil nil
;;                         "--no-verbose"
;;                         "--convert-links"
;;                         (concat "--user-agent=" user-agent)
;;                         (concat "--referer=" referer)
;;                         "-O" file
;;                         query)
;;           (browse-url (concat "file://" file))
;;           ;; clean up response
;;           (fundamental-mode)
;;           (setq buffer-read-only nil)
;;           (buffer-disable-undo)
;;           (when (re-search-forward "You must enable javascript to view this page." nil t)
;;             (goto-char (line-end-position))
;;             (forward-line 1)
;;             (delete-region (point-min) (point)))
;;           (when (re-search-forward "External links" nil t)
;;             (goto-char (line-beginning-position))
;;             (delete-region (point) (point-max)))
;;           (goto-char (point-min))
;;           (while (re-search-forward "phone Send" nil t)
;;             (delete-region (line-beginning-position) (1+ (line-end-position))))
;;           (setq buffer-read-only nil)
;;           (goto-char (point-min))
;;           )))))

;; get lyrics from azlyrics.com
(defun mingus-get-lyrics-azlyrics (artist title)
  "Return the lyrics for a song matching ARTIST and TITLE
by scraping the azlyrics.com site."
  (interactive)
  (let* ((start-regexp "<!-- Usage of azlyrics.com")
         (end-regexp "<!-- MxM banner -->")
         (ret-regexp "
")
         (bracket-regexp " *\\[[^\]].*\\]")
         (starting-spaces-regexp "^ +")
         (ending-spaces-regexp " +$")
         (feat-regexp "<span class=\"feat\">\\(.*\\)</span>")
         (site "azlyrics.com")
         ;;(user-agent "Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)")
         (user-agent "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; WOW64; Trident/4.0; SLCC1)")
         (referer "http://www.google.com/")
         (file (shell-command-to-string "echo -n /tmp/mingus-lyrics-$$.html"))
         (parsed-title
          (replace-regexp-in-string ending-spaces-regexp ""
                                    (replace-regexp-in-string starting-spaces-regexp ""
                                                              (replace-regexp-in-string bracket-regexp "" title))))
         (query (concat "http://www.google.com/search?q="
                        "lyrics "
                        (if artist "\"" artist "\" " "")
                        "\"" parsed-title "\" "
                        "site:" site
                        "&btnI=Search"))
         (lyrics))
    ;; TODO: make this call asynchronous (using `start-process')
    (call-process "wget" nil nil nil
                  "--no-verbose"
                  "--convert-links"
                  (concat "--user-agent=" user-agent)
                  (concat "--referer=" referer)
                  "-O" file
                  query)
    (message "query: %s" query)
    (message "wget call: wget --no-verbose --convert-links --user-agent=\"%s\" --referer=%s -O %s %s" user-agent referer file query)
    (with-temp-buffer
      (buffer-disable-undo)
      (condition-case err
          (progn
            (insert-file-contents file)
            ;; clean up response
            (fundamental-mode)
            (goto-char (point-min))
            (when (re-search-forward start-regexp nil t)
              (goto-char (line-beginning-position))
              (forward-line 1)
              (let ((point (point)))
                (forward-line -3)
                (delete-region (point) point))
              (forward-line -2)
              (delete-region (point-min) (point)))
            (when (re-search-forward end-regexp nil t)
              (delete-region (line-beginning-position) (point-max)))
            (goto-char (point-min))
            (while (re-search-forward ret-regexp nil t)
              (replace-match ""))
            (goto-char (point-min))
            (while (re-search-forward feat-regexp nil t)
              (replace-match "\\1"))
            (shr-render-region (point-min) (point-max))
            (goto-char (point-max))
            (delete-blank-lines)
            (goto-char (point-min))
            (insert (upcase artist) ": " (upcase title))
            (newline)
            (newline)
            (setq lyrics (buffer-substring-no-properties (point-min) (point-max))))
        ('error
         (message "Error trying to format lyrics result: %s" err)))
      lyrics)))

;; get lyrics from leoslyrics api
;; this site seems to be no longer working (2010-04-06)
(defun mingus-get-lyrics-leoslyrics (artist title)
  "Return the lyrics for a song matching ARTIST and TITLE
using the api.leoslyrics.com site."
  (interactive)
  (let ((query (concat "wget -q \"http://api.leoslyrics.com/api_search.php?auth=emacs"
                       (if artist (concat "&artist=" (url-hexify-string artist)) "")
                       "&songtitle=" (url-hexify-string title)
                       "\" -O - | xmlstarlet sel -t -v \"/leoslyrics/searchResults/result/@hid\"")))
    ;;(message "hid query: %s" query)
    (let ((hid (shell-command-to-string query)))
      (when hid
        ;;(message "hid: %s" (url-hexify-string hid))
        (let ((query (concat "wget -q \"http://api.leoslyrics.com/api_lyrics.php?auth=emacs&hid="
                             (url-hexify-string hid)
                             "\" -O - | xmlstarlet sel -t -v \"/leoslyrics/lyric/text/text()\""
                             " | xmlstarlet unesc | tr -d '\r'")))
          ;;(message "lyrics query: %s" query)
          (let ((lyrics (shell-command-to-string query)))
            lyrics))))))

;; get lyrics from metrolyrics.com
(defun mingus-get-lyrics-metrolyrics (artist title)
  "Return the lyrics for a song matching ARTIST and TITLE
by scraping the metrolyrics.com site."
  (interactive)
  (let* ((start-regexp "<div id=\"lyrics-body-text\">")
         (end-regexp "</div>")
         (ret-regexp "
")
         (bracket-regexp " *\\[[^\]].*\\]")
         (starting-spaces-regexp "^ +")
         (ending-spaces-regexp " +$")
         (site "metrolyrics.com")
         ;;(user-agent "Mozilla/4.0 (MSIE 6.0; Windows NT 5.0)")
         (user-agent "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; WOW64; Trident/4.0; SLCC1)")
         (referer "http://www.google.com/")
         (file (shell-command-to-string "echo -n /tmp/mingus-lyrics-$$.html"))
         (parsed-title
          (replace-regexp-in-string ending-spaces-regexp ""
                                    (replace-regexp-in-string starting-spaces-regexp ""
                                                              (replace-regexp-in-string bracket-regexp "" title))))
         (query (concat "http://www.google.com/search?q="
                        "lyrics "
                        (if artist "\"" artist "\" " "")
                        "\"" parsed-title "\" "
                        "site:" site
                        "&btnI=Search"))
         (lyrics))
    ;; TODO: make this call asynchronous (using `start-process')
    (call-process "wget" nil nil nil
                  "--no-verbose"
                  "--convert-links"
                  (concat "--user-agent=" user-agent)
                  (concat "--referer=" referer)
                  "-O" file
                  query)
    (message "query: %s" query)
    (message "wget call: wget --no-verbose --convert-links --user-agent=\"%s\" --referer=%s -O %s %s" user-agent referer file query)
    (with-temp-buffer
      (buffer-disable-undo)
      (condition-case err
          (progn
            (insert-file-contents file)
            ;; clean up response
            (fundamental-mode)
            (goto-char (point-min))
            (when (re-search-forward start-regexp nil t)
              (goto-char (line-beginning-position))
              (forward-line 1)
              (let ((point (point)))
                (forward-line -3)
                (delete-region (point) point))
              (forward-line -2)
              (delete-region (point-min) (point)))
            (when (re-search-forward end-regexp nil t)
              (delete-region (line-beginning-position) (point-max)))
            (goto-char (point-min))
            (while (re-search-forward ret-regexp nil t)
              (replace-match ""))
            (shr-render-region (point-min) (point-max))
            (goto-char (point-max))
            (delete-blank-lines)
            (goto-char (point-min))
            (insert (upcase artist) ": " (upcase title))
            (newline)
            (newline)
            (setq lyrics (buffer-substring-no-properties (point-min) (point-max))))
        ('error
         (message "Error trying to format lyrics result: %s" err)))
      lyrics)))

;; get lyrics
;; TODO: add ability to query multiple lyric sites when a result is not found on one
(defun mingus-get-lyrics ()
  "Display lyrics for the selected song."
  (interactive)
  (let ((details (car (mingus-get-details-for-song))))
    (when details
      (let ((artist (plist-get details 'Artist))
            (title (plist-get details 'Title))
            (funct 'mingus-get-lyrics-azlyrics))
        ;;(funct 'mingus-get-lyrics-leoslyrics))
        ;;(funct 'mingus-get-lyrics-metrolyrics))
        ;; remove ", The" from artist
        (setq artist (replace-regexp-in-string ", The$" "" artist))
        ;; remove anything in parenthesis from title
        (setq title (replace-regexp-in-string " ?([^)]*)" "" title))
        ;; call lyrics api
        (let ((buffer-name (concat "*" artist ": " title "*"))
              (lyrics (funcall funct artist title)))
          ;; if no lyrics returned, try again with song title only (helps with covers)
          (when (or (not lyrics)
                    (zerop (length lyrics)))
            (setq lyrics (funcall funct nil title)))
          (if (and lyrics
                   (> (length lyrics) 0))
              (progn
                (get-buffer-create buffer-name)
                (set-buffer buffer-name)
                (setq buffer-read-only nil)
                (erase-buffer)
                (insert lyrics)
                (delete-trailing-whitespace)
                (switch-to-buffer buffer-name)
                (goto-char (point-min))
                (view-mode))
            (message "No lyrics found for Artist: %s, Title: %s" artist title)))))))

;; add hook to set key bindings
(defun local-mingus-playlist-hook-mingus-get-lyrics ()
  ;;(local-set-key (kbd "C-c l") 'mingus-get-lyrics)
  (local-set-key (kbd "C-c C-l") 'mingus-get-lyrics))
(add-hook 'mingus-playlist-hook #'local-mingus-playlist-hook-mingus-get-lyrics)

;;-----------------------------------------------------------------------
;;;; Mingus Song Rating System
;;-----------------------------------------------------------------------

(init-message 3 "Mingus Song Rating System")

;; directory to store rating play lists
(defcustom mingus-ratings-directory
  `,(expand-file-name "~/.song-ratings")
  "Directory to store rating play lists."
  :type 'string
  :group 'mingus)

;; rating play list prefix
(defcustom mingus-ratings-prefix
  "songs-rated-"
  "Ratings play list files prefix."
  :type 'string
  :group 'mingus)

;; get rating for selected song
(defun mingus-get-song-rating ()
  "Return song rating of the selected song."
  (interactive)
  (let ((details (car (mingus-get-details-for-song))))
    (when details
      (