;; [[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
;;
;; Timestamp: <2017-08-30 04:44 (kyle)>
;;
;; 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 'cycle-buffer-backward-permissive)
  ;;   (global-set-key (kbd "<f8>") 'cycle-buffer-backward-permissive)) ; 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
  )

(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-<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 'cycle-buffer)
    (global-set-key (kbd "C-<tab>") 'cycle-buffer)) ; defaults to undefined

  ;; cycle buffer backward
  (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 SPC") 'just-one-space) ; defaults to undefined
    (when (fboundp 'eval-after-load-with-byte-compile)
      (eval-after-load-with-byte-compile "gud" ; gud overwrites key binding
        (global-set-key (kbd "C-x SPC") 'just-one-space)))) ; defaults to undefined

  ;; 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'

  ;; 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

  ;; 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-<return>") 'complete-tag)) ; defaults to undefined

  ;; anything
  (when (fboundp 'anything)
    (global-set-key (kbd "M-\\") 'anything)) ; defaults to `delete-horizontal-space'

  ;; 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'
  )

(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::*General%20Settings][General Settings:1]]
;;==============================================================================
;;; General Settings
;;==============================================================================

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

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

(init-message 2 "General 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]]
;;------------------------------------------------------------------------------
;;; General Settings: Environment
;;------------------------------------------------------------------------------

(init-message 2 "General 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" "CST+6")
;; 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
          '("buzz"
            "buzz.local"
            "kyle-work"
            "smith-virtual"))
  "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]]
;;------------------------------------------------------------------------------
;;; General Settings: Global Variables
;;------------------------------------------------------------------------------

(init-message 2 "General 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]]
;; make sure `system-name' is set correctly
(when (string= system-name "localhost.localdomain")
  (let ((name (shell-command-to-string "uname -n")))
    (when (> (length name) 0)
      (setq system-name (substring name 0 -1)))))
;; Global Variables:9 ends here

;; [[file:init-emacs.org::*Global%20Variables][Global Variables:10]]
;; 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:10 ends here

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

;; [[file:init-emacs.org::*Global%20Variables][Global Variables:12]]
;; 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:12 ends here

;; [[file:init-emacs.org::*Global%20Variables][Global Variables:13]]
;; 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:13 ends here

;; [[file:init-emacs.org::*Load%20Path][Load Path:1]]
(init-message 2 "General 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]]
;;------------------------------------------------------------------------------
;;; General Settings: General
;;------------------------------------------------------------------------------

(init-message 2 "General 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 4 and Convert TABs to Spaces")

;; set tab indentation, width, and convert tabs to spaces
(setq indent-tabs-mode nil
      tab-width 4
      standard-indent 4
      tab-always-indent 'complete
      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]]
;;------------------------------------------------------------------------------
;;; General Settings: System
;;------------------------------------------------------------------------------

(init-message 2 "General 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]]
;;------------------------------------------------------------------------------
;;; General Settings: Files
;;------------------------------------------------------------------------------

(init-message 2 "General 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 before-save-hook--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 '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
(add-hook 'write-file-functions 'delete-trailing-whitespace)
;; 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::*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 time and date in mode line
(setq display-time-day-and-date t)
(setq display-time-string-forms '(" " (format-time-string "%a %Y-%m-%d %H:%M" now) " "))
(display-time-mode 1)
;; 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 (buffer-file-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::*Buffers%20and%20Windows][Buffers and Windows:1]]
;;------------------------------------------------------------------------------
;;; General Settings: Buffers and Windows
;;------------------------------------------------------------------------------

(init-message 2 "General 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::*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 x-select-enable-clipboard t                                    ; cutting and pasting uses clipboard
        x-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 (:stipple nil
                           :foreground "#00ff00"
                           :background "#000000"
                           ;; :inverse-video nil
                           ;; :box nil
                           ;; :strike-through nil
                           ;; :overline nil
                           ;; :underline nil
                           ;; :slant normal
                           ;; :weight normal
                           ;; :height 109
                           ;; :width normal
                           ;; :family "misc-fixed"
                           ))))
   '(cursor ((t (:background "#00ff00")))))

  ;; ;; black foreground on white background
  ;; (custom-set-faces
  ;;  '(default ((t (:inherit nil :stipple nil :background "white" :foreground "black"
  ;;                          :inverse-video nil :box nil :strike-through nil
  ;;                          :overline nil :underline nil :slant normal :weight normal
  ;;                          :height 79 :width normal :foundry "unknown"
  ;;                          :family "DejaVu Sans Mono")))))
  )
;; GUI:1 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::*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
(unless (fboundp 'with-eval-after-load)
  (defmacro with-eval-after-load (file &rest body)
    `(eval-after-load ,file
       `(funcall (function ,(lambda () ,@body))))))
(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 (lst)
  "Return space delimited version of items in LST."
  (do ((x lst (cdr x))
          result)
      ((not x) (apply #'concat (reverse result)))
    (if (cdr x)
        (push (concat (car x) " ") result)
      (push (car x) result))))
;; 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 (str)
  "Return list of characters in STR."
  (cl-loop for x across str 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 (lst &optional delim)
  "Convert LST of strings into a single string.
\nUse optional DELIM as a delimiter."
  (if delim
      (cl-reduce (lambda (x y) (concat x delim y)) lst)
    (cl-reduce (lambda (x y) (concat x y)) lst)))
;; 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 (str)
  "Remove trailing carriage returns and new lines from STR.
\nLike the Perl chomp command."
  (if (and
       (stringp str)
       (string-match "\r?\n$" str))
      (replace-match "" t nil str)
    str))
;; 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 (str)
  "Remove starting and trailing whitespace from STR."
  (if (stringp str)
      (replace-regexp-in-string "^[ \t\n]*" ""
                                (replace-regexp-in-string "[ \t\n]*$" "" str))
    str))
;; 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 lst)
  "Call FN for each element in list LST."
  (when lst
    (funcall fn (car lst))
    (for-each fn (cdr lst))))
;; 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 (lst)
  "Return true if LST is a list of one element."
  (and (consp lst) (null (cdr lst))))
;; 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 (lst elm)
  "Append ELM to end of list LST."
  (append lst (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 lst)
  "Call function FN for each element in list LST and return the non-nil results."
  (let (acc)
    (dolist (x lst (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 lst)
  "Call function FN for each element in list LST 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 lst)
      (list nil nil)
    (let* ((wins (car lst))
           (max (funcall fn wins)))
      (dolist (x (cdr lst))
        (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 (lst)
  "Return sorted LST (using the Quicksort algorithm)."
  (if (null lst) nil
    (let* ((elt (car lst))
           (rst (cdr lst))
           (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)))
    (save-excursion
      (forward-line)
      (transpose-lines 1))
    (forward-line)
    (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)))
    (save-excursion
      (forward-line)
      (transpose-lines -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 a word.
With argument ARG, do this that many times."
  (interactive "p")
  (delete-region (point) (progn
                           (let ((space (and (not (bolp))
                                             (char-equal (char-before) ? ))))
                             (forward-word arg)
                             (if (and space
                                      (not (eolp))
                                      (char-equal (char-after) ? ))
                                 (1+ (point))
                               (point))))))
;; 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 (point-at-bol))
    (let ((beg (point)))
      (if (eobp)
          (goto-char (point-at-eol))
        (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 (point-at-bol))
    (let ((beg (point)))
      (if (eobp)
          (goto-char (point-at-eol))
        (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) (point-at-bol))))
    (when line
      (goto-char (point-min))
      (forward-line (1- line)))
    (goto-char (point-at-bol))
    (delete-region (point)
                   (progn
                     (forward-line 1)
                     (point)))
    (if (<= (+ (point) col) (point-at-eol))
        (forward-char col)
      (goto-char (point-at-eol)))))
;; 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 (point-at-eol))
                       (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 (point-at-bol) (point-at-eol))))
      (when comment
        (comment-region (point-at-bol) (point-at-eol)))
      (when (and (fboundp 'org-at-table-p) (org-at-table-p))
        (org-table-insert-row)
        (delete-region (point-at-bol) (1+ (point-at-eol))))
      (goto-char (point-at-eol))
      (newline)
      (insert line)
      (when (or (eq major-mode 'emacs-lisp-mode)
                (eq major-mode 'lisp-mode))
        (forward-line -1)
        (goto-char (point-at-bol))
        (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)))
    (move-to-column col)))
;; 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 (point-at-bol) (point-at-eol))
      (goto-char (point-at-eol))
      (if (eobp)
          (newline)
        (forward-line 1))
      (open-line 1)
      (yank))
    (forward-line 1)
    (while (re-search-forward "[0-9]+" (point-at-eol) 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 (point-at-bol) (point-at-eol)))
;; 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 (point-at-eol))
        ;; 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 (point-at-eol))
                (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-find-file-hook))))))
;; 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-file-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."
  (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-file-functions 'remove-tabs-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::*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) (point-at-eol)) 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) (point-at-bol))
      (forward-line 1)
      (goto-char (point-at-bol)))
    (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")
                     ("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 (str)
  "Escape XML in STR."
  ;; & => &amp;
  (setq str (replace-regexp-in-string "&" "&amp;" str))
  ;; ' => &apos;
  (setq str (replace-regexp-in-string "'" "&apos;" str))
  ;; ! => &bang;
  ;;(setq str (replace-regexp-in-string "!" "&bang;" str))
  ;; = => &eq;
  ;;(setq str (replace-regexp-in-string "=" "&eq;" str))
  ;; > => &gt;
  (setq str (replace-regexp-in-string ">" "&gt;" str))
  ;; < => &lt;
  (setq str (replace-regexp-in-string "<" "&lt;" str))
  ;; ? => &quest;
  ;;(setq str (replace-regexp-in-string "\?" "&quest;" str))
  ;; " => &quot;
  (setq str (replace-regexp-in-string "\"" "&quot;" str))
  ;; / => &slash;
  ;;(setq str (replace-regexp-in-string "/" "&slash;" str))
  ;; return result
  str)
;; 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 (str)
  "Unescape XML in STR."
  ;; &apos; => '
  (setq str (replace-regexp-in-string "&apos;" "'" str))
  ;; &bang; => !
  ;;(setq str (replace-regexp-in-string "&bang;" "!" str))
  ;; &eq; => =
  ;;(setq str (replace-regexp-in-string "&eq;" "=" str))
  ;; &gt; => >
  (setq str (replace-regexp-in-string "&gt;" ">" str))
  ;; &lt; => <
  (setq str (replace-regexp-in-string "&lt;" "<" str))
  ;; &quest; => ?
  ;;(setq str (replace-regexp-in-string "&quest;" "\?" str))
  ;; &quot; => "
  (setq str (replace-regexp-in-string "&quot;" "\"" str))
  ;; &slash; => /
  ;;(setq str (replace-regexp-in-string "&slash;" "/" str))
  ;; &amp; => &
  (setq str (replace-regexp-in-string "&amp;" "&" str))
  ;; return result
  str)
;; 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 (str &optional do-not-cap-ends)
  "Capitalize STR 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 str) 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 str) 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) (point-at-eol))))
         (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) (point-at-bol))))
    (do ((x start (1+ x)))
        ((> x end))
      (insert (number-to-string x))
      (when (< x end)
        (or (zerop (forward-line 1))
            (progn
              (goto-char (point-at-eol))
              (newline)))
        (let ((pos (+ (point-at-bol) 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 (point-at-eol))
    (while (< (- (point) (point-at-bol)) col)
      (insert char))
    (goto-char (+ (point-at-bol) 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 (point-at-bol))
    (while (looking-at " +") (forward-char 1))
    (while (looking-at ";+") (forward-char 1))
    (let ((start (point)))
      (forward-line -1)
      (let ((len (- (point-at-eol) (point-at-bol)))
            (spacer (char-before (point-at-eol))))
        (forward-line 1)
        (while (search-forward (char-to-string spacer) (point-at-eol) t)
          (replace-match ""))
        (goto-char start)
        (while (looking-at " ")
          (delete-char 1 t))
        (goto-char (point-at-eol))
        (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 (point-at-eol))
          (insert " ")
          (insert (make-string (- len (- (point) (point-at-bol))) ?=)))))))
;; 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 (point-at-eol))
          (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) (point-at-bol))))))
;; 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 (point-at-bol))
      ;; 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 (point-at-bol)))
        ;; 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 (point-at-bol))
        (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 (point-at-bol)))
        (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 (point-at-eol) t)
                     (not (equal (get-char-property (point) 'face)
                                 'font-lock-comment-face)))
                ;; remove extra whitespace
                (goto-char (point-at-bol))
                (re-search-forward equal-regexp (point-at-eol))
                (replace-match " = ")
                ;; put point before the equal sign
                (backward-char 2)
                ;; store point if larger than others
                (when (> (- (point) (point-at-bol)) pos)
                  (setq pos (- (point) (point-at-bol)))))
              (goto-char (point-at-bol))
              (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 (point-at-eol) t)
                     (not (equal (get-char-property (point) 'face)
                                 'font-lock-comment-face)))
                (backward-char 2)
                ;; pad as needed
                (while (< (- (point) (point-at-bol)) pos)
                  (insert " ")))
              (goto-char (point-at-bol))
              (forward-line 1))
            ;; handle lines that ends in a comment
            (goto-char (point-min))
            (while (< (point) (point-max))
              (goto-char (point-at-bol))
              (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 (point-at-eol) 'face)
                                 'font-lock-comment-face))
                     (equal (get-char-property (point-at-eol) '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 (point-at-eol) t)
                (replace-match " "))
              (goto-char (point-at-bol))
              (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 (point-at-bol))
                (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 (point-at-bol))
                  (forward-char change-prev)
                  ;; get face-prev of first non-whitespace character
                  (unless face-prev
                    (save-excursion
                      (while (and (< (point) (point-at-eol))
                                  (looking-at whitespace-regexp))
                        (forward-char 1))
                      (when (< (point) (point-at-eol))
                        (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) (point-at-eol))
                              (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) (point-at-eol))
                              (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) (point-at-eol))
                             (< change (- (point) (point-at-bol)))
                             (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) (point-at-bol)))))
                ;; 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 (point-at-bol))
                  (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 (point-at-bol))
                    (forward-char change-prev)
                    ;; find start of face change
                    ;; move forward until whitespace is reached
                    (while (and (< (point) (point-at-eol))
                                (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) (point-at-eol))
                                (or
                                 (looking-at whitespace-regexp)
                                 (not (equal face (get-char-property (point) 'face)))))
                      (forward-char 1))
                    ;; space as needed
                    (while (< (- (point) (point-at-bol)) 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 (point-at-bol))
              (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 (point-at-eol) 'face)
                                 'font-lock-comment-face))
                     (equal (get-char-property (point-at-eol) '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 (point-at-bol))
      (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))
                         (point-at-bol)))
                (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))
                       (point-at-eol)))
                (space (make-string (- (re-search-forward indentation-regexp) (point-at-bol)) ? ))
                (class (progn
                         (goto-char (point-at-bol))
                         (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 (point-at-eol))
            (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)
                           (point-at-bol)
                         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)
                         (point-at-eol)
                       nil)))
              (space (make-string (- (re-search-forward indentation-regexp) (point-at-bol) 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 (point-at-eol))
            (delete-region (point) (progn (forward-line 1) (goto-char (point-at-eol)) (point)))))))))

(init-message 3 "c-toggle-comment-type")

(defalias 'c-toggle-comment-type 'java-toggle-comment-type)
;; java-toggle-comment-type: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 (point-at-bol))
        (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 (point-at-bol))
            (forward-line 3)
            (let ((beg (point)))
              (forward-sexp 2)
              (goto-char (point-at-bol))
              (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 "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 (point-at-bol))
        (when (search-forward "::" (point-at-eol) 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 (point-at-bol))
            (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 (point-at-bol))
              (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 (point-at-bol))))
              ;; remove comment lines
              (goto-char (point-min))
              (while (re-search-forward "^#" (point-max) t)
                (delete-region (point-at-bol) (point-at-eol))
                (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 (point-at-bol))
                (insert " ")
                (forward-line 1))
              ;; copy encoded block
              (setq block (buffer-substring (point-min) (point-max))))
            ;; delete attr data
            (goto-char attr)
            (delete-region (point) (point-at-eol))
            (forward-line 1)
            (goto-char (point-at-bol))
            (while (char-equal (char-after (point)) ? )
              (delete-region (point-at-bol) (point-at-eol))
              (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 (str)
      (cl-loop for x across str collect x))
    (defun list-to-string (lst)
      (cl-reduce (lambda (x y) (concat x y)) lst))
    ;;(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 (point-at-bol))
      (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 (point-at-bol))
            (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 (point-at-bol))
        (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/")
                         ("elpy" . "http://jorgenschaefer.github.io/packages/")
                         ("gnu" . "http://elpa.gnu.org/packages/")
                         ("melpa" . "http://melpa.org/packages/"))
      ;; package-archive-priorities '(("org" . 9)
      ;;                              ("elpy" . 9)
      ;;                              ("gnu" . 5)
      ;;                              ("melpa" . 2))
      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
  :config (paradox-enable))
;; Paradox: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
  :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)

              ;; auto-newline and hungry-delete turned off
              (when (fboundp 'c-toggle-auto-hungry-state) (c-toggle-auto-hungry-state nil))

              ;; ;; 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
              (use-package flyspell
                :ensure t
                :config (flyspell-prog-mode))

              ;; initialize eldoc
              (use-package eldoc
                :ensure t
                :config (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)

              ;; ;; flymake mode
              ;; (use-package flymake
              ;;   :ensure t
              ;;   :config (flymake-mode 1))
              )
            (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)

            ;; mode compile (smart compile)
            (use-package mode-compile
              :disabled t
              :ensure t
              :commands (mode-compile mode-compile-kill)
              :config (bind-keys :map c-mode-base-map
                                 ("C-c c" . mode-compile)
                                 ("C-c k" . mode-compile-kill)))))
;; 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
                         (">" . scroll-calendar-left)
                         ("<" . scroll-calendar-right)
                         ("C-x >" . scroll-calendar-left)
                         ("C-x <" . scroll-calendar-right)))
            (add-hook 'calendar-load-hook 'local-calendar-load-hook)))

;; calendar remind
(use-package calendar-remind
  :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
  :config (progn
            ;; only prompt once for recursive deletes
            (setq dired-recursive-deletes 'top)

            ;; dired hook for more settings
            (defun local-dired-mode-hook ()
              ;; ;; RET use same buffer
              ;; (put 'dired-find-alternate-file 'disabled nil)
              ;; ;; edit file names within dired
              ;; (define-key dired-mode-map (kbd "e") 'wdired-change-to-wdired-mode)

              ;; RET and mouse click use same buffer
              (define-key dired-mode-map (kbd "<return>") 'dired-single-buffer)
              (define-key dired-mode-map (kbd "<mouse-1>") 'dired-single-buffer-mouse)
              ;; ^ use same buffer
              (define-key dired-mode-map (kbd "^") (lambda () (interactive) (dired-single-buffer "..")))
              ;; 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 (make dired use a single buffer)
            (use-package dired-single
              :ensure t)

            ;; 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
  :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
              (use-package flyspell
                :ensure t
                :config (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::*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
  :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::*Java:%20JDEE%20Mode][Java: JDEE Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Java: JDEE Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Java: JDEE Mode")

;; jdee-mode
(use-package jdee
  :ensure t
  ;;:load-path (lambda () (expand-file-name "jdee" emacs-modules-dir))
  :mode (("\\.java\\'" . jdee-mode)
         ("\\.jml\\'" . jdee-mode)
         ("\\.mj\\'" . jdee-mode))
  :commands (jdee-find-class-source-file)
  :functions (jdee-dbs-self-test)
  :config (progn
            ;; jdk locations and default
            (setq jdee-jdk-registry (quote (("1.6" . "/usr/lib/jvm/java-6-oracle")
                                            ("1.7" . "/usr/lib/jvm/java-7-oracle")
                                            ("1.8" . "/usr/lib/jvm/java-8-oracle")))
                  jdee-jdk (quote ("1.7")))

            ;; global classpath
            ;; (setq jdee-global-classpath '(("/usr/share/java/log4j-1.2.12.jar"
            ;;                                "./bin" "./lib" "./src" "./classes" "./config")))

            ;; ;; jdee-server
            ;; (setq jdee-server-dir (expand-file-name "jdee-server/target" emacs-modules-dir))
            ;; java hook
            (defun local-java-mode-hook ()
              ;; set outline header regexp
              (setq-local outline-regexp "\\(?:\\([ \t]*.*\\(class\\|interface\\)[ \t]+[a-zA-Z0-9_]+[ \t\n]*\\({\\|extends\\|implements\\)\\)\\|[ \t]*\\(public\\|private\\|static\\|final\\|native\\|synchronized\\|transient\\|volatile\\|strictfp\\| \\|\t\\)*[ \t]+\\(\\([a-zA-Z0-9_]\\|\\( *\t*< *\t*\\)\\|\\( *\t*> *\t*\\)\\|\\( *\t*, *\t*\\)\\|\\( *\t*\\[ *\t*\\)\\|\\(]\\)\\)+\\)[ \t]+[a-zA-Z0-9_]+[ \t]*(\\(.*\\))[ \t]*\\(throws[ \t]+\\([a-zA-Z0-9_, \t\n]*\\)\\)?[ \t\n]*{\\)")
              ;;(hide-sublevels 1)
              )
            (add-hook 'java-mode-hook 'local-java-mode-hook)))
;; Java: JDEE 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)
  :functions (js-send-last-sexp
              js-send-last-sexp-and-go)
  :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))

            ;; js-comint
            (use-package js-comint
              :ensure t
              :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)
                          (skewer-mode -1))    ; disable skewer-mode as it uses similar key bindings
                        (add-hook 'js2-mode-hook 'local-js2-mode-hook)))

            ;; ;; ac-js2 (auto-complete source for js2-mode)
            ;; (use-package ac-js2
            ;;   :config (add-hook 'js2-mode-hook 'ac-js2-mode))
            ))
;; Javascript: js2 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
  :commands (emacs-lisp-mode)
  :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
              (use-package flyspell
                :ensure t
                :config (flyspell-prog-mode))

              ;; initialize eldoc
              (use-package eldoc
                :ensure t
                :config (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)

            ;; 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))))
            ))
;; 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-interactive-eval
             slime-last-expression
             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 (auto-complete source for slime)
            (use-package ac-slime
              :disabled t
              :ensure t
              :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)))))

(init-message 3 "Elisp Slime Nav Mode (elisp-slime-nav-mode)")

;; elisp-slime-nav-mode
(use-package elisp-slime-nav
  :ensure t
  :diminish 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
;;------------------------------------------------------------------------------

;; markdown-mode
(use-package markdown-mode
  :ensure t
  :mode (("\\.text\\'" . markdown-mode)
         ("\\.markdown\\'" . markdown-mode)
         ("\\.md\\'" . markdown-mode))
  :config (progn
            ;; convert org tables to markdown
            (use-package org-table
              :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
  :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
              (use-package flyspell
                :ensure t
                :config (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" (point-at-eol) t)
                         (search-forward "#!/usr/bin/env perl" (point-at-eol) 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)
  :config (progn
            ;; 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)

            ;; jedi
            (use-package jedi
              :ensure t
              :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::*Ruby%20Mode][Ruby Mode:1]]
;;------------------------------------------------------------------------------
;;; Modes: Ruby Mode
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Ruby Mode")

;; ruby-mode
(use-package ruby-mode
  :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)

            ;; ;; 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)

            ;; robe (Code navigation, documentation lookup and completion for Ruby)
            (use-package robe
              :ensure t
              :config (add-hook 'ruby-mode-hook 'robe-mode))

            ;; inf-ruby
            (use-package inf-ruby
              :disabled t
              :ensure t
              :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 (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)
                        ;;             ))))

            ;; ;; 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" (point-at-eol) t)
                         (search-forward "#!/usr/bin/env ruby" (point-at-eol) 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)
            ))
;; 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" (point-at-eol) t)
                         (search-forward "#!/bin/bash" (point-at-eol) t)
                         (search-forward "#!/bin/csh" (point-at-eol) t)
                         (search-forward "#!/bin/tsh" (point-at-eol) t)
                         (search-forward "#!/usr/bin/env sh" (point-at-eol) t)
                         (search-forward "#!/usr/bin/env bash" (point-at-eol) t)
                         (search-forward "#!/usr/bin/env csh" (point-at-eol) t)
                         (search-forward "#!/usr/bin/env tsh" (point-at-eol) t)
                         (search-forward "#=========" (point-at-eol) t)
                         (search-forward "#---------" (point-at-eol) 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
            ;; use color
            (use-package ansi-color
              :ensure t
              :config (add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on))

            ;; set prompt to read only ???
            (setq comint-prompt-read-only t)

            ;; start a shell
            ;;(shell)
            ))
;; 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
            ;; mysql
            (use-package mysql
              :config (setq sql-product 'mysql))

            ;; tsql
            (use-package 'tsql
              :disabled t)

            ;; ;; 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
            ))
;; 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
(add-to-list 'auto-mode-alist '("\\.txt\\'" . text-mode) t)
(add-to-list 'auto-mode-alist '("\\.text\\'" . text-mode) t)
(add-to-list 'auto-mode-alist '("README" . text-mode) t)
(add-to-list 'auto-mode-alist '("INSTALL" . text-mode) t)
(add-to-list 'auto-mode-alist '("CHANGELOG" . text-mode) t)
(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)
  (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
  (use-package flyspell
    :ensure t
    :config (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
  :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
              (use-package flyspell
                :ensure t
                :config (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
  :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::*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::*anything][anything:1]]
;;------------------------------------------------------------------------------
;;; Modules: anything
;;------------------------------------------------------------------------------

(init-message 2 "Modules: anything")

(use-package anything
  :ensure t
  :commands (anything))
;; anything: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-reqexp)
  :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::*ascii][ascii:1]]
;;------------------------------------------------------------------------------
;;; Modules: ascii
;;------------------------------------------------------------------------------

(init-message 2 "Modules: ascii")

(use-package ascii
  :ensure t
  :commands (ascii-on ascii-off ascii-display ascii-customize))
;; ascii: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
  :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
  :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)
  :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")))

            ;; setup lookout for CSV import/export
            (use-package lookout
              :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
  :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\\|compilation\\)\\*")
              "*Buffer regexps to always show when buffer switching.")
            ;; buffers to never show
            (defvar local-bs-never-show-regexps '("^\\s-" "^\\*" "TAGS$" "^Map_Sym.txt$")
              "*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-str-in-regexps (str regexps)
              "Return non-nil if STR matches anything in REGEXPS list."
              (let ((case-fold-search nil))
                (catch 'done
                  (dolist (regexp regexps)
                    (when (string-match regexp str)
                      (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-str-in-regexps buffer local-bs-always-show-regexps))
                       (local-bs-str-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")

            ;; add ignore rules to ido
            (use-package ido
              :ensure t
              :config (progn
                        (setq ido-ignore-buffers '(local-bs-ignore-buffer))))

            ;; add ignore rules to cycle-buffer
            (use-package cycle-buffer
              :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)))

(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 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))

            ;; set colors for a dark background
            (use-package color
              :ensure t
              :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)))))))

            ;; 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))))
;; company-mode: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::*cycle-buffers][cycle-buffers:1]]
;;------------------------------------------------------------------------------
;;; Modules: cycle-buffers
;;------------------------------------------------------------------------------

(init-message 2 "Modules: cycle-buffers")

(use-package cycle-buffer
  :commands (cycle-buffer
             cycle-buffer-backward
             cycle-buffer-permissive
             cycle-buffer-backward-permissive
             cycle-buffer-toggle-interesting)
  :config (progn
            ;; ;; create cycle functions that catch errors and ignore them
            ;; (dolist (funct '("cycle-buffer"
            ;;                  "cycle-buffer-backward"
            ;;                  "cycle-buffer-permissive"
            ;;                  "cycle-buffer-backward-permissive"))
            ;;   (eval (read
            ;;          (concat "(defun " funct "-noerror (&optional distance)\n"
            ;;                  "  \"Call `" funct "' catching any errors thrown.\"\n"
            ;;                  "  (interactive \"p\")\n"
            ;;                  "  (ignore-errors\n"
            ;;                  "    (" funct " distance)))\n"))))

            ;; add cycle error to debug ignored list
            ;;(add-to-list 'debug-ignored-errors "There is no appropriate buffer to switch to." t)
            (add-to-list 'debug-ignored-errors "There's no point in switching to the current buffer." t)))
;; cycle-buffers: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::*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::*emacs-w3m][emacs-w3m:1]]
;;------------------------------------------------------------------------------
;;; Modules: emacs-w3m
;;------------------------------------------------------------------------------

(init-message 2 "Modules: emacs-w3m")

;; only use if w3m command is available on system
(if (executable-find "w3m")
    (use-package w3m
      :ensure t
      :commands (w3m
                 w3m-browse-url
                 w3m-find-file
                 w3m-search
                 w3m-weather
                 w3m-antenna
                 w3m-namazu)
      :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)))

                ;; w3m-session (persistent sessions)
                (use-package w3m-session
                  :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
                            ))

                ;; 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)
                ))
  (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)
  :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::*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::*hl-line+][hl-line+:1]]
;;------------------------------------------------------------------------------
;;; Modules: hl-line
;;------------------------------------------------------------------------------

(init-message 2 "Modules: hl-line")

(use-package hl-line+
  :ensure t
  :config (progn
            ;; hl-line-face
            (set-face-foreground hl-line-face "#000000")

            ;; highlight when idle code taken from: http://www.emacswiki.org/emacs/HighlightCurrentLine
            (defun hl-line-toggle-when-idle (&optional arg)
              "Turn on or off using `global-hl-line-mode' when Emacs is idle.
    When on, use `global-hl-line-mode' whenever Emacs is idle.
    With prefix argument, turn on if ARG > 0; else turn off."
              (interactive "P")
              (when (and (boundp 'hl-line-when-idle-p)
                         (boundp 'hl-line-idle-timer))
                (setq hl-line-when-idle-p
                      (if arg (> (prefix-numeric-value arg) 0) (not hl-line-when-idle-p)))
                (cond (hl-line-when-idle-p
                       (timer-activate-when-idle hl-line-idle-timer)
                       (message "Turned ON using `global-hl-line-mode' when Emacs is idle."))
                      (t
                       (cancel-timer hl-line-idle-timer)
                       (message "Turned OFF using `global-hl-line-mode' when Emacs is idle.")))))

            (defun hl-line-highlight-now ()
              "Turn on `global-hl-line-mode' and highlight current line now."
              (unless global-hl-line-mode
                (global-hl-line-mode 1)
                (when (fboundp 'global-hl-line-highlight) (global-hl-line-highlight))
                (add-hook 'pre-command-hook 'hl-line-unhighlight-now)))

            (defun hl-line-unhighlight-now ()
              "Turn off `global-hl-line-mode' and unhighlight current line now."
              (global-hl-line-mode -1)
              (when (fboundp 'global-hl-line-unhighlight) (global-hl-line-unhighlight))
              (remove-hook 'pre-command-hook 'hl-line-unhighlight-now))

            ;; turn on highlight when idle
            ;;(hl-line-toggle-when-idle 1)
            ))
;; hl-line+: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
  :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)
            ;; (add-hook 'ibuffer-mode-hook
            ;;           (lambda ()
            ;;             (ibuffer-switch-to-saved-filter-groups "default")))
            ;; (add-to-list 'ibuffer-never-show-regexps "^\\*" t)
            ;; (defun local-ibuffer-mode-hook ()
            ;;   (hl-line-mode 1))
            ;; (add-hook 'ibuffer-mode-hook 'local-ibuffer-mode-hook)
            ;; (defun local-ibuffer-mode-hook ()
            ;;   (defvar cycle-buffer-filter-extra
            ;;     '((and (not (string-match "^\\*.*\\*\\(<[0-9]+>\\)?$" (buffer-name)))
            ;;            (not (string= "*slime-repl clisp*" (buffer-name))))
            ;;       cycle-buffer-interesting)
            ;;     "*List of forms that are evaluated in addition to cycle-buffer-filter for
            ;; the non-permissive versions of the cycle-buffer commands."))
            ;; (add-hook 'ibuffer-mode-hook 'local-ibuffer-mode-hook)
            ))
;; ibuffer:1 ends here

;; [[file:init-emacs.org::*icomplete][icomplete:1]]
;;------------------------------------------------------------------------------
;;; Modules: icomplete
;;------------------------------------------------------------------------------

(init-message 2 "Modules: icomplete")

(use-package icomplete
  :ensure t
  :config (progn
            (use-package icomplete+
              :ensure t)
            (icomplete-mode 1)))
;; icomplete: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)
;; imdb: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::*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
  :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
  :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
  :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 ("C-x g" . magit-status) ; defaults to undefined
                       ("C-x M-g" . magit-dispatch-popup)) ; defaults to undefined
            (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))
            (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 (point-at-bol))
        (when (re-search-forward " \\[[0-9]\\]$" (point-at-eol) t)
          (replace-match ""))
        (goto-char (point-at-eol))
        (let ((rating (mingus-get-song-rating)))
          (when rating
            (insert (concat " ["
                            (number-to-string (mingus-get-song-rating))
                            "]"))))
        (when highlight
          (put-text-property (point-at-bol) (point-at-eol) '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 (point-at-bol) (point-at-eol) '(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 (point-at-bol) (point-at-eol)) 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 (- (point-at-eol) 2))))
              (unless (and (= (get-byte (- (point-at-eol) 1)) 93)
                           (= (get-byte (- (point-at-eol) 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 (point-at-eol))
                      (if rating
                          (insert (concat " [" (number-to-string rating) "]"))
                        (insert " [0]"))))))))
          (forward-line 1))))))

;; advise `mingus'
(advice-add 'mingus :after #'mingus-display-all-song-ratings)

;;-----------------------------------------------------------------------
;;;; 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 (point-at-eol))
;;             (forward-line 1)
;;             (delete-region (point-min) (point)))
;;           (when (re-search-forward "External links" nil t)
;;             (goto-char (point-at-bol))
;;             (delete-region (point) (point-max)))
;;           (goto-char (point-min))
;;           (while (re-search-forward "phone Send" nil t)
;;             (delete-region (point-at-bol) (1+ (point-at-eol))))
;;           (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 (point-at-bol))
              (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 (point-at-bol) (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"))
            (html2text)
            (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 (point-at-bol))
              (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 (point-at-bol) (point-max)))
            (goto-char (point-min))
            (while (re-search-forward ret-regexp nil t)
              (replace-match ""))
            (html2text)
            (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)
                (setq buffer-read-only t)
                (switch-to-buffer buffer-name)
                (goto-char (point-min)))
            (message "No lyrics found for Artist: %s, Title: %s" artist title)))))))

;; 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"))

;; 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)
  (local-set-key (kbd "C-c C-u") 'mingus-mpc-update))
(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
      (let* ((file (plist-get details 'file))
             (song-name (propertize
                         (replace-regexp-in-string "^.*/\\([^/]+\\)\\..*$" "\\1" file)
                         'face
                         'font-lock-keyword-face))
             (get-cmd (concat
                       "cd " mingus-ratings-directory " && "
                       "(for x in $(ls " mingus-ratings-prefix "*) ; do grep -q -F \""
                       (replace-regexp-in-string "\"" "\"" file)
                       "\" \"${x}\" && echo ${x: -1}; done)")))
        ;;(message "get-cmd: %s" get-cmd)
        ;; make sure ratings directory exists
        (unless (file-exists-p mingus-ratings-directory)
          (make-directory mingus-ratings-directory))
        ;; get rating, if there is one
        (let ((rating (shell-command-to-string get-cmd)))
          (when (string-match "\r?\n$" rating)
            (setq rating (replace-match "" t nil rating)))
          (when (zerop (length rating))
            (setq rating "0"))
          (let ((rating-name (propertize rating 'face 'font-lock-keyword-face)))
            ;; print or return rating
            (if (called-interactively-p 'any)
                (message "Rating for %s is %s" song-name rating-name)
              (string-to-number rating))))))))

;; set a rating for selected song
(defun mingus-set-song-rating (rating)
  "Set song rating of the selected song.
\nRATING may be a number from 0 to 5, where 1 is least favorite
and 5 is most favorite.  0 will unset the rating."
  (interactive)
  (unless (and (>= rating 0) (<= rating 5))
    (error "Rating must be a number from 0 through 5"))
  (let ((details (car (mingus-get-details-for-song))))
    (when details
      (let* ((file (plist-get details 'file))
             (song-name (propertize
                         (replace-regexp-in-string "^.*/\\([^/]+\\)\\..*$" "\\1" file)
                         'face
                         'font-lock-keyword-face))
             (rating-name (propertize (number-to-string rating) 'face 'font-lock-keyword-face))
             (playlist (concat mingus-ratings-prefix (number-to-string rating)))
             (clear-cmd (concat
                         "cd " mingus-ratings-directory " && "
                         "(for x in $(ls " mingus-ratings-prefix "*) ; do grep -v -F \""
                         (replace-regexp-in-string "\"" "\"" file)
                         "\" \"${x}\" > tmp ; mv tmp \"${x}\" ; done)"))
             (set-cmd (concat
                       "cd " mingus-ratings-directory " && "
                       "(echo \""
                       (replace-regexp-in-string "\"" "\"" file)
                       "\" >> " playlist ") && "
                       "(cat " playlist " | sort > tmp ; mv tmp " playlist ")")))
        ;;(message "clear-cmd: %s" clear-cmd)
        ;;(message "set-cmd: %s" set-cmd)
        ;; make sure ratings directory exists
        (unless (file-exists-p mingus-ratings-directory)
          (make-directory mingus-ratings-directory))
        ;; clear song from any play lists
        (shell-command clear-cmd)
        ;; if rating > 0, add song to corresponding ratings play list
        (if (> rating 0)
            ;; set rating
            (if (> (shell-command set-cmd) 0)
                (error "Could not set rating for %s" song-name)
              (message "%s rating was set to %s" song-name rating-name))
          ;; rating was cleared
          (message "%s rating was cleared" song-name))
        (let (buffer-read-only)
          (buffer-disable-undo)
          (mingus-display-song-rating nil))))))
(defun mingus-set-song-rating-1 ()
  "Call `mingus-set-song-rating' with a rating of 1."
  (interactive)
  (mingus-set-song-rating 1))
(defun mingus-set-song-rating-2 ()
  "Call `mingus-set-song-rating' with a rating of 2."
  (interactive)
  (mingus-set-song-rating 2))
(defun mingus-set-song-rating-3 ()
  "Call `mingus-set-song-rating' with a rating of 3."
  (interactive)
  (mingus-set-song-rating 3))
(defun mingus-set-song-rating-4 ()
  "Call `mingus-set-song-rating' with a rating of 4."
  (interactive)
  (mingus-set-song-rating 4))
(defun mingus-set-song-rating-5 ()
  "Call `mingus-set-song-rating' with a rating of 5."
  (interactive)
  (mingus-set-song-rating 5))
(defun mingus-set-song-rating-0 ()
  "Call `mingus-set-song-rating' with a rating of 0."
  (interactive)
  (mingus-set-song-rating 0))

(eval-after-load-with-byte-compile "mingus"
  ;; add hook to set key bindings
  (defun local-mingus-playlist-hook-mingus-set-song-rating ()
    (local-set-key (kbd "<f1>") 'mingus-set-song-rating-1)
    (local-set-key (kbd "<f2>") 'mingus-set-song-rating-2)
    (local-set-key (kbd "<f3>") 'mingus-set-song-rating-3)
    (local-set-key (kbd "<f4>") 'mingus-set-song-rating-4)
    (local-set-key (kbd "<f5>") 'mingus-set-song-rating-5)
    (local-set-key (kbd "<f6>") 'mingus-set-song-rating-0))
  (add-hook 'mingus-playlist-hook 'local-mingus-playlist-hook-mingus-set-song-rating))
;; mingus:1 ends here

;; [[file:init-emacs.org::*multiple-cursors][multiple-cursors:1]]
;;------------------------------------------------------------------------------
;;; Modules: multiple-cursors
;;------------------------------------------------------------------------------

(init-message 2 "Modules: multiple-cursors")

(use-package multiple-cursors
  :ensure t
  :config (progn
            ;; keybindings
            (bind-keys ("C-c C->" . mc/edit-lines)
                       ("C-c C-<" . mc/mark-all-like-this)
                       ("C->" . mc/mark-next-like-this)
                       ("C-<" . mc/mark-previous-like-this))))
;; multiple-cursors:1 ends here

;; [[file:init-emacs.org::*neotree][neotree:1]]
;;------------------------------------------------------------------------------
;;; Modules: neotree
;;------------------------------------------------------------------------------

(init-message 2 "Modules: neotree")

(use-package neotree
  :ensure t
  :config (progn
            ;; open tree at current file node
            (setq neo-smart-open t)
            ;; work with projectile
            (setq projectile-switch-project-action 'neotree-projectile-action)))
;; neotree:1 ends here

;; [[file:init-emacs.org::*outline][outline:1]]
;;------------------------------------------------------------------------------
;;; Modules: outline
;;------------------------------------------------------------------------------

(init-message 2 "Modules: outline")

(use-package outline
  :ensure t
  :config (progn
            ;; use outline for all programming buffers
            (add-hook 'prog-mode-hook 'outline-minor-mode)

            ;; set outline prefix key to "\M-#" instead of "\C-c@"
            ;; this needs to be set before outline mode is loaded
            ;;(defvar outline-minor-mode-prefix (kbd "M-#")))) ; defaults to `calc-dispatch'

            (defun outline-minor-mode-hook--prefix-key ()
              "Add additional prefix key to `outline-mode-prefix-map'."
              (local-set-key (kbd "C-c C-o") outline-mode-prefix-map))
              ;;(local-set-key (kbd "M-#") outline-mode-prefix-map))
            (add-hook 'outline-minor-mode-hook 'outline-minor-mode-hook--prefix-key)

            ;; outshine (org-mode like behavior in outline-mode)
            (use-package outshine
              :ensure t
              :functions (outshine-comment-region
                          outshine-mimic-org-log-note-marker)
              :config (progn
                        ;; turn on outshine
                        (add-hook 'outline-minor-mode-hook 'outshine-hook-function)))))
;; outline:1 ends here

;; [[file:init-emacs.org::*persistent-scratch][persistent-scratch:1]]
;;------------------------------------------------------------------------------
;;; Modules: persistent-scratch
;;------------------------------------------------------------------------------

(init-message 2 "Modules: persistent-scratch")

(use-package persistent-scratch
  :ensure t
  :config (progn
            ;; enable autosave and restore last saved state
            (persistent-scratch-setup-default)))
;; persistent-scratch:1 ends here

;; [[file:init-emacs.org::*pivotal-tracker][pivotal-tracker:1]]
;;------------------------------------------------------------------------------
;;; Modules: pivotal-tracker
;;------------------------------------------------------------------------------

(init-message 2 "Modules: pivotal-tracker")

(use-package pivotal-tracker
  :ensure t
  :config (progn
            (let ((api-key-file (expand-file-name "~/.pivotal-api-token")))
              (when (file-exists-p api-key-file)
                (setq pivotal-api-token
                      (chomp
                       (with-temp-buffer
                         (insert-file-contents api-key-file)
                         (buffer-string))))))))
;; pivotal-tracker:1 ends here

;; [[file:init-emacs.org::*proced][proced:1]]
;;------------------------------------------------------------------------------
;;; Modules: proced
;;------------------------------------------------------------------------------

(init-message 2 "Modules: proced")

(use-package proced
  :ensure t
  :commands (proced))
;; proced:1 ends here

;; [[file:init-emacs.org::*projectile][projectile:1]]
;;------------------------------------------------------------------------------
;;; projectile (project interaction library)
;;
;; Install `ack-grep' and `exuberant-ctags' Ubuntu packages for more
;; projectile functionality.
;;------------------------------------------------------------------------------

(init-message 2 "Modules: projectile")

(use-package projectile
  :ensure t
  :diminish (projectile-mode . "Proj")
  :config (progn
            ;; enable projectile globally
            (projectile-mode)

            ;; open the root directory when switching projects
            (setq projectile-switch-project-action 'projectile-dired)

            ;; use ivy
            (setq projectile-completion-system 'ivy)))
;; projectile:1 ends here

;; [[file:init-emacs.org::*ps-ccrypt][ps-ccrypt:1]]
;;------------------------------------------------------------------------------
;;; Modules: ps-ccrypt
;;------------------------------------------------------------------------------

(init-message 2 "Modules: ps-ccrypt")

(use-package ps-ccrypt)
;; ps-ccrypt:1 ends here

;; [[file:init-emacs.org::*psvn][psvn:1]]
;;------------------------------------------------------------------------------
;;; Modules: psvn
;;------------------------------------------------------------------------------

(init-message 2 "Modules: psvn")

(use-package psvn
  :disabled t
  :ensure t
  :commands (psvn svn-checkout svn-examine svn-status)
  :config (progn
            ;; ignore whitespace with diff command
            ;;(setq svn-status-default-diff-arguments '("--diff-cmd" "diff" "-x" "-wbBu")))
            (setq svn-status-default-diff-arguments '("--diff-cmd" "diff" "-x" "-wu"))))
;; psvn:1 ends here

;; [[file:init-emacs.org::*recentf][recentf:1]]
;;------------------------------------------------------------------------------
;;; Modules: recentf
;;------------------------------------------------------------------------------

(init-message 2 "Modules: recentf")

(use-package recentf
  :ensure t
  :config (progn
            (recentf-mode 1)
            (setq recentf-max-menu-items 25)))
;; recentf:1 ends here

;; [[file:init-emacs.org::*regex-tool][regex-tool:1]]
;;------------------------------------------------------------------------------
;;; Modules: regex-tool
;;------------------------------------------------------------------------------

(init-message 2 "Modules: regex-tool")

(use-package regex-tool
  :ensure t
  :commands (regex-tool))
;; regex-tool:1 ends here

;; [[file:init-emacs.org::*simple-mpc][simple-mpc:1]]
;;------------------------------------------------------------------------------
;;; Modules: simple-mpc
;;------------------------------------------------------------------------------

(init-message 2 "Modules: simple-mpc")

(use-package simple-mpc
  :ensure t
  :commands (simple-mpc-call-mpc-string
             simple-mpc-goto-line
             simple-mpc-get-current-playlist-position
             simple-mpc-maybe-refresh-playlist
             simple-mpc-view-current-playlist)
  ;;:bind* ("C-c C-m" . simple-mpc-switch-to-current-playlist) ; defaults to undefined
  :config (progn
            ;; keybindings
            (bind-keys :map simple-mpc-current-playlist-mode-map
                       ;; recenter playlist
                       ("g" . simple-mpc-recenter-playlist)
                       ;; refresh playlist
                       ("G" . simple-mpc-refresh-playlist)
                       ;; lookup lyrics
                       ("C-c C-l" . simple-mpc-get-lyrics)
                       ;; update mpd
                       ("C-c C-u" . simple-mpc-mpd-update)
                       ;; set song ratings
                       ("<f1>" . simple-mpc-set-song-rating-1)
                       ("<f2>" . simple-mpc-set-song-rating-2)
                       ("<f3>" . simple-mpc-set-song-rating-3)
                       ("<f4>" . simple-mpc-set-song-rating-4)
                       ("<f5>" . simple-mpc-set-song-rating-5)
                       ("<f6>" . simple-mpc-set-song-rating-0))

            ;; custom playlist settings
            (setq simple-mpc-playlist-auto-refresh nil) ; do not auto refresh playlist
            ;; (setq simple-mpc-playlist-format "[[%artist%\t%title%]|%file%\t]\t\\[ \\]") ; show artist, title, and file
            ;; (setq simple-mpc-table-separator "\t") ; use table format
            (setq simple-mpc-playlist-format "[[%artist% - %title%]|%file%] \\[ \\]") ; show artist, title, and file
            (setq simple-mpc-table-separator nil) ; do not use table format

            ;; turn off undo in playlist
            (defun simple-mpc-view-current-playlist--disable-undo (&optional ignore-auto noconfirm keep-point)
              "Disable undo in playlist buffer."
              (buffer-disable-undo (get-buffer-create simple-mpc-current-playlist-buffer-name)))
            ;; advise `simple-mpc-view-current-playlist'
            (advice-add 'simple-mpc-view-current-playlist :before #'simple-mpc-view-current-playlist--disable-undo)

            ;; get current song position in playlist
            (defun simple-mpc-current-song-position ()
              "Return the position in the playlist of the current song."
              (string-to-number
               (simple-mpc-call-mpc-string
                (append (list "--format" "%position%") '("current")))))

            ;; recenter playlist
            (defun simple-mpc-recenter-playlist ()
              "If the current buffer is a playlist buffer, recenter point on current song."
              (interactive)
              (when (string= (buffer-name) simple-mpc-current-playlist-buffer-name)
                (simple-mpc-goto-line (simple-mpc-get-current-playlist-position))
                (recenter-top-bottom)))

            ;; switch to playlist buffer or generate it
            (defun simple-mpc-switch-to-current-playlist ()
              "Switch to or create playlist."
              (interactive)
              (if (and (get-buffer simple-mpc-current-playlist-buffer-name)
                       (with-current-buffer simple-mpc-current-playlist-buffer-name
                         (> (buffer-size) 0)))
                  (switch-to-buffer simple-mpc-current-playlist-buffer-name)
                (simple-mpc-view-current-playlist)))

            ;; refresh playlist
            (defun simple-mpc-refresh-playlist ()
              "If the current buffer is a playlist buffer, refresh its contents."
              (interactive)
              (simple-mpc-maybe-refresh-playlist nil))

            ;; update mpc
            (defun simple-mpc-mpd-update ()
              "Update (refresh) mpd (Music Player Daemon)"
              (interactive)
              (message "Updating mpd (Music Player Daemon)...")
              (call-process "mpc" nil nil nil "--wait update"))))

;;-----------------------------------------------------------------------
;;; simple-mpc highlight current song
;;-----------------------------------------------------------------------

(init-message 3 "simple-mpc: Highlight Current Song")

(eval-after-load-with-byte-compile "simple-mpc"
  ;; position of highlight song
  (defvar simple-mpc-highlight-current-song-position nil)

  ;; timer to set highlighting
  (defvar simple-mpc-highlight-current-song-timer nil)

  ;; highlight song
  (defun simple-mpc-highlight-song (position)
    "Highlight song at POSITION in playlist buffer."
    (when (get-buffer simple-mpc-current-playlist-buffer-name)
      (save-excursion
        (with-current-buffer simple-mpc-current-playlist-buffer-name
          (let (buffer-read-only)
            (buffer-disable-undo)
            (unless (and simple-mpc-highlight-current-song-position
                         (= simple-mpc-highlight-current-song-position position))
              (when (and simple-mpc-highlight-current-song-position
                         (/= simple-mpc-highlight-current-song-position position))
                (simple-mpc-goto-line simple-mpc-highlight-current-song-position)
                (put-text-property (point-at-bol) (point-at-eol) 'face nil))
              (simple-mpc-goto-line position)
              (put-text-property (point-at-bol) (point-at-eol) 'face 'font-lock-comment-face)
              (setq simple-mpc-highlight-current-song-position position)))))))

  ;; highlight current song timer
  (defun simple-mpc-highlight-current-song ()
    "Highlight current song in playlist buffer."
    (when (timerp simple-mpc-highlight-current-song-timer)
      (cancel-timer simple-mpc-highlight-current-song-timer))
    (when (get-buffer simple-mpc-current-playlist-buffer-name)
      (simple-mpc-highlight-song (simple-mpc-current-song-position))
      (setq simple-mpc-highlight-current-song-timer
            (run-with-idle-timer 5 nil 'simple-mpc-highlight-current-song))))

  ;; advise `simple-mpc-view-current-playlist'
  (defun simple-mpc-view-current-playlist--highlight-current-song (&optional ignore-auto noconfirm keep-point)
    (simple-mpc-highlight-current-song))
  (advice-add 'simple-mpc-view-current-playlist :after #'simple-mpc-view-current-playlist--highlight-current-song)
  ;; advise `simple-mpc-play-current-line'
  (advice-add 'simple-mpc-play-current-line :after #'simple-mpc-highlight-current-song))

;;-----------------------------------------------------------------------
;;; simple-mpc song rating system
;;-----------------------------------------------------------------------

(init-message 3 "simple-mpc: Song Rating System")

(eval-after-load-with-byte-compile "simple-mpc"
  ;; directory to store rating play lists
  (defcustom simple-mpc-ratings-directory
    `,(expand-file-name "~/.song-ratings")
    "Directory to store rating play lists."
    :type 'string
    :group 'simple-mpc)

  ;; rating play list prefix
  (defcustom simple-mpc-ratings-prefix
    "songs-rated-"
    "Ratings play list files prefix."
    :type 'string
    :group 'simple-mpc)

  ;; song rating regexp
  (defvar simple-mpc-song-rating-regexp
    "\\[[0-9 ]\\]"
    "Song rating bracket regexp.")

  ;; mpc --format '(album "%album%" artist "%artist%" date "%date%" file "%file%" genre "%genre%" modified "%mtime%" position %position% time %time% title "%title%")' playlist

  (defun simple-mpc-set-song-details ()
    "Set song details for each song in simple-mpc playlist buffer.
\nProperties:  album, artist, date, file, genre, modified,
position, time, and title."
    (save-excursion
      (with-current-buffer simple-mpc-current-playlist-buffer-name
        (let (buffer-read-only)
          (buffer-disable-undo)
          (mapc (lambda (line)
                  (let* ((parts (split-string line "\t" nil nil))
                         (details `((:album . ,(nth 0 parts))
                                    (:artist . ,(nth 1 parts))
                                    (:date . ,(nth 2 parts))
                                    (:file . ,(nth 3 parts))
                                    (:genre . ,(nth 4 parts))
                                    (:modified . ,(nth 5 parts))
                                    (:position . ,(nth 6 parts))
                                    (:time . ,(nth 7 parts))
                                    (:title . ,(or (nth 8 parts)
                                                   (nth 3 parts))))))
                    (simple-mpc-goto-line (string-to-number (cdr (assq :position details))))
                    (put-text-property (point-at-bol) (point-at-eol) 'details details)))
                (split-string
                 (simple-mpc-call-mpc-string
                  (append '("--format" "%album%\t%artist%\t%date%\t%file%\t%genre%\t%mtime%\t%position%\t%time%\t%title%")
                          '("playlist")))
                 "\n" t))))))

  (defun simple-mpc-get-song-details ()
    "Return an alist of properties of the song at the current position.
\nSee `simple-mpc-set-song-details' for the list of properties
returned."
    (get-text-property (point-at-bol) 'details))

  ;; display song rating
  (defun simple-mpc-display-song-rating ()
    "Display song rating of currently selected song."
    (when (string= (buffer-name) simple-mpc-current-playlist-buffer-name)
      (let (buffer-read-only
            (pos (point)))
        (buffer-disable-undo)
        (goto-char (point-at-bol))
        (let ((rating (simple-mpc-get-song-rating)))
          (when (and rating
                     (re-search-forward simple-mpc-song-rating-regexp (point-at-eol) t))
            (replace-match (concat "["
                                   (if (zerop rating)
                                       " "
                                     (number-to-string rating))
                                   "]"))))
        (goto-char pos))))

  ;; background task to display all song ratings
  (defun simple-mpc-display-all-song-ratings ()
    "Display all song ratings in simple-mpc playlist buffer."
    (let ((song-ratings (make-hash-table :test 'equal)))
      (dolist (file (directory-files simple-mpc-ratings-directory t (concat "^" simple-mpc-ratings-prefix)))
        (let ((rating (string-to-number (substring file -1))))
          (with-temp-buffer
            (insert-file-contents file)
            (goto-char (point-min))
            (while (not (eobp))
              (puthash (buffer-substring (point-at-bol) (point-at-eol)) rating song-ratings)
              (forward-line 1)))))
      (save-excursion
        (with-current-buffer simple-mpc-current-playlist-buffer-name
          (let (buffer-read-only)
            (buffer-disable-undo)
            (goto-char (point-min))
            (while (not (eobp))
              (let* ((file (cdr (assq :file (simple-mpc-get-song-details))))
                     (rating (gethash file song-ratings)))
                (when (and rating
                           (re-search-forward simple-mpc-song-rating-regexp (point-at-eol) t))
                  (replace-match (concat "[" (number-to-string rating) "]"))))
              (goto-char (point-at-bol))
              (forward-line 1)))))))

  ;; display all song ratings in simple-mpc playlist buffer after `simple-mpc-view-current-playlist' is called
  (defun simple-mpc-view-current-playlist--display-all-song-ratings (&optional ignore-auto noconfirm keep-point)
    "Display all song ratings in simple-mpc playlist buffer after `simple-mpc-view-current-playlist' is called."
    (simple-mpc-set-song-details)
    (simple-mpc-display-all-song-ratings))
  ;; advise `simple-mpc-view-current-playlist'
  (advice-add 'simple-mpc-view-current-playlist :after #'simple-mpc-view-current-playlist--display-all-song-ratings)

  ;; get rating for selected song
  (defun simple-mpc-get-song-rating ()
    "Return song rating of the selected song."
    (interactive)
    (let ((details (simple-mpc-get-song-details)))
      (when details
        (let* ((file (cdr (assq :file details)))
               (artist (cdr (assq :artist details)))
               (title (cdr (assq :title details)))
               (get-cmd (concat
                         "cd " simple-mpc-ratings-directory " && "
                         "(for x in $(ls " simple-mpc-ratings-prefix "*) ; do grep -q -F \""
                         (replace-regexp-in-string "\"" "\"" file)
                         "\" \"${x}\" && echo ${x: -1}; done)")))
          ;;(message "get-cmd: %s" get-cmd)
          ;; make sure ratings directory exists
          (unless (file-exists-p simple-mpc-ratings-directory)
            (make-directory simple-mpc-ratings-directory))
          ;; get rating, if there is one
          (let ((rating (shell-command-to-string get-cmd)))
            (when (string-match "\r?\n$" rating)
              (setq rating (replace-match "" t nil rating)))
            (when (zerop (length rating))
              (setq rating "0"))
            ;; print or return rating
            (if (called-interactively-p 'any)
                (message "Rating for \"%s - %s\" is %s" artist title rating)
              (string-to-number rating)))))))

  ;; set a rating for selected song
  (defun simple-mpc-set-song-rating (rating)
    "Set song rating of the selected song.
  \nRATING may be a number from 0 to 5, where 1 is least favorite
  and 5 is most favorite.  0 will unset the rating."
    (interactive)
    (unless (and (>= rating 0) (<= rating 5))
      (error "Rating must be a number from 0 through 5"))
    (let ((details (simple-mpc-get-song-details)))
      (when details
        (let* ((file (cdr (assq :file details)))
               (artist (cdr (assq :artist details)))
               (title (cdr (assq :title details)))
               (playlist (concat simple-mpc-ratings-prefix (number-to-string rating)))
               (clear-cmd (concat
                           "cd " simple-mpc-ratings-directory " && "
                           "(for x in $(ls " simple-mpc-ratings-prefix "*) ; do grep -v -F \""
                           (replace-regexp-in-string "\"" "\"" file)
                           "\" \"${x}\" > tmp ; mv tmp \"${x}\" ; done)"))
               (set-cmd (concat
                         "cd " simple-mpc-ratings-directory " && "
                         "(echo \""
                         (replace-regexp-in-string "\"" "\"" file)
                         "\" >> " playlist ")")))
          ;;(message "clear-cmd: %s" clear-cmd)
          ;;(message "set-cmd: %s" set-cmd)
          ;; make sure ratings directory exists
          (unless (file-exists-p simple-mpc-ratings-directory)
            (make-directory simple-mpc-ratings-directory))
          ;; clear song from any play lists
          (shell-command clear-cmd)
          ;; if rating > 0, add song to corresponding ratings play list
          (if (> rating 0)
              ;; set rating
              (if (> (shell-command set-cmd) 0)
                  (error "Could not set rating for \"%s - %s\"" artist title)
                (message "\"%s - %s\" rating was set to %s" artist title rating))
            ;; rating was cleared
            (message "\"%s - %s\" rating was cleared" artist title))
          ;; update displayed song rating
          (simple-mpc-display-song-rating)))))

  (defun simple-mpc-set-song-rating-1 ()
    "Call `simple-mpc-set-song-rating' with a rating of 1."
    (interactive)
    (simple-mpc-set-song-rating 1))

  (defun simple-mpc-set-song-rating-2 ()
    "Call `simple-mpc-set-song-rating' with a rating of 2."
    (interactive)
    (simple-mpc-set-song-rating 2))

  (defun simple-mpc-set-song-rating-3 ()
    "Call `simple-mpc-set-song-rating' with a rating of 3."
    (interactive)
    (simple-mpc-set-song-rating 3))

  (defun simple-mpc-set-song-rating-4 ()
    "Call `simple-mpc-set-song-rating' with a rating of 4."
    (interactive)
    (simple-mpc-set-song-rating 4))

  (defun simple-mpc-set-song-rating-5 ()
    "Call `simple-mpc-set-song-rating' with a rating of 5."
    (interactive)
    (simple-mpc-set-song-rating 5))

  (defun simple-mpc-set-song-rating-0 ()
    "Call `simple-mpc-set-song-rating' with a rating of 0."
    (interactive)
    (simple-mpc-set-song-rating 0)))

;;-----------------------------------------------------------------------
;;; simple-mpc fetch lyrics commands
;;-----------------------------------------------------------------------

(init-message 3 "simple-mpc: Fetch Lyrics Commands")

(eval-after-load-with-byte-compile "simple-mpc"
    ;; get lyrics from azlyrics.com
  (defun simple-mpc-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 (point-at-bol))
                (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 (point-at-bol) (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"))
              (html2text)
              (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 simple-mpc-get-lyrics ()
    "Display lyrics for the selected song."
    (interactive)
    (let ((details (simple-mpc-get-song-details)))
      (when details
        (let* ((file (cdr (assq :file details)))
               (artist (cdr (assq :artist details)))
               (title (cdr (assq :title details)))
               (funct 'simple-mpc-get-lyrics-azlyrics))
          ;; 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))
                (with-current-buffer (get-buffer-create buffer-name)
                  (buffer-disable-undo)
                  (let (buffer-read-only)
                    (erase-buffer)
                    (insert lyrics)
                    (delete-trailing-whitespace))
                  (setq buffer-read-only t)
                  (switch-to-buffer buffer-name)
                  (goto-char (point-min)))
              (message "No lyrics found for \"%s - %s\"" artist title))))))))
;; simple-mpc:1 ends here

;; [[file:init-emacs.org::*smerge][smerge:1]]
;;------------------------------------------------------------------------------
;;; Modules: smerge
;;------------------------------------------------------------------------------

(init-message 2 "Modules: smerge")

;; auto turn on smerge mode when a file with merge conflicts is loaded
(when (fboundp 'smerge-mode)
  (defun smerge-mode-maybe ()
    ;; do not perform the search on very large files (to avoid a delay when loaded)
    (when (<= (buffer-size) 10000)
      (save-excursion
        (goto-char (point-min))
        (when (re-search-forward "^<<<<<<< " nil t)
          (smerge-mode 1)))))
  (add-hook 'find-file-hook 'smerge-mode-maybe t))
;; smerge:1 ends here

;; [[file:init-emacs.org::*smex][smex:1]]
;;------------------------------------------------------------------------------
;;; Modules: smex
;;------------------------------------------------------------------------------

(init-message 2 "Modules: smex")

(use-package smex
  :ensure t
  :config (smex-initialize))
;; smex:1 ends here

;; [[file:init-emacs.org::*sokoban][sokoban:1]]
;;------------------------------------------------------------------------------
;;; Modules: sokoban
;;------------------------------------------------------------------------------

(init-message 2 "Modules: sokoban")

(use-package sokoban
  :ensure t
  :commands (sokoban sokoban-mode)
  :config (setq sokoban-levels-dir (expand-file-name "sokoban/sokoban-levels" emacs-modules-dir)))
;; sokoban:1 ends here

;; [[file:init-emacs.org::*split-move][split-move:1]]
;;------------------------------------------------------------------------------
;;; Modules: split-move
;;------------------------------------------------------------------------------

(init-message 2 "Modules: split-move")

(use-package split-move
  :commands (split-move-up split-move-down))
;; split-move:1 ends here

;; [[file:init-emacs.org::*sudoku][sudoku:1]]
;;------------------------------------------------------------------------------
;;; Modules: sudoku
;;------------------------------------------------------------------------------

(init-message 2 "Modules: sudoku")

(use-package sudoku
  :commands (sudoku))
;; sudoku:1 ends here

;; [[file:init-emacs.org::*switch-window][switch-window:1]]
;;------------------------------------------------------------------------------
;;; Modules: switch-window
;;------------------------------------------------------------------------------

(init-message 2 "Modules: switch-window")

(use-package switch-window
  :ensure t
  :commands (switch-window switch-window-then-delete)
  :config (progn
            ;; use home keys to select windows
            (setq switch-window-shortcut-style 'qwerty)))
;; switch-window:1 ends here

;; [[file:init-emacs.org::*swiper%20(ivy)][swiper (ivy):1]]
;;------------------------------------------------------------------------------
;;; Modules: swiper (ivy)
;;------------------------------------------------------------------------------
;;
;; Adds wildcard name completion to common tasks.
;; Replaces `completing-read-function' with `ivy-completing-read'.

(init-message 2 "Modules: swiper (ivy)")

(use-package swiper
  :ensure t
  :diminish ivy-mode
  :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 (various completion functions using ivy)
            (use-package counsel
              :disabled t
              :ensure t
              :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))))))
;; swiper (ivy):1 ends here

;; [[file:init-emacs.org::*timeclock][timeclock:1]]
;;------------------------------------------------------------------------------
;;; Modules: timeclock
;;------------------------------------------------------------------------------

(init-message 2 "Modules: timeclock")

(use-package timeclock
  :ensure t
  :config (progn
            ;;(timeclock-modeline-display)

            ;; keybindings
            (bind-keys ("C-c ti" . timeclock-in)
                       ("C-c to" . timeclock-out)
                       ("C-c tc" . timeclock-change)
                       ("C-c tr" . timeclock-reread-log)
                       ("C-c tu" . timeclock-update-modeline)
                       ("C-c tw" . timeclock-when-to-leave-string)
                       ("C-c tv" . timeclock-visit-timelog)
                       ("C-c ts" . timeclock-status-string)
                       ("C-c td" . timeclock-modeline-display)
                       ("C-c tg" . timeclock-generate-report))))
;; timeclock:1 ends here

;; [[file:init-emacs.org::*time-stamp][time-stamp:1]]
;;------------------------------------------------------------------------------
;;; time-stamp (update header timestamps on file save)
;;
;; When there is a "Timestamp: <>" in the first 20 lines of a file,
;; emacs will write the time-stamp there when saving the file.
;; Timestamp is case insensitive and a dash is optional (i.e. Time-stamp).
;;------------------------------------------------------------------------------

(init-message 2 "Modules: time-stamp")

(use-package time-stamp
  :ensure t
  :config (progn
            (setq time-stamp-active t
                  time-stamp-line-limit 20
                  time-stamp-start "[Tt][Ii][Mm][Ee][-]?[Ss][Tt][Aa][Mm][Pp]:[    ]+\\\\?[\"<]+"
                  time-stamp-format "%04y-%02m-%02d %02H:%02M (%u)")
            (add-hook 'write-file-functions 'time-stamp)))
;; time-stamp:1 ends here

;; [[file:init-emacs.org::*tramp][tramp:1]]
;;------------------------------------------------------------------------------
;;; Modules: tramp
;;------------------------------------------------------------------------------

(init-message 2 "Modules: tramp")

(use-package tramp
  :ensure t
  :commands (tramp)
  :functions (tramp-dissect-file-name
              tramp-file-name-localname
              tramp-tramp-file-p)
  :config (progn
            (setq tramp-default-method "ssh")
            (add-to-list 'tramp-default-method-alist '("\\`localhost\\'" "\\`root\\'" "su") t)))

;;------------------------------------------------------------------------------
;;; tramp file file as root command
;;------------------------------------------------------------------------------

(init-message 3 "tramp: Find File as Root")

(eval-after-load-with-byte-compile "tramp"
  ;; prefix
  (defvar find-file-root-prefix
    "/sudo:root@localhost:"
    "*The file name prefix used to open a file with `find-file-root'.")

  ;; seperate command history
  (defvar find-file-root-history nil
    "History list for files found using `find-file-root'.")

  ;; hook
  (defvar find-file-root-hook nil
    "Normal hook for functions to run after finding a \"root\" file.")

  ;; find file root
  (defun find-file-root ()
    "*Open a file as the root user.
\nPrepends `find-file-root-prefix' to the selected file name so
that it maybe accessed via the corresponding tramp method."
    (interactive)
    (require 'tramp)
    ;; bind the variable `file-name-history' locally so there is a separate
    ;; history list for "root" files
    (let* ((file-name-history find-file-root-history)
           (name (or buffer-file-name default-directory))
           (tramp (and (tramp-tramp-file-p name) (tramp-dissect-file-name name)))
           path dir file)
      ;; when called from a "root" file, fix up the path
      (when tramp
        (setq path (tramp-file-name-localname tramp)
              dir (file-name-directory path)))
      ;; ask for file name
      (when (setq file (read-file-name "Find file (root): " dir path))
        (find-file (concat find-file-root-prefix file))
        ;; if this all succeeded, save our new history list
        (setq find-file-root-history file-name-history)
        ;; allow some user customization
        (run-hooks 'find-file-root-hook))))

  ;; find alternative file as root
  (defun find-alternative-file-root ()
    (interactive)
    (when buffer-file-name
      (find-alternate-file
       (concat "/sudo:root@localhost:"
               buffer-file-name))))

  ;; find file as root or find alternative file as root
  (defun find-file-root-or-find-alternative-file-root ()
    "If current buffer is read-only, run `file-alternative-file-root',
otherwise run `find-file-root'."
    (interactive)
    (if buffer-read-only
        (find-alternative-file-root)
      (find-file-root))))
;; tramp:1 ends here

;; [[file:init-emacs.org::*undo-tree][undo-tree:1]]
;;------------------------------------------------------------------------------
;;; Modules: undo-tree
;;------------------------------------------------------------------------------

(init-message 2 "Modules: undo-tree")

(use-package undo-tree
  :ensure t
  :diminish undo-tree-mode
  :config (progn
            ;; keybindings
            (bind-keys ("<M-mouse-5>" . undo-tree-redo) ; defaults to undefined
                       ("<M-mouse-4>" . undo-tree-undo)) ; defaults to undefined

            ;; turn on undo-tree globally
            (global-undo-tree-mode 1)))
;; undo-tree:1 ends here

;; [[file:init-emacs.org::*web-query][web-query:1]]
;;------------------------------------------------------------------------------
;;; web-query (web site query helper)
;;
;; Only use if w3m command is available on system.
;;------------------------------------------------------------------------------

(init-message 2 "Modules: web-query")

(if (executable-find "w3m")
    (use-package web-query
      :commands (web-query
                 web-query-word
                 web-query-word-at-point
                 web-query-symbol-by-mode
                 web-query-symbol-by-mode-at-point)
      :bind* ("C-c w" . web-query))     ; defaults to undefined
  (message "Warning: Could not find w3m command"))
;; web-query:1 ends here

;; [[file:init-emacs.org::*webjump][webjump:1]]
;;------------------------------------------------------------------------------
;;; Modules: webjump
;;------------------------------------------------------------------------------

(init-message 2 "Modules: webjump")

(use-package webjump
  :ensure t
  :bind* ("C-c j" . webjump)            ; defaults to undefined
  :config (progn
            ;; add some sites
            (add-to-list 'webjump-sites '("Urban Dictionary" . [simple-query "www.urbandictionary.com" "http://www.urbandictionary.com/define.php?term=" ""]) t)))
;; webjump:1 ends here

;; [[file:init-emacs.org::*weblogger][weblogger:1]]
;;------------------------------------------------------------------------------
;;; Modules: weblogger
;;------------------------------------------------------------------------------

(init-message 2 "Modules: weblogger")

(use-package weblogger
  :ensure t
  :commands (weblogger-select-configuration
             weblogger-setup-weblog
             weblogger-start-entry)
  :config (progn
            ;; add weblog sites
            (setq weblogger-config-alist `(("nullman" "http://www.blogger.com/api" ,user-mail-address "" "6007591")
                                           ("Nullman on Life" "http://www2.blogger.com/api" ,user-mail-address "" "6007591")))))
;; weblogger:1 ends here

;; [[file:init-emacs.org::*which-key][which-key:1]]
;;------------------------------------------------------------------------------
;;; Modules: which-key
;;------------------------------------------------------------------------------

(init-message 2 "Modules: which-key")

(use-package which-key
  :ensure t
  :config (which-key-mode))
;; which-key:1 ends here

;; [[file:init-emacs.org::*wtf][wtf:1]]
;;------------------------------------------------------------------------------
;;; Modules: wtf
;;------------------------------------------------------------------------------

(init-message 2 "Modules: wtf")

(use-package wtf
  :commands (wtf-is wtf-get-term-at-point))
;; wtf:1 ends here

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

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

;; [[file:init-emacs.org::*Setup][Setup:1]]
;;------------------------------------------------------------------------------
;;; Menus: Setup
;;------------------------------------------------------------------------------

(init-message 2 "Menus: Setup")
;; Setup:1 ends here

;; [[file:init-emacs.org::*Easy%20Menu][Easy Menu:1]]
;;------------------------------------------------------------------------------
;;;; Menus: Setup: Easy Menu
;;------------------------------------------------------------------------------

(init-message 3 "Menus: Setup: Easy Menu")

;; easymenu
(require 'easymenu)
;; Easy Menu:1 ends here

;; [[file:init-emacs.org::*Auto-Menu][Auto-Menu:1]]
;;------------------------------------------------------------------------------
;;;; Menus: Setup: Auto-Menu
;;------------------------------------------------------------------------------

(init-message 3 "Menus: Setup: Auto-Menu")

;; auto-menu
(require 'auto-menu)
;; Auto-Menu:1 ends here

;; [[file:init-emacs.org::*Find%20or%20Browse%20File][Find or Browse File:1]]
;;------------------------------------------------------------------------------
;;;; Menus: Setup: Find or Browse File
;;------------------------------------------------------------------------------

(init-message 3 "Menus: Setup: Find or Browse File")

;; find or browse file
(defun find-or-browse-file (file)
  "Based on file type either open FILE or browse FILE."
  (let ((file (expand-file-name file)))
    (if (string= (file-name-extension file) "html")
        (browse-url (concat "file://" file))
      (find-file file))))
;; Find or Browse File:1 ends here

;; [[file:init-emacs.org::*Buffer-Switch%20Menu][Buffer-Switch Menu:1]]
;;------------------------------------------------------------------------------
;;; Menus: Buffer-Switch Menu
;;------------------------------------------------------------------------------

(init-message 2 "Menus: Buffer-Switch Menu")

;; buffer-switch menu
(auto-menu
 "Buffer-Switch"
 `(("*scratch*" "(switch-to-buffer \"*scratch*\")" "Switch to '*scratch*' buffer.")
   ("New *scratch*" "(switch-to-buffer (generate-new-buffer-name \"*scratch*\"))" "Create and switch to a '*scratch*' buffer.")
   ("Current Mode *scratch*" "(switch-to-scratch-for-current-mode)" "Switch to '*scratch-MODE*' buffer.")
   ("*messages*" "(switch-to-buffer \"*Messages*\")" "Switch to '*Messages*' buffer.")))
;; Buffer-Switch Menu:1 ends here

;; [[file:init-emacs.org::*Dired%20Menu][Dired Menu:1]]
;;------------------------------------------------------------------------------
;;; Menus: Dired Menu
;;------------------------------------------------------------------------------

(init-message 2 "Menus: Dired Menu")

;; dired menu
(auto-menu
 "Dired"
 ;;(append '(("recent" "context-dired" "Run `cdired' to list recent files.")) ; no longer installed
 (auto-menu-dired `(("home" . "~/")
                    ,(cons "emacs" emacs-home-dir)
                    ;; ,(cons "emacs-modules" (concat emacs-home-dir "/modules"))
                    ;; ,(cons "emacs-mode-abbrevs" (concat emacs-home-dir "/mode-abbrevs"))
                    ;; ,(cons "emacs-init" local-init-dir)
                    ;; ,(cons "emacs-modules" local-modules-dir)
                    ;; ,(cons "emacs-work-modules" local-work-modules-dir)
                    ("bin" . "~/bin")
                    ("org" . "~/org")
                    ("web" . "~/web")
                    ("web/org" . "~/web/org")
                    ("public_html" . "~/public_html")
                    ("plans" . "~/plans")
                    ("reminders" . "~/reminders")
                    ;;("wiki" . "~/wiki")
                    ("doc" . "~/doc")
                    ("dev" . "~/dev")
                    ("prj" . "~/prj")
                    ("media" . "/home/data/media")
                    ("music" . "/home/data/media/audio/Music")
                    ("text" . "/home/data/media/text")
                    ("github" . "~/github/nullman")
                    ("clojure" . "~/dev/clojure")
                    ("clisp" . "~/dev/clisp")
                    ("erlang" . "~/dev/erlang")
                    ("basic" . "~/dev/basic")
                    ("java" . "~/dev/java")
                    ("javascript" . "~/dev/javascript")
                    ,(cons "emacs-help" (concat emacs-home-dir "/help")))))
;;)
;; Dired Menu:1 ends here

;; [[file:init-emacs.org::*Load%20Menu][Load Menu:1]]
;;------------------------------------------------------------------------------
;;; Menus: Load Menu
;;------------------------------------------------------------------------------

(init-message 2 "Menus: Load Menu")

;; load menu
(auto-menu
 "Load"
 `(("Restore Context" "context-restore" "Restore previous context save.")
   ("Home Files..."
    ,(auto-menu-file '((".alias" . "~/.alias")
                       (".alias-local" . "~/.alias-local")
                       (".alias-work" . "~/.alias-work")
                       (".funct" . "~/.funct")
                       (".funct-local" . "~/.funct-local")
                       (".funct-work" . "~/.funct-work")
                       (".profile" . "~/.profile")
                       (".profile-local" . "~/.profile-local")
                       (".profile-work" . "~/.profile-work")
                       (".profile_run" . "~/.profile_run")
                       (".bashrc" . "~/.bashrc")
                       (".clisprc" . "~/.clisprc")
                       (".xbindkeysrc" . "~/.xbindkeysrc"))))
   ("Emacs Initialization..."
    ,(auto-menu-file `(("init-emacs.org" . ,(expand-file-name "init-emacs.org" emacs-home-dir))
                       ("customization.el" . ,(expand-file-name "customization.el" emacs-home-dir)))))
   ;; ("Emacs Initialization..."
   ;;  ,(auto-menu-file-dir local-init-dir "\\.el$" "find-file"))
   ("Emacs Personal Modules..."
    ,(auto-menu-file-dir local-modules-dir "\\.el$" "find-file" t))
   ("Bin Files..."
    ;;,(auto-menu-file-dir "~/bin" nil "find-file" t))
    ,(auto-menu-file '(("get-emacs-modules" . "~/bin/get-emacs-modules"))))
   ("Web Org Files..."
    ,(auto-menu-file-dir "~/web/org" "\\.org$" "find-file" t))
   ("Org Files..."
    ,(auto-menu-file-dir "~/org" "\\.\\(org\\|org\\.cpt\\)$" "find-file" t))
   ("Bookmarks" "load-bookmarks" "Load `~/lynx_bookmarks.html' file.")
   ("Emacs Work Modules..."
    ,(auto-menu-file-dir local-work-modules-dir "\\.el$" "find-file" t))
   ("Clojure Files..."
    ,(auto-menu-file-dir "~/dev/clojure" "\\.clj$" "find-file" t))
   ("CLisp Files..."
    ,(auto-menu-file-dir "~/dev/clisp" "\\.lisp$" "find-file" t))
   ("Erlang Files..."
    ,(auto-menu-file-dir "~/dev/erlang" "\\.erl$" "find-file" t))
   ("BASIC Files..."
    ,(auto-menu-file-dir "~/dev/basic" "\\.bas$" "find-file" t))
   ("Javascript Files..."
    ,(auto-menu-file-dir "~/dev/javascript" "\\.js$" "find-file" t))
   ))
;; Load Menu:1 ends here

;; [[file:init-emacs.org::*Application%20Menu][Application Menu:1]]
;;------------------------------------------------------------------------------
;;;