dotfiles/.emacs.d/emacs.org

1490 lines
45 KiB
Org Mode
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#+TITLE: Emacs Configuration
#+STARTUP: indent
* Startup
** Disable the emacs startup screen.
#+HEADER: :noweb-ref startup
#+BEGIN_SRC emacs-lisp
(setq inhibit-startup-screen +1)
#+END_SRC
* Custom settings
Store options set via =customize-*= in a separate file (Emacs stores
them in =init.el= by default).
#+HEADER: :noweb-ref custom-settings
#+BEGIN_SRC emacs-lisp
(setq custom-file "~/.emacs.d/custom.el")
(if (file-exists-p custom-file)
(load custom-file))
(setf custom-safe-themes t)
#+END_SRC
* UI
** Highlight the current line
#+HEADER: :noweb-ref look-and-feel
#+BEGIN_SRC emacs-lisp
(global-hl-line-mode +1)
#+END_SRC
** Powerline
Make the mode line prettier.
#+HEADER: :noweb-ref look-and-feel
#+BEGIN_SRC emacs-lisp
(use-package powerline
:ensure t
:config
(powerline-default-theme))
#+END_SRC
** Nyan-mode
Visualize the current position within the buffer in the modeline with nyancat!
#+HEADER: :noweb-ref look-and-feel
#+BEGIN_SRC emacs-lisp
(use-package nyan-mode
:ensure t
:config
(nyan-mode)
(nyan-start-animation))
#+END_SRC
** Display Time & Battery Status
#+HEADER: :noweb-ref look-and-feel
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
** Theme
#+HEADER: :noweb-ref look-and-feel
#+BEGIN_SRC emacs-lisp
(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))
#+END_SRC
** Major mode icons
Display major-mode names as icons in the mode line when possible.
#+HEADER: :noweb-ref look-and-feel
#+BEGIN_SRC emacs-lisp
(use-package mode-icons
:ensure t
:defer 5
:config (mode-icons-mode))
#+END_SRC
** Which-Key
Display key binding completions after a delay.
#+HEADER: :noweb-ref look-and-feel
#+BEGIN_SRC emacs-lisp
(use-package which-key
:ensure t
:diminish which-key-mode
:config
(which-key-setup-side-window-right-bottom)
(which-key-mode))
#+END_SRC
** Helm
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(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)))))
#+END_SRC
*** helm-descbinds
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package helm-descbinds
:ensure t
:bind (("C-h b" . helm-descbinds)
("C-h w" . helm-descbinds)))
#+END_SRC
*** helm-ag
Helm search plugin for [[Ag%20(The%20Silver%20Searcher)][Ag (The Silver Searcher)]]
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package helm-ag
:ensure t
:commands (helm-ag))
#+END_SRC
*** helm-flyspell
#+HEADER: :noweb-ref packages
#+begin_src emacs-lisp
(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)))
#+end_src
*** helm-swoop
Replace isearch-forward with helm-swoop for a nicer experience.
#+BEGIN_NOTES
Quite usefully, using prefix arguments expands the lines of context
shown around the search results.
#+END_NOTES
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(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)
)
#+END_SRC
** Undo-Tree
Visualize and traverse undo history as a directed graph.
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package undo-tree
:ensure t
:diminish undo-tree-mode
:config (global-undo-tree-mode))
#+END_SRC
** Multiple Cursors
#+HEADER: :noweb-ref look-and-feel
#+BEGIN_SRC emacs-lisp
(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)))
#+END_SRC
* Coding
** Languages
*** Lisps
#+NAME: lisps
| Mode | Description |
|------------+---------------------------|
| lisp | Common Lisp |
| emacs-lisp | Emacs Lisp |
| scheme | Scheme |
| lfe | Lisp-Flavored Erlang |
| clojure | Clojure |
| hy | Hy (Lisp-flavored Python) |
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp :noweb yes
;; 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)))
#+END_SRC
**** Lisp-Flavored Erlang
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package lfe-mode
:ensure t
:mode "\\.lfe$")
#+END_SRC
**** Clojure
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package clojure-mode
:ensure t
:mode (("\\.clj[sx]?$" . clojure-mode)
("\\.edn$" . clojure-mode)))
#+END_SRC
***** Cider
Communicates with the clojure REPL.
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package cider
:ensure t
:commands (cider-jack-in cider)
:config (setq org-babel-clojure-backend 'cider))
#+END_SRC
**** Hy
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package hy-mode
:ensure t
:mode "\\.hy$")
(use-package ob-hy
:ensure t
:defer t)
#+END_SRC
*** Erlang
A distributed, fault-tolerant functional language.
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(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")))))
#+END_SRC
*** Elixir
Ruby-flavoured Erlang.
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package elixir-mode
:ensure t
:mode "\\.exs?$")
(use-package alchemist
:ensure t
:after elixir-mode)
(use-package ob-elixir
:ensure t
:after ob)
#+END_SRC
*** Haskell
A strongly typed, pure functional language.
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(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))
#+END_SRC
*** Elm
A functional, reactive language for the web that compiles to
JavaScript.
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(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))
#+END_SRC
*** Idris
A functional language with dependent types.
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package idris-mode
:ensure t
:mode "\.idr$")
#+END_SRC
*** Web
**** HTML
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package web-mode
:ensure t
:mode "\\.html?$")
#+END_SRC
**** SCSS
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package scss-mode
:ensure t
:mode "\\.scss$"
:config (add-hook 'scss-mode-hook
(lambda ()
"Customize SCSS indentation"
(setq css-indent-offset 2))))
#+END_SRC
*** JavaScript
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package js2-mode
:ensure t
:mode ".js$")
#+END_SRC
*** PHP
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(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 '+))))
#+END_SRC
*** Python
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package python-mode
:ensure t
:mode "\.py$")
#+END_SRC
**** Elpy
Full functionality requires a number of python packages to be
installed:
#+BEGIN_SRC sh :exports code
# 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
#+END_SRC
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package elpy
:ensure t
:after python
:config (elpy-enable))
#+END_SRC
**** Cython
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package cython-mode
:ensure t
:mode "\.pyx$")
#+END_SRC
**** Company-Jedi
Configure jedi and company-mode to provide auto-completion for python.
#+HEADER: :noweb-ref programming
#+begin_src emacs-lisp
(use-package jedi
:ensure t
:commands jedi:setup
:config (progn
(setq jedi:use-shortcuts t)
(jedi:install-server)))
(use-package pungi
:ensure t
:commands pungi:setup-jedi
:init (add-hook #'python-mode-hook
(lambda ()
(when buffer-file-name
#'pungi:setup-jedi))))
(use-package company-jedi
:ensure t
:config (progn
(defun my/enable-company-jedi ()
(when buffer-file-name
(add-to-list 'company-backends 'company-jedi)))
(add-hook #'python-mode-hook
#'my/enable-company-jedi)))
#+end_src
*** Ruby
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package rvm
:ensure t
:commands (rvm-use
rvm-use-default))
#+END_SRC
*** Yaml
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package yaml-mode
:ensure t
:mode "\.yml$")
#+END_SRC
*** Docker
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package dockerfile-mode
:ensure t
:mode "^Dockerfile$")
#+END_SRC
*** Graphviz
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package graphviz-dot-mode
:ensure t
:mode "\.dot$"
:config
(setq graphviz-dot-indent-width 2))
#+END_SRC
*** Gnuplot
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package gnuplot
:ensure t)
#+END_SRC
*** PlantUML
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package plantuml-mode
:ensure t
:mode "\\.plantuml\\'"
:commands plantuml-mode)
#+END_SRC
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.
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package editorconfig
:ensure t
:diminish editorconfig-mode
:config
(editorconfig-mode 1))
#+END_SRC
*** Projectile
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(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))
#+END_SRC
*** Autocomplete
**** Company
Install and configure Company for auto-completion.
#+HEADER: :noweb-ref autocomplete
#+BEGIN_SRC emacs-lisp
(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)))
#+END_SRC
**** Auto-Complete
Not using this for auto-completion anymore, but several packages
require it.
#+HEADER: :noweb-ref autocomplete
#+begin_src emacs-lisp
(use-package auto-complete
:ensure t
:defer t)
#+end_src
*** Flycheck
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package flycheck
:ensure t
:diminish ""
:init
(add-hook 'after-init-hook #'global-flycheck-mode))
#+END_SRC
*** Web Mode
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(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))))
#+END_SRC
*** Skewer
Live web development in Emacs.
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(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)))
#+END_SRC
*** Yasnippet
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package yasnippet
:ensure t
:defer t
:diminish yas-minor-mode
:config (yas-global-mode 1))
#+END_SRC
*** Ag (The Silver Searcher)
This is a code searching tool that replaces =ack=, and is an order of
magnitude faster.
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package ag
:ensure t
:commands (ag))
#+END_SRC
*** Expand Region
Increase selected region by semantic units.
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package expand-region
:ensure t
:bind (("C-=" . er/expand-region)))
#+END_SRC
*** Nameless
Hide package namespaces in emacs-lisp code.
#+BEGIN_SRC emacs-lisp
(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))
#+END_SRC
** Libraries
*** Dash
A modern list api for Emacs. No 'cl required.
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package dash
:ensure t
:config (dash-enable-font-lock))
#+END_SRC
*** Stream
Lazy sequences in Emacs (compatible with seq.el).
#+HEADER: :noweb-ref programming
#+BEGIN_SRC emacs-lisp
(use-package stream
:ensure t
:if (version<= "25.1" emacs-version)
:defer t)
#+END_SRC
* Writing
** Style
*** End sentences with a single space
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(setq sentence-end-double-space nil)
#+END_SRC
** Formats
*** Org
**** Pretty bullets
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package org-bullets
:ensure t
:hook (org-mode . org-bullets-mode))
#+END_SRC
**** Modules
#+NAME: org-module-table
| org-habit |
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp :noweb yes
(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)
#+END_SRC
**** Tasks
***** Enforce dependencies
Require child tasks and checkboxes to be done before a parent task can
be marked done.
#+BEGIN_SRC emacs-lisp
(setq
org-enforce-todo-dependencies t
org-enforce-todo-checkbox-dependencies t)
#+END_SRC
***** Keep logs in their own drawer
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(setq org-log-into-drawer t)
#+END_SRC
***** Log completion
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(setq org-log-done 'time)
#+END_SRC
***** Habits
Shift the consistency graph over a bit to make room for task
names.
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(setq org-habit-graph-column 70)
(setq org-habit-show-habits-only-for-today nil)
#+END_SRC
**** Refiling
#+BEGIN_SRC emacs-lisp
(setq org-refile-targets '((org-agenda-files . (:maxlevel . 6))))
#+END_SRC
**** Babel
***** Syntax highlighting
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(setq-default org-src-fontify-natively t)
#+END_SRC
***** HTTP
#+HEADER: :noweb-ref packages
#+begin_src emacs-lisp
(use-package ob-http
:ensure t
:after ob)
#+end_src
***** Language evaluation
Org-babel evaluation will be turned on for the following
languages. Setting ~Confirm Evaluation~ to ~No~ disables the
[[http://orgmode.org/manual/Code-evaluation-security.html][security prompt]] for that language.
#+NAME: org-babel-languages
| 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 |
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp :noweb yes
(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)
#+END_SRC
***** Reload images on source execution
#+HEADER: :noweb-ref packages
#+begin_src emacs-lisp
(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)
#+end_src
**** Wrap text in blocks
A useful snippet for marking a region and wrapping it in an org block.
Taken from [[http://pragmaticemacs.com/emacs/wrap-text-in-an-org-mode-block/][Pragmatic Emacs]]
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 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)
#+END_SRC
**** Complete keywords with Company
Taken from https://emacs.stackexchange.com/a/30691.
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
**** Exporting
***** LaTeX
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp :noweb yes
(use-package ox-latex
:defer t
:config
<<configure-ox-latex>>)
#+END_SRC
****** Document classes
Add org latex class definitions for some popular LaTeX classes,
including:
- [[HTTPS://ctan.org/pkg/koma-script?lang=en][KOMA-Script]]
- [[https://ctan.org/pkg/memoir?lang=en][Memoir]]
- [[https://ctan.org/pkg/hitec?lang=en][Hitec]]
- [[https://ctan.org/pkg/tufte-latex?lang=en][Tufte]]
- [[https://ctan.org/pkg/labbook?lang=en][Labbook]] (based on KOMA-Script)
#+HEADER: :noweb-ref configure-ox-latex
#+BEGIN_SRC emacs-lisp
(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}"))))
#+END_SRC
****** 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.
#+NAME: ox-latex-minted-mappings
#+CAPTION: Minted language mappings
| Language | Mapping |
|----------+--------------|
| dot | text |
| org | text |
| ditaa | text |
| plantuml | text |
| csv | text |
| conf | linux-config |
#+HEADER: :noweb-ref configure-ox-latex
#+BEGIN_SRC emacs-lisp :noweb yes
(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))
#+END_SRC
****** TeX Engine
Prepare the LaTeX export process, and default the compiler to xelatex,
as it has better unicode support than pdflatex.
#+BEGIN_NOTES
The =%latex= expansion variable is used so that org documents can
override the latex compiler using the file-level =LATEX_COMPILER=
directive.
#+END_NOTES
#+HEADER: :noweb-ref configure-ox-latex
#+BEGIN_SRC emacs-lisp
(setq org-latex-pdf-process
(-repeat 3 "%latex -shell-escape -interaction nonstopmode -output-directory %o %f"))
;; Default to XeLaTeX
(setq org-latex-compiler "xelatex")
#+END_SRC
*** LaTeX
**** AUCTeX
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package tex-site
:ensure auctex
:mode ("\\.tex$" . TeX-latex-mode))
#+END_SRC
**** LaTeX-Extra
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package latex-extra
:ensure t
:diminish latex-extra-mode
:commands latex-extra-mode
:init (add-hook 'LaTeX-mode-hook #'latex-extra-mode))
#+END_SRC
*** Markdown
#+HEADER: :noweb-ref packages
#+begin_src emacs-lisp
(use-package markdown-mode
:ensure t
:mode "\\.md$")
#+end_src
** Tools
*** Flyspell
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(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)))
#+END_SRC
*** Auto-Fill
Automatically wrap paragraphs while writing in text modes.
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(mapcar (lambda (mode-hook)
(add-hook mode-hook #'auto-fill-mode))
'(text-mode-hook
org-mode-hook))
#+END_SRC
*** 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.
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package unfill
:ensure t
:commands (unfill-paragraph
unfill-region)
:bind ("M-Q" . unfill-paragraph))
#+END_SRC
*** Writegood
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(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)))
#+END_SRC
*** Define Word
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package define-word
:ensure t
:bind ("C-c d" . define-word-at-point))
#+END_SRC
* Finances
** Ledger
Command-line double-entry accounting system.
https://www.ledger-cli.org/
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package ledger-mode
:ensure t
:mode "\\.ledger$")
#+END_SRC
* Mail
** Gnus
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package gnus
:commands gnus
:init (progn (defun my/configure-gnus ()
<<gnus>>
)
(setq gnus-before-startup-hook 'my/configure-gnus)))
#+END_SRC
*** Avoid rich-text messages
#+HEADER: :noweb-ref gnus
#+BEGIN_SRC emacs-lisp
(setq mm-discouraged-alternatives '("text/html" "text/richtext"))
#+END_SRC
*** Summary view formatting
Taken from http://groups.google.com/group/gnu.emacs.gnus/browse_thread/thread/a673a74356e7141f
#+HEADER: :noweb-ref gnus
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
*** Inline images
#+HEADER: :noweb-ref gnus
#+BEGIN_SRC emacs-lisp
(require 'mm-decode)
(add-to-list 'mm-attachment-override-types "image/.*")
(setq mm-inline-large-images t)
#+END_SRC
* Publishing
** Htmlize
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(use-package htmlize
:ensure t
:commands (htmlize-region htmlize-buffer htmlize-file))
#+END_SRC
* Source Control
** Git-Gutter
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(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)))))
#+END_SRC
** Magit
#+HEADER: :noweb-ref packages
#+BEGIN_SRC emacs-lisp
(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))
#+END_SRC
* Other functionality
** Disable tab indenting by default
#+HEADER: :noweb-ref other
#+BEGIN_SRC emacs-lisp
(setq-default indent-tabs-mode nil)
#+END_SRC
** Prefer encrypted auth sources
New credentials will be stored in the gpg-encrypted authinfo by
default.
#+HEADER: :noweb-ref other
#+BEGIN_SRC emacs-lisp
(setq auth-sources '("~/.authinfo.gpg" "~/.authinfo" "~/.netrc"))
#+END_SRC
** Rename file and buffer
Taken from [[http://emacsredux.com/blog/2013/05/04/rename-file-and-buffer/][Emacs Redux]]
#+HEADER: :noweb-ref other
#+BEGIN_SRC emacs-lisp
;; 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)))))))
#+END_SRC
** Eval and Replace
Taken from [[http://emacsredux.com/blog/2013/06/21/eval-and-replace/][Emacs Redux]]
#+HEADER: :noweb-ref other
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
** Smarter navigation to the beginning of a line
Taken from [[http://emacsredux.com/blog/2013/05/22/smarter-navigation-to-the-beginning-of-a-line/][Emacs Redux]]
#+HEADER: :noweb-ref other
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
** Edit file with sudo
Taken from [[http://www.emacswiki.org/TrampMode#toc32][EmacsWiki]]
#+HEADER: :noweb-ref other
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
** 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.
#+HEADER: :noweb-ref other
#+begin_src emacs-lisp
(setq backup-directory-alist '(("." . "~/.emacs.d/backups")))
#+end_src
Disk space is cheap. Save lots.
#+HEADER: :noweb-ref other
#+begin_src emacs-lisp
(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)))
#+end_src
** Disable lock files
Lock files have only ever gotten in my way.
#+HEADER: :noweb-ref other
#+BEGIN_SRC emacs-lisp
(setq create-lockfiles nil)
#+END_SRC
** History
From http://www.wisdomandwonder.com/wordpress/wp-content/uploads/2014/03/C3F.html
#+HEADER: :noweb-ref other
#+begin_src emacs-lisp
(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))
#+end_src
** Copy filename to clipboard
http://emacsredux.com/blog/2013/03/27/copy-filename-to-the-clipboard/
https://github.com/bbatsov/prelude
#+HEADER: :noweb-ref other
#+begin_src emacs-lisp
(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))))
#+end_src
** Prompt for 'y or n' instead of 'yes or no'
Because typing out "yes" and "no" is irritating.
#+HEADER: :noweb-ref other
#+BEGIN_SRC emacs-lisp
(defalias 'yes-or-no-p #'y-or-n-p)
#+END_SRC
** Support ANSI colors in compilation buffers
http://stackoverflow.com/a/13408008
#+HEADER: :noweb-ref other
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
** 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).
#+HEADER: :noweb-ref other
#+BEGIN_SRC emacs-lisp
(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))
#+END_SRC
* 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.
#+HEADER: :noweb-ref auto-load
#+BEGIN_SRC emacs-lisp
(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")
#+END_SRC
* Configuration file layout
Here I define the emacs.el file that gets generated by the code in
this org file.
#+BEGIN_SRC emacs-lisp :tangle yes :noweb no-export :exports code
;;;; 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>>
#+END_SRC