dotfiles/.emacs.d/emacs.org

46 KiB
Raw Blame History

Emacs Configuration

Startup

Disable the emacs startup screen.

  (setq inhibit-startup-screen +1)

Custom settings

Store options set via customize-* in a separate file (Emacs stores them in init.el by default).

  (setq custom-file "~/.emacs.d/custom.el")
  (if (file-exists-p custom-file)
      (load custom-file))

  (setf custom-safe-themes t)

UI

Highlight the current line

  (global-hl-line-mode +1)

Powerline

Make the mode line prettier.

  (use-package powerline
    :ensure t
    :config

    (powerline-default-theme))

Nyan-mode

Visualize the current position within the buffer in the modeline with nyancat!

  (use-package nyan-mode
    :ensure t
    :config
    (nyan-mode)
    (nyan-start-animation))

Display Time & Battery Status

  (setq display-time-24hr-format t)
  (setq display-time-load-average-threshold 0.9)
  (display-time-mode t)

  (setq battery-mode-line-format
        "[🔋%b%p%%%% (%t)]")
  (display-battery-mode t)

Theme

  (use-package moe-theme
    :ensure t
    :config

    (setq moe-theme-resize-markdown-title '(1.5 1.4 1.3 1.2 1.0 1.0))
    (setq moe-theme-resize-org-title '(1.5 1.4 1.3 1.2 1.1 1.0 1.0 1.0 1.0))
    (setq moe-theme-resize-rst-title '(1.5 1.4 1.3 1.2 1.1 1.0))

    (setq moe-theme-highlight-buffer-id t)
    (moe-theme-set-color 'cyan)
    (powerline-moe-theme)
    (moe-dark))

Major mode icons

Display major-mode names as icons in the mode line when possible.

  (use-package mode-icons
    :ensure t
    :defer 5
    :config (mode-icons-mode))

Which-Key

Display key binding completions after a delay.

  (use-package which-key
    :ensure t
    :diminish which-key-mode
    :config
    (which-key-setup-side-window-right-bottom)
    (which-key-mode))

Helm

  (use-package helm
    :ensure t
    :diminish helm-mode
    :bind (("M-x" . helm-M-x)
           ("M-y" . helm-show-kill-ring)
           ("C-x b" . helm-mini)
           ("C-x C-b" . helm-buffers-list)
           ("C-x C-f" . helm-find-files)
           ("C-x C-r" . helm-recentf)
           ("C-x c o" . helm-occur))
    :config (progn
              (require 'helm-config)
              (helm-mode 1)
              (add-hook 'eshell-mode-hook
                        (lambda ()
                          (define-key eshell-mode-map (kbd "TAB") 'helm-esh-pcomplete)
                          (define-key eshell-mode-map (kbd "C-c C-l") 'helm-eshell-history)))))

helm-descbinds

  (use-package helm-descbinds
    :ensure t
    :bind (("C-h b" . helm-descbinds)
           ("C-h w" . helm-descbinds)))

helm-ag

Helm search plugin for Ag (The Silver Searcher)

  (use-package helm-ag
    :ensure t
    :commands (helm-ag))

helm-flyspell

  (use-package helm-flyspell
    :ensure t
    :commands helm-flyspell-correct
    :init (eval-after-load 'flyspell
            '(define-key flyspell-mode-map (kbd "C-;") 'helm-flyspell-correct)))

helm-swoop

Replace isearch-forward with helm-swoop for a nicer experience.

Quite usefully, using prefix arguments expands the lines of context shown around the search results.

  (use-package helm-swoop
    :ensure t
    :commands (helm-swoop)
    :bind (("C-s" . helm-swoop))
    :config
    ;; Defaults to (lambda () (thing-at-point 'symbol)).
    ;; Setting it to return nil, as I find it tends to be more annoying than useful.
    (setq helm-swoop-pre-input-function (lambda () nil))
    ;; Enable syntax highlighting. It makes it easier for my eyes to
    ;; parse the results, and doesn't seem to slow things down
    ;; measurably.
    (setq helm-swoop-speed-or-color t)
    )

Undo-Tree

Visualize and traverse undo history as a directed graph.

  (use-package undo-tree
    :ensure t
    :diminish undo-tree-mode
    :config (global-undo-tree-mode))

Multiple Cursors

  (use-package multiple-cursors
    :bind (("C-S-c C-S-c" . mc/edit-lines)
           ("C->" . mc/mark-next-like-this)
           ("C-<" . mc/mark-previous-like-this)
           ("C-c C-<" . mc/mark-all-like-this)
           ("C-M->" . mc/mark-more-like-this-extended)))

Coding

Languages

Lisps

Mode Description
lisp Common Lisp
emacs-lisp Emacs Lisp
scheme Scheme
lfe Lisp-Flavored Erlang
clojure Clojure
hy Hy (Lisp-flavored Python)
  ;; SLIME
  (if (file-exists-p "~/quicklisp/slime-helper.el")
      (load (expand-file-name "~/quicklisp/slime-helper.el")))

  (setq inferior-lisp-program "clisp")

  (use-package paredit
    :ensure t
    :commands (paredit-mode)
    :diminish " ")

  (use-package rainbow-identifiers
    :ensure t
    :commands (rainbow-identifiers-mode))

  (use-package rainbow-delimiters
    :ensure t
    :commands (rainbow-delimiters-mode))

  (let ((lisp-mode-hooks
         (mapcar (lambda (lisp)
                   (intern (concat lisp "-mode-hook")))
                 (mapcar 'car (cddr '<<lisps()>>)))))
    (mapc (lambda (hook)
            (message (format "Installing LISP mode hook for %S" hook))
            (add-hook hook (lambda ()
                             (show-paren-mode t)
                             (electric-indent-mode t)
                             (paredit-mode t)
                             (rainbow-delimiters-mode t)
                             (rainbow-identifiers-mode t))))
          (cons 'eval-expression-minibuffer-setup-hook
                lisp-mode-hooks)))
Lisp-Flavored Erlang
  (use-package lfe-mode
    :ensure t
    :mode "\\.lfe$")
Clojure
  (use-package clojure-mode
    :ensure t
    :mode (("\\.clj[sx]?$" . clojure-mode)
           ("\\.edn$" . clojure-mode)))
Cider

Communicates with the clojure REPL.

  (use-package cider
    :ensure t
    :commands (cider-jack-in cider)
    :config (setq org-babel-clojure-backend 'cider))
Hy
  (use-package hy-mode
    :ensure t
    :mode "\\.hy$")

  (use-package ob-hy
    :ensure t
    :defer t)

Erlang

A distributed, fault-tolerant functional language.

    (use-package erlang
      :ensure t
      :mode ("\.[eh]rl$" . erlang-mode)
      :config (add-hook 'erlang-mode-hook
                        (lambda ()
                          (setq inferior-erlang-machine-options '("-sname" "emacs"
                                                                  "-hidden")))))

Elixir

Ruby-flavoured Erlang.

  (use-package elixir-mode
    :ensure t
    :mode "\\.exs?$")

  (use-package alchemist
    :ensure t
    :after elixir-mode)

  (use-package ob-elixir
    :ensure t
    :after ob)

Haskell

A strongly typed, pure functional language.

  (use-package haskell-mode
    :ensure t
    :mode "\.hs$")

  (use-package hi2
    :ensure t
    :commands turn-on-hi2
    :init (add-hook 'haskell-mode-hook 'turn-on-hi2))

Elm

A functional, reactive language for the web that compiles to JavaScript.

  (use-package elm-mode
    :ensure t
    :mode "\.elm$"
    :config
    (add-hook 'elm-mode-hook #'elm-oracle-setup-completion)
    (add-to-list 'company-backends 'company-elm))

Idris

A functional language with dependent types.

  (use-package idris-mode
    :ensure t
    :mode "\.idr$")

Web

HTML
  (use-package web-mode
    :ensure t
    :mode "\\.html?$")
SCSS
  (use-package scss-mode
    :ensure t
    :mode "\\.scss$"
    :config (add-hook 'scss-mode-hook
                      (lambda ()
                        "Customize SCSS indentation"
                        (setq css-indent-offset 2))))

JavaScript

  (use-package js2-mode
    :ensure t
    :mode ".js$")

PHP

  (use-package php-mode
    :ensure t
    :mode (("\\.php$" . php-mode)
           ("\\.inc$" . php-mode))
    :config (add-hook 'php-mode-hook (lambda ()
                                       "Customize PHP indentation"
                                       (c-set-offset 'arglist-cont-nonempty 'c-lineup-arglist)
                                       (c-set-offset 'substatement-open 0)
                                       (c-set-offset 'case-label '+))))

Python

  (use-package python-mode
    :ensure t
    :mode "\.py$")
Elpy

Full functionality requires a number of python packages to be installed:

  # Either of these
  pip install rope
  pip install jedi
  # flake8 for code checks
  pip install flake8
  # importmagic for automatic imports
  pip install importmagic
  # and autopep8 for automatic PEP8 formatting
  pip install autopep8
  # and yapf for code formatting
  pip install yapf
  (use-package elpy
    :ensure t
    :after python
    :config (elpy-enable))
Cython
  (use-package cython-mode
    :ensure t
    :mode "\.pyx$")
Formatting (Black)
  (use-package! python-black
   :commands (python-black-buffer
              python-black-region
              python-black-statement
              python-black-on-save-mode))
Formatting (YAPF)
  (use-package! yapfify
   :commands (yapfify-region
              yapfify-buffer
              yapfify-region-or-buffer
              yapf-mode))
Poetry
  (use-package! poetry
   :commands (poetry-tracking-mode))

Ruby

  (use-package rvm
    :ensure t
    :commands (rvm-use
               rvm-use-default))

Yaml

  (use-package yaml-mode
    :ensure t
    :mode "\.yml$")

Docker

  (use-package dockerfile-mode
    :ensure t
    :mode "^Dockerfile$")

Graphviz

  (use-package graphviz-dot-mode
    :ensure t
    :mode "\.dot$"
    :config
    (setq graphviz-dot-indent-width 2))

Gnuplot

  (use-package gnuplot
    :ensure t)

PlantUML

  (use-package plantuml-mode
    :ensure t
    :mode "\\.plantuml\\'"
    :commands plantuml-mode)

Don't forget to configure org-plantuml-jar-path and plantuml-jar-path to point to a version of plantuml.jar on your system.

Tools

EditorConfig

Editor-agnostic coding style configuration.

  (use-package editorconfig
    :ensure t
    :diminish editorconfig-mode
    :config
    (editorconfig-mode 1))

Projectile

  (use-package projectile
    :ensure t
    :defer t
    :diminish " 📁"
    :bind-keymap ("C-c p" . projectile-command-map)
    :config
    (projectile-mode t))

  (use-package helm-projectile
    :ensure t
    :after (helm projectile)
    :config (helm-projectile-on))

Autocomplete

Company

Install and configure Company for auto-completion.

  (use-package company
    :ensure t
    :commands (company-mode)
    :config (progn
              (add-hook 'prog-mode-hook 'company-mode)

              (bind-key "C-n" #'company-select-next company-active-map)
              (bind-key "C-p" #'company-select-previous company-active-map)))
Auto-Complete

Not using this for auto-completion anymore, but several packages require it.

  (use-package auto-complete
    :ensure t
    :defer t)

Flycheck

  (use-package flycheck
    :ensure t
    :diminish " ✓"
    :init
    (add-hook 'after-init-hook #'global-flycheck-mode))

Web Mode

  (use-package web-mode
    :ensure t
    :mode ("\\.html$" . web-mode)
    :config (add-hook 'web-mode-hook (lambda ()
                                       (setq web-mode-markup-indent-offset 4)
                                       (setq web-mode-css-indent-offset 4)
                                       (setq web-mode-code-indent-offset 4))))

Skewer

Live web development in Emacs.

  (use-package skewer-mode
    :ensure t
    :commands (run-skewer
               skewer-mode
               skewer-css-mode
               skewer-html-mode)
    :init (progn (add-hook 'js2-mode-hook 'skewer-mode)
                 (add-hook 'css-mode-hook 'skewer-css-mode)
                 (add-hook 'html-mode-hook 'skewer-html-mode)))

Yasnippet

  (use-package yasnippet
    :ensure t
    :defer t
    :diminish yas-minor-mode
    :config (yas-global-mode 1))

  (use-package yasnippet-snippets
    :ensure t)

Ag (The Silver Searcher)

This is a code searching tool that replaces ack, and is an order of magnitude faster.

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

Expand Region

Increase selected region by semantic units.

  (use-package expand-region
    :ensure t
    :bind (("C-=" . er/expand-region)))

Nameless

Hide package namespaces in emacs-lisp code.

  (use-package nameless
    :ensure t
    :commands nameless-mode-from-hook
    :init
    (add-hook 'emacs-lisp-mode-hook #'nameless-mode-from-hook)
    :config
    (setq nameless-private-prefix t))

Language Server Protocol

IDE-level integration supporting multiple languages.

  (use-package lsp-mode
    :ensure t
    :init (setq lsp-auto-guess-root t
                lsp-keep-workspace-alive nil
                lsp-enable-xref t
                lsp-prefer-flymake nil
                lsp-auto-configure t
                lsp-response-timeout 3)
    :hook ((prog-mode . lsp-mode)))
Language Server Installation
PHP Intelephense npm i intelephense
Python Python Language Server pip install python-language-server[all]
Python (Mypy) Mypy plugin for the Python Language Server pip install pyls-mypy
Language server implementations
Company integration
  (use-package company-lsp
    :ensure t
    :init (setq company-lsp-async t)
    :hook ((python-mode . (lambda ()
                              (add-to-list 'company-backends 'company-lsp)))
             (js2-mode . (lambda ()
                           (add-to-list 'company-backends 'company-lsp)))))
Fancy UI
  (use-package lsp-ui
    :ensure t
    :hook (lsp-mode . lsp-ui-mode)
    :config
    ;; Disable eldoc-mode
    (global-eldoc-mode -1))

Libraries

Dash

A modern list api for Emacs. No 'cl required.

  (use-package dash
    :ensure t
    :config (dash-enable-font-lock))

Stream

Lazy sequences in Emacs (compatible with seq.el).

  (use-package stream
    :ensure t
    :if (version<= "25.1" emacs-version)
    :defer t)

Writing

Style

End sentences with a single space

  (setq sentence-end-double-space nil)

Formats

Org

Pretty bullets
  (use-package org-bullets
    :ensure t
    :hook (org-mode . org-bullets-mode))
Modules
org-habit
  (let ((modules (mapcar (lambda (m) (intern (car m)))
                         '<<org-module-table()>>)))
    (mapcar (lambda (m) (add-to-list 'org-modules m))
            modules))
  (org-load-modules-maybe t)
Tasks
Enforce dependencies

Require child tasks and checkboxes to be done before a parent task can be marked done.

  (setq
   org-enforce-todo-dependencies t
   org-enforce-todo-checkbox-dependencies t)
Keep logs in their own drawer
  (setq org-log-into-drawer t)
Log completion
  (setq org-log-done 'time)
Habits

Shift the consistency graph over a bit to make room for task names.

  (setq org-habit-graph-column 70)
  (setq org-habit-show-habits-only-for-today nil)
Refiling
  (setq org-refile-targets '((org-agenda-files . (:maxlevel . 6))))
Babel
Syntax highlighting
  (setq-default org-src-fontify-natively t)
HTTP
  (use-package ob-http
    :ensure t
    :after ob)
Language evaluation

Org-babel evaluation will be turned on for the following languages. Setting Confirm Evaluation to No disables the security prompt for that language.

Language Alias Confirm Evaluation? Description
emacs-lisp Yes Emacs Lisp
graphviz-dot dot No Directed and undirected graphs
gnuplot No Graphs
ditaa No Ascii diagrams
plantuml No Flow charts
mscgen No Message sequence charts
haskell Yes A pure, functional language
python Yes A dynamic, all-purpose language
hy Yes Python Lisp dialect
ruby Yes A dynamic, all-purpose language
shell Yes Shell scripts
http No HTTP requests
sql No SQL Queries
ledger No Double-Entry Accounting
  (defvar my/org-babel-evaluated-languages ())
  (defvar my/org-src-lang-modes ())
  (defvar my/org-babel-no-confirm-languages ())

  (defun my/org-confirm-babel-evaluate (lang body)
    (not (member (intern lang) my/org-babel-no-confirm-languages)))

  (let ((language-table (cddr '<<org-babel-languages()>>)))
    (mapcar (lambda (lang-pair)
              (let* ((alias (if (not (string= (cadr lang-pair) "")) (cadr lang-pair)))
                     (lang (intern (car lang-pair)))
                     (lang-or-alias (if alias (intern alias) lang))
                     (confirm (not (string= (cl-caddr lang-pair) "No"))))
                (if alias
                    (add-to-list 'my/org-src-lang-modes (cons alias lang)))
                (if (not confirm)
                    (add-to-list 'my/org-babel-no-confirm-languages lang-or-alias))
                (add-to-list 'my/org-babel-evaluated-languages lang-or-alias)
                lang-or-alias))
            language-table))

  (mapcar (lambda (alias)
            (add-to-list 'org-src-lang-modes alias))
          my/org-src-lang-modes)

  (org-babel-do-load-languages
   'org-babel-load-languages
   (mapcar (lambda (lang)
             (cons lang t))
           my/org-babel-evaluated-languages))

  (setq org-confirm-babel-evaluate 'my/org-confirm-babel-evaluate)
Reload images on source execution
  (defun my/redisplay-org-images ()
    (when org-inline-image-overlays
      (org-redisplay-inline-images)))

  (add-hook 'org-babel-after-execute-hook
            'my/redisplay-org-images)
Wrap text in blocks

A useful snippet for marking a region and wrapping it in an org block.

Taken from Pragmatic Emacs

  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  ;; function to wrap blocks of text in org templates                       ;;
  ;; e.g. latex or src etc                                                  ;;
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  (defun org-begin-template ()
    "Make a template at point."
    (interactive)
    (if (org-at-table-p)
        (call-interactively 'org-table-rotate-recalc-marks)
      (let* ((choices '(("s" . "SRC")
                        ("e" . "EXAMPLE")
                        ("q" . "QUOTE")
                        ("v" . "VERSE")
                        ("c" . "CENTER")
                        ("l" . "LaTeX")
                        ("h" . "HTML")
                        ("a" . "ASCII")))
             (key
              (key-description
               (vector
                (read-key
                 (concat (propertize "Template type: " 'face 'minibuffer-prompt)
                         (mapconcat (lambda (choice)
                                      (concat (propertize (car choice) 'face 'font-lock-type-face)
                                              ": "
                                              (cdr choice)))
                                    choices
                                    ", ")))))))
        (let ((result (assoc key choices)))
          (when result
            (let ((choice (cdr result)))
              (cond
               ((region-active-p)
                (let ((start (region-beginning))
                      (end (region-end)))
                  (goto-char end)
                  (insert "#+END_" choice "\n")
                  (goto-char start)
                  (insert "#+BEGIN_" choice "\n")))
               (t
                (insert "#+BEGIN_" choice "\n")
                (save-excursion (insert "#+END_" choice))))))))))

  ;;bind to key
  (define-key org-mode-map (kbd "C-<") 'org-begin-template)
Complete keywords with Company

Taken from https://emacs.stackexchange.com/a/30691.

  (defun org-keyword-backend (command &optional arg &rest ignored)
    (interactive (list 'interactive))
    (cl-case command
      (interactive (company-begin-backend 'org-keyword-backend))
      (prefix (and (eq major-mode 'org-mode)
                   (cons (company-grab-line "^#\\+\\(\\w*\\)" 1)
                         t)))
      (candidates (mapcar #'upcase
                          (cl-remove-if-not
                           (lambda (c) (string-prefix-p arg c))
                           (pcomplete-completions))))
      (ignore-case t)
      (duplicates t)))

  (eval-after-load 'company
    '(add-to-list 'company-backends 'org-keyword-backend))

  (add-hook 'org-mode-hook 'company-mode)
Exporting
LaTeX
  (use-package ox-latex
    :defer t
    :config
    <<configure-ox-latex>>)
Document classes

Add org latex class definitions for some popular LaTeX classes, including:

  (seq-map (apply-partially #'add-to-list 'org-latex-classes)
           '(("koma-letter"
              "\\documentclass{scrlttr2}"
              ("\\section{%s}" . "\\section*{%s}")
              ("\\subsection{%s}" . "\\subsection*{%s}")
              ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
              ("\\paragraph{%s}" . "\\paragraph*{%s}")
              ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
             ("koma-article"
              "\\documentclass{scrartcl}"
              ("\\section{%s}" . "\\section*{%s}")
              ("\\subsection{%s}" . "\\subsection*{%s}")
              ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
              ("\\paragraph{%s}" . "\\paragraph*{%s}")
              ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
             ("koma-book"
              "\\documentclass{scrbook}"
              ("\\section{%s}" . "\\section*{%s}")
              ("\\subsection{%s}" . "\\subsection*{%s}")
              ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
              ("\\paragraph{%s}" . "\\paragraph*{%s}")
              ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
             ("koma-book-chapters"
              "\\documentclass{scrbook}"
              ("\\chapter{%s}" . "\\chapter*{%s}")
              ("\\section{%s}" . "\\section*{%s}")
              ("\\subsection{%s}" . "\\subsection*{%s}")
              ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
              ("\\paragraph{%s}" . "\\paragraph*{%s}")
              ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
             ("koma-report"
              "\\documentclass{scrreprt}"
              ("\\chapter{%s}" . "\\chapter*{%s}")
              ("\\section{%s}" . "\\section*{%s}")
              ("\\subsection{%s}" . "\\subsection*{%s}")
              ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
              ("\\paragraph{%s}" . "\\paragraph*{%s}")
              ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
             ("memoir"
              "\\documentclass{memoir}"
              ("\\section{%s}" . "\\section*{%s}")
              ("\\subsection{%s}" . "\\subsection*{%s}")
              ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
              ("\\paragraph{%s}" . "\\paragraph*{%s}")
              ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
             ("hitec"
              "\\documentclass{hitec}"
              ("\\section{%s}" . "\\section*{%s}")
              ("\\subsection{%s}" . "\\subsection*{%s}")
              ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
              ("\\paragraph{%s}" . "\\paragraph*{%s}")
              ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
             ("paper"
              "\\documentclass{paper}"
              ("\\section{%s}" . "\\section*{%s}")
              ("\\subsection{%s}" . "\\subsection*{%s}")
              ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
              ("\\paragraph{%s}" . "\\paragraph*{%s}")
              ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
             ("letter"
              "\\documentclass{letter}"
              ("\\section{%s}" . "\\section*{%s}")
              ("\\subsection{%s}" . "\\subsection*{%s}")
              ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
              ("\\paragraph{%s}" . "\\paragraph*{%s}")
              ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
             ("tufte-handout"
              "\\documentclass{tufte-handout}"
              ("\\section{%s}" . "\\section*{%s}")
              ("\\subsection{%s}" . "\\subsection*{%s}")
              ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
              ("\\paragraph{%s}" . "\\paragraph*{%s}")
              ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
             ("tufte-book"
              "\\documentclass{tufte-book}"
              ("\\section{%s}" . "\\section*{%s}")
              ("\\subsection{%s}" . "\\subsection*{%s}")
              ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
              ("\\paragraph{%s}" . "\\paragraph*{%s}")
              ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
             ("tufte-book-chapters"
              "\\documentclass{tufte-book}"
              ("\\chapter{%s}" . "\\chapter*{%s}")
              ("\\section{%s}" . "\\section*{%s}")
              ("\\subsection{%s}" . "\\subsection*{%s}")
              ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
              ("\\paragraph{%s}" . "\\paragraph*{%s}")
              ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
             ("labbook"
              "\\documentclass{labbook}"
              ("\\chapter{%s}" . "\\chapter*{%s}")
              ("\\section{%s}" . "\\section*{%s}")
              ("\\subsection{%s}" . "\\labday{%s}")
              ("\\subsubsection{%s}" . "\\experiment{%s}")
              ("\\paragraph{%s}" . "\\paragraph*{%s}")
              ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))))
Source Highlighting

Configure org-mode LaTeX export to use minted for syntax highlighting.

Some languages / markups I use aren't supported by minted, so I map them here so they don't fail.

Language Mapping
dot text
org text
ditaa text
plantuml text
csv text
conf linux-config
Minted language mappings
  (setq org-latex-listings 'minted)
  (setq org-latex-minted-options
        '(("fontsize" "\\scriptsize")))
  (seq-map (lambda (mapping)
             (add-to-list 'org-latex-minted-langs
                          (cons (intern (car mapping)) (cdr mapping))))
           (seq-drop '<<ox-latex-minted-mappings()>> 2))
  (add-to-list 'org-latex-packages-alist
               '("" "minted" nil))
TeX Engine

Prepare the LaTeX export process, and default the compiler to xelatex, as it has better unicode support than pdflatex.

The %latex expansion variable is used so that org documents can override the latex compiler using the file-level LATEX_COMPILER directive.

  (setq org-latex-pdf-process
        (-repeat 3 "%latex -shell-escape -interaction nonstopmode -output-directory %o %f"))

  ;; Default to XeLaTeX
  (setq org-latex-compiler "xelatex")

LaTeX

AUCTeX
  (use-package tex-site
    :ensure auctex
    :mode ("\\.tex$" . TeX-latex-mode))
LaTeX-Extra
  (use-package latex-extra
    :ensure t
    :diminish latex-extra-mode
    :commands latex-extra-mode
    :init (add-hook 'LaTeX-mode-hook #'latex-extra-mode))

Markdown

  (use-package markdown-mode
    :ensure t
    :mode "\\.md$")

Tools

Flyspell

  (use-package flyspell
    :ensure t
    :commands flyspell-mode
    :diminish flyspell-mode
    :init (mapcar (lambda (mode-hook)
                    (add-to-list mode-hook #'flyspell-mode))
                  '(text-mode-hook
                    org-mode-hook)))

Auto-Fill

Automatically wrap paragraphs while writing in text modes.

  (mapcar (lambda (mode-hook)
            (add-hook mode-hook #'auto-fill-mode))
          '(text-mode-hook
            org-mode-hook))

Unfill

Re-flowing paragraphs with fill-paragraph is nice, but there are occasions when it's useful to do the inverse, and get rid of the line breaks.

  (use-package unfill
    :ensure t
    :commands (unfill-paragraph
               unfill-region)
    :bind ("M-Q" . unfill-paragraph))

Writegood

  (use-package writegood-mode
   :ensure t
   :commands writegood-mode
   :diminish writegood-mode
   :init (mapcar (lambda (mode-hook)
                   (add-hook mode-hook #'writegood-mode))
                 '(text-mode-hook
                   org-mode-hook)))

Define Word

  (use-package define-word
    :ensure t
    :bind ("C-c d" . define-word-at-point))

Finances

Ledger

Command-line double-entry accounting system. https://www.ledger-cli.org/

  (use-package ledger-mode
    :ensure t
    :mode "\\.ledger$")

Mail

Gnus

  (use-package gnus
    :commands gnus
    :init (progn (defun my/configure-gnus ()
                     <<gnus>>
                     )
                   (setq gnus-before-startup-hook 'my/configure-gnus)))

Avoid rich-text messages

  (setq mm-discouraged-alternatives '("text/html" "text/richtext"))

Summary view formatting

Taken from http://groups.google.com/group/gnu.emacs.gnus/browse_thread/thread/a673a74356e7141f

  (when window-system
    (setq gnus-sum-thread-tree-indent "  ")
    (setq gnus-sum-thread-tree-root "") ;; "● ")
    (setq gnus-sum-thread-tree-false-root "") ;; "◯ ")
    (setq gnus-sum-thread-tree-single-indent "") ;; "◎ ")
    (setq gnus-sum-thread-tree-vertical        "│")
    (setq gnus-sum-thread-tree-leaf-with-other "├─► ")
    (setq gnus-sum-thread-tree-single-leaf     "╰─► "))
  (setq gnus-summary-line-format
        (concat
         "%0{%U%R%z%}"
         "%3{│%}" "%1{%d%}" "%3{│%}" ;; date
         "  "
         "%4{%-20,20f%}"               ;; name
         "  "
         "%3{│%}"
         " "
         "%1{%B%}"
         "%s\n"))
  (setq gnus-summary-display-arrow t)

Inline images

  (require 'mm-decode)

  (add-to-list 'mm-attachment-override-types "image/.*")
  (setq mm-inline-large-images t)

Publishing

Htmlize

  (use-package htmlize
    :ensure t
    :commands (htmlize-region htmlize-buffer htmlize-file))

Source Control

Git-Gutter

  (use-package git-gutter
    :ensure t
    :diminish git-gutter-mode
    :bind (("C-x g n" . git-gutter:next-hunk)
           ("C-x g p" . git-gutter:previous-hunk))
    :defer 1
    :config
    (progn
      (global-git-gutter-mode t)
      (defadvice ediff-make-temp-file (before make-temp-file-suspend-ll
                                              activate compile preactivate)
        "Disable git-gutter when running ediff"
        (global-git-gutter-mode 0))

      (add-hook 'ediff-cleanup-hook
                '(lambda ()
                   (global-git-gutter-mode t)))))

Magit

  (use-package magit
    :ensure t
    :commands (magit-init
               magit-status
               magit-diff
               magit-commit)
    :bind (("C-c m s" . magit-status)
           ("C-c m d" . magit-diff)
           ("C-c m c" . magit-commit)
           ("C-c m l l" . magit-log-head)
           ("C-c m l b" . magit-log-buffer-file)
           ("C-c m l r" . magit-reflog-head))
    :config
    (progn
      (defadvice magit-status (around magit-fullscreen activate)
        (window-configuration-to-register :magit-fullscreen)
        ad-do-it
        (delete-other-windows))

      (defadvice magit-quit-window (around magit-restore-screen activate)
        ad-do-it
        (jump-to-register :magit-fullscreen))))

  (use-package magit-blame
    :ensure magit
    :commands magit-blame-mode
    :bind ("C-c m b" . magit-blame-addition))

Other functionality

Disable tab indenting by default

  (setq-default indent-tabs-mode nil)

Prefer encrypted auth sources

New credentials will be stored in the gpg-encrypted authinfo by default.

  (setq auth-sources '("~/.authinfo.gpg" "~/.authinfo" "~/.netrc"))

Rename file and buffer

Taken from Emacs Redux

  ;; emacsredux.com
  (defun rename-file-and-buffer ()
    "Rename the current buffer and file it is visiting."
    (interactive)
    (let ((filename (buffer-file-name)))
      (if (not (and filename (file-exists-p filename)))
          (message "Buffer is not visiting a file!")
        (let ((new-name (read-file-name "New name: " filename)))
          (cond
           ((vc-backend filename) (vc-rename-file filename new-name))
           (t
            (rename-file filename new-name t)
            (rename-buffer new-name)
            (set-visited-file-name new-name)
            (set-buffer-modified-p nil)))))))

Eval and Replace

Taken from Emacs Redux

  (defun eval-and-replace ()
    "Replace the preceding sexp with its value."
    (interactive)
    (backward-kill-sexp)
    (condition-case nil
        (prin1 (eval (read (current-kill 0)))
               (current-buffer))
      (error (message "Invalid expression")
             (insert (current-kill 0)))))

  (global-set-key (kbd "C-)") 'eval-and-replace)

Smarter navigation to the beginning of a line

Taken from Emacs Redux

  (defun smarter-move-beginning-of-line (arg)
    "Move point back to indentation of beginning of line.

  Move point to the first non-whitespace character on this line.
  If point is already there, move to the beginning of the line.
  Effectively toggle between the first non-whitespace character and
  the beginning of the line.

  If ARG is not nil or 1, move forward ARG - 1 lines first.  If
  point reaches the beginning or end of the buffer, stop there."
    (interactive "^p")
    (setq arg (or arg 1))

    ;; Move lines first
    (when (/= arg 1)
      (let ((line-move-visual nil))
        (forward-line (1- arg))))

    (let ((orig-point (point)))
      (back-to-indentation)
      (when (= orig-point (point))
        (move-beginning-of-line 1))))

  ;; remap C-a to `smarter-move-beginning-of-line'
  (global-set-key [remap move-beginning-of-line]
                  'smarter-move-beginning-of-line)

Edit file with sudo

Taken from EmacsWiki

  (require 'dired)
  (defun sudo-edit-current-file ()
    (interactive)
    (let ((my-file-name) ; fill this with the file to open
          (position))    ; if the file is already open save position
      (if (equal major-mode 'dired-mode) ; test if we are in dired-mode
          (progn
            (setq my-file-name (dired-get-file-for-visit))
            (find-alternate-file (prepare-tramp-sudo-string my-file-name)))
        (setq my-file-name (buffer-file-name); hopefully anything else is an already opened file
              position (point))
        (find-alternate-file (prepare-tramp-sudo-string my-file-name))
        (goto-char position))))


  (defun prepare-tramp-sudo-string (tempfile)
    (if (file-remote-p tempfile)
        (let ((vec (tramp-dissect-file-name tempfile)))

          (tramp-make-tramp-file-name
           "sudo"
           (tramp-file-name-user nil)
           (tramp-file-name-host vec)
           (tramp-file-name-localname vec)
           (format "ssh:%s@%s|"
                   (tramp-file-name-user vec)
                   (tramp-file-name-host vec))))
      (concat "/sudo:root@localhost:" tempfile)))

  (define-key dired-mode-map [s-return] 'sudo-edit-current-file)

Backups

Borrowed from Sacha Chua https://github.com/sachac/.emacs.d/

This is one of the things people usually want to change right away. By default, Emacs saves backup files in the current directory. These are the files ending in ~ that are cluttering up your directory lists. The following code stashes them all in ~/.emacs.d/backups, where I can find them with C-x C-f (find-file) if I really need to.

  (setq backup-directory-alist '(("." . "~/.emacs.d/backups")))

Disk space is cheap. Save lots.

  (setq delete-old-versions -1)
  (setq version-control t)
  (setq vc-make-backup-files t)
  (setq auto-save-file-name-transforms '((".*" "~/.emacs.d/auto-save-list/" t)))

Disable lock files

Lock files have only ever gotten in my way.

  (setq create-lockfiles nil)

History

From http://www.wisdomandwonder.com/wordpress/wp-content/uploads/2014/03/C3F.html

  (setq savehist-file "~/.emacs.d/savehist")
  (savehist-mode 1)
  (setq history-length t)
  (setq history-delete-duplicates t)
  (setq savehist-save-minibuffer-history 1)
  (setq savehist-additional-variables
        '(kill-ring
          search-ring
          regexp-search-ring))

Copy filename to clipboard

http://emacsredux.com/blog/2013/03/27/copy-filename-to-the-clipboard/ https://github.com/bbatsov/prelude

  (defun prelude-copy-file-name-to-clipboard ()
    "Copy the current buffer file name to the clipboard."
    (interactive)
    (let ((filename (if (equal major-mode 'dired-mode)
                        default-directory
                      (buffer-file-name))))
      (when filename
        (kill-new filename)
        (message "Copied buffer file name '%s' to the clipboard." filename))))

Prompt for 'y or n' instead of 'yes or no'

Because typing out "yes" and "no" is irritating.

  (defalias 'yes-or-no-p #'y-or-n-p)

Support ANSI colors in compilation buffers

http://stackoverflow.com/a/13408008

  (require 'ansi-color)
  (defun colorize-compilation-buffer ()
    (toggle-read-only)
    (ansi-color-apply-on-region compilation-filter-start (point))
    (toggle-read-only))
  (add-hook 'compilation-filter-hook 'colorize-compilation-buffer)

Re-bind modifiers on OSX

On mac keyboards, the command key placement works better for me as Meta rather than the default (Super), because it's right where my muscle memory expects a PC keyboard's Alt key.

The control keys are typically pretty terrible, too, but I find it easier to rebind Caps Lock to Control in the system preferences (which is a nice thing to do in other environments, as well).

  (when (equal 'darwin system-type)
    ;; Command as meta, because alt/option's placement is terrible on
    ;; mac keyboards (this doesn't interfere with Spotlight's ⌘-Space
    ;; binding)
    (setq ns-command-modifier 'meta))

Auto-loading elisp files

Any elisp files dropped into ~/.emacs.local.d/ will be automatically loaded.

I usually use this is a testing ground for new configuration before adding it here, and also for any personal / sensitive configuration.

  (defun my/load-elisp-directory (path)
    (let ((file-pattern "\\.elc?$"))
      (when (file-directory-p path)
        (mapcar (lambda (lisp-file)
                  (load-file lisp-file))
                (directory-files (expand-file-name path) t file-pattern)))))

  (my/load-elisp-directory "~/.emacs.local.d")

Configuration file layout

Here I define the emacs.el file that gets generated by the code in this org file.

  ;;;; Do not modify this file by hand.  It was automatically generated
  ;;;; from `emacs.org` in the same directory. See that file for more
  ;;;; information.
  ;;;;

  <<startup>>
  <<custom-settings>>
  <<look-and-feel>>
  <<packages>>
  <<programming>>
  <<autocomplete>>
  <<other>>
  <<auto-load>>