#+TITLE: Doom Emacs Configuration File Execute ~doom sync~ after modifying this file to tangle it to ~config.el~. The following block of comments is from the default configuration. #+begin_src emacs-lisp ;;; $DOOMDIR/config.el -*- lexical-binding: t; -*- ;; Place your private configuration here! Remember, you do not need to run 'doom ;; sync' after modifying this file! ;; Whenever you reconfigure a package, make sure to wrap your config in an ;; `after!' block, otherwise Doom's defaults may override your settings. E.g. ;; ;; (after! PACKAGE ;; (setq x y)) ;; ;; The exceptions to this rule: ;; ;; - Setting file/directory variables (like `org-directory') ;; - Setting variables which explicitly tell you to set them before their ;; package is loaded (see 'C-h v VARIABLE' to look up their documentation). ;; - Setting doom variables (which start with 'doom-' or '+'). ;; ;; Here are some additional functions/macros that will help you configure Doom. ;; ;; - `load!' for loading external *.el files relative to this one ;; - `use-package!' for configuring packages ;; - `after!' for running code after a package has loaded ;; - `add-load-path!' for adding directories to the `load-path', relative to ;; this file. Emacs searches the `load-path' when you load packages with ;; `require' or `use-package'. ;; - `map!' for binding new keys ;; ;; To get information about any of these functions/macros, move the cursor over ;; the highlighted symbol at press 'K' (non-evil users must press 'C-c c k'). ;; This will open documentation for it, including demos of how they are used. ;; Alternatively, use `C-h o' to look up a symbol (functions, variables, faces, ;; etc). ;; ;; You can also try 'gd' (or 'C-c c d') to jump to their definition and see how ;; they are implemented. #+end_src These packages are loaded into ~packages.el~. The following comments are provided by default. #+begin_src emacs-lisp :tangle packages.el ;; -*- no-byte-compile: t; -*- ;;; $DOOMDIR/packages.el ;; To install a package with Doom you must declare them here and run 'doom sync' ;; on the command line, then restart Emacs for the changes to take effect -- or ;; use 'M-x doom/reload'. ;; To install SOME-PACKAGE from MELPA, ELPA or emacsmirror: ;(package! some-package) ;; To install a package directly from a remote git repo, you must specify a ;; `:recipe'. You'll find documentation on what `:recipe' accepts here: ;; https://github.com/radian-software/straight.el#the-recipe-format ;(package! another-package ; :recipe (:host github :repo "username/repo")) ;; If the package you are trying to install does not contain a PACKAGENAME.el ;; file, or is located in a subdirectory of the repo, you'll need to specify ;; `:files' in the `:recipe': ;(package! this-package ; :recipe (:host github :repo "username/repo" ; :files ("some-file.el" "src/lisp/*.el"))) ;; If you'd like to disable a package included with Doom, you can do so here ;; with the `:disable' property: ;(package! builtin-package :disable t) ;; You can override the recipe of a built in package without having to specify ;; all the properties for `:recipe'. These will inherit the rest of its recipe ;; from Doom or MELPA/ELPA/Emacsmirror: ;(package! builtin-package :recipe (:nonrecursive t)) ;(package! builtin-package-2 :recipe (:repo "myfork/package")) ;; Specify a `:branch' to install a package from a particular branch or tag. ;; This is required for some packages whose default branch isn't 'master' (which ;; our package manager can't deal with; see radian-software/straight.el#279) ;(package! builtin-package :recipe (:branch "develop")) ;; Use `:pin' to specify a particular commit to install. ;(package! builtin-package :pin "1a2b3c4d5e") ;; Doom's packages are pinned to a specific commit and updated from release to ;; release. The `unpin!' macro allows you to unpin single packages... ;(unpin! pinned-package) ;; ...or multiple packages ;(unpin! pinned-package another-pinned-package) ;; ...Or *all* packages (NOT RECOMMENDED; will likely break things) ;(unpin! t) #+end_src * User specific settings Some functionality uses this to identify you, e.g. GPG configuration, email clients, file templates and snippets. It is optional. This could be changed to rely on system environment variables. #+begin_src emacs-lisp (setq user-full-name "Leni Ven" user-mail-address "leniv@stanford.edu") #+end_src If you use ~org~ and don't want your org files in the default location below, change ~org-directory~. It must be set before org loads! #+begin_src emacs-lisp (setq org-directory "~/org/") #+end_src * Interface ** Key Bindings Modifications to the default key bindings to mimic spacemacs - ~SPC SPC~ is mapped to ~M-x~ (~#'execute-extended-command~) - ~SPC !~ is mapped to ~M-!~ (~#'shell-command~) - ~SPC :~ is mapped to ~M-:~ (~#'eval-expression~) - ~,~ is mapped to the local (major mode) leader ~,~ - ~SPC b 0~ deletes the current buffer and window like Spacemacs ~SPC b x~ #+begin_src emacs-lisp (setq doom-localleader-key ",") (map! :leader :desc "Execute shell command" "!" #'shell-command) (map! :leader :desc "Execute extended command (emacs M-x)" "SPC" #'execute-extended-command) (map! :leader :desc "Evaluate expression (emacs M-:)" ":" #'eval-expression) (map! :leader :desc "Kill buffer and window" "b 0" #'kill-buffer-and-window) (map! :nvi "C" nil) ; remove this one weird binding #+end_src ** Font settings Doom exposes five (optional) variables for controlling fonts in Doom: - ~doom-font~ -- the primary font to use - ~doom-variable-pitch-font~ -- a non-monospace font (where applicable) - ~doom-big-font~ -- used for ~doom-big-font-mode~; use this for presentations or streaming. - ~doom-unicode-font~ -- for unicode glyphs - ~doom-serif-font~ -- for the ~fixed-pitch-serif~ face See ~C-h v doom-font~ for documentation and more examples of what they accept. If you or Emacs can't find your font, use ~M-x describe-font~ to look them up, ~M-x eval-region~ to execute ELisp code, and ~M-x doom/reload-font~ to refresh your font settings. If Emacs still can't find your font, it likely wasn't installed correctly. Font issues are rarely Doom issues! There are two ways to load a theme. Both assume the theme is installed and available. You can either set ~doom-theme~ or manually load a theme with the ~load-theme~ function. #+begin_src emacs-lisp (setq default-font "Source Code Pro" default-font-size 14.0 doom-font (font-spec :family default-font :size default-font-size :weight 'semi-light) doom-variable-pitch-font (font-spec :family default-font :size (+ default-font-size 1.0)) doom-unicode-font (font-spec :family default-font :size default-font-size) doom-theme 'doom-lantern) #+end_src ** Splash Screen #+begin_src emacs-lisp (defun sun-position-banner () (let* ( (sunrise '( "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀" "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀" "⠀⠀⠀⣤⣄⠀⠀⠀⠀⢾⡀⠀⠀⠸⠇⠀⠀⢀⡷⠀⠀⠀⠀⣠⣤⠀⠀⠀" "⠀⠀⠀⠈⠻⣷⣄⠀⠀⠈⠁⠀⠀⣀⣀⠀⠀⠈⠁⠀⠀⣠⣾⠟⠁⠀⠀⠀" "⠀⠀⠀⠀⠀⠈⠁⠀⠀⢀⣴⣾⣿⣿⣿⣿⣷⣦⡀⠀⠀⠈⠁⠀⠀⠀⠀⠀" "⠀⠀⢠⣤⣀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⠀⠀⠀⣀⣤⡄⠀⠀" "⠀⠀⠀⠀⠁⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠀⠀⠈⠀⠀⠀⠀" "⢠⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⡄" "⠈⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠁")) (longest-line (apply #'max (mapcar #'length sunrise)))) (put-text-property (point) (dolist (line sunrise (point)) (insert (+doom-dashboard--center +doom-dashboard--width (concat line (make-string (max 0 (- longest-line (length line))) 32))) "\n")) 'face 'doom-dashboard-banner))) (setq +doom-dashboard-ascii-banner-fn #'sun-position-banner) #+end_src ** Line numbers This determines the style of line numbers in effect. If set to ~nil~, line numbers are disabled. For relative line numbers, set this to ~relative~. #+begin_src emacs-lisp (setq display-line-numbers-type 'relative) (global-display-line-numbers-mode) #+end_src ** Indentation Style Hooks #+begin_src emacs-lisp (defun custom/common-program-hook () (setq whitespace-style '(face spaces tabs newline trailing space-mark tab-mark newline-mark) whitespace-line-column 80) (display-fill-column-indicator-mode) ;;(whitespace-mode) (setq indent-tabs-mode t indent-line-function 'tab-to-tab-stop tab-width 2) (indent-tabs-mode) (smart-tabs-mode-enable) ) (defun custom/common-richtext-hook () (setq whitespace-style '(face spaces tabs newline trailing space-mark tab-mark newline-mark)) (setq whitespace-line-column nil) ) (add-hook 'text-mode-hook #'custom/common-richtext-hook) #+end_src * Package-specific Settings ** Editor *** Smart Tabs #+begin_src emacs-lisp :tangle packages.el (package! smart-tabs-mode) #+end_src #+begin_src emacs-lisp (use-package! smart-tabs-mode :config (print! "Configuring smart-tabs-mode") (smart-tabs-insinuate 'c 'c++ 'java 'javascript)) (setq-default indent-tabs-mode t indent-line-function 'tab-to-tab-stop tab-width 2) #+end_src *** Whitespace mode #+begin_src emacs-lisp :tangle packages.el (package! whitespace) #+end_src #+begin_src emacs-lisp (use-package! whitespace :config (setq whitespace-style '(face tabs tab-mark spaces space-mark trailing newline newline-mark) whitespace-line-column 80 whitespace-display-mappings '( (space-mark 32 [183] [46]) ; 32 SPACE 「 」, 183 MIDDLE DOT 「·」, 46 FULL STOP 「.」 (newline-mark 10 [172 10]) ; 10 LINE FEED, 172 Not Sign「¬」 (tab-mark 9 [10141 9] [92 9]) ; 9 TAB, 10141 Triangle-headed rightwards arrow 「➝」 )) (global-whitespace-mode +1) ) #+end_src *** Format Note that ~onsave~ was intentionally turned off because it messes with version control systems. #+begin_src emacs-lisp (after! format (print! "Configuring (after! format ...)") '(not emacs-lisp-mode sql-mode ; Broken ;; tex related modes are broken tex-mode latex-mode bibtex-mode )) #+end_src *** Spell #+begin_src emacs-lisp (after! flyspell (print! "Configuring (after! flyspell ...)") (setq flyspell-default-dictionary "english")) #+end_src ** Languages *** Emacs Lisp #+begin_src emacs-lisp (defun custom/lisp-family-hook () (setq indent-line-function 'tab-to-tab-stop tab-width 2) (indent-tabs-mode) ) (add-hook 'lisp-mode-hook #'custom/lisp-family-hook) (add-hook 'lisp-data-mode-hook #'custom/lisp-family-hook) (add-hook 'emacs-lisp-mode-hook #'custom/lisp-family-hook) #+end_src *** Org Rather than using a common prefix ~, i~ like Spacemacs to consolidate all insertion operations, we put them in different categories. Some keybindings are removed. #+begin_src emacs-lisp (map! :after org :localleader :map org-mode-map :desc "LaTeX Preview" "X" #'org-latex-preview ;; Remove some clutter "h" nil "n" nil "i" nil "@" nil "q" nil "o" nil "I" nil ; 'org-id-get-create' "A" nil ; 'org-archive-subtree' (:prefix ("b". "table") :desc "Edit formulae" "F" #'org-table-edit-formulas :desc "Eval formula" "f" #'org-table-eval-formula (:prefix ("m" . "move") :desc "Move row up" "K" #'org-table-move-row-up :desc "Move row down" "J" #'org-table-move-row-down :desc "Move column left" "H" #'org-table-move-column-left :desc "Move column right" "L" #'org-table-move-column-right :desc "Move cell up" "k" #'org-table-move-cell-up :desc "Move cell down" "j" #'org-table-move-cell-down :desc "Move cell left" "h" #'org-table-move-cell-left :desc "Move cell right" "l" #'org-table-move-cell-right ) ) (:prefix ("h" . "headings") :desc "Consult heading" "." #'consult-org-heading :desc "Insert heading" "h" #'org-insert-heading :desc "Insert todo heading" "t" #'org-insert-todo-heading :desc "Insert subheading" "i" #'org-insert-subheading :desc "Insert todo subheading" "t" #'org-insert-todo-subheading :desc "Previous visible heading" "[" #'org-previous-visible-heading :desc "Next visible heading" "]" #'org-next-visible-heading ) (:prefix ("o" . "tags/properties") :desc "Set tags command" "t" #'org-set-tags-command :desc "Set property" "s" #'org-set-property :desc "Delete property" "d" #'org-delete-property :desc "Property action" "a" #'org-property-action ) (:prefix ("i" . "insert") :desc "Item" "i" #'org-toggle-item :desc "Citation" "c" #'org-cite-insert :desc "Footnote" "f" #'org-footnote-new "I" #'org-id-get-create ) (:prefix ("l" . "links") ;; Description update :desc "Insert/Modify Link" "l" #'org-insert-link ) ) #+end_src *** LaTeX The target indentation style of ~LaTeX~ is as follows: #+begin_src tex :tangle no \begin{enumerate}[1.] \item Some item 1. Note that item is not indented. Item 1 continued. 1 level of indentation. \item \begin{tikzpicture}[ xscale=2,yscale=3 ] \node[dot] (x) at (0,0); \node[dot] (y) at (0,1); \draw (x) -- (y) \node[midway,fill=white] {$f$}; \end{tikzpicture} \end{enumerate} #+end_src For some reason the keymap binding has to use ~LaTeX-mode-map~ or ~TeX-mode-map~ instead of ~latex-mode-map~. Also some original keybindings are removed so they can be displayed correctly in prompts. See e.g. ~tex-buf.el~ for an example. When unbinding these keys, use ~:g~ flag to ensure no extraneous keys are introduced. #+begin_src emacs-lisp (after! latex (print! "Configuring (after! latex ...)") (add-hook 'tex-mode-hook #'custom/common-program-hook) (add-hook 'LaTeX-mode-hook #'custom/common-program-hook) (setq-default TeX-electric-sub-and-superscript nil) (local-unset-key "C-c C-l") (local-unset-key "C-c `") ) (map! :after latex :localleader :map TeX-mode-map :desc "View Compilation Log" "l" #'TeX-recenter-output-buffer :desc "Next Error" "e" #'TeX-next-error :desc "Close Environment" "]" #'LaTeX-close-environment (:prefix ("f" . "Fold") :desc "Fold Mode" "f" #'TeX-fold-mode :desc "Environment" "e" #'TeX-fold-env :desc "Buffer" "b" #'TeX-fold-buffer :desc "Region" "r" #'TeX-fold-region :desc "Paragraph" "p" #'TeX-fold-paragraph :desc "Dwim" "d" #'TeX-fold-dwim) ) (map! :after latex :map TeX-mode-map :g "C-c C-l" nil :g "C-c `" nil ) #+end_src *** Lean #+begin_src emacs-lisp :tangle packages.el (package! lean4-mode :recipe ( :host github :repo "leanprover/lean4" :files ("lean4-mode/*.el"))) #+end_src *** LilyPond Add the necessary hooks for LilyPond mode. #+begin_src emacs-lisp (use-package! lilypond-mode :init (print! "Initializing LilyPond-mode") (add-to-list 'auto-mode-alist '("\\.ly\\'" . LilyPond-mode)) :config (add-hook 'LilyPond-mode-hook #'custom/common-program-hook) ) #+end_src ** Tools *** LSP File path is removed from breadcrumb since it is provided by ~doom-modeline~ and since it clutters the header-line. #+begin_src emacs-lisp (after! lsp-mode (print! "Configuring (after! lsp-mode ...)") (setq lsp-headerline-breadcrumb-enable t lsp-headerline-breadcrumb-enable-symbol-numbers nil lsp-headerline-breadcrumb-segments '(symbols) )) #+end_src *** Magit #+begin_src emacs-lisp (map! :after magit :localleader :map git-commit-mode-map :desc "Finish" "c" #'with-editor-finish :desc "Cancel" "q" #'with-editor-cancel ) #+end_src Temporarily pin the versions at 28.2 due to ~defvar-keymap~ being a Emacs 29 addition. See [[https://emacs.stackexchange.com/questions/75827/doom-emacs-error-running-hook-global-git-commit-mode-because-void-variable][this stackexchange post]]. #+begin_src emacs-lisp :tangle packages.el (package! transient :pin "c2bdf7e12c530eb85476d3aef317eb2941ab9440" :recipe (:host github :repo "magit/transient")) (package! with-editor :pin "bbc60f68ac190f02da8a100b6fb67cf1c27c53ab" :recipe (:host github :repo "magit/with-editor")) #+end_src *** Emacs IPython Notebook (ein) WIP #+begin_src emacs-lisp (map! :after ein :localleader :map ein:notebook-mode-map (:prefix ("m" . "move") :desc "Up" "k" #'ein-markdown-move-up :desc "Down" "j" #'ein-markdown-move-down ) ) #+end_src