init.el
Table of Contents
1. overview
1.1. purpose
Documentation for my emacs config. It provides the actual configuration as well as useful context like how the configuration works or relavent documentation.
The configuration itself follows three principles:
- Portable: This config should work on any machine whether its ran in a terminal or gui.
- Minimal: This config is small enough to understand fully.
- Useful: 95% of what you need to be effective with emacs is provided.
1.2. installing
Simply run org-babel-tangle
to export the code in this file to your init file.
1.3. links
This config, and a lot of the org mode settings, was inspired by Org Mode - Organize Your Life In Plain Text! A great read if you want to learn more about configuring org mode.
For more emacs inspiration check out Rougier on Github. He's doing some of the best UI/UX work in emacs at the moment.
Another great read is Literate DevOps which shows the power of org source blocks.
2. init.el
2.1. global changes
A catch all for settings that work across all emacs modes.
(setq default-directory "~/" ring-bell-function 'ignore tab-always-indent 'complete ;; Tab indents a line. If the line is indented then it runs completion-at-point help-window-select t ;; Automatically focus on help window when they pop up split-width-threshold nil ;; Split windows vertically custom-file "~/.emacs.d/custom.el" ;; Contains customized variables x-super-keysym 'meta ;; Use command key on mac as meta compilation-scroll-output 'first-error ;; Automatically scroll to first error in a completion buffer ) (add-to-list 'exec-path "/usr/local/bin/") (global-visual-line-mode 1) (savehist-mode) ;; save shell history (defalias 'yes-or-no-p 'y-or-n-p) ;; don't ask for yes/no as for y/n (add-hook 'compilation-finish-functions 'switch-to-buffer-other-window 'compilation)
2.2. backups
Sensible settings for emacs backups. All backups and autosaves are put in the ~/.emacs.d/
folder so temp files don't pollute the filesystem.
(thoughts on other ways to manage backups)
(setq backup-directory-alist `(("." . ,(concat user-emacs-directory "backup"))) backup-by-copying t ;; Don't de-link hard links version-control t ;; Use version numbers on backups delete-old-versions t ;; Automatically delete excess backups: kept-new-versions 20 ;; how many of the newest versions to keep kept-old-versions 5) ;; and how many of the old (unless (file-directory-p "~/.emacs.d/auto-save") (make-directory "~/.emacs.d/auto-save")) (setq auto-save-file-name-transforms '((".*" "~/.emacs.d/auto-save/" t)))
2.3. elisp
A couple of convenience functions to make elisp more readable.
(defun first (list) "The first item in the list (car)" (nth 0 list)) (defun second (list) "The second item in the list" (nth 1 list)) (defun rest (list) "All items in a list after the first (cdr)" (cdr list))
2.4. helpers
2.4.1. last command
I use this as my main command runner. The first time it's run it opens M-x. After that it cycles through the previous commands you run. So, if you run this twice it will show the last command you ran. I have it bound to C-;
in my keybindings.
(defun execute-last-command () "Executes the last extended command that was run" (interactive) (let* ((cmd-str (first extended-command-history)) (cmd (intern-soft cmd-str))) (message (concat "Executing: `" cmd-str "`")) (command-execute cmd))) (defun execute-command-or-search-history () (interactive) (call-interactively (if (minibufferp) 'previous-history-element 'execute-extended-command)))
2.4.2. tangle helpers
I like to keep my configs in org files. The functions below find those files and tangle the output.
(defun tangle-init () (interactive) (save-window-excursion (find-file "~/org/projects/emacs.org") (widen) (beginning-of-buffer) (re-search-forward "* init") (org-narrow-to-subtree) (org-babel-tangle) (widen))) (defun tangle-snippets () (interactive) (save-window-excursion (find-file "~/org/projects/emacs.org") (widen) (end-of-buffer) ;; Backwards because searching forwards will find this line (re-search-backward "* Snippets") (org-narrow-to-subtree) (org-babel-tangle) (widen))) (defun tangle-dot-files () (interactive) (save-window-excursion (find-file "~/org/projects/dotfiles.org") (org-babel-tangle)))
2.4.3. split-region
(defun split-region (del rep) "Spilts a region by the given delimiter and replaces it with the given rep" (interactive (list (read-string "delimeter: " "") (read-string "replace: " "\n"))) (let ((s (buffer-substring-no-properties (region-beginning) (region-end)))) (delete-region (region-beginning) (region-end)) (insert (replace-regexp-in-string del rep s t t))))
2.4.4. align-regex (with space)
(defadvice align-regexp (around align-regexp-with-spaces activate) (let ((indent-tabs-mode nil)) ad-do-it))
2.4.5. kill-processes
(defun kill-processes (regex) "Kill all processes whose names match the given regex." (interactive "sEnter regex to match processes: ") (dolist (process (process-list)) (let ((name (process-name process))) (when (and name (string-match-p "nrepl" name)) (delete-process process) (message "Killed process: %s" name)))))
2.4.6. launch
(defun insert-return () "Presses the RETURN key" (funcall (lookup-key (current-local-map) (kbd "RET")))) (defun launch (cmd) "Opens a shell and runs the given command. Useful for running long running commands from emacs." (interactive "sCommand to run: ") (let* ((shell-name (format "*Launch: %s*" (truncate-string-to-width cmd 10))) (buffer (shell shell-name))) (sit-for 1) (insert cmd) (insert-return)))
2.4.7. list directories
Recursively list all directories under a directory
(defun list-directories-recursively (directory) "List all directories recursively in DIRECTORY." (let ((directories (list directory))) (dolist (file (directory-files-recursively directory "" t)) (when (file-directory-p file) (push file directories))) directories))
2.5. keybindings
(defun global-set-keys (key-action-pairs) "Binds a list of keybindings in the form (keybinding action)" (when key-action-pairs (let ((key (first (first key-action-pairs))) (action (second (first key-action-pairs)))) (global-set-key (kbd key) action)) (global-set-keys (cdr key-action-pairs)))) (global-set-keys '(;; Emacs ("<C-wheel-down>" ignore) ("<C-wheel-up>" ignore) ("C-;" execute-command-or-search-history) ("M-^" execute-command-or-search-history) ; set ctrl-; to ^; iterm ("C-'" previous-history-element) ("C-S-<right>" enlarge-window-horizontally) ("C-S-<left>" shrink-window-horizontally) ("C-S-<up>" shrink-window) ("C-S-<down>" enlarge-window) ("C-x ," rename-buffer) ;; Navigation ("M-," pop-global-mark) ("C-x e" end-of-buffer) ("C-c C-e" eval-defun) ("C-x t" beginning-of-buffer) ("C-x i" info) ("C-x a" align-regexp) ("C-x C-g" goto-line) ("C-c r" replace-regexp) ;; Editing ("C-x y" (lambda () (interactive) (popup-menu 'yank-menu))) ("M-w" backward-kill-word) ("C-x q" kmacro-end-and-call-macro) ("C-x c" comment-line) ;; Actions ("C-c b" compile) ("C-c C-b" (lambda () (interactive) (save-buffer) (recompile))) ("C-c t" (lambda () (interactive) (print "Missing test runner for this major mode."))) ("M-." xref-find-definitions) ("C-c D" (lambda () (interactive) (print "Missing disassembler for this major mode."))) ("C-c d" (lambda () (interactive) (print "Missing debugger for this major mode."))) ("C-c f" (lambda () (interactive) (print "Missing formatter for this major mode."))) ("C-c h" (lambda () (interactive) (print "Missing help for this major mode."))) ("C-h d" (lambda () (interactive) (call-interactively 'man))) ))
2.6. package managers
Two package managers are used:
-
A package manager with the ability to pull from github.
-
A package manager with a great interface. Straight is setup to use this as a front end.
(defvar bootstrap-version) (let ((bootstrap-file (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory)) (bootstrap-version 6)) (unless (file-exists-p bootstrap-file) (with-current-buffer (url-retrieve-synchronously "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el" 'silent 'inhibit-cookies) (goto-char (point-max)) (eval-print-last-sexp))) (load bootstrap-file nil 'nomessage)) ;; Use Package (straight-use-package 'use-package) (setq straight-use-package-by-default t) ;; Profile startup time (require 'use-package) (setq use-package-always-defer t) (setq use-package-compute-statistics t)
2.7. ui
2.7.1. nano
A fantastic UI for emacs. I highly recommend checking out Rougier's other emacs work.
Nano emacs overrides a lot of defaults. I like to run it as early as possible so it doesn't override some of the changes I make.
(when (window-system) (straight-use-package '(nano-emacs :type git :host github :repo "rougier/nano-emacs")) ;; Need to setq before calling nano-faces (setq nano-font-family-monospaced "Roboto Mono" nano-font-size 16) (require 'nano-theme-light) (nano-theme-set-light) (require 'nano-colors) ;;(require 'nano-minibuffer) (require 'nano-faces) (nano-faces) (require 'nano-theme) (nano-theme) (require 'nano-modeline)) ;; Hack to override nano custom show paren (set-face-foreground 'show-paren-match "#00f") (set-face-attribute 'show-paren-match nil :weight 'extra-bold) (set-face-attribute 'font-lock-string-face nil :foreground "indian red") (set-face-attribute 'region nil :background "#D8D9DA")
2.7.2. gui
Custom UI changes when running in the gui.
(when (window-system) (setq ns-use-native-fullscreen t mac-command-modifier 'meta mac-option-modifier 'meta mac-use-title-bar nil) (progn (tool-bar-mode 0) (menu-bar-mode -1) (scroll-bar-mode -1) (set-face-attribute 'default nil :font "Roboto Mono" :height 160)))
2.7.3. terminal
Custom UI changes when running in a terminal.
(when (not (window-system)) (progn (load-theme 'tsdh-dark t) (menu-bar-mode -1) (set-frame-font "Roboto Mono 16") (display-battery-mode 1)))
2.8. packages
Favorites:
- auto-yasnippet: On the fly templates.
- avy: Fast buffer navigation.
- iedit: Edit all occurences of a word at the same time.
- multiple-cursors: Edit multiple lines at the same time.
- vundo: Navigate and view emacs undo tree.
- yasnippet: A templating system for managing snippets
Full List:
- 2.8.1. ace window
- 2.8.2. auto-yasnippet
- 2.8.3. avy
- 2.8.4. c
- 2.8.5. c++
- 2.8.6. cider
- 2.8.7. clojure
- 2.8.8. company
- 2.8.9. csv-mode
- 2.8.10. dired
- 2.8.11. disaster
- 2.8.12. dockerfile
- 2.8.13. eglot
- 2.8.14. electric
- 2.8.15. erc
- 2.8.16. exec-path-from-shell
- 2.8.17. flycheck
- 2.8.18. htmlize
- 2.8.19. ido
- 2.8.20. iedit
- 2.8.21. json
- 2.8.22. magit
- 2.8.23. man
- 2.8.24. mu4e
- 2.8.25. multiple-cursors
- 2.8.26. plantuml
- 2.8.27. paredit
- 2.8.28. python
- 2.8.29. rainbow deleminter
- 2.8.30. paren
- 2.8.31. slime
- 2.8.32. tramp
- 2.8.33. vterm
- 2.8.34. vundo
- 2.8.35. yasnippet
- 2.8.36. yaml
- 2.8.37. elisp
- 2.8.38. cleanup
2.8.1. ace window
Makes switching windows easier.
(use-package ace-window :bind ("C-x o" . ace-window) :init (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)) (setf aw-dispatch-alist '()))
2.8.2. auto-yasnippet
Inline snippets for on the fly templating.
(use-package auto-yasnippet :bind ("M-w" . #'aya-create) ("M-y" . #'aya-expand) :init (setq aya-marker "$"))
2.8.3. avy
Jump to anywhere in a buffer by typing the text of the location you want to jump to.
(use-package avy :bind ("C-o" . avy-goto-char-timer))
2.8.4. c
(require 'cc-mode) (define-key c-mode-base-map (kbd "C-c C-b") nil) (define-key c-mode-base-map (kbd "C-c d") 'disaster)
2.8.5. c++
(defun my-c++-mode-hook () (setq c-basic-offset 4) (c-set-offset 'substatement-open 0) (flycheck-mode)) (add-hook 'c++-mode-hook 'my-c++-mode-hook) (define-key c++-mode-map (kbd "C-c C-b") nil)
2.8.6. cider
Clojure IDE for interactive development.
(defun cider-smart-run-tests () "Saves all buffers before running cider tests" (interactive) (let* ((buffers (buffer-list)) (test-buffers (seq-filter (lambda (b) (string-match ".*test.clj" (buffer-name b))) buffers))) (save-current-buffer (dolist (buffer test-buffers) (set-buffer buffer) (save-buffer) (cider-eval-buffer))) (cider-test-run-project-tests nil))) (use-package cider :bind ("C-c d" . cider-debug-defun-at-point) ("C-c i" . cider-inspect) ("C-c t" . cider-test-run-ns-tests) ("C-c p" . cider-profile-toggle) ("C-c P" . cider-profile-summary) ("C-c r" . cider-toggle-trace-var) ("C-c g" . cider-goto-test) ("C-c m" . cider-macroexpand-1) ("C-c ." . xref-find-definitions) ("C-c h" . cider-doc) :hook (cider-repl-mode-hook . (lambda () (setq scroll-conservatively 101))) :config (setq cider-repl-display-help-banner nil cider-repl-pop-to-buffer-on-connect nil cider-clojure-cli-aliases ":dev" cider-clojure-cli-command "clojure") (cider-auto-test-mode 1)) (defun clj-clerk-show () (interactive) (when-let ((filename (buffer-file-name))) (save-buffer) (cider-interactive-eval (concat "(nextjournal.clerk/show! \"" filename "\")")))) (defun clj-clerk-open () (interactive) (cider-interactive-eval "(require '[nextjournal.clerk :as clerk])") (cider-interactive-eval "(clerk/serve! {:browse? true})") ; (cider-interactive-eval "(clerk/serve! {:watch-paths [\"notebooks\" \"src\"]})") ) (defun clj-portal-open () (interactive) (cider-interactive-eval "(require '[portal.api :as p])") (cider-interactive-eval "(p/open {:theme :portal.colors/zerodark})") (cider-interactive-eval "(add-tap #'p/submit)"))
2.8.7. clojure
(use-package clojure-mode :defer t :config (defface font-lock-func-face '((nil (:foreground "#7F0055" :weight bold)) (t (:bold t :italic t))) "Font Lock mode face used for function calls." :group 'font-lock-highlighting-faces) (font-lock-add-keywords 'clojure-mode '(("(\\s-*\\(\\_<\\(?:\\sw\\|\\s_\\)+\\)\\_>" 1 'font-lock-func-face))))
2.8.8. company
Text completion framework.
(use-package company :hook (c++-mode . company-mode) (c-mode . company-mode) :bind(:map company-active-map ("<return>" . nil) ("RET" . nil) ("<tab>" . company-complete-selection)))
2.8.9. csv-mode
(use-package csv-mode)
2.8.10. dired
Builtin filesystem navigation.
(use-package dired :straight (:type built-in) :hook ((dired-mode . hl-line-mode) (dired-mode . dired-hide-details-mode)) :custom (dired-recursive-copies 'always) (dired-recursive-deletes 'always) (dired-dwim-target t) ;;use to copy to the next buffer visible ;; Auto refresh Dired, but be quiet about it (global-auto-revert-non-file-buffers t) (auto-revert-verbose nil) :init (setq dired-kill-when-opening-new-dired-buffer t))
2.8.11. disaster
Live disassembler for c and c++.
(use-package disaster :commands (disaster) :init (setq disaster-assembly-mode 'nasm-mode disaster-objdump "objdump -Sl --no-show-raw-insn -d") :bind ("C-c o" . disaster))
2.8.12. dockerfile
(use-package dockerfile-mode :defer t)
2.8.13. eglot
Language server protocol (LSP) for emacs.
(use-package eglot :hook (c++-mode . eglot-ensure) (c-mode . eglot-ensure) :init (add-hook 'eglot-managed-mode-hook (lambda () (eglot-inlay-hints-mode -1))) ) (with-eval-after-load 'eglot (add-to-list 'eglot-server-programs `(c++-mode . ("clangd" "--compile-commands-dir=/tmp"))))
2.8.14. electric
Builtin mode for adding closed character when an open one is added (eg brackets or parens).
(use-package electric :hook (java-mode . electric-pair-mode) (c-mode . electric-pair-mode) (c++-mode . electric-pair-mode))
2.8.15. erc
Builtin irc client.
(use-package erc :defer t :config (setq erc-autojoin-channels-alist '(("libera.chat")) erc-hide-list '("JOIN" "PART" "QUIT") erc-server "irc.libera.chat" erc-nick (getenv "ERC_NICK") erc-track-exclude-types '("JOIN" "NICK" "PART" "QUIT") erc-track-shorten-function nil erc-join-buffer 'bury)) (defun erc-clear-notifications () (interactive) (setq erc-modified-channels-alist nil) (erc-modified-channels-update))
2.8.16. exec-path-from-shell
Sets the path variable for emac's spawned shells to be the same as user shells.
Tips on speeding it up: https://github.com/purcell/exec-path-from-shell/issues/75
There are interactive and non-interactive shells. Non-interactive is faster. Exec path from shell can start those but they need shell configs (.bashrc) to be in special file (.profile). This mean that the package runtime depends on shell startup time. Conda can slow this down.
(when (memq window-system '(mac ns x)) (use-package exec-path-from-shell :init (setq exec-path-from-shell-variables '("PATH" "MANPATH" "PYTHONPATH" "P_E" "P_A") exec-path-from-shell-arguments '("-l")) (exec-path-from-shell-initialize)))
2.8.17. flycheck
Syntax checker.
(use-package flycheck :hook (('c++-mode-hook . flycheck-mode)) :config (setq flycheck-gcc-language-standard "c++17") (setq flycheck-clang-language-standard "c++17") (setq flycheck-gcc-include-path ()) (set-face-attribute 'flycheck-error nil :underline '(:color "dark gray" :style wave)) (set-face-attribute 'flycheck-warning nil :underline '(:color "dark gray" :style wave)) (set-face-attribute 'flycheck-info nil :underline '(:color "light gray" :style wave)) )
2.8.18. htmlize
2.8.19. ido
Auto complete for emacs inputs.
(defun ido-my-keys () "Keybindings for navigating ido results ." (define-key ido-common-completion-map (kbd "C-n") 'ido-next-match) (define-key ido-common-completion-map (kbd "C-p") 'ido-prev-match) (define-key ido-common-completion-map (kbd "C-<return>") 'ido-select-text)) (use-package ido :bind ("C-<tab>" . ido-hippie-expand) ("C-j" . minibuffer-complete-and-exit) :init (setq ido-enable-regexp t) (setq ido-separator "\n") (setq ido-use-filename-at-point 'guess) (setq ido-create-new-buffer 'always) (setq ido-enable-flex-matching t) (setq ido-auto-merge-work-directories-length -1) ;; disable auto complete (ido-mode 1) (add-hook 'ido-setup-hook 'ido-my-keys) :config (ido-everywhere t))
2.8.20. iedit
Edit all instances of a word in a buffer in realtime.
(use-package iedit :ensure t :bind ("C-\\" . iedit-mode))
2.8.21. json
(use-package json-mode)
2.8.22. magit
2.8.23. man
Man page viewer.
(use-package man :bind ("C-x m" . man) :config (custom-set-variables '(Man-notify-method 'bully)))
2.8.24. mu4e
Email client built on mu
.
mu4e is installed when you install mu.
(straight-use-package '(mu4e :files (:defaults "mu4e/*.el"))) (require 'smtpmail) (let ((addr (rot13 (base64-decode-string (getenv "P_A")))) (pass (rot13 (base64-decode-string (getenv "P_E")))) (name "Zach Dingels") (mail-dir "~/docs/mail/")) (setq user-mail-address addr mu4e-get-mail-command "offlineimap" mu4e-mu-binary (executable-find "mu") mu4e-maildir mail-dir message-send-mail-function 'smtpmail-send-it smtpmail-stream-type 'tls smtpmail-default-smtp-server "smtp.fastmail.com" smtpmail-auth-credentials `(("smtp.fastmail.com" 465 addr pass)) smtpmail-smtp-server "smtp.fastmail.com" smtpmail-smtp-service 465 mu4e-sent-folder "/sent" mu4e-drafts-folder "/drafts" mu4e-trash-folder "/trash" mu4e-refile-folder "/archive")) (setq mu4e-bookmarks '((:name "Inbox" :query "maildir:/Inbox" :key ?i) (:name "Archive" :query "maildir:/Archive" :key ?a) (:name "Drafts" :query "maildir:/Drafts" :key ?d) (:name "Sent" :query "maildir:/Sent" :key ?s) (:name "Note" :query "maildir:/Note" :key ?n)))
2.8.25. multiple-cursors
Edit text using multiple cursors at the same time.
(use-package multiple-cursors :bind (("C->" . mc/mark-next-like-this) ("C-<" . mc/mark-previous-like-this)))
2.8.26. plantuml
Text based language for creating diagrams. It's compatible with org mode.
(use-package plantuml-mode :config (setq org-plantuml-jar-path (expand-file-name "~/tools/plantuml.jar")) (setq plantuml-default-exec-mode 'jar) (org-babel-do-load-languages 'org-babel-load-languages '((plantuml . t))))
2.8.27. paredit
Editing and navigation for s-expressions.
(use-package paredit :ensure t :hook (emacs-lisp-mode-hook . enable-paredit-mode) (elisp-mode-hook . enable-paredit-mode) (eval-expression-minibuffer-setup-hook . enable-paredit-mode) (clojure-mode-hook . enable-paredit-mode) (lisp-mode-hook . enable-paredit-mode) (cider-mode-hook . enable-paredit-mode) (janet-mode-hook . enable-paredit-mode) :bind (("M-F" . paredit-forward-slurp-sexp) ("M-P" . paredit-backward-slurp-sexp)))
2.8.28. python
(use-package python :defer t :bind (("C-c [" . python-indent-shift-left) ("C-c ]" . python-indent-shift-right) ("C-c /" . comment-line) ("C-j" . python-eval-print-last-sexp) ("C-c <tab>" . #'company-complete)) :init (setq python-indent-guess-indent-offset t python-indent-guess-indent-offset-verbose nil eldoc-echo-area-use-multiline-p nil python-shell-interpreter "/Users/zach/tools/conda/envs/dev/bin/python"))
2.8.29. rainbow deleminter
Changes the color of parenthesis based on the level of nesting.
(use-package rainbow-delimiters :custom-face (rainbow-delimiters-depth-1-face ((t (:foreground "conflower blue")))) (rainbow-delimiters-depth-2-face ((t (:foreground "light slate blue")))) (rainbow-delimiters-depth-3-face ((t (:foreground "medium slate blue")))) (rainbow-delimiters-depth-4-face ((t (:foreground "slate blue")))) (rainbow-delimiters-depth-5-face ((t (:foreground "dark slate blue")))) (rainbow-delimiters-depth-6-face ((t (:foreground "midnight blue")))))
2.8.30. paren
Highlights the matching parenthesis when the cursor is over it's pair.
(use-package paren :ensure t :config (set-face-foreground 'show-paren-match "#00f") (set-face-attribute 'show-paren-match nil :weight 'extra-bold) (show-paren-mode 1))
2.8.31. slime
IDE for common lisp.
(use-package slime :init ;; (load (expand-file-name "~/.quicklisp/slime-helper.el")) ;; slows down startup. :defer t :hook (slime-repl-mode-hook . enable-paredit-mode) :config (setq inferior-lisp-program "sbcl") (show-paren-mode 1))
2.8.32. tramp
Builtin tool for working with remote machines.
use-package does not work with tramp.
(require 'tramp) (customize-set-variable 'tramp-default-method "ssh") (setq recentf-keep '(file-remote-p file-readable-p)) (defun tramp-ensure-dissected-file-name (vec-or-filename) "Return a `tramp-file-name' structure for VEC-OR-FILENAME. VEC-OR-FILENAME may be either a string or a `tramp-file-name'. If it's not a Tramp filename, return nil." (cond ((tramp-file-name-p vec-or-filename) vec-or-filename) ((tramp-tramp-file-p vec-or-filename) (tramp-dissect-file-name vec-or-filename))))
2.8.33. vterm
2.8.34. vundo
A visualizer for the undo tree.
(use-package vundo :config (setq vundo-glyph-alist vundo-unicode-symbols))
2.8.35. yasnippet
A template library.
(use-package yasnippet :ensure t :hook ((text-mode prog-mode conf-mode org-mode snippet-mode) . yas-minor-mode-on) :init (setq yas-snippet-dir "~/.emacs.d/snippets") :config (yas-global-mode 1) (yas-reload-all))
2.8.36. yaml
(use-package yaml-mode)
2.8.37. elisp
Various elisp libraries.
(use-package dash) (use-package request) (use-package s)
2.8.38. cleanup
Hide an extra buffer created for straight after all packages have been setup.
(kill-buffer "*straight-process*")
2.9. org
Inspirational write up on organizing org mode.
There is a lot to org mode so this section will get it's own writeup in the future…
(use-package org :bind (("C-c a" . org-agenda) ("C-c c" . org-capture) :map org-mode-map ("C-c b" . org-babel-tangle-block)) :hook (org-mode . visual-line-mode) (org-agenda-finalize-hook . (lambda () (hl-line-mode))) (org-mode . variable-pitch-mode) (org-mode . buffer-face-mode) (org-mode . (lambda () (print "hello") (setq line-spacing 0.10))) :config ;; General (setq org-directory "~/org" org-startup-folded t org-hide-emphasis-markers t ;; When you use *bold*, don't display the * org-tags-column 1 ; org-html-htmlize-output-type 'css org-startup-with-inline-images t org-image-actual-width nil org-html-postamble t org-html-postamble-format '(("en" "<p class=\"date\">Date: %d</p><p class=\"author\">Author: <a href=http://zach.dingels.io>%a</a></p><p><a href=https://creativecommons.org/licenses/by-sa/4.0/>license</a></p")) org-html-preamble t org-html-preamble-format '(("en" "<p><a href=\"https://dingels.io\">home</a></p>"))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Todos ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <<org-todo>> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Agenda ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <<org-agenda>> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Capture ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <<org-capture>> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Refile ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <<org-refile>> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Babel ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <<org-babel>> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Crypt ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <<org-crypt>> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Faces ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; <<org-faces>> ) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Customized export to html ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (with-eval-after-load 'org-html <<org-htlm-override>> <<org-html-others>> <<org-html-toc-collapse>>)
2.9.1. find-entry
find-entry
let's you navigate an org file like you would navigate your filesystem using IDO. It starts by giving you all the options for top level headings. After selecting a heading with tab the options will update to all the sub-headings of the selected heading.
(straight-use-package '(find-entry :type git :host github :repo "dingelsz/find-entry")) (use-package find-entry :bind ("C-x f" . find-entry))
2.10. splash Screen
Custom text for the scratch buffer.
(setq inhibit-splash-screen t) (switch-to-buffer "*scratch*") (insert (concat ";; ----------------------------------------------------------------------------\n" ";; Festina Lente\n" ";; ----------------------------------------------------------------------------\n")) (end-of-buffer) (load custom-file)
3. email
mu4e is an email client for emacs. It uses mu to index and search email. It requires a third tool to retrieve email. I use offlineimap with the configs below.
3.1. install
sudo port install mu sudo port install offlineimap
3.2. configs
# ~/.config/offlineimap/config [general] # List of accounts to be synced, separated by a comma. accounts = main pythonfile = ~/.offlineimap.py [Account main] # Identifier for the local repository; e.g. the maildir to be synced via IMAP. localrepository = local # Identifier for the remote repository; i.e. the actual IMAP, usually non-local. remoterepository = fastmail [Repository local] # OfflineIMAP supports Maildir, GmailMaildir, and IMAP for local repositories. type = Maildir # Where should the mail be placed? localfolders = ~/docs/mail [Repository fastmail] # Remote repos can be IMAP or Gmail, the latter being a preconfigured IMAP. # SSL and STARTTLS are enabled by default. type = IMAP remotehost = imap.fastmail.com remoteusereval = getuser() remotepasseval = getpass() ssl = yes # Necessary for SSL connections, if using offlineimap version > 6.5.4 sslcacertfile = ~/docs/mail/.cert.pem
# ~/.offlineimap.py import base64 import codecs import os def decode(x): return codecs.decode(base64.b64decode(x).decode(), "rot_13") def getuser(): return decode(os.environ["P_A"]) def getpass(): return decode(os.environ["P_E"])
3.3. useful links
4. sync via git
See org->git for an overview of how to automatically sync your org files with git.
4.1. cron
# M H D M W /PATH/TO/SCRIPT * * * * * /usr/local/sbin/org-sync >> /Users/zach/org/org-sync.log 2>&1