#+TITLE: Doom-emacs config #+AUTHOR: Judah Sotomayor #+STARTUP: overview Welcome to my configuration! I hope you enjoy your time here :) It's not all very well documented, but I have done my best to split everything into a logical order. Perhaps in 10 years I will still be using it, but who knows. * Setting Basics ** Packages #+begin_src emacs-lisp :tangle "packages.el" ;; -*- no-byte-compile: t; -*- #+end_src ** Set name, org-roam-directory, etc. Some basic settings for Emacs #+begin_src emacs-lisp (setq tab-always-indent t) (setq user-full-name "Judah Sotomayor" user-mail-address "") #+end_src #+begin_src emacs-lisp :tangle "packages.el" (package! noCtrlC :recipe (:host nil :type git :repo "https://git.freedomland.xyz/judahsotomayor/noctrlc")) #+end_src * Theme and Font Set the theme. /Use something dark/ +I also prefer relative line numbers because of *evil* mode+ Relative line numbers don't seem to work, because of folding in Org-mode. #+begin_src emacs-lisp (setq doom-theme 'doom-xcode) (setq doom-font (font-spec :family "Hack Nerd Font Mono" :size 16 :weight 'medium)) (setq auto-save-default nil) ;I don't like autosaving. Let me do it myself. #+end_src #+RESULTS: ** Doom splash screen I really don't like the widgets, and I think it takes longer to load so I get rid of them #+begin_src emacs-lisp (remove-hook '+doom-dashboard-functions #'doom-dashboard-widget-shortmenu) (remove-hook '+doom-dashboard-functions #'doom-dashboard-widget-footer) #+end_src Set a sweet splash image #+begin_src emacs-lisp (setq fancy-splash-image (concat doom-private-dir "emacs.png")) #+end_src * Evil configuration I want a non-ESC way to get back to normal mode: #+begin_src emacs-lisp (map! :desc "Switch to normal mode" :i "C-c" #'evil-normal-state) (after! org-mode (map! :desc "Delete previous character in insert mode" :i "C-h" #'evil-delete-backward-char)) (map! :desc "Increment number below or after cursor" :n "C-a" #'evil-numbers/inc-at-pt) (map! :desc "Decrement number below or after cursor" :n "C-x" #'evil-numbers/dec-at-pt) (map! :n "g j" #'evil-next-visual-line) (map! :n "g k" #'evil-previous-visual-line) #+end_src * Terminal setup I like to just use bash: #+begin_src emacs-lisp (defun bash nil "Lauch term with /bin/bash" (interactive) (term "/bin/bash")) (defun dash nil "Lauch term with /bin/dash" (interactive) (term "/bin/dash")) (defun zsh nil "Lauch term with /bin/zsh" (interactive) (term "/bin/zsh")) #+end_src #+RESULTS: : zsh ** Shell mappings #+begin_src emacs-lisp (map! :leader (:prefix ("k" . "shell") :desc "Start a bash shell" :n "b" #'bash :desc "Start a dash shell" :n "d" #'dash :desc "Start a zsh shell" :n "z" #'zsh :desc "Start an elisp repl" :n "e" #'+emacs-lisp/open-repl :desc "Start a python repl" :n "j" #'+python/open-repl)) #+end_src #+RESULTS: ,#+RESULTS: I don't like the modeline in the terminal. ,#+begin_src emacs-lisp (add-hook 'term-mode-hook 'hide-mode-line-mode) #+end_src * Sage-math #+begin_src emacs-lisp (use-package! sage-shell-mode :defer) ;; Ob-sagemath supports only evaluating with a session. (setq org-babel-default-header-args:sage '((:session . t) (:results . "output"))) ;; C-c c for asynchronous evaluating (only for SageMath code blocks). (with-eval-after-load "org" (define-key org-mode-map (kbd "C-c c") 'ob-sagemath-execute-async)) #+end_src I like to have a shortcut for calc as well, for simpler calculations #+begin_src emacs-lisp (map! :leader :desc "The Emacs Calculator" "C" #'calc) #+end_src * Beancount ** FavaGTK :outdated: I want to launch favagtk more easily. Let's do that here: #+begin_src emacs-lisp (defun fava () (interactive) (async-shell-command "flatpak run org.gnome.gitlab.johannesjh.favagtk")) (map! :leader :desc "Start favagtk" "r b" #'fava) #+end_src * Useful Functions ** Get the date from the shell I want to grab the current date and put it in the buffer. Because I sometimes use Fish or another shell, it's good to make sure bash is running the command using the src_bash{`-c`} flag. #+begin_src emacs-lisp (defun insert-current-date () (interactive) (insert (string-trim (shell-command-to-string "date '+%Y-%m-%d'")))) (defun insert-current-date-alt () (interactive) (insert (string-trim (shell-command-to-string "date '+%B %d, %Y'")))) (map! :leader (:prefix ("i" . "insert") (:prefix ("d" . "date") :desc "ISO 8601 (%Y-%m-%d)" "i" #'insert-current-date :desc "Month Day, Year (%B %d, %Y)" "m" #'insert-current-date-alt))) #+end_src #+RESULTS: : insert-current-date-alt ** Convert regex strings to rx #+begin_src elisp :tangle packages.el (package! xr) #+end_src #+begin_src elisp (use-package! xr) #+end_src * Creating Diagrams and graphs ** TODO set default values using org-babel's features for that. * Securing Sensitive Files ** Age.el #+begin_src emacs-lisp :tangle "packages.el" (package! age) #+end_src *** Config #+begin_src emacs-lisp (use-package! age :ensure t :demand t :custom (age-program "age") (age-default-identity "~/.age/personal") (age-default-recipient "~/.age/personal.pub") :config (age-file-enable)) #+end_src *** Preprocessor :PROPERTIES: :CUSTOM_ID: ripgrep-pre :END: This preprocessor script allows me to use Ripgrep with Age to filter agenda files. You can see the configuration for that in [[#agenda-efficient][this section]]. #+begin_src zsh :tangle "/home/user/age-preprocessor.zsh" #!/usr/bin/env zsh case "$1" in *.age) # The -s flag ensures that the file is non-empty. if [ -s "$1" ]; then exec /usr/bin/age --decrypt -i ~/.age/personal $1 else exec cat fi ;; *) ;; esac #+end_src ** Org-mode security settings These mostly concern limiting evaluation of code-blocks without confirmation. The final two lines concern local variables, which may try to evaluate code. Emacs has better default values now, so it will ask to evaluate local variables. #+begin_src emacs-lisp (setq org-confirm-babel-evaluate t) (setq org-link-shell-confirm-function 'yes-or-no-p) (setq org-link-elisp-confirm-function 'yes-or-no-p) (setq enable-local-variables t) (setq enable-local-eval 'maybe) #+end_src #+RESULTS: : maybe #+begin_src emacs-lisp (setq templates/post-capture-props "#+date: [%<%Y-%m-%d %a>]\n#+lastmod:\n#+categories[]:\n#+tags[]:\n#+images[]: ") (setq templates/post-capture-title "#+TITLE: ${title}\n") (setq templates/post-capture-template (concat templates/post-capture-title templates/post-capture-props)) #+end_src * Org-mode for a great todo list ** Making the Agenda features more efficient Using ripgrep we can automatically narrow org-agenda files. *** Finding Files with Ripgrep :PROPERTIES: :CUSTOM_ID: agenda-efficient :END: This piece of code will allow us to capture all the agenda files using the preprocessor we wrote [[#ripgrep-pre][here]] #+name: search-agenda-files #+begin_src sh :exports code :tangle no rg --type-add 'aorg:*.org.age' \ -torg -taorg \ --pre ~/age-preprocessor.zsh --pre-glob '*.age' -l TODO /home/user/org #+end_src Now, of course, this code is not useful as it is--after all, we can't tangle a ~.sh~ script into [[file:config.el]]. *** Adding results to agenda files The rubber hits the road here. I'll call that shell command to set the agenda files correctly. #+begin_src emacs-lisp (defun set-org-agenda-files-ripgrep () (setq org-agenda-files (split-string (shell-command-to-string "rg --type-add \'aorg:*.org.age\' -torg -taorg --pre ~/age-preprocessor.zsh --pre-glob \'*.age\' -l TODO /home/user/org "))) (setq org-agenda-files (remove "/home/user/org/archive.sec.org.age" org-agenda-files))) #+end_src #+RESULTS: : set-org-agenda-files-ripgrep And then we want to call this before building the agenda: #+begin_src emacs-lisp (add-hook 'org-agenda-mode-hook 'set-org-agenda-files-ripgrep) #+end_src *** Filtering the agenda I don't want scheduled items to duplicate if the deadline is up. #+begin_src emacs-lisp (after! org (setq org-agenda-skip-scheduled-if-deadline-is-shown t)) ;(setq org-agenda-start-day "-8d") ;(setq org-agenda-span 9) ;(setq org-agenda-todo-ignore-deadlines 'far) ;(setq org-agenda-tags-todo-honor-ignore-options t)) #+end_src #+RESULTS: : t ** Basic settings #+begin_src emacs-lisp (setq org-log-done 'time) (after! org (setq org-log-done 'time) (setq org-archive-location "~/10-19-personal-projects/11-zettelkasten/archive.sec.org.age") (setq org-hide-emphasis-markers nil)) (setq org-directory "~/10-19-personal-projects/11-zettelkasten/") (setq org-roam-directory org-directory) #+end_src #+RESULTS: : ~/org/ *** Keymap #+begin_src emacs-lisp (map! :map org-agenda-keymap "j" #'evil-next-line "k" #'evil-previous-line) (map! :map org-super-agenda-header-map "j" #'evil-next-line "k" #'evil-previous-line) #+end_src #+RESULTS: ** Appearances *** Images Preferences We want to show images when loading a file, and also after evaluating code blocks. #+begin_src emacs-lisp (setq org-startup-with-inline-images t) ;; Show images after evaluating code blocks. (add-hook 'org-babel-after-execute-hook 'org-display-inline-images) #+end_src *** Org-super-agenda Super-agenda allows many nice configurations to the agenda buffer. #+begin_src emacs-lisp :tangle "packages.el" (package! org-super-agenda) #+end_src Is it working now? It sure seems to be, so IDK what was up with it earlier. #+begin_src emacs-lisp (use-package! org-super-agenda :after org-roam :config (org-super-agenda-mode)) #+end_src Configure the Super Agenda to neatly organize everything. #+begin_src emacs-lisp (setq org-super-agenda-groups '(;; Each group has an implicit boolean OR operator between its selectors. (:name "Calendar" :and (:todo nil :not (:scheduled (before "2024-03-17")) :not (:deadline (before "2024-03-17"))) :order 10) (:name "Today" ; Optionally specify section name :time-grid t ; Items that appear on the time grid :todo "TODAY") ; Items that have this TODO keyword (:name "Important" ;; Single arguments given alone :tag "bills" :priority<= "A") (:name "Active Projects" :and (:todo "PROJ" :not (:scheduled (after "2024-03-17")) :deadline (after "2024-03-17"))) (:name "School" :tag "school" ) ;; Set order of multiple groups at once (:order-multi (2 (:name "Shopping in town" ;; Boolean AND group matches items that match all subgroups :and (:tag "shopping" :tag "@town")) (:name "Food-related" ;; Multiple args given in list with implicit OR :tag ("food" "dinner")) (:name "Habits" :habit t :tag "personal") (:name "Space-related (non-moon-or-planet-related)" ;; Regexps match case-insensitively on the entire entry :and (:regexp ("space" "NASA") ;; Boolean NOT also has implicit OR between selectors :not (:regexp "moon" :tag "planet"))))) ;; Groups supply their own section names when none are given (:todo "WAITING" :order 8) ; Set order of this section (:todo ("SOMEDAY" "TO-READ" "CHECK" "TO-WATCH" "WATCHING") ;; Show this group at the end of the agenda (since it has the ;; highest number). If you specified this group last, items ;; with these todo keywords that e.g. have priority A would be ;; displayed in that group instead, because items are grouped ;; out in the order the groups are listed. :order 9) (:priority<= "B" ;; Show this section after "Today" and "Important", because ;; their order is unspecified, defaulting to 0. Sections ;; are displayed lowest-number-first. :order 1))) #+end_src ** org-edna #+begin_src emacs-lisp :tangle "packages.el" (package! org-edna) #+end_src Edna allows better dependency handling for todos and the like. #+begin_src emacs-lisp (use-package! org-edna) (org-edna-mode) #+end_src ** Org-habit #+begin_src emacs-lisp (use-package org-habit :custom (org-habit-graph-column 1) (org-habit-preceding-days 10) (org-habit-following-days 1) (org-habit-show-habits-only-for-today t)) #+end_src ** Anki editing in org-mode Anki editor is a good one for large cards that need high complexity. #+begin_src emacs-lisp :tangle packages.el (package! anki-editor) #+end_src *** inline-anki Inline anki is far better for small cards, and where it is best to maintain a /single source of truth/. #+begin_src emacs-lisp :tangle packages.el (package! asyncloop) (package! inline-aki :recipe (:host github :repo "meedstrom/inline-anki")) #+end_src #+begin_src emacs-lisp (setq inline-anki-note-type "Katex and Markdown Cloze") (setq inline-anki-use-tags t) #+end_src **** Inline Anki symbol By default, [[*inline-anki][Inline-anki]] uses _underscore_ to specify the card type. This is okay, but I'd rather find something that isn't already used. #+begin_src emacs-lisp (add-to-list 'org-emphasis-alist '("." nil)) (setq inline-anki-emphasis-type "_") #+end_src #+RESULTS: : _ ** calfw Calendar View :ARCHIVE: #+begin_src emacs-lisp :tangle "packages.el" (package! calfw :recipe (:host github :type git :repo "haji-ali/emacs-calfw")) #+end_src * Programming Items ** Editorconfig I need to make sure some different files work with #+begin_src emacs-lisp (after! editorconfig-mode (add-to-list 'editorconfig-mode-alist '(cpp-mode . "cpp"))) #+end_src ** LSP In order for editorconfig to do its thing, indentation by the lsp must be disabled. #+begin_src emacs-lisp (setq lsp-enable-indentation nil) #+end_src emacs-lisp * Website ** Capture template #+begin_src emacs-lisp (setq templates/post-capture-props "#+date: [%<%Y-%m-%d %a>]\n#+lastmod:\n#+categories[]:\n#+tags[]:\n#+images[]: ") (setq templates/post-capture-title "#+TITLE: ${title}\n") (setq templates/post-capture-template (concat templates/post-capture-title templates/post-capture-props)) #+end_src ** Hugo base directory #+begin_src emacs-lisp (setq org-hugo-base-dir (concat org-directory (file-name-as-directory "website"))) (setq org-hugo-default-section-directory "posts") #+end_src * Crafting a Writing Environment For writing I like to automate as much as possible. This means creating an environment that does citations and such /for/ me. ** Export settings *** Ox-latex #+begin_src emacs-lisp (after! org ;; Import ox-latex to get org-latex-classes and other funcitonality ;; for exporting to LaTeX from org (use-package! ox-latex :init :config (setq org-latex-with-hyperref nil) ;; stop org adding hypersetup{author..} to latex export ;; (setq org-latex-prefer-user-labels t) (setq org-latex-logfiles-extensions (quote ("lof" "lot" "tex~" "aux" "idx" "log" "out" "toc" "nav" "snm" "vrb" "dvi" "fdb_latexmk" "blg" "brf" "fls" "entoc" "ps" "spl" "bbl" "xmpi" "run.xml" "bcf" "acn" "acr" "alg" "glg" "gls" "ist"))) (unless (boundp 'org-latex-classes) (setq org-latex-classes nil)))) #+end_src *** Lualatex as PDF Processor I've found that lualatex does a good job processing PDFs. $hi$ #+begin_src emacs-lisp (after! ox-latex (setq org-latex-pdf-process '("lualatex --output-directory=/home/user/Documents -shell-escape -interaction nonstopmode %f" "lualatex --output-directory=/home/user/Documents -shell-escape -interaction nonstopmode %f"))) #+end_src #+RESULTS: | lualatex --output-directory=/home/user/Documents -shell-escape -interaction nonstopmode %f | lualatex --output-directory=/home/user/Documents -shell-escape -interaction nonstopmode %f | $x + 1 = 3$ #+RESULTS: : luamagick #+begin_src emacs-lisp (setq-default org-html-with-latex 'verbatim) (unless (boundp 'org-latex-classes) (setq org-latex-classes nil)) (add-to-list 'org-latex-classes '("ethz" "\\documentclass[a4paper,11pt,titlepage]{memoir} \\usepackage[utf8]{inputenc} \\usepackage[T1]{fontenc} \\usepackage{fixltx2e} \\usepackage{graphicx} \\usepackage{longtable} \\usepackage{float} \\usepackage{wrapfig} \\usepackage{rotating} \\usepackage[normalem]{ulem} \\usepackage{amsmath} \\usepackage{textcomp} \\usepackage{marvosym} \\usepackage{wasysym} \\usepackage{amssymb} \\usepackage[hidelinks]{hyperref} \\usepackage{mathpazo} \\usepackage{color} \\usepackage{enumerate} \\definecolor{bg}{rgb}{0.95,0.95,0.95} \\tolerance=1000 [NO-DEFAULT-PACKAGES] [PACKAGES] [EXTRA] \\linespread{1.1} \\hypersetup{pdfborder=0 0 0}" ("\\chapter{%s}" . "\\chapter*{%s}") ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) (add-to-list 'org-latex-classes '("article" "\\documentclass[11pt,a4paper]{article} \\usepackage[utf8]{inputenc} \\usepackage[T1]{fontenc} \\usepackage{fixltx2e} \\usepackage{graphicx} \\usepackage{longtable} \\usepackage{float} \\usepackage{wrapfig} \\usepackage{rotating} \\usepackage[normalem]{ulem} \\usepackage{amsmath} \\usepackage{textcomp} \\usepackage{marvosym} \\usepackage{wasysym} \\usepackage{amssymb} \\usepackage[hidelinks]{hyperref} \\usepackage{mathpazo} \\usepackage{color} \\usepackage{enumerate} \\definecolor{bg}{rgb}{0.95,0.95,0.95} \\tolerance=1000 [NO-DEFAULT-PACKAGES] [PACKAGES] [EXTRA] \\linespread{1.1} \\hypersetup{pdfborder=0 0 0}" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}"))) (add-to-list 'org-latex-classes '("ebook" "\\documentclass[11pt, oneside]{memoir} \\setstocksize{9in}{6in} \\settrimmedsize{\\stockheight}{\\stockwidth}{*} \\setlrmarginsandblock{2cm}{2cm}{*} % Left and right margin \\setulmarginsandblock{2cm}{2cm}{*} % Upper and lower margin \\checkandfixthelayout % Much more laTeX code omitted " ("\\chapter{%s}" . "\\chapter*{%s}") ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}"))) #+end_src #+RESULTS: | mcdowellcv | \documentclass[]{mcdowellcv} | *** COMMENT Fixing dvipng image handling #+begin_src emacs-lisp (defun +org-refresh-latex-images-previews-h () (dolist (buffer (doom-buffers-in-mode 'org-mode (buffer-list))) (with-current-buffer buffer (+org--toggle-inline-images-in-subtree (point-min) (point-max) 'refresh) (unless (eq org-latex-preview-default-process 'dvisvgm) (org-clear-latex-preview (point-min) (point-max)) (org--latex-preview-region (point-min) (point-max)))))) (add-hook 'doom-load-theme-hook #'+org-refresh-latex-images-previews-h) #+end_src *** Export Function #+begin_src emacs-lisp (defun eww-open-this-file () (set 'directory (file-name-directory buffer-file-name)) (set 'filename (file-name-sans-extension buffer-file-name)) (set 'extension ".html") (set 'filename (format "%s%s" filename extension)) (eww-open-file filename) (evil-window-left) ) (defun org-export-and-open-eww () "Export current file to html and open in eww" (interactive) (org-html-export-to-html) (if (equal (file-name-extension buffer-file-name) "org") (eww-open-this-file) (message "Failed") ) ) #+end_src We'll want a handy shortcut for this. #+begin_src emacs-lisp (map! :leader :desc "Export to html and diplay with eww" "r E" #'org-export-and-open-eww) #+end_src #+RESULTS: : /home/user/.config/doom/ *** Delete links from inline anki #+begin_src elisp (defun inline-anki-link-filter (link backend info) "Rewrite links in export to preserve link text only" (if (eq backend 'inline-anki--ox-anki-html-backend) (save-match-data ; is usually a good idea (and (string-match "\\[(?:\\[([^\\]\\[]*)\\])(?:\\[(.*)\\])?\\]" link) (match-string 2 link))))) #+end_src #+RESULTS: : inline-anki-link-filter #+begin_src elisp (add-to-list 'org-export-filter-link-functions 'inline-anki-link-filter) #+end_src #+begin_src elisp #+end_src #+RESULTS: | inline-anki-link-filter | ** Automatic Citations with *citar* and *org-cite* :PROPERTIES: :custom_id: citation-settings :END: Citar is a sweet little package for managing citations. We want a general [[file:~/org/references.bib][bibliography file]], a [[file:~/Zotero/styles/][styles directory]], and a default set of styles. *** Citar setup First of all, we must configure citar. #+begin_src elisp :tangle packages.el (package! citar-org-roam) #+end_src #+begin_src emacs-lisp (use-package! citar :custom (citar-bibliography "~/10-19-personal-projects/11-zettelkasten/references.bib") (citar-file-note-extensions '(".org")) (org-cite-global-bibliography '("~/10-19-personal-projects/11-zettelkasten/references.bib")) (org-cite-csl-styles-dir (expand-file-name "~/Zotero/styles/")) (org-cite-export-processors '((t . (csl "apa.csl")) )) :hook (LaTeX-mode . citar-capf-setup) (org-mode . citar-capf-setup)) #+end_src *** Icons for some prettification #+begin_src emacs-lisp (after! citar (setq citar-indicator-files-icons (citar-indicator-create :symbol (nerd-icons-faicon "nf-fa-file_o" :face 'nerd-icons-green :v-adjust -0.1) :function #'citar-has-files :padding " " ; need this because the default padding is too low for these icons :tag "has:files")) (setq citar-indicator-links-icons (citar-indicator-create :symbol (nerd-icons-faicon "nf-fa-link" :face 'nerd-icons-orange :v-adjust 0.01) :function #'citar-has-links :padding " " :tag "has:links")) (setq citar-indicator-notes-icons (citar-indicator-create :symbol (nerd-icons-codicon "nf-cod-note" :face 'nerd-icons-blue :v-adjust -0.3) :function #'citar-has-notes :padding " " :tag "has:notes")) (setq citar-indicator-cited-icons (citar-indicator-create :symbol (nerd-icons-faicon "nf-fa-circle_o" :face 'nerd-icon-green) :function #'citar-is-cited :padding " " :tag "is:cited")) (setq citar-indicators (list citar-indicator-files-icons citar-indicator-links-icons citar-indicator-notes-icons citar-indicator-cited-icons))) #+end_src ** Scholarly Writing Environment with Org-mode I like to keep formatting simple. Let's use a package or two to set a decent document class: #+begin_src emacs-lisp (add-to-list 'org-latex-classes '("student-apa7" "\\documentclass[stu]{apa7} \\usepackage[]{multicol} \\usepackage{mathptmx} [NO-DEFAULT-PACKAGES] [NO-PACKAGES]" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) (add-to-list 'org-latex-classes '("student-turabian" "\\documentclass{turabian-researchpaper} \\usepackage[]{multicol} \\usepackage{mathptmx} [NO-PACKAGES] " ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}") ("\\usepackage{biblatex-chicago}"))) (add-to-list 'org-latex-classes '("student-mla" "\\documentclass[stu]{mla} \\hypersetup{hidelinks} \\usepackage[]{multicol} \\usepackage{mathptmx} " ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) ;; org-latex-compilers = ("pdflatex" "xelatex" "lualatex"), which are the possible values for %latex #+end_src *** Engraving Faces Ever wonder why code export sucks with \LaTeX ? Me neither! Let's fix it! #+begin_src emacs-lisp :tangle "packages.el" (package! engrave-faces) #+end_src #+begin_src emacs-lisp (use-package! engrave-faces) (setq org-latex-listings 'engraved) #+end_src ** Zettelkasten environment with org-roam Org-roam enables features essential to a Zettelkasten such as inter-ID linking. #+begin_src emacs-lisp (use-package! org-roam :after md-roam) #+end_src I use several capture templates to make it easy to get notes into my various sections. I only use [[#md-roam-config][Markdown]] in the team wiki, so I have it set to that. I also have a capture template form my [[Website]] #+begin_src emacs-lisp (after! org-roam :ensure t :custom (setq org-roam-capture-templates `( ("d" "default" plain "%?" :target (file+head "%<%Y%m%d-%H%M%S>.org" "#+TITLE: ${title}\n") :unnarrowed t) ("s" "school" plain "%?" :target (file+head "liberty/${title}.org" "#+TITLE: ${title}\n") :unnarrowed t) ("e" "encrypted" plain "%?" :target (file+head "%<%Y%m%d-%H%M%S>.sec.org.age" "#+TITLE: ${title}\n#+FILETAGS: :secure:noexport:\n\n* No Export Below This Line") :unnarrowed t) ("c" "CCDC Wiki" plain "" :target (file+head "training-resources/content/${title}.md" "---\ntitle: ${title}\nid: %<%Y-%m-%dT%H%M%S>\ncategory: \n---\n") :unnarrowed t) ("w" "Website" plain "%?" :target (file+head "website/src/posts/%<%Y%m%d-%H%M%S>.org" "#+TITLE: ${title}\n#+DRAFT: true\n") :unnarrowed t)))) #+end_src #+RESULTS: | d | default | plain | %? | :target | (file+head %<%Y%m%d-%H%M%S>.org #+TITLE: ${title} | *** Keybinds Org-roam has many commands, of which I have bound the most important below. This entails creating a local leader. I use =r= for this purpose. It is close and goes well with *roam*. #+begin_src emacs-lisp (after! org-roam (map! :leader (:prefix ("r" . "roam") :desc "Search for a node in org-roam files" "f" #'org-roam-node-find :desc "Insert the link to a node from org-roam" "i" #'org-roam-node-insert :desc "Rescan org-roam files and add new nodes to database" "s" #'org-roam-db-sync :desc "Jump to a random node" "r" #'org-roam-node-random :desc "Capture inside an existing or new node" "c" #'org-roam-capture :desc "Go to or create a daily note" "d" #'org-roam-dailies-goto-today :desc "Seek a daily note" "D" #'org-roam-dailies-goto-date :desc "Extract a subtree to a new file" "e" #'org-roam-extract-subtree)) (map! :desc "Alternative keybind to insert a roam link while in insert mode" :i "M-[" #'org-roam-node-insert)) #+end_src *** Nice UI to access Zettelkasten notes with Org-roam ui **** Package #+begin_src emacs-lisp :tangle packages.el (package! org-roam-ui) #+end_src #+begin_src emacs-lisp (use-package! websocket :after org-roam) (use-package! org-roam-ui :after org-roam ;; or :after org ;; normally we'd recommend hooking orui after org-roam, but since org-roam does not have ;; a hookable mode anymore, you're advised to pick something yourself ;; if you don't care about startup time, use ;; :hook (after-init . org-roam-ui-mode) :config (setq org-roam-ui-sync-theme t org-roam-ui-follow t org-roam-ui-update-on-save t org-roam-ui-open-on-start t)) (after! org-roam-ui (map! :leader (:prefix ("r" . "roam") (:prefix ("u" . "roam-ui") :desc "focus the current node in org-roam-ui view" "f" #'org-roam-ui-node-zoom :desc "focus the current node's local graph in org-roam-ui view" "l" #'org-roam-ui-node-local :desc "begin org-roam ui mode" "u" #'open-org-roam-ui )))) #+END_SRC *** Default Browser for Export #+begin_src emacs-lisp (setq browse-url-browser-function 'browse-url-generic browse-url-generic-program "surf") #+end_src ** Journal Environment with org-roam #+begin_src emacs-lisp (after! org-roam (setq org-roam-dailies-capture-templates `(("d" "default" entry "* %?" :target (file+head "%<%Y-%m-%d>.sec.org.age" "#+title: %<%Y-%m-%d>\n"))))) #+end_src *** Property getters and setters These are to fulfill my need to get property values for generating my [[id:6672f401-32a1-49ef-8004-ac77ece67f5b][journal index]]. #+begin_src emacs-lisp (require 'cl-lib) (defun org-global-props-key-re (key) "Construct a regular expression matching key and an optional plus and eating the spaces behind. Test for existence of the plus: (match-beginning 1)" (concat "^" (regexp-quote key) "\\(\\+\\)?[[:space:]]+")) (defun org-global-props (&optional buffer) "Get the plists of global org properties of current buffer." (with-current-buffer (or buffer (current-buffer)) (org-element-map (org-element-parse-buffer) 'keyword (lambda (el) (when (string-equal (org-element-property :key el) "PROPERTY") (nth 1 el)))))) (defun org-global-prop-value (key) "Get global org property KEY of current buffer. Adding up values for one key is supported." (let ((key-re (org-global-props-key-re key)) (props (org-global-props)) ret) (cl-loop with val for prop in props when (string-match key-re (setq val (plist-get prop :value))) do (setq val (substring val (match-end 0)) ret (if (match-beginning 1) (concat ret " " val) val))) ret)) #+end_src ** Resume setup for a stellar CV *** ox-extra for ":ignore:" tags I want to be able to ignore headings on export. #+begin_src emacs-lisp (use-package! ox-extra :after (org) :config (ox-extras-activate '(latex-header-blocks ignore-headlines))) #+end_src *** McDowell Resume Template This template is supposed to be the standard. #+begin_src emacs-lisp (add-to-list 'org-latex-classes '("mcdowellcv" "\\documentclass[]{mcdowellcv} \\usepackage{amsmath} \\usepackage[]{multicol} \\usepackage[hidelinks]{hyperref} [NO-DEFAULT-PACKAGES] [NO-PACKAGES]" ("\\begin{cvsection}{%s}" "\\end{cvsection}") ("\\begin{cvsubsection}{%s}" "\\end{cvsubsection}"))) #+end_src *** Altacv template :ARCHIVE: This is no longer really used. #+begin_src emacs-lisp (add-to-list 'org-latex-classes '("altacv" "\\documentclass[10pt,a4paper,ragged2e,withhyper]{altacv} \\usepackage[rm]{roboto} \\usepackage[defaultsans]{lato} \\usepackage{paracol} [NO-DEFAULT-PACKAGES] [NO-PACKAGES] % Change the page layout if you need to \\geometry{left=1.25cm,right=1.25cm,top=1.5cm,bottom=1.5cm,columnsep=1.2cm} % Use roboto and lato for fonts \\renewcommand{\\familydefault}{\\sfdefault} % Change the colours if you want to \\definecolor{SlateGrey}{HTML}{2E2E2E} \\definecolor{LightGrey}{HTML}{666666} \\definecolor{DarkPastelRed}{HTML}{450808} \\definecolor{PastelRed}{HTML}{8F0D0D} \\definecolor{GoldenEarth}{HTML}{E7D192} \\colorlet{name}{black} \\colorlet{tagline}{black} \\colorlet{heading}{black} \\colorlet{headingrule}{black} \\colorlet{subheading}{black} \\colorlet{accent}{black} \\colorlet{emphasis}{SlateGrey} \\colorlet{body}{LightGrey} % Change some fonts, if necessary \\renewcommand{\\namefont}{\\Huge\\rmfamily\\bfseries} \\renewcommand{\\personalinfofont}{\\footnotesize} \\renewcommand{\\cvsectionfont}{\\LARGE\\rmfamily\\bfseries} \\renewcommand{\\cvsubsectionfont}{\\large\\bfseries} % Change the bullets for itemize and rating marker % for \cvskill if you want to \\renewcommand{\\itemmarker}{{\\small\\textbullet}} \\renewcommand{\\ratingmarker}{\\faCircle} " ("\\cvsection{%s}" . "\\cvsection*{%s}") ("\\cvevent{%s}" . "\\cvevent*{%s}"))) #+end_src * Company-mode for great autocompletes I don't really want company-mode to run on timeouts. I want VIM-like autocompletion, where =C-x o= and friends gives me my autocompletion. #+begin_src emacs-lisp (after! company-mode (setq company-idle-delay nil)) (setq company-idle-delay nil) #+end_src * Initializing shell environment variables ** Package #+begin_src emacs-lisp :tangle "packages.el" (package! exec-path-from-shell) #+end_src ** Config We need to bring in the correct SSH agent values, so that Emacs is aware of where it is running. #+begin_src emacs-lisp (use-package! exec-path-from-shell) (after! exec-path-from-shell (dolist (var '("SSH_AUTH_SOCK" "SSH_AGENT_PID" "GPG_AGENT_INFO")) (add-to-list 'exec-path-from-shell-variables var)) (exec-path-from-shell-initialize) ) #+end_src * Md-roam :PROPERTIES: :CUSTOM_ID: md-roam-config :END: ** Packages #+begin_src emacs-lisp :tangle "packages.el" (package! md-roam :recipe (:host github :repo "nobiot/md-roam")) #+end_src ** Config #+begin_src emacs-lisp ;; file-truename is optional; it seems required when you use symbolic ;; links, which Org-roam does not resolve (use-package! md-roam :config (setq org-roam-file-extensions '("org" "md")) ; enable Org-roam for a markdown extension (setq md-roam-file-extension "md") ; default "md". Specify an extension such as "markdown" (md-roam-mode 1) (setq md-roam-file-extension-single "md") (setq md-roam-use-org-extract-ref nil) (org-roam-db-autosync-mode 1)) #+end_src * Misc. #+begin_src emacs-lisp (add-to-list 'org-tags-exclude-from-inheritance "hastodos") (add-to-list 'org-tags-exclude-from-inheritance "ignore") #+end_src * Graphics in org-mode ** Org Plot[fn:1] Org-plot can be enabled by a flag in the init file. We can use some of the variables in =org-plot= to use the current doom theme colours. #+begin_src emacs-lisp (defvar +org-plot-term-size '(1050 . 650) "The size of the GNUPlot terminal, in the form (WIDTH . HEIGHT).") (after! org-plot (defun +org-plot-generate-theme (_type) "Use the current Doom theme colours to generate a GnuPlot preamble." (format " fgt = \"textcolor rgb '%s'\" # foreground text fgat = \"textcolor rgb '%s'\" # foreground alt text fgl = \"linecolor rgb '%s'\" # foreground line fgal = \"linecolor rgb '%s'\" # foreground alt line # foreground colors set border lc rgb '%s' # change text colors of tics set xtics @fgt set ytics @fgt # change text colors of labels set title @fgt set xlabel @fgt set ylabel @fgt # change a text color of key set key @fgt # line styles set linetype 1 lw 2 lc rgb '%s' # red set linetype 2 lw 2 lc rgb '%s' # blue set linetype 3 lw 2 lc rgb '%s' # green set linetype 4 lw 2 lc rgb '%s' # magenta set linetype 5 lw 2 lc rgb '%s' # orange set linetype 6 lw 2 lc rgb '%s' # yellow set linetype 7 lw 2 lc rgb '%s' # teal set linetype 8 lw 2 lc rgb '%s' # violet # border styles set tics out nomirror set border 3 # palette set palette maxcolors 8 set palette defined ( 0 '%s',\ 1 '%s',\ 2 '%s',\ 3 '%s',\ 4 '%s',\ 5 '%s',\ 6 '%s',\ 7 '%s' ) " (doom-color 'fg) (doom-color 'fg-alt) (doom-color 'fg) (doom-color 'fg-alt) (doom-color 'fg) ;; colours (doom-color 'red) (doom-color 'blue) (doom-color 'green) (doom-color 'magenta) (doom-color 'orange) (doom-color 'yellow) (doom-color 'teal) (doom-color 'violet) ;; duplicated (doom-color 'red) (doom-color 'blue) (doom-color 'green) (doom-color 'magenta) (doom-color 'orange) (doom-color 'yellow) (doom-color 'teal) (doom-color 'violet))) (defun +org-plot-gnuplot-term-properties (_type) (format "background rgb '%s' size %s,%s" (doom-color 'bg) (car +org-plot-term-size) (cdr +org-plot-term-size))) (setq org-plot/gnuplot-script-preamble #'+org-plot-generate-theme) (setq org-plot/gnuplot-term-extra #'+org-plot-gnuplot-term-properties)) #+end_src ** Mermaid.js Mermaid.js requires the mmcli executable from npm. Mermaid is a tool that allows you to graph many kinds of entities: - Relationship diagrams - Flowcharts - Gantt diagrams There's other kinds too. The package on ELPA is perfect. Needs no config, fits right in with Babel. *** Package #+begin_src emacs-lisp :tangle "packages.el" (package! ob-mermaid) #+end_src *** Config #+begin_src emacs-lisp (use-package! ob-mermaid) #+end_src ** SVGBob SVGBob is an ASCII art renderer. It can do all kinds of nifty things with just a few basic .------./\ *** Package #+begin_src emacs-lisp :tangle "packages.el" (package! ob-svgbob :recipe (:host nil :type git :repo "https://git.tecosaur.net/tec/ob-svgbob")) #+end_src *** Configuration #+begin_src emacs-lisp (use-package! ob-svgbob) (setq org-svgbob-executable "svgbob_cli") (setq org-babel-svgbob--parameters '(:background transparent)) #+end_src * Archiving #+begin_src emacs-lisp (setq org-archive-location "/home/judah/10-19-personal-projects/11-zettelkasten/archive.sec.org.age::") #+end_src * Init.el I like to have all my config in one place. #+begin_src emacs-lisp :tangle "init.el" ;;; init.el -*- lexical-binding: t; -*- ;; This file controls what Doom modules are enabled and what order they load ;; in. Remember to run 'doom sync' after modifying it! ;; NOTE Press 'SPC h d h' (or 'C-h d h' for non-vim users) to access Doom's ;; documentation. There you'll find a link to Doom's Module Index where all ;; of our modules are listed, including what flags they support. ;; NOTE Move your cursor over a module's name (or its flags) and press 'K' (or ;; 'C-c c k' for non-vim users) to view its documentation. This works on ;; flags as well (those symbols that start with a plus). ;; ;; Alternatively, press 'gd' (or 'C-c c d') on a module to browse its ;; directory (for easy access to its source code). (doom! :input ;;bidi ; (tfel ot) thgir etirw uoy gnipleh ;;chinese ;;japanese ;;layout ; auie,ctsrnm is the superior home row :completion company ; the ultimate code completion backend ;;helm ;;ido ;;ivy vertico ; the search engine of the future :ui ;;deft ; notational velocity for Emacs doom ; what makes DOOM look the way it does doom-dashboard ; a nifty splash screen for Emacs ;;doom-quit ; DOOM quit-message prompts when you quit Emacs ;;(emoji +unicode) ; 🙂 hl-todo ; highlight TODO/FIXME/NOTE/DEPRECATED/HACK/REVIEW ;;hydra indent-guides ; highlighted indent columns ligatures ; ligatures and symbols to make your code pretty again ;;minimap ; show a map of the code on the side modeline ; snazzy, Atom-inspired modeline, plus API nav-flash ; blink cursor line after big motions ;;neotree ; a project drawer, like NERDTree for vim ophints ; highlight the region an operation acts on (popup +defaults) ; tame sudden yet inevitable temporary windows ;;tabs ; a tab bar for Emacs treemacs ; a project drawer, like neotree but cooler ;;unicode ; extended unicode support for various languages (vc-gutter +pretty) ; vcs diff in the fringe vi-tilde-fringe ; fringe tildes to mark beyond EOB window-select ; visually switch windows ;;workspaces ; tab emulation, persistence & separate workspaces zen ; distraction-free coding or writing :editor (evil +everywhere); come to the dark side, we have cookies file-templates ; auto-snippets for empty files fold ; (nigh) universal code folding (format ) ; automated prettiness ;;god ; run Emacs commands without modifier keys ;;lispy ; vim for lisp, for people who don't like vim multiple-cursors ; editing in many places at once ;;objed ; text object editing for the innocent ;;parinfer ; turn lisp into python, sort of ;;rotate-text ; cycle region at point between text candidates snippets ; my elves. They type so I don't have to word-wrap ; soft wrapping with language-aware indent :emacs (dired +icons) ; making dired pretty [functional] electric ; smarter, keyword-based electric-indent ibuffer ; interactive buffer management undo ; persistent, smarter undo for your inevitable mistakes vc ; version-control and Emacs, sitting in a tree :term ;;eshell ; the elisp shell that works everywhere ;;shell ; simple shell REPL for Emacs term ; basic terminal emulator for Emacs vterm ; the best terminal emulation in Emacs :checkers (syntax +flymake ) ; tasing you for every semicolon you forget (spell +flyspell +everywhere) ; tasing you for misspelling mispelling grammar ; tasing grammar mistake every you make :tools ;;ansible (biblio +icons) ; Writes a PhD for you (citation needed) ;;debugger ; FIXME stepping through code, to help you add bugs ;;direnv ;;docker editorconfig ; let someone else argue about tabs vs spaces ;;ein ; tame Jupyter notebooks with emacs (eval +overlay) ; run code, run (also, repls) ;;gist ; interacting with github gists (lookup +dictionary +offline) ; navigate your code and its documentation (lsp +eglot) ; M-x vscode magit ; a git porcelain for Emacs ;;make ; run make tasks from Emacs ;;pass ; password manager for nerds pdf ; pdf enhancements ;;prodigy ; FIXME managing external services & code builders ;;rgb ; creating color strings ;;taskrunner ; taskrunner for all your projects ;;terraform ; infrastructure as code ;;tmux ; an API for interacting with tmux ;;tree-sitter ; syntax and parsing, sitting in a tree... ;;upload ; map local to remote projects via ssh/ftp :os ;;(:if IS-MAC macos) ; improve compatibility with macOS ;;tty ; improve the terminal Emacs experience :lang ;;agda ; types of types of types of types... (beancount +lsp) ; mind the GAAP (cc +lsp) ; C > C++ == 1 ;;clojure ; java with a lisp ;;common-lisp ; if you've seen one lisp, you've seen them all ;;coq ; proofs-as-programs ;;crystal ; ruby at the speed of c ;;csharp ; unity, .NET, and mono shenanigans data ; config/data formats ;;(dart +flutter) ; paint ui and not much else ;;dhall ;;elixir ; erlang done right ;;elm ; care for a cup of TEA? emacs-lisp ; drown in parentheses ;;erlang ; an elegant language for a more civilized age ;;ess ; emacs speaks statistics ;;factor ;;faust ; dsp, but you get to keep your soul ;;fortran ; in FORTRAN, GOD is REAL (unless declared INTEGER) ;;fsharp ; ML stands for Microsoft's Language ;;fstar ; (dependent) types and (monadic) effects and Z3 ;;gdscript ; the language you waited for ;;(go +lsp) ; the hipster dialect ;;(graphql +lsp) ; Give queries a REST ;;(haskell +lsp) ; a language that's lazier than I am ;;hy ; readability of scheme w/ speed of python ;;idris ; a language you can depend on ;;json ; At least it ain't XML ;;(java +lsp) ; the poster child for carpal tunnel syndrome ;;javascript ; all(hope(abandon(ye(who(enter(here)))))) ;;julia ; a better, faster MATLAB ;;kotlin ; a better, slicker Java(Script) (latex +lsp +cdlatex +fold) ; writing papers in Emacs has never been so fun ;;lean ; for folks with too much to prove ;;ledger ; be audit you can be lua ; one-based indices? one-based indices markdown ; writing docs for people to ignore ;;nim ; python + lisp at the speed of c ;;nix ; I hereby declare "nix geht mehr!" ;;ocaml ; an objective camel (org +roam2 +gnuplot +pomodoro +noter +present +pretty) ; organize your plain life in plain text ;;php ; perl's insecure younger brother ;;plantuml ; diagrams for confusing people more ;;purescript ; javascript, but functional python ; beautiful is better than ugly ;;qt ; the 'cutest' gui framework ever ;;racket ; a DSL for DSLs ;;raku ; the artist formerly known as perl6 ;;rest ; Emacs as a REST client ;;rst ; ReST in peace ;;(ruby +rails) ; 1.step {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"} (rust +lsp) ; Fe2O3.unwrap().unwrap().unwrap().unwrap() ;;scala ; java, but good ;;(scheme +guile) ; a fully conniving family of lisps sh ; she sells {ba,z,fi}sh shells on the C xor ;;sml ;;solidity ; do you need a blockchain? No. ;;swift ; who asked for emoji variables? ;;terra ; Earth and Moon in alignment for performance. web ; the tubes ;;yaml ; JSON, but readable ;zig ; C, but simpler :email ;;(mu4e +org +gmail) ;;notmuch ;;(wanderlust +gmail) :app ;;calendar ;;emmgs ;;everywhere ; *leave* Emacs!? You must be joking ;;irc ; how neckbeards socialize ;;(rss +org) ; emacs as an RSS reader ;;twitter ; twitter client https://twitter.com/vnought :config literate (default +bindings +smartparens) ) #+end_src * Footnotes [fn:1] Stolen from Tecosaur's [[https://git.tecosaur.net/tec/emacs-config][config]] * Other Editing ** Lillypond *** ob-lilypond **** package #+begin_src emacs-lisp :tangle "packages.el" (package! ob-lilypond :recipe (:host github :type git :repo "mjago/ob-lilypond")) #+end_src **** config #+begin_src emacs-lisp (use-package! ob-lilypond) (setq ly-arrange-mode t) #+end_src