Table of Contents

1 Overview

This Emacs configuration is in Org/Babel 'literate' programming style.

This file, init-emacs.org, is converted (automatically on save) into init-emacs.el, which is then compiled into init-emacs.elc using org-babel-generate-elisp, which is a custom generator that runs a lot faster than org-babel-tangle.

The 3 section tangles init.el which contains the bootstrap code that defines key methods like org-babel-generate-elisp and runs init-emacs.el.

It was inspired and influenced by the Emacs Starter Kit and Grant Rettke's Creation and Conservation of Computer Files (C3F) Emacs setup. Grant's post on reddit motivated me to convert my (over 10 years old and over 10K lines long) Emacs configuration system to an Org/Babel based one.

Emacs outshines all other editing software in approximately the same way that the noonday sun does the stars. It is not just bigger and brighter; it simply makes everything else vanish.

– Neal Stephenson, "In the Beginning was the Command Line"

2 Information

2.1 Font-Lock Faces

Faces that may be set with font-lock


font-lock-comment-face font-lock-string-face font-lock-keyword-face font-lock-builtin-face font-lock-function-name-face font-lock-variable-name-face font-lock-type-face font-lock-constant-face font-lock-warning-face

3 Init

Tangles init.el bootstrap file.

Note: This section is not automatically tangled on save. If changes are made to it, call org-babel-tangle-block.

;; -*- mode: emacs-lisp; lexical-binding: t; no-byte-compile: t -*-
;;==============================================================================
;; init.el
;;
;;; Bootstrap Emacs Initialization File
;;
;; Author: Kyle W T Sherman
;;
;; This file was generated from init-emacs.org and should not be edited
;; manually.
;;
;; init-emacs.org ==> init.el
;;==============================================================================

;;------------------------------------------------------------------------------
;;; Bootstrap (Org/Babel)
;;------------------------------------------------------------------------------

;; generate elisp and compiled elisp files from an org-babel file
(defun org-babel-generate-elisp-file (file &optional byte-compile force)
  "Generate an emacs-lisp file from an org-babel FILE.
Additionally, byte compile the file if BYTE-COMPILE is non-nil.
Process file even if timestamp is not newer than target if FORCE is non-nil."
  (let* ((file-base (expand-file-name (file-name-sans-extension file)))
         (file-org (concat (file-name-base file) ".org"))
         (file-elisp (concat file-base ".el"))
         (file-comp (concat file-elisp "c"))
         (heading-regexp "^\*+ ")
         (heading-comment-regexp "^\*+ COMMENT ")
         (begin-regexp "^#\\+BEGIN_SRC emacs-lisp")
         (begin-tangle-regexp "^#\\+BEGIN_SRC .*:tangle ")
         (end-regexp "^#\\+END_SRC")
         (indent-regexp "^  "))
    ;; generate elisp file if needed
    (when (or force
              (not (file-exists-p file-elisp))
              (file-newer-than-file-p file-org file-elisp))
      (message "Writing %s..." file-elisp)
      (with-temp-file file-elisp
        (insert-file-contents file)
        (goto-char (point-min))
        (let (code
              headings-counts
              (level 1)
              (comment-level 0)
              (end-comment ""))
          (while (not (eobp))
            (cond
             ;; comment heading
             ((looking-at heading-comment-regexp)
              (setq level (/ (- (match-end 0) (point-at-bol) 8) 2))
              (when (or (zerop comment-level)
                        (< level comment-level))
                (setq comment-level level))
              (delete-region (point-at-bol) (progn (forward-line) (point))))
             ;; normal heading
             ((looking-at heading-regexp)
              (setq level (/ (- (match-end 0) (point-at-bol)) 2))
              (when (or (zerop comment-level)
                        (<= level comment-level))
                (setq comment-level 0)
                (if (assoc level headings-counts)
                    (setf (cdr (assoc level headings-counts))
                          (cons (buffer-substring-no-properties (match-end 0) (point-at-eol)) 1))
                  (setq headings-counts (append headings-counts (list (cons level (cons "No heading" 1)))))))
              (delete-region (point-at-bol) (progn (forward-line) (point))))
             ;; start of tangled source block
             ((and (looking-at begin-regexp)
                   (zerop comment-level)
                   (not (looking-at begin-tangle-regexp))) ; skip blocks with their own tangle directive
              (let* ((heading-count (cdr (assoc level headings-counts)))
                     (heading (car heading-count))
                     (count (cdr heading-count)))
                (delete-region (point-at-bol) (progn (forward-line) (point)))
                (unless (bobp)
                  (newline))
                (when (fboundp 'org-link-escape)
                  (insert (format ";; [[file:%s::*%s][%s:%s]]\n" file-org (org-link-escape heading) heading count))
                  (setq end-comment (format ";; %s:%s ends here\n" heading count))
                  (incf (cddr (assoc level headings-counts))))
                (setq code t)))
             ;; end of tangled source block
             ((and code
                   (looking-at end-regexp))
              (delete-region (point-at-bol) (progn (forward-line) (point)))
              (insert end-comment)
              (setq code nil
                    end-comment ""))
             ;; inside tangled source block
             (code
              (when (looking-at indent-regexp)
                (delete-char (if (boundp 'org-edit-src-content-indentation)
                                 org-edit-src-content-indentation
                               2)))
              (forward-line))
             ;; outside tangled source block
             (t
              (delete-region (point-at-bol) (progn (forward-line) (point))))))
          (time-stamp))
        (message "Wrote %s..." file-elisp)))
    ;; byte compile elisp file if needed
    (when (and byte-compile
               (or (not (file-exists-p file-comp))
                   (file-newer-than-file-p file-elisp file-comp)))
      (byte-compile-file file-elisp))))

;; generate and load main init file
(let* ((file-base (expand-file-name "~/.emacs.d/init-emacs"))
       (file-org (concat file-base ".org"))
       (file-elisp (concat file-base ".el")))
  ;; do not try to byte compile the generated file as it will fail since our environment is not setup
  (org-babel-generate-elisp-file file-org)
  (if (file-exists-p file-elisp)
      (load file-elisp)
    (message "Error loading %s" file-elisp)))

;;------------------------------------------------------------------------------
;;; Slow Bootstrap (Org/Babel)
;;------------------------------------------------------------------------------

;; (let* ((emacs-dir (expand-file-name (file-name-directory (or (buffer-file-name) load-file-name))))
;;        (modules-dir (expand-file-name "modules" emacs-dir)))
;;   (add-to-list 'load-path (expand-file-name "org-mode/lisp" modules-dir))
;;   (add-to-list 'load-path (expand-file-name "org-mode/contrib/lisp" modules-dir))

;;   ;; load org-mode and org-babel
;;   (require 'org-install)
;;   (require 'ob-tangle)

;;   ;; load all literate org-mode files in this directory
;;   (mapc #'org-babel-load-file (directory-files emacs-dir t "\\.org$")))

;;==============================================================================
;;; init.el ends here
;;==============================================================================

4 Start

Status messages are written to the \*Messages\* buffer throughout the initialization process to help debug loading errors.

;; -*- mode: emacs-lisp; lexical-binding: t -*-
;;==============================================================================
;; init-emacs.org
;;
;;; Main Emacs Settings File
;;
;; Author: Kyle W T Sherman
;;
;; Timestamp: <>
;;
;; 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))

5 Key Bindings

;;==============================================================================
;;; Key Bindings
;;==============================================================================

(init-message 1 "Key Bindings")

5.1 Function Keys

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

5.2 Extended Keys

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

5.3 Standard Keys

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

5.4 Modes and Module Keys

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

5.5 Grouped Prefix Keys

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

6 General Settings

General Emacs (non-mode, non-module, non-package) settings.

;;==============================================================================
;;; General Settings
;;==============================================================================

(init-message 1 "General Settings")

6.1 Debugging

;;------------------------------------------------------------------------------
;;; General Settings: Debugging
;;------------------------------------------------------------------------------

(init-message 2 "General Settings: Debugging")

Turn debugging on when errors occur. This will also trap normal (expected) errors, so it should not normally be on.

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

6.2 Environment

;;------------------------------------------------------------------------------
;;; General Settings: Environment
;;------------------------------------------------------------------------------

(init-message 2 "General Settings: Environment")

Set coding system to UTF-8.

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

Set timezone to CST.

;; set timezone to CST
(setenv "TZ" "CST+6")

Do not abbreviate printed objects.

;; set object print depth
(setq print-length nil
      print-level nil
      eval-expression-print-length nil
      eval-expression-print-level nil)

Determine which operating system we are running on. (Linux or Windows.)

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

Determine if we are running on a work computer.

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

Make the user's home directory the default directory.

;; cd to home
(cd "~")

Setup shell environment.

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

6.3 Global Variables

;;------------------------------------------------------------------------------
;;; General Settings: Global Variables
;;------------------------------------------------------------------------------

(init-message 2 "General Settings: Global Variables")

Set Emacs home directory.

;; set emacs home directory
(defconst emacs-home-dir
  ;;(file-truename "~/.emacs.d")
  (expand-file-name "~/.emacs.d")
  "Emacs configuration home directory.")

Macro for setting emacs-home-dir sub-directories.

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

Set Emacs modules directory. This is used for non-ELPA modules that are manually installed.

;; set emacs modules directory
(defconst emacs-modules-dir
  (emacs-home-sub-dir "modules")
  "Emacs modules directory.")

Set local initialization directory. This is not currently used.

;; ;; set local init directory
;; (defconst local-init-dir
;;   (emacs-home-sub-dir "local-init")
;;   "Emacs local initialization directory.")

Set local modules directory. This is used for custom modules that I've written.

;; set local modules directory
(defconst local-modules-dir
  (emacs-home-sub-dir "local-modules")
  "Emacs local modules directory.")

Set local work modules directory. This is used for custom modules that I use for work.

;; set local work modules directory
(defconst local-work-modules-dir
  (emacs-home-sub-dir "local-work-modules")
  "Emacs local work modules directory.")

Set Emacs customizations file. Used to save customizations made with the customize command. I normally move these into this file.

;; set customization file
(defconst customization-file
  (expand-file-name "customization.el" emacs-home-dir)
  "Emacs customization file.")
(setq custom-file customization-file)

Set init-emacs.org true file name.

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

Make sure `system-name' is set correctly.

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

Set various versions of user's name.

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

Set user email addresses.

;; set email address
(defconst user-mail-address
  (if (getenv "EMAIL")
      (getenv "EMAIL")
    (concat "kyle" "w" "sherman" "@" "gmail" "." "com"))
  "User email address.")
;; 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.")

Function that returns an email signature in the form of NAME <MAIL> with an optional fortune added.

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

6.4 Load Path

Add other configuration directories to load-path.

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

6.5 General

;;------------------------------------------------------------------------------
;;; General Settings: General
;;------------------------------------------------------------------------------

(init-message 2 "General Settings: General")

Do not show the startup splash screen.

(init-message 3 "Disable Splash Screen")

;; disable splash screen
(setq inhibit-startup-screen t)

Hide the menu-bar. Use C-M-z to activate it.

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

Set default buffer mode to `text-mode'.

;; (init-message 3 "Set Default Buffer Mode to `text-mode'")

;; ;; set default buffer mode to `text-mode'
;; (setq initial-major-mode 'text-mode)

Set default buffer mode to `org-mode'.

(init-message 3 "Set Default Buffer Mode to `org-mode'")

;; set default buffer mode to `org-mode'
(setq initial-major-mode 'org-mode)

Start with an empty \*scratch\* buffer.

(init-message 3 "Start with Empty Scratch Buffer")

;; clear scratch buffer
(setq initial-scratch-message nil)

Set \*scratch\* buffer mode to `emacs-lisp-mode'.

;; (init-message 3 "Set Scratch Buffer Mode to `emacs-lisp-mode'")

;; ;; set scratch buffer mode to `emacs-lisp-mode'
;; (setq initial-major-mode 'emacs-lisp-mode)

Ask before closing Emacs.

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

Make backspace key work correctly.

(init-message 3 "Make Backspace Key Work Correctly")

;; make baskspace key work
(normal-erase-is-backspace-mode 1)

Add some characters to word boundaries.

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

Ignore comments when parsing s-expressions.

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

Wrap lines by default.

(init-message 3 "Wrap Lines by Default")

;; wrap lines
(setq truncate-lines nil)

Auto-wrap longlines and show hard newlines.

;; (init-message 3 "Auto-Wrap Longlines and Show Hard Newlines")

;; ;; longlines (auto-wrap and show hard newlines)
;; (setq longlines-auto-wrap t
;;       longlines-show-hard-newlines t)

Turn off auto-fill-mode and turn on visual-line-mode as the default behavior.

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

Prevent next-line from inserting newlines. (This stops the cursor at the end of the file.)

(init-message 3 "Prevent `next-line' from Inserting Newlines")

;; stop cursor at the end of the file
(setq next-line-add-newlines nil)

Keep the cursor in the same column when using page-up and page-down.

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

Only scroll one line at a time when moving past the edge of a window.

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

Searches and matches should ignore case.

(init-message 3 "Ignore Case on Search Matches")

;; make searches case-insensitive
(setq case-fold-search t)

Highlight search matches.

(init-message 3 "Highlight Search Matches")

;; highlight search matches
(setq search-highlight t
      ;;isearch-highlight t
      query-replace-highlight t)

Highlight marked regions.

(init-message 3 "Hightlight Marked Regions")

;; make current selection visible
(transient-mark-mode 1)
(setq-default transient-mark-mode t)

Set default tab indentation and width to 4. Also convert tabs to spaces.

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

Set default automatic line-wrapping column to 78. This is used with auto-fill-mode and the fill-paragraph command.

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

Set default right-margin comment indent column to 40. Have comment-fill-column use the value of fill-column.

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

Have up and down cursor movements attempt to keep point on the original column.

(init-message 3 "Have Cursor Movements Attempt to Keep Point on Original Column")

;; turn on goal column support
(put 'set-goal-column 'disabled nil)

Sentences and colons should have two spaces after them.

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

Highlight matching parenthesis when the cursor is on one of them.

(init-message 3 "Highlight Matching Parenthesis")

;; highlight matching parenthesis
(show-paren-mode 1)

Highlight tabs.

(init-message 3 "Highlight TABs")

;; highlight tabs
(setq highlight-tabs t)
(setq-default highlight-tabs highlight-tabs)

Highlight trailing whitespace.

(init-message 3 "Highlight Trailing Whitespace")

;; highlight trailing white spaces
(setq show-trailing-whitespace t)
(setq-default show-trailing-whitespace show-trailing-whitespace)

Set title bar to current buffer's file name.

;; (init-message 3 "Set Title Bar to Current File Name")

;; ;; set current buffer's file name, and full path in title bar
;; (setq frame-title-format '("%b" (buffer-file-name ": %f")))

Set default font to Droid Sans Mono-12 or system 9x15.

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

Turn on syntax highlighting.

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

When text is highlighted, typing will replace the highlighted text.

(init-message 3 "Typing Replaces Highlighted Text")

;; replace highlighted text with typed text
(delete-selection-mode t)

Set commenting style to indent.

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

Have the apropos command search all symbols and order by relevance.

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

Set default grep command.

(init-message 3 "Set Default `grep' Command")

;; set grep command
(setq grep-command "grep -n -H -i -r -e ")

Set email sources.

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

Set default browser.

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

Set print settings.

;; (init-message 3 "Turn off Print Header")

;; ;; print settings
;; (setq ps-print-header nil)

Make single character deletion commands (delete and backspace) delete an active region without saving to the kill ring.

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

Set regular expression to match the beginning of an outline heading.

;; (init-message 3 "Set Outline Regular Expression")

;; ;; set outline regexp
;; (setq outline-regexp "\~")

Disable vc-git as it likes to throw debugger errors when revert-buffer is called.

(init-message 3 "Disable `vc-git'.")

;; disable vc-git
(setq vc-handled-backends nil)

Set time zones to use for display-time-world.

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

6.6 System

;;------------------------------------------------------------------------------
;;; General Settings: System
;;------------------------------------------------------------------------------

(init-message 2 "General Settings: System")

Increase the Emacs Lisp garbage collection threshold to reduce the frequency of garbage collections.

;; reduce frequency of garbage collections
(setq gc-cons-threshold 20000000)       ; defaults to 800000

Allow Emacs to use a larger number of variable bindings and unwind protects.

;; set max variable bindings
(setq max-specpdl-size 10000)           ; defaults to 1300

Allow Emacs to use a larger number of recursions (depth) with eval, apply, funcall functions.

;; set max eval depth
(setq max-lisp-eval-depth 10000)        ; defaults to 600

Prevent the message log from getting too large.

;; set max message log size
(setq message-log-max 2048)             ; defaults to 1000

Increase the maximum size of history lists.

;; set max history list size
(setq history-length 250)               ; defaults to 30

Remove duplicate entries in history lists.

;; remove duplicates from history lists
(setq history-delete-duplicates t)      ; defaults to nil

Make all calls to yes-or-no-p use y-or-n-p instead.

;; change all calls to `yes-or-no-p' to `y-or-n-p'
(fset 'yes-or-no-p 'y-or-n-p)

Enable some functions that are disabled by default.

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

6.7 Files

;;------------------------------------------------------------------------------
;;; General Settings: Files
;;------------------------------------------------------------------------------

(init-message 2 "General Settings: Files")

Enable file local variables, but prompt before running eval on any of them.

;; enable file variables
(setq enable-local-variables t
      enable-local-eval 'maybe)

Set temporary files directory to '/tmp' so any temporary files do not clutter the file system and get cleaned up.

;; set temporary files dir to '/tmp/'
(setq temporary-file-directory "/tmp/")

Turn off auto-save files.

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

Turn off backup files.

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

Turn off lock files.

;; do not make lock files
(setq create-lockfiles nil)
(setq-default create-lockfiles nil)

Follow symlinks of version control files without asking or warning.

;; follow symlinks to version control files without asking or warning
(setq vc-follow-symlinks t)
(setq-default vc-follow-symlinks vc-follow-symlinks)

Turn on auto-compression mode, which will handle uncompressing and compressing various formats as files are loaded and saved.

;; handle gzip/zip/jar/tar files
(auto-compression-mode t)

If a file is already being visited by another buffer under a different name, switch to it instead of loading the file into a new buffer.

;; reuse existing buffers, following file links
(setq find-file-existing-other-name t)

Make sure all files end with a newline when they are saved.

;; end files with a newline
(setq require-final-newline t)

Don't warn when trying to modify read-only buffers.

;; ;; kill text in read-only buffers without warning
;; (setq kill-read-only-ok t)

Automatically revert buffers when the file they are visiting changes.

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

Automatically create directories in file path on file save.

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

Delete trailing whitespace and newlines on file save.

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

Make shell scripts executable when saving (and reset the buffer mode).

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

Save bookmarks file every time it changes.

;; auto-save bookmarks
(setq bookmark-save-flag 1)

Save desktop history.

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

Save minibuffer history.

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

Save place in files.

;; save place in files
(setq save-place t)
(setq-default save-place save-place)

Load TAGS file.

;; ;; load tags table
;; (let ((file (expand-file-name "TAGS" local-init-dir)))
;;   (when (file-exists-p file) (visit-tags-table file)))

6.8 Mode Line

;;------------------------------------------------------------------------------
;;; General Settings: Mode Line
;;------------------------------------------------------------------------------

(init-message 2 "General Settings: Mode Line")

Show the day, date, and time in the mode line.

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

Show line number in the mode line.

;; show line number in mode line
(line-number-mode 1)

Show column number in the mode line.

;; show column number in mode line
(column-number-mode 1)

Set mode line format.

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

Set mode line for projectile-mode.

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

Set mode line for vc-mode.

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

Set mode line modes.

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

Add count words paragraph to mode line.

;; ;;------------------------------------------------------------------------------
;; ;;; Add Count Words Paragraph To Mode Line
;; ;;------------------------------------------------------------------------------

;; (init-message 3 "Count Words")

;; ;; store count in variable
;; (defvar count-words-paragraph
;;   nil
;;   "*Current value returned from `count-words-paragraph' function.")

;; ;; only setup timer once
;; (unless count-words-paragraph
;;   ;; seed count-words-paragraph
;;   (setq count-words-paragraph "0  ")
;;   ;; create timer to keep count-words-paragraph updated
;;   (run-with-idle-timer 0.5 t
;;                        (lambda ()
;;                          (let ((count (number-to-string (count-words-paragraph))))
;;                            (while (< (length count) 3)
;;                              (setq count (concat count " ")))
;;                            (setq count-words-paragraph count)))))

;; ;; add count words paragraph the mode line
;; (unless (and (listp (nth 8 mode-line-format))
;;              (memq 'count-words-paragraph (nth 8 mode-line-format)))
;;   (push (cons '#(" w:" 0 3 (help-echo "mouse-1: select (drag to resize), mouse-2 = C-x 1, mouse-3 = C-x 0"))
;;               '(count-words-paragraph))
;;         (nthcdr 8 mode-line-format)))

;; ;; set mode line
;; (set-default 'mode-line-format mode-line-format)

6.9 Buffers and Windows

;;------------------------------------------------------------------------------
;;; General Settings: Buffers and Windows
;;------------------------------------------------------------------------------

(init-message 2 "General Settings: Buffers and Windows")

Use C-<left> and C-<right> to undo/redo window changes.

;; allow undo/redo of window settings
(when (fboundp 'winner-mode)
  (winner-mode 1))

Turn on imenu indexes. This parses the current buffer and adds an Index menu item that has links to sections based on the buffer type.

TODO: This needs to be added to major mode hooks for modes where we want this feature. However, this can cause a loading delay.

;; ;; turn on imenu bar index
;; (imenu-add-menubar-index)

Automatically scroll the compilation buffer.

;; auto scroll compilation buffer
(setq compilation-scroll-output t)

Delay buffer fontification to increase scroll speed.

;; delay buffer fontification to increase scroll speed
(setq jit-lock-defer-time 0.05)

Preserve buffer point for each window.

;; preserve buffer point for each window
(setq switch-to-buffer-preserve-window-point t)

6.10 Calendar and Diary

;;------------------------------------------------------------------------------
;;; General Settings: Calendar and Diary
;;------------------------------------------------------------------------------

(init-message 2 "General Settings: Calendar and Diary")

Do not show diary entries when calendar is run.

;; turn off diary entries view when calendar is run
(setq calendar-view-diary-initially-flag nil)

Set number of diary days to show.

;; ;; set number of diary days to show
;; (setq diary-number-of-entries 10)

Turn on diary appointments.

;; ;; turn on diary appointments
;; (add-hook 'diary-hook 'appt-make-list)

Turn on calendar marks for diary entries.

;; ;; turn on calendar marks for diary entries
;; (setq mark-diary-entries-in-calendar t)

6.11 GUI

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

7 Functions

Custom functions: Standard functions, Emacs extending/helper functions, complex functions, esoteric functions, games, and mini-programs.

;;==============================================================================
;;; Functions
;;==============================================================================

(init-message 1 "Functions")

7.1 Initialization Functions

Functions that are used to initialize Emacs.

;;------------------------------------------------------------------------------
;;; Functions: Initialization Functions
;;------------------------------------------------------------------------------

(init-message 2 "Functions: Initialization Functions")

7.1.1 safe-substring

A version of substring that does not throw errors.

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

7.1.2 require-if-available

Require symbols and load library strings without throwing any errors.

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

7.1.3 load-file-if-available

Load elisp file if it exists. Does not throw an error if it does not exist.

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

7.1.4 compile-file-if-needed

Compile an elisp file if the source is newer.

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

7.1.5 eval-after-load-with-byte-compile

Byte compiled version of eval-after-load.

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

7.1.6 safe-load

Load files, tracking errors thrown.

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

7.1.7 save-mark-and-excursion

This macro is like `save-excursion', but also saves and restores the mark location and `mark-active'. This macro does what `save-excursion' did before Emacs 25.1.

Author: Daniel Colascione <dancol@dancol.org> Source: http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=255a011f0ecf004b31c59945b10154b10fac3af1

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

7.2 Advice Functions

Modifications to existing functions using advice-add.

;;------------------------------------------------------------------------------
;;; Functions: Advice Functions
;;------------------------------------------------------------------------------

(init-message 2 "Advice Functions")

7.2.1 Compile Goto Error Org

Open compile errors of tangled source in org source file.

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

7.2.2 Find Tag Refresh ETags

;; ;;------------------------------------------------------------------------------
;; ;;;; Functions: Advice Functions: Find Tag Refresh ETags
;; ;;------------------------------------------------------------------------------

;; (init-message 3 "Functions: Advice Functions: Find Tag Refresh ETags")

;; ;; refresh etags
;; (defun refresh-etags (&optional extension)
;;   "Run etags on all peer files in current dir having EXTENSION and reload them silently.
;; \nEXTENSION defaults to 'el'."
;;   (interactive)
;;   (shell-command (format "etags *.%s" (or extension "el")))
;;   (let ((tags-revert-without-query t))
;;    (visit-tags-table default-directory nil)))

;; ;; refresh etags when tag not found (by Järneström Jonas)
;; (defun find-tag--refresh-etags (orig-fun &rest args)
;;   "Refresh etags and reload tags if tag not found, and redo find-tag.
;; \nIf buffer is modified, ask about saving before running etags."
;;   (let ((extension (file-name-extension (buffer-file-name))))
;;    (condition-case nil
;;        (apply orig-fun args)
;;      ('error
;;       (and (buffer-modified-p)
;;            (not (ding))
;;            (yes-or-no-p "Buffer is modified, save it? ")
;;            (save-buffer))
;;       (refresh-etags extension)
;;        (apply orig-fun args)))))
;; ;; advise `find-tag'
;; (advice-add 'find-tag :around #'find-tag--refresh-etags)

7.3 General Functions

;;------------------------------------------------------------------------------
;;; Functions: General Functions
;;------------------------------------------------------------------------------

(init-message 2 "Functions: General Functions")

7.3.1 list-to-string

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

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

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

7.3.3 join-strings

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

7.3.4 file-to-string

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

7.3.5 chomp

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

7.3.6 trim

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

7.3.7 for-each

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

7.3.8 is-single

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

7.3.9 append-element

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

7.3.10 map-integer

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

7.3.11 filter

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

7.3.12 most

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

7.3.13 queue

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

7.3.14 quicksort

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

7.3.15 hash-table-dump

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

7.4 Emacs Functions

;;------------------------------------------------------------------------------
;;; Functions: Emacs Functions
;;------------------------------------------------------------------------------

(init-message 2 "Emacs Functions")

7.4.1 inside-string

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

7.4.2 inside-comment

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

7.4.3 try-finally

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

7.4.4 save-buffer-always

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

7.4.5 save-buffer-always-maybe

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

7.4.6 describe-function-or-variable-at-point

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

7.4.7 mode-line-add

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

7.4.8 insert-line-below

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

7.4.9 insert-line-above

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

7.4.10 move-line-down

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

7.4.11 move-line-up

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

7.4.12 kill-word-enhanced

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

7.4.13 kill-region-or-word

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

7.4.14 kill-duplicate-lines

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

7.4.15 indent-or-expand

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

7.4.16 swap-windows

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

7.4.17 toggle-window-split

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

7.4.18 enlarge-window-5

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

7.4.19 shrink-window-5

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

7.4.20 compile-elisp

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

7.4.21 join-next-line

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

7.4.22 sort-all-lines

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

7.4.23 delete-word

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

7.4.24 copy-line

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

7.4.25 cut-line

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

7.4.26 delete-line

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

7.4.27 delete-to-end-of-line

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

7.4.28 duplicate-line

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

7.4.29 duplicate-line-inc

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

7.4.30 duplicate-sexp

;; ;;------------------------------------------------------------------------------
;; ;;;; Functions: Emacs Functions: duplicate-sexp
;; ;;------------------------------------------------------------------------------

;; (init-message 3 "Functions: Emacs Functions: duplicate-sexp")

;; ;; duplicate sexp
;; (defun duplicate-sexp (&optional comment line)
;;   "Duplicate the sexp containing the point.
;; \nIf COMMENT is non-nil, also comment out the original sexp.
;; If LINE is non-nil, duplicate the sexp at that line instead."
;;   (interactive "*")
;;   (let ((is-at-start-of-sexp
;;         (lambda()
;;           (and (looking-at "(\\|\\[")
;;                (not (nth 3 (syntax-ppss))) ;; not inside string
;;                (not (nth 4 (syntax-ppss)))))) ;; not inside comment
;;        offset)
;;    (save-excursion
;;      (when line
;;        (goto-line line))
;;      (setq offset (point))
;;      (while (not (funcall is-at-start-of-sexp))
;;        (paredit-backward))
;;      (setq offset (- (point) offset))
;;      (set-mark-command nil)
;;      (while (and (bounds-of-thing-at-point 'sexp)
;;                  (<= (point) (car (bounds-of-thing-at-point 'sexp)))
;;                  (not (= (point) (line-end-position))))
;;        (forward-sexp)
;;        (while (looking-at " ")
;;          (forward-char 1)))
;;      (kill-ring-save (mark) (point))
;;      (paredit-newline)
;;      (yank)
;;      (exchange-point-and-mark))))

7.4.31 goto-line-query

;; ;;------------------------------------------------------------------------------
;; ;;;; Functions: Emacs Functions: goto-line-query
;; ;;------------------------------------------------------------------------------

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

;; ;; query user for line to go to
;; ;; already defined as goto-line
;; (defun goto-line-query (line)
;;   "Goto LINE or prompt user for a line number to goto."
;;   (interactive "nGoto line: ")
;;   (goto-line line))

7.4.32 goto-line-enhanced

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

7.4.33 forward-word-enhanced

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

7.4.34 backword-word-enhanced

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

7.4.35 forward-sexp-enhanced

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

7.4.36 backward-sexp-enhanced

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

7.4.37 scroll-up-enhanced

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

7.4.38 scroll-down-enhanced

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

7.4.39 scroll-up-command-enhanced

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

7.4.40 scroll-down-command-enhanced

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

7.4.41 downcase-word-enhanced

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

7.4.42 upcase-word-enhanced

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

7.4.43 capitalize-word-enhanced

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

7.4.44 eval-current-sexp

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

7.4.45 eval-sexp-buffer

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

7.4.46 eval-and-replace-last-sexp

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

7.4.47 eval-and-replace-current-sexp

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

7.4.48 macroexpand-and-replace

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

7.4.49 calc-eval-and-replace-region

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

7.4.50 calc-eval-and-replace-line

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

7.4.51 next-error-recenter-top-bottom

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

7.4.52 indent-current-sexp

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

7.4.53 indent-sexp-buffer

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

7.4.54 comment-or-uncomment-sexp

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

7.4.55 rename-buffer-and-file

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

7.4.56 move-buffer-and-file

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

7.4.57 delete-buffer-and-file

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

7.4.58 expand-relative-file-name

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

7.4.59 remove-trailing-blanks

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

7.4.60 remove-tabs

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

7.4.61 indent-down

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

7.4.62 server-start-maybe

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

7.4.63 load-bookmarks

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

7.4.64 find-file-updir

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

7.4.65 find-file-eof

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

7.4.66 mark-full-word

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

7.4.67 term-buffer

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

7.4.68 term-ansi

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

7.4.69 switch-to-scratch

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

7.4.70 switch-to-scratch-for-current-mode

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

7.4.71 new-scratch

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

7.4.72 new-emacs-lisp-scratch

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

7.4.73 recreate-scratch-when-killed

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

7.4.74 switch-to-messages

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

7.4.75 diff-current-buffer

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

7.4.76 get-char-property-here

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

7.4.77 comments-in-buffer

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

7.4.78 count-words

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

7.4.79 count-words-paragraph

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

7.4.80 date-offset

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

7.4.81 ascii-table

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

7.4.82 match-paren

;; ;;------------------------------------------------------------------------------
;; ;;;; Functions: Emacs Functions: match-paren
;; ;;------------------------------------------------------------------------------

;; (init-message 3 "Functions: Emacs Functions: match-paren")

;; ;; jump to matching parenthesis
;; (defun match-paren (arg)
;;   "Go to the matching parenthesis if point is on a parenthesis."
;;   (interactive "P")
;;   (cond
;;    ((and mark-active (looking-at "\\s\(")) (forward-list 1))
;;    ((and mark-active (looking-back "\\s\)")) (backward-list 1))
;;    ((looking-at "\\s\(") (forward-list 1) (backward-char 1))
;;    ((looking-at "\\s\)") (forward-char 1) (backward-list 1))))

7.4.83 memory-use-counts-pretty

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

7.4.84 git-paste-cleanup

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

7.4.85 execute-buffer

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

7.4.86 file-in-exec-path

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

7.4.88 unicode-shell

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

7.5 Emacs Grouped Functions

;;------------------------------------------------------------------------------
;;; Functions: Emacs Grouped Functions
;;------------------------------------------------------------------------------

(init-message 2 "Emacs Grouped Functions")

7.5.1 Buffer Kill

;;------------------------------------------------------------------------------
;;;; Functions: Emacs Grouped Functions: Buffer Kill
;;------------------------------------------------------------------------------

(init-message 3 "Buffer Kill")
  1. kill-buffer

    Prompt user when a modified buffer is about to be killed, with the option to see the differences, save the buffer, or kill the buffer.

    ;; ;;------------------------------------------------------------------------------
    ;; ;;;;; Functions: Emacs Grouped Functions: Buffer Kill: kill-buffer
    ;; ;;------------------------------------------------------------------------------
    
    ;; (init-message 4 "Functions: Emacs Grouped Functions: Buffer Kill: kill-buffer")
    
    ;; (defun kill-buffer--check (orig-fun &rest args)
    ;;   "Prompt user when a buffer is about to be killed and it has been modified,
    ;; with the option to see the differences, save the buffer, or kill the buffer."
    ;;   (let ((buffer-file-name (buffer-file-name))
    ;;        backup-file)
    ;;    (if (and (buffer-modified-p)
    ;;             buffer-file-name
    ;;             (file-exists-p buffer-file-name)
    ;;             (setq backup-file (car (find-backup-file-name buffer-file-name))))
    ;;        (let ((answer (completing-read (format "Buffer modified %s, (d)iff, (s)ave, (k)ill? " (buffer-name))
    ;;                                       '("d" "s" "k") nil t)))
    ;;          (cond ((string= answer "d")
    ;;                 (set-buffer-modified-p nil)
    ;;                 (let ((orig-buffer (current-buffer))
    ;;                       (file-to-diff (if (file-newer-than-file-p buffer-file-name backup-file)
    ;;                                         buffer-file-name
    ;;                                       backup-file)))
    ;;                   (set-buffer (get-buffer-create (format "%s last-revision" (file-name-nondirectory file-to-diff))))
    ;;                   (buffer-disable-undo)
    ;;                   (insert-file-contents file-to-diff nil nil nil t)
    ;;                   (set-buffer-modified-p nil)
    ;;                   (setq buffer-read-only t)
    ;;                   (ediff-buffers (current-buffer) orig-buffer)))
    ;;                ((string= answer "k")
    ;;                 (set-buffer-modified-p nil)
    ;;                 (apply orig-fun args))
    ;;                (t
    ;;                 (save-buffer)
    ;;                 (apply orig-fun args))))
    ;;      (apply orig-fun args))))
    ;; ;; advise `kill-buffer'
    ;; (advice-add 'kill-buffer :around #'kill-buffer--check)
    
  2. kill-buffer-query-functions-maybe-bury

    Do not kill certain buffers, clear and bury them instead.

    ;;------------------------------------------------------------------------------
    ;;;;; 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)
    
  3. kill-or-bury-buffer

    Either kill buffer or bury it depending on the name.

    ;; ;;------------------------------------------------------------------------------
    ;; ;;;;; Functions: Emacs Grouped Functions: Buffer Kill: kill-or-bury-buffer
    ;; ;;------------------------------------------------------------------------------
    
    ;; (init-message 4 "Functions: Emacs Grouped Functions: Buffer Kill: kill-or-bury-buffer")
    
    ;; ;; kill or bury buffer
    ;; (defun kill-or-bury-buffer (&optional no-prompt)
    ;;   "Either kill buffer or bury it depending on the name.
    ;; \nBuffer names listed in `bury-buffer-names' are cleared and buried.
    ;; If NO-PROMPT is non-nil then current buffer is killed without prompting."
    ;;   (interactive)
    ;;   (if (member (buffer-name (current-buffer)) bury-buffer-names)
    ;;      (progn
    ;;        (kill-region (point-min) (point-max))
    ;;        (bury-buffer))
    ;;    (if no-prompt
    ;;        (kill-buffer (current-buffer))
    ;;      (if (fboundp 'ido-kill-buffer)
    ;;          (ido-kill-buffer)
    ;;        (kill-buffer)))))
    
  4. kill-other-window-buffer

    Kill buffer in other window.

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

7.5.2 Clipboard

X clipboard cut and paste functions.

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.

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

7.5.3 Automatic Indent on Yank

Automatically indent on yank.

;; ;;------------------------------------------------------------------------------
;; ;;;; Functions: Emacs Grouped Functions: Automatic Indent on Yank
;; ;;------------------------------------------------------------------------------

;; (init-message 3 "Functions: Emacs Grouped Functions: Automatic Indent on Yank")

;; ;; modes to automatically indent in
;; (defvar yank-indent-modes '(emacs-lisp-mode
;;                            lisp-interaction-mode
;;                            c-mode c++-mode
;;                            tcl-mode sql-mode
;;                            perl-mode cperl-mode
;;                            java-mode jde-mode
;;                            LaTeX-mode TeX-mode
;;                            xml-mode nxml-mode
;;                            ruby-mode)
;;   "Modes in which to indent regions that are yanked (or yank-popped).")

;; ;; (defvar yank-advised-indent-threshold 1000
;; ;;   "Threshold (# chars) over which indentation does not automatically occur.")

;; ;; (defun yank-advised-indent-function (beg end)
;; ;;   "Do indentation, as long as the region isn't too large."
;; ;;   (if (<= (- end beg) yank-advised-indent-threshold)
;; ;;       (indent-region beg end nil)))

;; ;; indent yanked text
;; (defun yank--indent (&optional arg)
;;   "If current mode is one of `yank-indent-modes', indent yanked
;; text (with prefix arg do not indent)."
;;   (when (and (not arg)
;;             (member major-mode yank-indent-modes))
;;    (let ((transient-mark-mode nil))
;;      ;;(yank-advised-indent-function (region-beginning) (region-end)))))
;;      (indent-region (region-beginning) (region-end) nil))))
;; ;; advise `yank'
;; (advice-add 'yank :after #'yank--indent)

;; ;; yank-pop advice
;; (defun yank-pop--indent (&optional arg)
;;   "If current mode is one of `yank-indent-modes', indent yanked
;; text (with prefix arg do not indent)."
;;   (when (and (not arg)
;;             (member major-mode yank-indent-modes))
;;    (let ((transient-mark-mode nil))
;;      ;;(yank-advised-indent-function (region-beginning) (region-end)))))
;;      (indent-region (region-beginning) (region-end) nil))))
;; ;; advise `yank-pop'
;; (advice-add 'yank-pop :after #'yank-pop--indent)

7.6 Text Conversion Functions

;;------------------------------------------------------------------------------
;;; Functions: Text Conversion Functions
;;------------------------------------------------------------------------------

(init-message 2 "Functions: Text Conversion Functions")

7.6.1 string-match-replace

;; (init-message 3 "Functions: Text Conversion Functions: string-match-replace")

;; ;; search and replace within a string
;; ;; use `replace-regexp-in-string' instead
;; (defun string-match-replace (regexp string replacement
;;                                    &optional start fixedcase literal subexp)
;;   "Use `string-match' to search for REGEXP in STRING, then uses
;; `replace-match' to replace all matches with REPLACEMENT, optionally starting
;; at position START.
;; \nSee `replace-match' for information about the other optional parameters."
;;   (save-match-data
;;    (while (string-match regexp string start)
;;      (replace-match replacement fixedcase literal string subexp))))

7.6.2 escape-xml

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

7.6.3 unescape-xml

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

7.6.4 titleize

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

7.6.5 titleize-word-enhanced

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

7.6.6 titleize-line-or-region

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

7.6.7 unfill-paragraph

Convert a multi-line paragraph into a single line of text.

Copied from Howard Abrams' dot-Emacs file, who in turn got it from someone else.

https://github.com/howardabrams/dot-files/blob/master/emacs.org#unfill-paragraph

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

7.6.8 double-space-punctuation

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

7.6.9 single-space-punctuation

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

7.7 Text Inserting Functions

;;------------------------------------------------------------------------------
;;; Functions: Text Inserting Functions
;;------------------------------------------------------------------------------

(init-message 2 "Text Inserting Functions")

7.7.1 insert-timestamp

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

7.7.2 insert-path

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

7.7.3 uuid

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

7.7.4 insert-uuid

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

7.7.5 uuid-xml

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

7.7.6 insert-uuid-xml

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

7.7.7 insert-incrementing-vertical-numbers

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

7.7.8 append-char-to-column

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

7.7.9 append-equal-to-column-80

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

7.7.10 append-dash-to-column-80

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

7.7.11 append-asterisk-to-column-80

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

7.7.12 insert-lisp-comment-block-equal

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

7.7.13 insert-lisp-comment-block-dash

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

7.7.14 insert-center-lisp-comment

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

7.7.15 insert-c-comment-block

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

7.7.16 insert-c-comment-stub

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

7.7.17 insert-db-change-log-template-line

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

7.7.18 insert-db-change-log-template-line-legacy

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

7.7.19 insert-xml-header

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

7.7.20 insert-lexical-binding

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

7.7.21 insert-figlet

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

7.8 External Program Functions

;;------------------------------------------------------------------------------
;;; Functions: External Program Functions
;;------------------------------------------------------------------------------

(init-message 2 "External Program Functions")

7.8.1 insert-date

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

7.8.2 insert-datetime

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

7.8.3 insert-time

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

7.8.4 insert-date-stamp

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

7.8.5 insert-fortune

TODO: Write versions of insert fortune/quote that remove all newlines and extra whitespace.

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

7.8.6 insert-quote

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

7.9 Newer Emacs Functionality Functions

;;------------------------------------------------------------------------------
;;; Functions: Newer Emacs Functionality Functions
;;------------------------------------------------------------------------------

(init-message 2 "New Emacs Functionality Functions")

7.9.1 line-number-at-pos

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

7.10 Grep Search Functions

;;------------------------------------------------------------------------------
;;; Functions: Grep Search Functions
;;------------------------------------------------------------------------------

(init-message 2 "Grep Searches")

7.10.1 grep-elisp

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

7.10.2 grep-elisp-extended

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

7.10.3 grep-custom

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

7.10.4 grep-custom-generate

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

7.10.5 grep-bin

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

7.10.6 grep-clojure

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

7.10.7 grep-clisp

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

7.10.8 grep-emacs-init

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

7.10.9 grep-home

;; ;;------------------------------------------------------------------------------
;; ;;;; Functions: Grep Search Functions: grep-home
;; ;;------------------------------------------------------------------------------

;; (init-message 3 "Functions: Grep Search Functions: grep-home")

;; ;; grep home
;; (grep-custom-generate grep-home "Grep shell home files: "
;;                      ("~/.bashrc"
;;                       "~/.alias" "~/.alias-local" "~/.alias-work"
;;                       "~/.funct" "~/.funct-local" "~/.funct-work"
;;                       "~/.profile" "~/.profile-local" "~/.profile-work")
;;                      ".*")

7.10.10 grep-home-init

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

7.10.11 grep-org

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

7.10.12 grep-web

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

7.11 TAGS File Functions

;;------------------------------------------------------------------------------
;;; Functions: TAGS File Functions
;;------------------------------------------------------------------------------

(init-message 2 "TAGS Files")

7.11.1 etags-create

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

7.12 Code Formatting Functions

;;------------------------------------------------------------------------------
;;; Functions: Code Formatting Functions
;;------------------------------------------------------------------------------

(init-message 2 "Code Formatting Functions")

7.12.1 indent-region-or-sexp

;;------------------------------------------------------------------------------
;;;; Functions: Code Formatting Functions: indent-region-or-sexp
;;------------------------------------------------------------------------------

(init-message 3 "Functions: Code Formatting Functions: indent-region-or-sexp")


7.12.2 find-code-block

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

7.12.3 lineup-assignment-commands

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

7.12.4 lineup-assignment-commands-indent

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

7.12.5 lineup-declaration-commands

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

7.12.6 lineup-declaration-commands-indent

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

7.12.7 lineup-comments

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

7.12.8 java-toggle-comment-type

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

7.12.9 c-fix-code

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

7.12.10 ruby-fix-code

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

7.12.11 java-fix-code

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

7.12.12 json-fix-code

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

7.12.13 xml-format

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

7.13 Code Inserting Functions

;;------------------------------------------------------------------------------
;;; Functions: Code Inserting Functions
;;------------------------------------------------------------------------------

(init-message 2 "Code Inserting Functions")

7.13.1 project-euler-insert-template

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

7.13.2 insert-tree

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

7.14 Esoteric Functions

;;------------------------------------------------------------------------------
;;; Functions: Esoteric Functions
;;------------------------------------------------------------------------------

(init-message 2 "Functions: Esoteric Functions")

7.14.1 Fahrenheit/Celsius Conversions

;;------------------------------------------------------------------------------
;;;; Functions: Esoteric Functions: Fahrenheit/Celsius Conversions
;;------------------------------------------------------------------------------

(init-message 3 "Fahrenheit/Celsius Conversions")
  1. fahrenheit-to-celsius
    ;;------------------------------------------------------------------------------
    ;;;;; 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))
    
  2. fahrenheit-to-celsius-query
    ;;------------------------------------------------------------------------------
    ;;;;; 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))
    
  3. celsius-to-fahrenheit
    ;;------------------------------------------------------------------------------
    ;;;;; 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))
    
  4. celsius-to-fahrenheit-query
    ;;------------------------------------------------------------------------------
    ;;;;; 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))
    

7.14.2 base-conversion

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

7.14.3 ldif-update-xml

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

7.15 Programs

;;------------------------------------------------------------------------------
;;; Functions: Programs
;;------------------------------------------------------------------------------

(init-message 2 "Functions: Programs")

7.15.1 National Debt

Return the current US national debt.

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

7.15.2 Flesch Readability Index

Compute the Flesch Readability Index of the current region or entire buffer.

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

7.15.3 Phone Number Words

Convert phone number NUM into word strings that may be used instead.

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

7.15.4 Keyboard Cat Mode

Buffer types out as you hit keyboard buttons.

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

7.15.5 Keyboard Display Mode

Display key presses using gxmessage.

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

7.15.6 Star Wars Scroll

Scroll current text buffer like Star Wars opening text.

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

7.16 Games

;;------------------------------------------------------------------------------
;;; Functions: Games
;;------------------------------------------------------------------------------

(init-message 2 "Functions: Games")

7.16.1 Towers of Hanoi

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

8 Package Manager

Package managers.

;;==============================================================================
;;; Package Manager
;;==============================================================================

(init-message 1 "Package Manager")

8.1 ELPA (Emacs Lisp Package Archive)

ELPA (Emacs Lisp Package Archive) configuration.

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

8.2 Paradox

Paradox Package Menu.

A modern Packages Menu. Colored, with package ratings, and customizable.

;;------------------------------------------------------------------------------
;;; Package Manager: Paradox
;;------------------------------------------------------------------------------

(init-message 2 "Package Manager: Paradox")

;; paradox package menu
(use-package paradox
  :ensure t
  :config (paradox-enable))

9 Modes

Mode package settings.

;;==============================================================================
;;; Modes
;;==============================================================================

(init-message 1 "Modes")

9.1 Setup

;;------------------------------------------------------------------------------
;;; Modes: Setup
;;------------------------------------------------------------------------------

(init-message 2 "Modes: Setup")

;; turn off electric mode for all cc modes
(setq-default c-electric-flag nil)

9.2 Auto-Indent Mode

Auto-Indent Mode (auto-indent-mode)

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: Auto-Indent Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: Auto-Indent Mode")

;; ;; auto-indent-mode
;; ;; disabled as it's too slow
;; (use-package auto-indent-mode
;;   :disabled t
;;   :ensure t
;;   :config (progn
;;            (auto-indent-global-mode)
;;            (setq auto-indent-indent-style 'conservative)))

9.3 Brainfuck Mode

Brainfuck Mode (brainfuck-mode)

;;------------------------------------------------------------------------------
;;; Modes: Brainfuck Mode
;;------------------------------------------------------------------------------

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

;; brainfuck-mode
(use-package brainfuck-mode
  :ensure t
  :mode ("\\.bf\\'" . brainfuck-mode))

9.4 BASIC Mode

BASIC Mode (basic-mode)

;;------------------------------------------------------------------------------
;;; Modes: BASIC Mode
;;------------------------------------------------------------------------------

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

;; basic-mode
(use-package basic
  :mode ("\\.bas\\'" . basic-mode))

9.5 C Mode

C Mode (c-mode and c++-mode)

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

9.6 Calendar Mode

Calendar Mode (calendar-mode and calendar-remind)

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

9.7 Crypt Mode

Crypt Mode (crypt++)

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: Crypt Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: Crypt Mode")

;; ;; crypt++ (file encryption support)
;; (use-package crypt++
;;   :disabled t
;;   :ensure t
;;   :init (setq crypt-encryption-type 'crypt
;;               crypt-encryption-file-extension "\\(Secure\\)$\\|\\(\\.enc\\)$"
;;               crypt-bind-insert-file nil
;;               crypt-freeze-vs-fortran nil)
;;   :config (progn
;;             (modify-coding-system-alist 'file "\\.bz\\'" 'no-conversion)
;;             (modify-coding-system-alist 'file "\\.bz2\\'" 'no-conversion)
;;             (modify-coding-system-alist 'file "\\.gpg\\'" 'no-conversion)
;;             (modify-coding-system-alist 'file "\\.gz\\'" 'no-conversion)
;;             (modify-coding-system-alist 'file "\\.Z\\'" 'no-conversion)

;;             ;; redefine crypt-build-encryption-alist
;;             (defun crypt-build-encryption-alist ()
;;               ;; Returns the encryption alist
;;               (list
;;                ;; crypt
;;                (list 'crypt
;;                      crypt-encryption-magic-regexp crypt-encryption-magic-regexp-inverse
;;                      (or crypt-encryption-file-extension "\\.\\(e\\|enc\\)$")
;;                      "mcrypt" "mcrypt"
;;                      '("--algorithm" "enigma" "--mode" "stream" "--bare" "--quiet" "--key")
;;                      '("--decrypt" "--algorithm" "enigma" "--mode" "stream" "--bare" "--quiet" "--key")
;;                      "Crypt" nil t)
;;                ;; DES (Cipher Block Chaining - CBC) [DES' default]
;;                (list 'des
;;                      crypt-encryption-magic-regexp crypt-encryption-magic-regexp-inverse
;;                      (or crypt-encryption-file-extension "\\(\\.des\\)$")
;;                      "mcrypt" "mcrypt"
;;                      '("--bzip2" "--algorithm" "des" "--keymode" "pkdes" "--bare" "--force" "--quiet" "--key")
;;                      '("--decrypt" "--bzip2" "--algorithm" "des" "--keymode" "pkdes" "--bare" "--force" "--quiet" "--key")
;;                      "DES" nil t)
;;                ;; DES (Electronic Code Book - ECB)
;;                (list 'des-ecb
;;                      crypt-encryption-magic-regexp crypt-encryption-magic-regexp-inverse
;;                      (or crypt-encryption-file-extension "\\(\\.des\\)$")
;;                      "des" "des"
;;                      '("-e" "-b" "-k")
;;                      '("-d" "-b" "-k")
;;                      "DES-ECB" nil t)
;;                ;; PGP
;;                (list 'pgp
;;                      crypt-encryption-magic-regexp crypt-encryption-magic-regexp-inverse
;;                      (or crypt-encryption-file-extension "\\(\\.pgp\\)$")
;;                      "pgp" "pgp"
;;                      '("+batchmode" "+verbose=0" "-c" "-f" "-z")
;;                      '("+batchmode" "+verbose=0" "-f" "-z")
;;                      "PGP" nil t)
;;                ;; Add new elements here ...
;;                ))))

9.8 Dired

Directory-Browsing Commands (dired)

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

9.9 Ediff Mode

A comprehensive visual interface to Unix diff and patch utilities, used to compare two different versions of a file.

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

9.10 Erlang Mode

Erlang Mode (erlang-mode)

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

9.11 Flymake Mode

Flymake Mode (flymake-mode)

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: Flymake Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: Flymake Mode")

;; ;; flymake-mode
;; ;; flymake mode is turned on for individual modes in their sections
;; ;; these functions and advice cause errors and warnings to appear in the
;; ;; minibuffer

;; (defun flymake-display-err-minibuffer ()
;;   "Display any errors or warnings for the current line in the minibuffer."
;;   (interactive)
;;   (let* ((line-no (flymake-current-line-no))
;;          (line-err-info-list (nth 0 (flymake-find-err-info flymake-err-info line-no)))
;;          (count (length line-err-info-list)))
;;     (while (> count 0)
;;       (when line-err-info-list
;;         (let* ((file (flymake-ler-file (nth (1- count) line-err-info-list)))
;;                (full-file (flymake-ler-full-file (nth (1- count) line-err-info-list)))
;;                (text (flymake-ler-text (nth (1- count) line-err-info-list)))
;;                (line (flymake-ler-line (nth (1- count) line-err-info-list))))
;;           (message "[%s] %s" line text)))
;;       (setq count (1- count)))))

;; (defun flymake-goto-next-error--display-message ()
;;   "Display the error in the minibuffer."
;;   (flymake-display-err-minibuffer))
;; ;; advise `flymake-goto-next-error'
;; (advice-add 'flymake-goto-next-error :after #'flymake-goto-next-error--display-message)

;; (defun flymake-goto-prev-error--display-message ()
;;   "Display the error in the minibuffer."
;;   (flymake-display-err-minibuffer))
;; ;; advise `flymake-goto-prev-error'
;; (advice-add 'flymake-goto-prev-error :after #'flymake-goto-prev-error--display-message)

;; (defun flymake-mode--post-command-stuff ()
;;   "Add functionality to the post command hook so that if the
;; cursor is sitting on a flymake error the error information is
;; displayed in the minibuffer."
;;   (setq-local post-command-hook (cons 'flymake-display-err-minibuffer post-command-hook)))
;; ;; advise `flymake-mode'
;; (advice-add 'flymake-mode :before #'flymake-mode--post-command-stuff)

9.12 Flymake Cursor

Flymake Cursor (flymake-cursor)

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

9.13 Fundamental Mode

Fundamental Mode (fundamental-mode)

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

9.14 GNU Plot Mode

GNU Plot Mode Graphing Tool (gnuplot and gnuplot-mode)

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

9.15 Go Mode

Go Mode (go-mode)

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

9.16 GPG Mode

GPG Mode (gpg-mode) File Encryption

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: GPG Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: GPG Mode")

;; ;; gpg-mode
;; (use-package gpg
;;   :disabled t
;;   :ensure t
;;   :commands (pgg-make-temp-file pgg-gpg-decrypt-region)
;;   :init (progn
;;           (defvar pgg-gpg-user-id "kyle"))
;;   :config (progn
;;             (define-generic-mode 'gpg-file-mode
;;               (list ?#)
;;               nil nil
;;               '(".gpg\\'" ".gpg-encrypted\\'")
;;               (list (lambda ()
;;                       (add-hook 'before-save-hook
;;                                 (lambda ()
;;                                   (let ((pgg-output-buffer (current-buffer)))
;;                                     (pgg-gpg-encrypt-region (point-min) (point-max)
;;                                                             (list pgg-gpg-user-id))))
;;                                 nil t)
;;                       (add-hook 'after-save-hook
;;                                 (lambda ()
;;                                   (let ((pgg-output-buffer (current-buffer)))
;;                                     (pgg-gpg-decrypt-region (point-min) (point-max)))
;;                                   (set-buffer-modified-p nil)
;;                                   (auto-save-mode nil))
;;                                 nil t)
;;                       (let ((pgg-output-buffer (current-buffer)))
;;                         (pgg-gpg-decrypt-region (point-min) (point-max)))
;;                       (auto-save-mode nil)
;;                       (set-buffer-modified-p nil)))
;;               "Mode for gpg encrypted files.")))

9.17 HTML Mode

HTML Mode (html-mode)

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: HTML Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: HTML Mode")

;; ;; html-mode
;; (use-package html-mode
;;   :disabled t
;;   :ensure t
;;   :mode (("\\.html\\'" . html-mode)
;;          ("\\.htm\\'" . html-mode)
;;          ;;("\\.xhtml\\'" . html-mode)
;;          ;;("\\.css\\'" . html-mode)
;;          ("\\.cfm\\'" . html-mode)
;;          ("\\.asp\\'" . html-mode))
;;   :config (progn
;;             ;; ;; turn on abbreviation mode
;;             ;; (abbrev-mode 1)

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

;;             ;; remove tabs
;;             ;;(add-hook 'html-mode-hook 'install-remove-tabs)
;;             ))

;; ;; html-helper-mode
;; (use-package html-helper-mode
;;   :disabled t
;;   :ensure t
;;   :mode (("\\.html\\'" . html-helper-mode)
;;          ("\\.htm\\'" . html-helper-mode)
;;          ;;("\\.xhtml\\'" . html-helper-mode)
;;          ;;("\\.css\\'" . html-helper-mode)
;;          ("\\.cfm\\'" . html-helper-mode)
;;          ("\\.asp\\'" . html-helper-mode))
;;   :config (progn
;;             (defun local-html-helper-mode-hook ()
;;               ;; tag-region
;;               (defun tag-region (b e el)
;;                 "Put \"<el>...</el>\" around text."
;;                 (let ((tb (concat "<" el ">")) ((te (concat "</" el ">")))
;;                       (insert-string
;;                        (concat tb (delete-and-extract-region b e) te))
;;                       (goto-char (- (point) (+ (length te) (- e b)))))))

;;               ;; tag-region-or-point
;;               (defun tag-region-or-point (el)
;;                 "Tag the region, or the point if there is no region."
;;                 (unless mark-active
;;                   (set-mark (point)))
;;                 (tag-region (region-beginning) (region-end) el))

;;               ;; keybindings
;;               (bind-keys :map html-mode-map
;;                          ("C-c b" . (tag-region-or-point "b"))
;;                          ("C-c i" . (tag-region-or-point "i"))
;;                          ("C-c e" . (tag-region-or-point "em"))
;;                          ("C-c s" . (tag-region-or-point "strong"))
;;                          ("C-c u" . (tag-region-or-point "u"))
;;                          ("C-c -" . (tag-region-or-point "strike"))
;;                          ("C-c t" . (tag-region-or-point "tt"))
;;                          ("C-c p" . (tag-region-or-point "pre"))))
;;             (add-hook 'html-helper-mode-hook 'local-html-helper-mode-hook)))

9.18 Java Mode

Java Mode (java-mode)

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: Java Mode
;; ;;------------------------------------------------------------------------------

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

;; ;; java-mode
;; (use-package java-mode
;;   :disabled t
;;   :ensure t
;;   :commands (java-mode)
;;   :mode (("\\.java$" . java-mode)
;;          ("\\.jml$" . java-mode)
;;          ("\\.mj$" . java-mode))
;;   :config (progn
;;             ;; turn debugging on when errors occur
;;             ;;(setq debug-on-error t)

;;             ;; pretty formatting
;;             (use-package hilit-java
;;               :disabled t
;;               :ensure t)

;;             ;; camel case
;;             (use-package camelCase
;;               :disabled t
;;               :ensure t
;;               :commands (camelCase)
;;               :config (progn
;;                         (defun local-jde-mode-hook ()
;;                           (camelCase-mode 1)
;;                           (local-set-key (kbd "M-<backspace>") 'camelCase-backward-kill-word))
;;                         (add-hook 'jde-mode-hook 'local-jde-mode-hook 'append)))

;;             ;; initialize cedet
;;             (use-package cedet
;;               :ensure t)

;;             ;; initialize semantic
;;             (use-package semantic-load
;;               :ensure t
;;               :config (progn
;;                         (global-semanticdb-minor-mode -1)
;;                         ;;(setq semantic-load-turn-useful-things-on t)
;;                         ))

;;             ;; initialize eldoc
;;             (use-package eldoc
;;               :ensure t)

;;             ;; increase the limit on number of lisp variable bindings and
;;             ;; unwind-protects; allows semantic to parse more complex java files
;;             ;;(setq max-specpdl-size 1080)

;;             ;; ;; turn on flyspell
;;             ;; (use-package flyspell
;;             ;;   :ensure t
;;             ;;   :config (add-hook 'java-mode-hook 'flyspell-prog-mode))

;;             ;; ;; turn on flymake mode
;;             ;; (use-package flymake
;;             ;;   :ensure t
;;             ;;   :config (flymake-mode 1))

;;             ;; ;; turn on flyspell
;;             ;; (use-package flyspell
;;             ;;   :ensure t
;;             ;;   :config (progn
;;             ;;             (defun local-java-mode-hook ()
;;             ;;               (flyspell-prog-mode)
;;             ;;               ;; keybindings
;;             ;;               (local-set-key (kbd "C-c C-c") 'jde-compile)
;;             ;;               (local-set-key (kbd "C-c C-b") 'jde-build)
;;             ;;               (local-set-key (kbd "C-c C-r") 'jde-run))
;;             ;;             (add-hook 'java-mode-hook 'local-java-mode-hook)))

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

;;             ;; remove tabs
;;             ;;(add-hook 'java-mode-hook 'install-remove-tabs)

;;             ;; ;; set preferred compilers
;;             ;; (setq java-compilers-list
;;             ;;       '("/usr/lib/jvm/java-6-sun/bin/javac"
;;             ;;         "/usr/lib/jvm/java-1.5.0-sun/bin/javac"
;;             ;;         "/usr/lib/jvm/java-6-sun/jre/bin/javac"
;;             ;;         "/usr/java/jdk1.6.0_02/bin/javac"
;;             ;;         "/usr/java/jre1.6.0_02/bin/javac"
;;             ;;         "/usr/java/jdk1.5.0_09/bin/javac"
;;             ;;         "/usr/java/jre1.5.0_09/bin/javac"
;;             ;;         "/usr/java/jre1.5.0_11/bin/javac"
;;             ;;         "/usr/java/jdk1.5.0_11/bin/javac"
;;             ;;         "/usr/lib/j2sdk1.5-sun/bin/javac"
;;             ;;         "/usr/lib/jvm/java-1.5.0-sun/bin/javac"
;;             ;;         "javac"))

;;             ;; ;; set jde variables
;;             ;; (setq jde-compiler '("javac" ""))
;;             ;; ;;(setq jde-read-compile-args t)
;;             ;; (setq jde-ant-home "/usr/bin/ant")
;;             ;; (setq jde-ant-buildfile "build.xml")
;;             ;; (setq jde-build-function (quote (jde-ant-build)))
;;             ;; (setq jde-check-version-flag nil)
;;             ;; (setq jde-debugger (quote ("jdb")))
;;             ;; ;; (setq jde-global-classpath (quote (
;;             ;; ;;                                    "/usr/share/java/log4j-1.2.12.jar"
;;             ;; ;;                                    "/opt/GigaSpacesEE/lib/jini/tools.jar"
;;             ;; ;;                                    "/opt/GigaSpacesEE/lib/jini/jsk-lib.jar"
;;             ;; ;;                                    "/opt/GigaSpacesEE/lib/jini/jsk-platform.jar"
;;             ;; ;;                                    "/opt/GigaSpacesEE/lib/JSpaces.jar"
;;             ;; ;;                                    "./bin" "./lib" "./src" "./classes" "./config")))
;;             ;; ;; (setq jde-jdk-registry (quote (("1.5" . "/usr/lib/jvm/java-1.5.0-sun")
;;             ;; ;;                                ("5.0" . "/usr/lib/jvm/java-1.5.0-sun")
;;             ;; ;;                                ("1.6" . "/usr/lib/jvm/java-6-sun")
;;             ;; ;;                                ("6.0" . "/usr/lib/jvm/java-6-sun"))))
;;             ;; (setq jde-jdk-registry (quote (("1.5" . "/usr/lib/jvm/java-6-sun"))))
;;             ;; (setq jde-jdk (quote ("1.5")))
;;             ;; ;;(setq jde-compile-option-target (quote ("1.5")))
;;             ;; (setq quack-default-program "csi -:c")
;;             ;; (setq quack-run-scheme-always-prompts-p nil)
;;             ;; ;;(setq save-place t nil (saveplace))
;;             ;; ;;(setq tool-bar-mode nil nil (tool-bar)))
;;             ;; ;;(setq jde-enable-abbrev-mode t)
;;             ;; ;;(setq jde-complete-function 'jde-complete-menu)
;;             ;; (setq jde-complete-function 'jde-complete-minibuf)
;;             ;; ;;(setq jde-complete-function 'jde-complete-in-line)

;;             ;; turn on else minor mode
;;             ;;(add-hook 'java-mode-hook 'else-mode)
;;             ))

9.19 Java: JDE Mode

JDE (Java Development Environment) Mode (jde-mode)

(Old JDE configuration.)

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: Java: JDE Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: Java: JDE Mode")

;; ;; jde-mode
;; ;; in Ubuntu install with 'apt-get install cedet-common cedet-contrib cogre ede eieio semantic speedbar elib jde'
;; (use-package jde
;;   :disabled t
;;   :ensure t
;;   :commands (jde-mode)
;;   :mode (("\\.java$" . jde-mode)
;;          ("\\.jml$" . jde-mode)
;;          ("\\.mj$" . jde-mode))
;;   :config (progn
;;             ;; turn debugging on when errors occur
;;             ;;(setq debug-on-error t)

;;             ;; pretty formatting
;;             (use-package hilit-java
;;               :disabled t
;;               :ensure t)

;;             ;; camel case
;;             (use-package camelCase
;;               :disabled t
;;               :ensure t
;;               :commands (camelCase)
;;               :config (progn
;;                         (defun local-jde-mode-hook ()
;;                           (camelCase-mode 1)
;;                           (local-set-key (kbd "M-<backspace>") 'camelCase-backward-kill-word))
;;                         (add-hook 'jde-mode-hook 'local-jde-mode-hook 'append)))

;;             ;; initialize cedet
;;             (use-package cedet
;;               :ensure t)

;;             ;; initialize semantic
;;             (use-package semantic-load
;;               :ensure t
;;               :config (progn
;;                         (global-semanticdb-minor-mode -1)
;;                         ;;(setq semantic-load-turn-useful-things-on t)
;;                         ))

;;             ;; javadoc-help
;;             (use-package javadoc-help
;;               :ensure t)

;;             ;; jdibug
;;             (use-package jdibug
;;               :ensure t
;;               :load-path (lambda () (expand-file-name "jdibug" emacs-modules-dir)))

;;             ;; increase the limit on number of lisp variable bindings and
;;             ;; unwind-protects; allows semantic to parse more complex java files
;;             ;;(setq max-specpdl-size 1080)

;;             ;; java hook
;;             (defun local-java-mode-hook ()
;;               ;; turn on flyspell
;;               (use-package flyspell
;;                 :ensure t
;;                 :config (flyspell-prog-mode))

;;               ;; turn on flymake mode
;;               (use-package flymake
;;                 :ensure t
;;                 :config (flymake-mode 1))

;;               ;; turn on eldoc mode
;;               (use-package eldoc
;;                 :ensure t
;;                 :config (eldoc-mode 1))

;;               ;; keybindings
;;               ;;(local-set-key (kbd "C-c c") 'jde-compile)
;;               (local-set-key (kbd "C-c C-c") 'jde-compile)
;;               ;;(local-set-key (kbd "C-c b") 'jde-build)
;;               (local-set-key (kbd "C-c C-b") 'jde-build)
;;               ;;(local-set-key (kbd "C-c r") 'jde-run))
;;               (local-set-key (kbd "C-c C-r") 'jde-run)
;;               (when (fboundp 'javadoc-lookup)
;;                 (local-set-key (kbd "C-h j") 'javadoc-lookup)))
;;             (add-hook 'java-mode-hook 'local-java-mode-hook)
;;             (add-hook 'jde-mode-hook 'local-java-mode-hook)

;;             ;; remove trailing blanks
;;             ;;(add-hook 'java-mode-hook 'install-remove-trailing-blanks)
;;             ;;(add-hook 'jde-mode-hook 'install-remove-trailing-blanks)

;;             ;; remove tabs
;;             ;;(add-hook 'java-mode-hook 'install-remove-tabs)
;;             ;;(add-hook 'jde-mode-hook 'install-remove-tabs)

;;             ;; set jde variables
;;             (setq jde-compiler '("javac" ""))
;;             ;;(setq jde-read-compile-args t)
;;             (setq jde-ant-home "/usr/bin/ant")
;;             (setq jde-ant-buildfile "build.xml")
;;             (setq jde-build-function (quote (jde-ant-build)))
;;             (setq jde-check-version-flag nil)
;;             (setq jde-debugger (quote ("jdb")))
;;             ;; (setq jde-global-classpath (quote (
;;             ;;                                    "/usr/share/java/log4j-1.2.12.jar"
;;             ;;                                    "/opt/GigaSpacesEE/lib/jini/tools.jar"
;;             ;;                                    "/opt/GigaSpacesEE/lib/jini/jsk-lib.jar"
;;             ;;                                    "/opt/GigaSpacesEE/lib/jini/jsk-platform.jar"
;;             ;;                                    "/opt/GigaSpacesEE/lib/JSpaces.jar"
;;             ;;                                    "./bin" "./lib" "./src" "./classes" "./config")))
;;             (setq jde-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")))
;;                   jde-jdk (quote ("1.8")))
;;             ;;(setq jde-compile-option-target (quote ("1.5")))
;;             (setq quack-default-program "csi -:c")
;;             (setq quack-run-scheme-always-prompts-p nil)
;;             ;;(setq save-place t nil (saveplace))
;;             ;;(setq tool-bar-mode nil nil (tool-bar)))
;;             ;;(setq jde-enable-abbrev-mode t)
;;             ;;(setq jde-complete-function 'jde-complete-menu)
;;             (setq jde-complete-function 'jde-complete-minibuf)
;;             ;;(setq jde-complete-function 'jde-complete-in-line)

;;             ;; turn on else minor mode
;;             ;;(add-hook 'java-mode-hook 'else-mode)

;;             ;; add alias for run command to be like other language modes
;;             (defalias 'run-java 'jde-run)
;;             (defalias 'run-jde 'jde-run)
;;             ))

9.20 Java: Flymake Mode for JDE

Flymake Mode (flymake-mode) for JDE Mode

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: Java: Flymake Mode for JDE
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: Java: Flymake Mode for JDE")

;; ;; fix needed to prevent "Symbol's function definition is void: senator-minor-mode" error
;; (unless (boundp 'senator-minor-mode)
;;   (defun senator-minor-mode () nil))

;; ;; flymake-mode for java
;; (eval-after-load-with-byte-compile "jde"
;;   (use-package jde-eclipse-compiler-server
;;     :disabled t
;;     :ensure t
;;     :commands (jde-ecj-flymake-init)
;;     :config (progn
;;               (setq jde-compiler `(("eclipse java compiler server" ,(expand-file-name "~/.common/.emacs.d/modules/ecj.jar"))))
;;               (add-to-list 'flymake-allowed-file-name-masks '(".+\\.java$" jde-ecj-flymake-init jde-ecj-flymake-cleanup) t)

;;               ;; flymake-mode for java
;;               ;; location of ecj.jar
;;               (defconst flymake-java-ecj-jar (expand-file-name "ecj.jar" emacs-modules-dir))
;;               (defvar flymake-java-version "1.6")
;;               (defvar flymake-java-sourcepath '("."))
;;               (defvar flymake-java-classpath '("."))

;;               (defun flymake-java-ecj-init ()
;;                 "Initialize flymake-mode for java using ecj."
;;                 (let* ((temp-file (flymake-init-create-temp-buffer-copy 'jde-ecj-create-temp-file))
;;                        (local-file (file-relative-name temp-file (file-name-directory buffer-file-name))))
;;                   ;;(local-file (expand-file-name temp-file)))
;;                   (list "java" (list "-jar" (expand-file-name flymake-java-ecj-jar)
;;                                      "-Xemacs"
;;                                      "-d" "none" ;"-warn:none"
;;                                      "-source" flymake-java-version
;;                                      "-target" flymake-java-version
;;                                      "-proceedOnError"
;;                                      "-sourcepath" (or (car jde-sourcepath) (car flymake-java-sourcepath))
;;                                      "-classpath" (jde-build-classpath (or jde-global-classpath flymake-java-classpath))
;;                                      local-file))))

;;               (defun flymake-java-ecj-cleanup ()
;;                 "Cleanup after `flymake-java-ecj-init'.
;; \nDelete temp file and directories."
;;                 (flymake-safe-delete-file flymake-temp-source-file-name)
;;                 (when flymake-temp-source-file-name
;;                   (flymake-safe-delete-directory (file-name-directory flymake-temp-source-file-name))))

;;               (defun jde-ecj-create-temp-file (file-name prefix)
;;                 "Create file FILE-NAME in a unique directory in the temp directory."
;;                 (file-truename (expand-file-name (file-name-nondirectory file-name)
;;                                                  (expand-file-name (int-to-string (random)) (flymake-get-temp-dir)))))

;;               ;; install flymake mode for java
;;               (use-package flymake
;;                 :ensure t
;;                 :config (progn
;;                           ;; initialize flymake
;;                           (add-to-list 'flymake-allowed-file-name-masks '(".+\\.java$" flymake-java-ecj-init flymake-java-ecj-cleanup) t)
;;                           (add-to-list 'compilation-error-regexp-alist '("\\(.*?\\):\\([0-9]+\\): error: \\(.*?\\)\n" 1 2 nil 2 3 (6 compilation-error-face)) t)
;;                           (add-to-list 'compilation-error-regexp-alist '("\\(.*?\\):\\([0-9]+\\): warning: \\(.*?\\)\n" 1 2 nil 1 3 (6 compilation-warning-face)) t))))))

9.21 Java: JDEE Mode

JDEE (Java Development Environment for Emacs) Mode (jdee-mode)

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

9.22 Java: Meghanada Mode

Java: Meghanada Mode (meghanada-mode)

A Java Development Environment for Emacs.

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: Java: Meghanada Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: Java: Meghanada Mode")

;; ;; meghanada-mode
;; (use-package meghanada
;;   :disabled t
;;   :config (progn
;;             ;; java hook
;;             (defun local-java-mode-hook ()
;;               ;; turn meghanada-mode on
;;               (meghanada-mode t))
;;             (add-hook 'java-mode-hook 'local-java-mode-hook)

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

;;             ;; remove tabs
;;             ;;(add-hook 'java-mode-hook 'install-remove-tabs)
;;             ))

9.23 Java: Android Mode

Java: Android Mode (android-mode)

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: Java: Android Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: Java: Android Mode")

;; ;; android-mode
;; (use-package android-mode
;;   :disabled t
;;   :load-path (lambda () (expand-file-name "~/android-sdk/tools/lib"))
;;   :config (progn
;;             (setq android-mode-sdk-dir (expand-file-name "~/android-sdk"))
;;             (use-package android
;;               :load-path (lambda () (expand-file-name "~/android-sdk/tools/lib")))))

9.24 Javascript Mode

Javascript Mode (javascript-mode)

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: Javascript Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: Javascript Mode")

;; ;; javascript-mode
;; (use-package javascript
;;   :disabled t
;;   :ensure t
;;   :mode (("\\.js\\'" . js-mode))
;;   :commands (javascript-mode js-mode)
;;   :config (progn
;;             ;; ;; flymake (using lintnode)
;;             ;; (use-package flymake-jslint
;;             ;;   :ensure t
;;             ;;   :load-path (lambda () (expand-file-name "lintnode" emacs-home-dir))
;;             ;;   :config (progn
;;             ;;             (setq lintnode-location dir
;;             ;;                   lintnode-jslint-excludes (list 'nomen 'plusplus 'onevar 'white)) ; 'nomen 'undef 'plusplus 'onevar 'white
;;             ;;             (add-hook 'js-mode-hook (lambda () (lintnode-hook)))
;;             ;;             ;; flymake-cursor
;;             ;;             (use-package flymake-cursor)))

;;             ;; flymake (using v8)
;;             (use-package flymake-jslint
;;               :ensure t
;;               :load-path (lambda () (expand-file-name "jslint-v8" emacs-home-dir))
;;               :config (progn
;;                         (setq lintnode-location dir
;;                               lintnode-jslint-excludes (list 'nomen 'plusplus 'onevar 'white)) ; 'nomen 'undef 'plusplus 'onevar 'white
;;                         ;;(add-hook 'js-mode-hook (lambda () (lintnode-hook)))
;;                         (add-hook 'js-mode-hook (lambda () (flymake-mode 1)))
;;                         ;; flymake-cursor
;;                         (use-package flymake-cursor
;;                           :ensure t)))))

9.25 Javascript: js2 Mode

Javascript Mode (js2-mode)

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

9.26 Javascript: js3 Mode

Javascript Mode (js3-mode)

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: Javascript: js3 Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: Javascript: js3 Mode")

;; ;; js3-mode
;; (use-package js3-mode
;;   :disabled t
;;   :ensure t
;;   :mode ("\\.js\\'" . js3-mode)
;;   :interpreter ("node" . js3-mode)
;;   :commands (js3-mode)
;;   :config (progn
;;             (setq js3-auto-indent-p t
;;                   js3-enter-indents-newline t
;;                   js3-indent-on-enter-key t)))

9.27 Ledger Mode

Ledger Mode (ledger-mode)

Mode for the accounting program ledger.

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

9.28 Lisp Mode

Lisp Mode (lisp-mode and emacs-lisp-mode)

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

9.29 Lisp: Clojure Mode

Clojure Mode (clojure-mode)

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: Lisp: Clojure Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: Lisp: Clojure Mode")

;; ;; clojure-mode
;; (use-package clojure-mode
;;   :disabled t
;;   :ensure t
;;   :load-path (lambda () (expand-file-name "clojure-mode" emacs-modules-dir))
;;   :mode (("\\.clj\\'" . clojure-mode)
;;          ("\\.clojure\\'" . clojure-mode))
;;   :config (progn
;;             ;; clojure hook
;;             (defun local-clojure-mode-hook ()
;;               ;; define keys
;;               ;; (local-set-key (kbd "C-c C-c") 'slime-eval-sexp)
;;               ;; (local-set-key (kbd "M-C-x") 'slime-eval-sexp)
;;               ;; (local-set-key (kbd "C-x C-e") 'slime-eval-last-expression)
;;               ;; (local-set-key (kbd "C-c C-k") 'slime-eval-buffer)
;;               (local-set-key (kbd "C-c C-c") 'lisp-eval-defun)
;;               (local-set-key (kbd "M-C-x") 'lisp-eval-defun)
;;               (local-set-key (kbd "C-c C-k") 'lisp-eval-buffer)
;;               (local-set-key (kbd "C-M-;") 'comment-or-uncomment-sexp)

;;               ;; replace clojure mode indenting style with normal lisp indenting
;;               ;;(setq lisp-indent-function 'lisp-indent-function)
;;               )
;;             (add-hook 'clojure-mode-hook 'local-clojure-mode-hook)

;;             ;; set inferior lisp program to clojure
;;             (setq inferior-lisp-program (concat
;;                                          "java -cp "
;;                                          (expand-file-name "~/.clojure/clojure.jar")
;;                                          " clojure.main"))

;;             ;; paraedit
;;             ;;(use-package clojure-paredit
;;             ;;  :ensure t)

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

;;             ;; remove tabs
;;             ;;(add-hook 'clojure-mode-hook 'install-remove-tabs)

;;             ;; lisp-eval-region for the entire buffer
;;             (defun lisp-eval-buffer ()
;;               "Call `lisp-eval-region' with `point-min' and `point-max' as parameters."
;;               (interactive)
;;               (lisp-eval-region (point-min) (point-max)))
;;             ))

9.30 Lisp: Slime Mode

Slime (Superior Lisp Interaction Mode for Emacs) Mode (slime-mode)

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

9.31 Makefile Mode

Makefile Mode (make-mode)

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

9.32 Markdown Mode

Markdown Mode (markdown-mode)

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

9.33 Muse Mode

Muse Mode (muse-mode)

Muse Mode is a web authoring and publishing environment.

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

9.34 Perl Mode

Perl Mode (cperl-mode)

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

9.35 Prolog Mode

Prolog Mode (prolog-mode)

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: Prolog Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: Prolog Mode")

;; ;; prolog-mode
;; (use-package prolog
;;   :disabled t
;;   :ensure t
;;   :mode ("\\.prolog$" . prolog-mode)
;;   :commands (run-prolog prolog-mode mercury-mode)
;;   :config (setq prolog-system 'gnu))    ; see `prolog-system' for options

9.36 Python Mode

Python Mode (python-mode)

Emacs package dependencies: auto-complete, epc, projectile, jedi OS package dependencies: python-pip, python-virtualenv

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

9.37 Ruby Mode

Ruby Mode (ruby-mode)

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

9.38 SH Mode

Shell Editing Mode (sh-mode)

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

9.39 Shell Mode

Shell Mode (shell-mode)

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

9.40 SQL Mode

SQL Mode (sql-mode)

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

9.41 Text Mode

Text Mode (text-mode)

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

9.42 Workgroups Mode

Workgroups Mode (workgroups-mode)

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: Workgroups Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: Workgroups Mode")

;; ;; workgroups-mode
;; (use-package workgroups
;;   :disabled t
;;   :ensure t
;;   :config (progn
;;             ;;(setq wg-prefix-key (kbd "C-z"))
;;             (setq wg-prefix-key (kbd "C-c w"))
;;             (workgroups-mode 1)
;;             (let ((file (expand-file-name "workgroups" emacs-home-dir)))
;;               (when (file-exists-p file)
;;                 (wg-load file)))
;;             (setq wg-switch-on-load nil)))

9.43 XML/SGML Mode

XML/SGML Mode (xml-mode and sgml-mode)

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: XML/SGML Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: XML/SGML Mode")

;; ;; sgml-mode
;; (use-package psgml
;;   :disabled t
;;   :ensure t
;;   :load-path (lambda () (expand-file-name "psgml" emacs-modules-dir))
;;   :commands (sgml-mode xml-mode)
;;   :mode (("\\.sgml$" . sgml-mode)
;;          ("\\.idd$" . sgml-mode)
;;          ("\\.ide$" . sgml-mode)
;;          ;;("\\.htm$" . xml-mode)
;;          ;;("\\.html$" . xml-mode)
;;          ("\\.xhtml$" . xml-mode)
;;          ("\\.xml$" . xml-mode)
;;          ("\\.xsl$" . xml-mode)
;;          ("\\.fo$" . xml-mode)
;;          ("\\.rdf$" . xml-mode)
;;          ("\\.rss$" . xml-mode))
;;   :config (progn
;;             ;; setup catalog files
;;             (setq sgml-catalog-files nil)
;;             (add-to-list 'sgml-catalog-files (expand-file-name "~/dtd/xhtml1/xhtml1.soc") t)
;;             (add-to-list 'sgml-catalog-files (expand-file-name "~/dtd/dita/dtd/dita.soc") t)
;;             (add-to-list 'sgml-catalog-files (expand-file-name "~/dtd/hodmacro/hodmacro.soc") t)

;;             ;; indent after deleting a tag
;;             (defun sgml-delete-tag--reindent (orig-fun &rest args)
;;               (dotimes (a args)
;;                 (apply orig-fun 1)
;;                 (indent-region (point-min) (point-max))))
;;             ;; advise `sgml-delete-tag'
;;             (advice-add 'sgml-delete-tag :around #'(sgml-delete-tag--reindent))

;;             ;; sgml mode hook
;;             (defun local-sgml-mode-hook ()
;;               ;; create faces to assign to markup categories
;;               (make-face 'sgml-comment-face)
;;               (make-face 'sgml-start-tag-face)
;;               (make-face 'sgml-end-tag-face)
;;               ;; assign attributes to faces
;;               (set-face-foreground 'sgml-comment-face "SeaGreen")
;;               (set-face-foreground 'sgml-start-tag-face "OrangeRed")
;;               (set-face-foreground 'sgml-end-tag-face "OrangeRed")
;;               ;; assign faces to markup categories
;;               (setq sgml-markup-faces
;;                     '((comment . sgml-comment-face)
;;                       (start-tag . sgml-start-tag-face)
;;                       (end-tag . sgml-end-tag-face)))
;;               ;; use the face settings
;;               (setq sgml-set-face t)
;;               ;; only allow valid elements to be inserted
;;               (setq sgml-omittag-transparent t)
;;               ;; automatically insert required elements
;;               (setq sgml-auto-insert-required-elements t)
;;               ;; enable abbreviations
;;               ;;(setq abbrev-mode t)
;;               ;;(read-abbrev-file (expand-file-name "~/.abbrev_defs"))
;;               ;;(setq save-abbrevs t)
;;               )
;;             (add-hook 'sgml-mode-hook 'local-sgml-mode-hook)

;;             ;;(make-face 'sgml-comment-face)
;;             ;;(make-face 'sgml-start-tag-face)
;;             ;;(make-face 'sgml-end-tag-face)
;;             ;;(make-face 'sgml-entity-face)
;;             ;;(make-face 'sgml-doctype-face)

;;             ;;(set-face-foreground 'sgml-comment-face "FireBrick")
;;             ;;(set-face-foreground 'sgml-start-tag-face "SlateBlue")
;;             ;;(set-face-foreground 'sgml-end-tag-face "SlateBlue")
;;             ;;(set-face-background 'sgml-entity-face "SlateBlue")
;;             ;;(set-face-foreground 'sgml-entity-face "Red")
;;             ;;(set-face-foreground 'sgml-doctype-face "FireBrick")

;;             ;;(setq sgml-set-face t)
;;             ;;(setq sgml-markup-faces
;;             ;;        '((comment . sgml-comment-face)
;;             ;;        (start-tag . sgml-start-tag-face)
;;             ;;        (end-tag . sgml-end-tag-face)
;;             ;;        (doctype . sgml-doctype-face)
;;             ;;        (entity . sgml-entity-face)))

;;             ;; ;; turn on abbreviation mode
;;             ;; (abbrev-mode 1)
;;             ))

9.44 XML Mode

XML Mode (nxml-mode)

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

9.45 Global Mode

Global Mode (global-mode-hook) configuration.

;; ;;------------------------------------------------------------------------------
;; ;;; Modes: Global Mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modes: Global Mode")

;; ;; global hook
;; (defun global-mode-hook ()
;;   ;; remove trailing blanks
;;   ;;(install-remove-trailing-blanks)

;;   ;; remove tabs (all but makefile-mode)
;;   ;;(unless (string= mode-name "Makefile")
;;   ;;  (install-remove-tabs))

;;   ;; turn on spell mode
;;   ;;(flyspell-mode 1)

;;   ;; set local key bindings
;;   ;; this is no longer used
;;   ;; (safe-load "keys-local")
;;   )
;; (add-hook 'after-change-major-mode-hook 'global-mode-hook)

10 Modules

Non-mode package configurations.

;;==============================================================================
;;; Modules
;;==============================================================================

(init-message 1 "Modules")

10.1 abook

Simple Address Book (abook)

;; ;;------------------------------------------------------------------------------
;; ;;; Modules: abook
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modules: abook")

;; (use-package addressbook
;;   :disabled t
;;   :ensure t
;;   :load-path (lambda () (expand-file-name "addressbook" emacs-modules-dir))
;;   :commands (abook))

10.2 abbrev-mode

Abbreviations Mode (abbrev-mode)

Setup abbreviation mode, including auto load and save of abbreviations file.

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

10.3 ace-jump-mode

Quick Cursor Location Minor Mode (ace-jump-mode)

;; ;;------------------------------------------------------------------------------
;; ;;; Modules: ace-jump-mode
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modules: ace-jump-mode")

;; (use-package ace-jump-mode
;;   :disabled t                           ; replaced by avy
;;   :ensure t
;;   :commands (ace-jump-mode ace-jump-mode-pop-mark)
;;   :bind* (("C-;" . ace-jump-mode)                ; defaults to undefined
;;           ("C-A-;" . ace-jump-mode-pop-mark)     ; defaults to undefined
;;           ("C-x ." . ace-jump-mode)              ; defaults to undefined
;;           ("C-x C-." . ace-jump-mode-pop-mark))  ; defaults to undefined
;;   :config (ace-jump-mode-enable-mark-sync))

10.4 ace-window

Quickly Switch Windows (ace-window)

;; ;;------------------------------------------------------------------------------
;; ;;; Modules: ace-window
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modules: ace-window")

;; (use-package ace-window
;;   :disabled t
;;   :ensure t
;;   :commands (ace-window)
;;   :config (progn
;;             ;; set jump keys
;;             (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))

;;             ;; keybindings
;;             (bind-keys ("C-x o" . ace-window)  ; defaults to `facemenu-keymap'
;;                        ("M-o" . ace-window)))) ; defaults to `facemenu-keymap'

10.5 alert

Growl-style notification system for Emacs (alert)

Set to use libnotify for the alerts. The command notify-send must exist in the user's PATH.

;;------------------------------------------------------------------------------
;;; Modules: alert
;;------------------------------------------------------------------------------

(init-message 2 "Modules: alert")

(use-package alert
  :ensure t
  :commands (alert)
  :config (setq alert-default-style 'libnotify))

10.6 analog-clock

Analog Clock (analog-clock)

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

10.7 anything

Quicksilver-like Candidate-Selection Framework (anything)

;;------------------------------------------------------------------------------
;;; Modules: anything
;;------------------------------------------------------------------------------

(init-message 2 "Modules: anything")

(use-package anything
  :ensure t
  :commands (anything))

10.8 anzu

Show Number of Matches in Mode-Line While Searching (anzu)

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

10.9 ascii

ASCII Code Display (ascii)

;;------------------------------------------------------------------------------
;;; Modules: ascii
;;------------------------------------------------------------------------------

(init-message 2 "Modules: ascii")

(use-package ascii
  :ensure t
  :commands (ascii-on ascii-off ascii-display ascii-customize))

10.10 auto-compile

Automatically Compile Emacs Lisp Libraries (auto-compile)

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

10.11 auto-complete

Auto Completion (auto-complete)

(Should not be enabled at the same time as `company-mode`.)

;; ;;------------------------------------------------------------------------------
;; ;;; Modules: auto-complete
;; ;;------------------------------------------------------------------------------

;; (init-message 2 "Modules: auto-complete")

;; (use-package auto-complete
;;   :disabled t
;;   :ensure t
;;   :diminish auto-complete-mode
;;   :config (progn
;;             (global-auto-complete-mode 1)

;;             ;; completion back-ends
;;             (when (require-if-available 'auto-complete-config)
;;               (ac-config-default))
;;             (setq-default ac-sources '(ac-source-abbrev
;;                                        ac-source-dictionary
;;                                        ac-source-filename
;;                                        ac-source-files-in-current-dir
;;                                        ac-source-functions
;;                                        ac-source-variables
;;                                        ac-source-symbols
;;                                        ac-source-features
;;                                        ac-source-words-in-all-buffer
;;                                        ac-source-words-in-same-mode-buffers))

;;             ;; keybindings
;;             (define-key ac-complete-mode-map (kbd "C-n") 'ac-next)
;;             (define-key ac-complete-mode-map (kbd "C-p") 'ac-previous)))

10.12 avy

Quick Cursor Jumping (avy)

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

10.13 bash-completion

Dynamic completion hooks for shell-mode and shell-command prompts that are based on BASH completion.

;;------------------------------------------------------------------------------
;;; Modules: bash-completion
;;------------------------------------------------------------------------------

(init-message 2 "Modules: bash-completion")

(use-package bash-completion
  :ensure t
  :config (bash-completion-setup))

10.14 bbdb

The Insidious Big Brother Database (bbdb)

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

10.15 boxquote

Quote Text with a Semi-Box (boxquote)

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

10.16 browse-kill-ring

Interactively Insert Items from Kill-Ring (browse-kill-ring)

;;------------------------------------------------------------------------------
;;; Modules: browse-kill-ring
;;----------