doom/config.org
Judah Sotomayor e66629c6bd
feat(org): Configure org project alist
Add configuration to produce blog to org-publish-alist
2024-08-29 15:20:30 -04:00

50 KiB
Raw Permalink Blame History

Doom-emacs config

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

;; -*- no-byte-compile: t; -*-

Set name, org-roam-directory, etc.

Some basic settings for Emacs

(setq tab-always-indent t)

(setq user-full-name "Judah Sotomayor"
      user-mail-address "")
(package! noCtrlC
  :recipe (:host nil :type git :repo "https://git.freedomland.xyz/judahsotomayor/noctrlc"))

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.

(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.
(remove-hook '+doom-dashboard-functions #'doom-dashboard-widget-shortmenu)
(remove-hook '+doom-dashboard-functions #'doom-dashboard-widget-footer)
(setq fancy-splash-image (concat doom-private-dir "emacs.png"))
(add-hook 'term-mode-hook 'hide-mode-line-mode)

Evil configuration

I want a non-ESC way to get back to normal mode:

(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)
(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)

Terminal setup

Shell mappings

(map! :leader (:prefix ("k" . "shell")
      :desc "Start an elisp repl"
      :n "e" #'+emacs-lisp/open-repl

      :desc "Start a python repl"
      :n "j" #'+python/open-repl))

I like to have a shortcut for calc as well, for simpler calculations

(map! :leader
      :desc "The Emacs Calculator"
      "C" #'calc)

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

`-c`
flag.

 (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)))

Convert regex strings to rx   COMMENT

(package! xr)
(use-package! xr)

Securing Sensitive Files

Age.el

(package! age)

Config

(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))

Preprocessor

This preprocessor script allows me to use Ripgrep with Age to filter agenda files. You can see the configuration for that in this section.

#!/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

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.

(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)
maybe
    (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))

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

This piece of code will allow us to capture all the agenda files using the preprocessor we wrote here

rg --type-add 'aorg:*.org.age' \
    -torg -taorg \
    --pre ~/age-preprocessor.zsh --pre-glob '*.age' -l TODO /home/judah/10-19-personal-projects/11-zettelkasten

Now, of course, this code is not useful as it isafter all, we can't tangle a .sh script into /judahsotomayor/doom/src/branch/main/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.

(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/judah/10-19-personal-projects/11-zettelkasten/")))
    (setq org-agenda-files (remove "/home/judah/10-19-personal-projects/11-zettelkasten/archive.sec.org.age" org-agenda-files)))

And then we want to call this before building the agenda:

(add-hook 'org-agenda-mode-hook 'set-org-agenda-files-ripgrep)

Filtering the agenda

I don't want scheduled items to duplicate if the deadline is up.

(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))
t

Basic settings

(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)
~/10-19-personal-projects/11-zettelkasten/

Appearances

Images Preferences

We want to show images when loading a file, and also after evaluating code blocks.

(setq org-startup-with-inline-images t)

;; Show images after evaluating code blocks.
(add-hook 'org-babel-after-execute-hook 'org-display-inline-images)

Org-super-agenda

Super-agenda allows many nice configurations to the agenda buffer.

(package! org-super-agenda)
(use-package! org-super-agenda
  :after org-roam
  :config (org-super-agenda-mode))
t

Configure the Super Agenda to neatly organize everything.

(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)))

org-edna

(package! org-edna)

Edna allows better dependency handling for todos and the like.

(use-package! org-edna)
(org-edna-mode)

Org-habit

(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))

Anki editing in org-mode

Anki editor is a good one for large cards that need high complexity.

(package! anki-editor)

inline-anki

Inline anki is far better for small cards, and where it is best to maintain a single source of truth.

(package! asyncloop)
(package! inline-aki
  :recipe (:host github :repo "meedstrom/inline-anki"))
(setq inline-anki-note-type "Katex and Markdown Cloze")
(setq inline-anki-use-tags t)
Inline Anki symbol

By default, Inline-anki uses underscore to specify the card type. This is okay, but I'd rather find something that isn't already used.

(add-to-list 'org-emphasis-alist '("." nil))
(setq inline-anki-emphasis-type "_")
_

calfw Calendar View   ARCHIVE

(package! calfw
  :recipe (:host github :type git :repo "haji-ali/emacs-calfw"))

Programming Items

LSP

In order for editorconfig to do its thing, indentation by the lsp must be disabled.

(setq lsp-enable-indentation nil)

Website

Capture template

(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))

Crafting a Writing Environment   export

For writing I like to automate as much as possible. This means creating an environment that does citations and such for me.

Export settings

\LaTeX

Ox-latex
(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))))
Lualatex as PDF Processor

I've found that lualatex does a good job processing PDFs. $hi$

(after! ox-latex
  (setq org-latex-pdf-process
        '("lualatex --output-directory=%o -shell-escape -interaction nonstopmode %f"
          "lualatex --output-directory=%o -shell-escape -interaction nonstopmode %f")))
lualatex output-directory=/home/judah/Documents -shell-escape -interaction nonstopmode %f lualatex output-directory=/home/judah/Documents -shell-escape -interaction nonstopmode %f

$x + 1 = 3$

luamagick
(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}")))
COMMENT Fixing dvipng image handling
(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)
Delete links from inline anki
(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)))))
inline-anki-link-filter
(add-to-list 'org-export-filter-link-functions
             'inline-anki-link-filter)
inline-anki-link-filter

HTML

Custom functions

A lot of this section I steal from writepermission.com. He has some great work for rss feed creation and other stuff.

(defun rw/format-rss-feed-entry (entry style project)
  "Format ENTRY for the RSS feed.
ENTRY is a file name.  STYLE is either 'list' or 'tree'.
PROJECT is the current project."
  (cond ((not (directory-name-p entry))
         (let* ((file (org-publish--expand-file-name entry project))
                (title (org-publish-find-title entry project))
                (date (format-time-string "%Y-%m-%d" (org-publish-find-date entry project)))
                (link (concat (file-name-sans-extension entry) ".html")))
           (with-temp-buffer
             (org-mode)
             (insert (format "* [[file:%s][%s]]\n" file title))
             (org-set-property "RSS_PERMALINK" link)
             (org-set-property "PUBDATE" date)
             (insert-file-contents file)
             (buffer-string))))
        ((eq style 'tree)
         ;; Return only last subdir.
         (file-name-nondirectory (directory-file-name entry)))
        (t entry)))

(defun rw/format-rss-feed (title list)
  "Generate RSS feed, as a string.
TITLE is the title of the RSS feed.  LIST is an internal
representation for the files to include, as returned by
`org-list-to-lisp'.  PROJECT is the current project."
  (concat "#+TITLE: " title "\n\n"
          (org-list-to-subtree list 1 '(:icount "" :istart ""))))

(defun rw/org-rss-publish-to-rss (plist filename pub-dir)
  "Publish RSS with PLIST, only when FILENAME is 'rss.org'.
PUB-DIR is when the output will be placed."
  (if (equal "rss.org" (file-name-nondirectory filename))
      (let ((file-name (org-rss-publish-to-rss plist filename pub-dir)))
        (shell-command (format "tail -n +2 %s > random-file-temp.xml" file-name file-name))
        (shell-command (format "mv random-file-temp.xml %s" file-name))
        file-name)))

(use-package! ox-rss)

We will need ox-rss for rss feed production.

(package! ox-rss)
Project list configuration

Finally, configure the project alist using a series of projects.

  1. blog-posts processes the normal .org file to create posts.
  2. blog-static brings static css and images into the publishing dir.
  3. blog-rss creates the rss feed as a special type of sitemap. It uses ox-rss, which we just loaded!
  4. Finally, the whole blog. This uses both blog-posts and blog-rss.
(setq org-html-htmlize-output-type 'css
      org-html-html5-fancy t
      org-html-metadata-timestamp-format "%Y-%m-%d"
      org-html-checkbox-type 'html
      org-html-doctype "html5")
(let ((blog--root (concat (file-name-as-directory org-directory) "blog"))
      (blog--public-root "~/10-19-personal-projects/15-blog")
      (blog--url "https://judah.freedomland.xyz")
      (blog--static-attachment-extensions (regexp-opt '("jpg" "jpeg" "gif" "png" "svg" "pdf" "css"))))
  (setq org-publish-project-alist
      (list
       (list "blog-posts"
             :auto-sitemap t
             :base-directory blog--root
             :exclude (regexp-opt '("rss.org"))
             :html-htmlized-css-url "static/style.css"
             :html-head-include-default-style nil
             :publishing-directory blog--public-root
             :publishing-function 'org-html-publish-to-html
             :recursive nil
             :sitemap-filename "index.org"
             :sitemap-title "Judah Sotomayor's Blog"
             :sitemap-sort-files 'anti-chronologically
             :sitemap-style 'tree)
       (list "blog-static"
             :base-directory (expand-file-name "static" blog--root)
             :base-extension blog--static-attachment-extensions
             :publishing-directory (expand-file-name "static" blog--public-root)
             :publishing-function 'org-publish-attachment
             :recursive t)
       (list "blog-rss"
             :auto-sitemap t
             :base-directory blog--root
             :exclude (regexp-opt '("rss.org" "index.org" "404.org"))
             :html-link-home blog--url
             :html-link-use-abs-url t
             :html-link-org-files-as-html t
             :publishing-directory blog--public-root
             :publishing-function 'rw/org-rss-publish-to-rss
             :rss-extension "xml"
             :sitemap-filename "rss.org"
             :sitemap-format-entry 'rw/format-rss-feed-entry
             :sitemap-function 'rw/format-rss-feed
             :sitemap-sort-files 'anti-chronologically
             :sitemap-style 'list)
       (list "blog"
             :components '("blog-posts" "blog-rss" "blog-static")))))

Automatic Citations with citar and org-cite

Citar is a sweet little package for managing citations. We want a general bibliography file, a styles directory, and a default set of styles.

Citar setup

First of all, we must configure citar.

(package! citar-org-roam)
(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))

Icons for some prettification

(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)))

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:

(add-to-list 'org-latex-classes
             '("student-apa7"
               "\\documentclass[stu]{apa7}
\\usepackage[]{multicol}
\\usepackage{mathptmx}
\\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[]{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

Engraving Faces

Ever wonder why code export sucks with \LaTeX ? Me neither! Let's fix it!

(package! engrave-faces)
(use-package! engrave-faces)
(setq org-latex-listings 'engraved)

Zettelkasten environment with org-roam

Org-roam enables features essential to a Zettelkasten such as inter-ID linking.

(use-package! org-roam
  :after md-roam)

I use several capture templates to make it easy to get notes into my various sections. I only use Markdown in the team wiki, so I have it set to that. I also have a capture template form my /judahsotomayor/doom/src/branch/main/Website

(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))))
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.

(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))

Nice UI to access Zettelkasten notes with Org-roam ui

Package
(package! org-roam-ui)
(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

                                                           ))))

Journal Environment with org-roam

(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 %A>\n* Where was I today?\n* Where am I at now?\n* Where will I be tomorrow?")))))

Where was I today?

Where am I at now?

Where will I be tomorrow?) |

Property getters and setters

These are to fulfill my need to get property values for generating my journal index.

(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))

Resume setup for a stellar CV

ox-extra for ":ignore:" tags

I want to be able to ignore headings on export.

(use-package! ox-extra
  :after (org)
  :config
  (ox-extras-activate '(latex-header-blocks ignore-headlines)))

McDowell Resume Template

This template is supposed to be the standard.

(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}")))

Altacv template   ARCHIVE

This is no longer really used.

(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}")))

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.

(after! company-mode
  (setq company-idle-delay nil))
(setq company-idle-delay nil)

Initializing shell environment variables

Package

(package! exec-path-from-shell)

Config

We need to bring in the correct SSH agent values, so that Emacs is aware of where it is running.

(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)
  )

Md-roam

Packages

(package! md-roam
  :recipe (:host github :repo "nobiot/md-roam"))

Config

;; 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))

Misc.

(add-to-list 'org-tags-exclude-from-inheritance "hastodos")
(add-to-list 'org-tags-exclude-from-inheritance "ignore")

Graphics in org-mode

Org Plot1

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.

(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))

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

(package! ob-mermaid)

Config

(use-package! ob-mermaid)

SVGBob

SVGBob is an ASCII art renderer. It can do all kinds of nifty things with just a few basic .——./\

Package

(package! ob-svgbob
  :recipe (:host nil :type git :repo "https://git.tecosaur.net/tec/ob-svgbob"))

Configuration

(use-package! ob-svgbob)
(setq org-svgbob-executable "svgbob_cli")

(setq org-babel-svgbob--parameters
      '(:background transparent))

Archiving

(setq org-archive-location "/home/judah/10-19-personal-projects/11-zettelkasten/archive.sec.org.age::")

Init.el

I like to have all my config in one place.

;;; 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 +lsp +treesitter)               ; 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 +lsp)               ; 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)
       )

Footnotes

Other Editing


1

Stolen from Tecosaur's config