#+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 '<>))))) (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 *** 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)) (use-package yasnippet-snippets :ensure t) #+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 *** Language Server Protocol IDE-level integration supporting multiple languages. #+HEADER: :noweb-ref packages #+begin_src emacs-lisp (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))) #+end_src #+CAPTION: Language server implementations | Language | Server | Installation | |---------------+--------------------------------------------+-------------------------------------------| | PHP | [[https://www.npmjs.com/package/intelephense][Intelephense]] | =npm i intelephense= | | Python | [[https://github.com/palantir/python-language-server][Python Language Server]] | =pip install python-language-server[all]= | | Python (Mypy) | [[https://github.com/tomv564/pyls-mypy][Mypy plugin for the Python Language Server]] | =pip install pyls-mypy= | **** Company integration #+HEADER: :noweb-ref packages #+begin_src emacs-lisp (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))))) #+end_src **** Fancy UI #+HEADER: :noweb-ref packages #+begin_src emacs-lisp (use-package lsp-ui :ensure t :hook (lsp-mode . lsp-ui-mode) :config ;; Disable eldoc-mode (global-eldoc-mode -1)) #+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))) '<>))) (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 '<>))) (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 <>) #+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 '<> 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 () <> ) (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. ;;;; <> <> <> <> <> <> <> <> #+END_SRC