#+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. * Task List ** TODO Reorganize into use-cases rather than packages * 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 org-roam-directory "~/org/") (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 work, because of foling in Org-mode. #+begin_src emacs-lisp (setq doom-theme 'doom-homage-black) (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 ** 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) #+end_src * Terminal setup I like to just use bash: #+begin_src emacs-lisp (defun bash () (interactive) (term "/bin/bash")) (map! :desc "Start a bash shell" "" #'bash) #+end_src 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 current-date () (interactive) (shell-command-to-string " bash -c 'echo -n $(date +%Y-%m-%d)'")) (defun insert-current-date () (interactive) (insert (current-date))) (map! :leader :desc "Insert the current date into the buffer" "i d" #'insert-current-date) #+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 ** 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 t) (setq org-link-elisp-confirm-function t) (setq enable-local-variables t) (setq enable-local-eval 'maybe) #+end_src #+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 #+begin_src emacs-lisp :tangle no (dolist (file (org-roam-list-files)) (message "processing %s" file) (with-current-buffer (or (find-buffer-visiting file) (find-file-noselect file)) (vulpea-project-update-tag) (save-buffer))) #+end_src #+RESULTS: Only include files with the hastodos tag. This section is contributed from [[https://gist.github.com/d12frosted/a60e8ccb9aceba031af243dff0d19b2e][d12frosted]] and use his vulpea.el package's functions. I ripped out the essentials because I don't want all the other stuff in that package. #+begin_src emacs-lisp (after! org-roam (defun vulpea-project-p () "Return non-nil if current buffer has any todo entry. TODO entries marked as done are ignored, meaning the this function returns nil if current buffer contains only completed tasks." (seq-find ; (3) (lambda (type) (eq type 'todo)) (org-element-map ; (2) (org-element-parse-buffer 'headline) ; (1) 'headline (lambda (h) (org-element-property :todo-type h))))) (defun vulpea-project-update-tag () "Update PROJECT tag in the current buffer." (when (and (not (active-minibuffer-window)) (vulpea-buffer-p)) (save-excursion (goto-char (point-min)) (let* ((tags (vulpea-buffer-tags-get)) (original-tags tags)) (if (vulpea-project-p) (setq tags (cons "hastodos" tags)) (setq tags (remove "hastodos" tags))) ;; cleanup duplicates (setq tags (seq-uniq tags)) ;; update tags if changed (when (or (seq-difference tags original-tags) (seq-difference original-tags tags)) (apply #'vulpea-buffer-tags-set tags)))))) (defun vulpea-buffer-p () "Return non-nil if the currently visited buffer is a note." (and buffer-file-name (string-prefix-p (expand-file-name (file-name-as-directory org-roam-directory)) (file-name-directory buffer-file-name)))) (defun vulpea-project-files () "Return a list of note files containing 'hastodos' tag." ; (seq-uniq (seq-map #'car (org-roam-db-query [:select [nodes:file] :from tags :left-join nodes :on (= tags:node-id nodes:id) :where (like tag (quote "%\"hastodos\"%"))])))) (defun vulpea-agenda-files-update (&rest _) "Update the value of `org-agenda-files'." (setq org-agenda-files (vulpea-project-files))) (add-hook 'find-file-hook #'vulpea-project-update-tag) (add-hook 'before-save-hook #'vulpea-project-update-tag) (advice-add 'org-agenda :before #'vulpea-agenda-files-update) (advice-add 'org-todo-list :before #'vulpea-agenda-files-update) ;; functions borrowed from `vulpea' library ;; https://github.com/d12frosted/vulpea/blob/6a735c34f1f64e1f70da77989e9ce8da7864e5ff/vulpea-buffer.el (defun vulpea-buffer-tags-get () "Return filetags value in current buffer." (vulpea-buffer-prop-get-list "filetags" "[ :]")) (defun vulpea-buffer-tags-set (&rest tags) "Set TAGS in current buffer. If filetags value is already set, replace it." (if tags (vulpea-buffer-prop-set "filetags" (concat ":" (string-join tags ":") ":")) (vulpea-buffer-prop-remove "filetags"))) (defun vulpea-buffer-tags-add (tag) "Add a TAG to filetags in current buffer." (let* ((tags (vulpea-buffer-tags-get)) (tags (append tags (list tag)))) (apply #'vulpea-buffer-tags-set tags))) (defun vulpea-buffer-tags-remove (tag) "Remove a TAG from filetags in current buffer." (let* ((tags (vulpea-buffer-tags-get)) (tags (delete tag tags))) (apply #'vulpea-buffer-tags-set tags))) (defun vulpea-buffer-prop-set (name value) "Set a file property called NAME to VALUE in buffer file. If the property is already set, replace its value." (setq name (downcase name)) (org-with-point-at 1 (let ((case-fold-search t)) (if (re-search-forward (concat "^#\\+" name ":\\(.*\\)") (point-max) t) (replace-match (concat "#+" name ": " value) 'fixedcase) (while (and (not (eobp)) (looking-at "^[#:]")) (if (save-excursion (end-of-line) (eobp)) (progn (end-of-line) (insert "\n")) (forward-line) (beginning-of-line))) (insert "#+" name ": " value "\n"))))) (defun vulpea-buffer-prop-set-list (name values &optional separators) "Set a file property called NAME to VALUES in current buffer. VALUES are quoted and combined into single string using `combine-and-quote-strings'. If SEPARATORS is non-nil, it should be a regular expression matching text that separates, but is not part of, the substrings. If nil it defaults to `split-string-default-separators', normally \"[ \f\t\n\r\v]+\", and OMIT-NULLS is forced to t. If the property is already set, replace its value." (vulpea-buffer-prop-set name (combine-and-quote-strings values separators))) (defun vulpea-buffer-prop-get (name) "Get a buffer property called NAME as a string." (org-with-point-at 1 (when (re-search-forward (concat "^#\\+" name ": \\(.*\\)") (point-max) t) (buffer-substring-no-properties (match-beginning 1) (match-end 1))))) (defun vulpea-buffer-prop-get-list (name &optional separators) "Get a buffer property NAME as a list using SEPARATORS. If SEPARATORS is non-nil, it should be a regular expression matching text that separates, but is not part of, the substrings. If nil it defaults to `split-string-default-separators', normally \"[ \f\t\n\r\v]+\", and OMIT-NULLS is forced to t." (let ((value (vulpea-buffer-prop-get name))) (when (and value (not (string-empty-p value))) (split-string-and-unquote value separators)))) (defun vulpea-buffer-prop-remove (name) "Remove a buffer property called NAME." (org-with-point-at 1 (when (re-search-forward (concat "\\(^#\\+" name ":.*\n?\\)") (point-max) t) (replace-match "")))) (setq org-agenda-files (vulpea-project-files))) #+end_src ** Basic settings #+begin_src emacs-lisp (setq org-log-done 'time) (after! org-mode (setq org-log-done 'time) (add-to-list 'org-tags-exclude-from-inheritance "hastodos") (setq org-hide-emphasis-markers nil)) (setq org-directory "~/org/") (setq org-roam-directory org-directory) #+end_src ** Appearances *** Deprecated: TODO Keywords I like to have a few different todo keywords for different sorts of activities. Purchasing todos: #+begin_src emacs-lisp :tangle no (setq org-todo-keywords '((sequence "PROJ(p)" "|" "COMPLETE") (type "TICKLE") (type "DELE") (type "WAIT") (sequence "TODO(t)" "|" "DONE") (sequence "DELEGATED" "VERIFY" "|" "DONE") (sequence "BUY(b)" "|" "BOUGHT") )) (setq org-todo-keyword-faces '(("TODO" . "salmon1") ("START" . "spring green" ) ("DELE" . "gold") ("TICKLE" . "magenta") ("WAIT" . "gold") ("PROJ" . "deep sky blue"))) #+end_src These settings aren't very useful for me, as I like default colors and keywords. *** Deprecated: Settings for org-modern #+begin_src emacs-lisp :tangle no (setq org-modern-todo-faces '(("START" :background "spring green" :foreground "black") ("DELE" :background "gold" :foreground "black") ("WAIT" :background "gold" :foreground "black") ("PROJ" :background "deep sky blue" :foreground "black") ("TICKLE" :background "magenta" :foreground "black"))) (setq org-modern-priority-faces '((?A :background "salmon1" :foreground "black") (?B :background "gold" :foreground "black") (?C :background "spring green" :foreground "black"))) #+end_src I currently have org-modern stripped out of my config. I probably won't need this again, but in case I do I want all my preferences to be there. *** 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-agenda deadlines I don't like agenda nagging me about upcoming events. It causes a lot of duplication! #+begin_src emacs-lisp (setq org-deadline-warning-days 0) #+end_src Turn it off with this snippet. ** Org-drill Set some good keybinds for quick access: #+begin_src emacs-lisp (use-package! org-drill :defer nil ) (map! :leader :desc "Start org-drill" "d d" #'org-drill-directory) (map! :leader :desc "Start org-drill in cram mode" "d c" #'org-drill-cram) #+end_src ** 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 ** 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 :tangle "packages.el" (package! org-heatmap :recipe (:host github :type git :repo "aspiers/org-heatmap")) #+end_src #+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 nil)) (use-package! org-heatmap :after (org) :config (org-heatmap-mode)) #+end_src ** Org-archive with structure Many thanks to Mark Edigmar's [[https://gist.github.com/edgimar/072d99d8650abe81a9fe7c8687c0c993][Gist]] *** Keymaps #+begin_src emacs-lisp (map! :leader :desc "Archive subtree" :n "m A" #'org-archive-subtree-default) #+end_src ** Anki editing in org-mode #+begin_src emacs-lisp :tangle packages.el (package! anki-editor) #+end_src ** calfw Calendar View #+begin_src emacs-lisp :tangle "packages.el" (package! calfw :recipe (:host github :type git :repo "haji-ali/emacs-calfw")) #+end_src * 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 #+begin_src emacs-lisp (add-to-list 'org-roam-capture-templates '("m" "Markdown" plain "" :target (file+head "training-resources/content/${title}.md" "---\ntitle: ${title}\nid: %<%Y-%m-%dT%H%M%S>\ncategory: \n---\n") :unnarrowed t)) #+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 $x + 1 = 3$ #+RESULTS: : luamagick #+begin_src emacs-lisp (setq-default org-html-with-latex `dvisvgm) (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} | *** 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/ ** Automatic Citations with *citar* and *org-cite* 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 emacs-lisp (use-package! citar :ensure t :demand t :custom (citar-bibliography "~/org/references.bib") (citar-file-note-extensions '(".org")) (org-cite-global-bibliography '("~/org/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)) (citar-org-roam-mode) #+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} \\hypersetup{hidelinks} \\usepackage{times} [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{times} [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}") ("\\usepackage{biblatex-chicago}"))) (add-to-list 'org-latex-classes '("student-mla" "\\documentclass[stu]{mla} \\hypersetup{hidelinks} \\usepackage{times} " ("\\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 :init (setq org-roam-directory "~/org/")) :custom #+end_src #+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#+HTML_HEAD: \n") :unnarrowed t) ("s" "school" plain "%?" :target (file+head "%<%Y%m%d-%H%M%S>.org" "#+TITLE: ${title} ,#+LATEX_CLASS: student-apa7 ,#+LATEX_OPTIONS: stu,hidelinks ,#+LATEX_HEADER: \\course{} ,#+LATEX_HEADER:\\authorsnames{Judah Sotomayor} ,#+LATEX_HEADER: \\authorsaffiliations{} ,#+LATEX_HEADER: \\professor{} ,#+LATEX_HEADER: \\usepackage{times} ,#+LATEX_HEADER: \\duedate{} ,#+OPTIONS: toc:nil\n") :unnarrowed t) ("c" "encrypted" plain "%?" :target (file+head "%<%Y%m%d-%H%M%S>.sec.org.age" "#+TITLE: ${title}\n#+FILETAGS: :secure:noexport:\n#+HTML_HEAD: \n\n\n* No Export Below This Line") :unnarrowed t)))) #+end_src *** 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 **** Function to pull up org-roam ui #+begin_src emacs-lisp (defun open-org-roam-ui () (interactive) (org-roam-ui-mode) (async-shell-command "surf http://localhost:35901/")) #+end_src *** Default Browser for Export #+begin_src emacs-lisp (setq browse-url-browser-function 'browse-url-generic browse-url-generic-program "surf") '(org-file-apps (quote ((auto-mode . emacs) ("\\.mm\\'" . default) ("\\.x?html?\\'" . "surf %s") ("\\.pdf\\'" . default)))) #+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 (after! org (use-package! ox-extra :config (ox-extras-activate '(latex-header-blocks ignore-headlines)))) #+end_src *** Resume template #+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 *** 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} [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}") ("\\cvsection{%s}" . "\\cvsection*{%s}") ("\\cvevent{%s}" . "\\cvevent*{%s}"))) #+end_src ** Better EViL keybinds *** Remapping =g-j/k= #+begin_src emacs-lisp (map! :n "g j" #'evil-next-visual-line) (map! :n "g k" #'evil-previous-visual-line) #+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 ** 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" (setq md-roam-file-extension-single "md") (setq md-roam-use-org-extract-ref nil) (org-roam-db-autosync-mode 1)) #+end_src ** COMMENT Capture template for documentation #+begin_src emacs-lisp (add-to-list 'org-roam-capture-templates '("m" "Markdown" plain "" :target (file+head "training-resources/content/${title}.md" "---\ntitle: ${title}\nid: %<%Y-%m-%dT%H%M%S>\ncategory: \n---\n") :unnarrowed t)) #+end_src * Funny Stuff ** Spray #+begin_src emacs-lisp (use-package! spray :commands spray-mode) #+end_src #+begin_src emacs-lisp (add-to-list 'org-tags-exclude-from-inheritance "hastodos") #+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))) #+end_src Now use the preamble we created: #+begin_src emacs-lisp (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 * 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 ; 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 +hugo +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]]