doom/config.org
2023-10-13 21:48:58 -04:00

30 KiB

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.

Task List

TODO Reorganize into use-cases rather than packages

Setting Basics

(setq tab-always-indent t)
(setq org-roam-directory "~/org/")

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.

(setq doom-theme 'doom-dark+)
(setq doom-font (font-spec :family "Hack Nerd Font Mono" :size 16 :weight 'medium))
(setq auto-save-default nil)

Doom splash screen

I really don't like the widgets, and I think it takes longer to load so I get rid of them

(remove-hook '+doom-dashboard-functions #'doom-dashboard-widget-shortmenu)
(remove-hook '+doom-dashboard-functions #'doom-dashboard-widget-footer)

Set a sweet splash image

(setq fancy-splash-image (concat doom-private-dir "emacs.png"))

User details

(setq user-full-name "Judah Sotomayor"
      user-mail-address "")

Evil configuration

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

(map! :desc "Switch to normal mode" "M-c" #'evil-normal-state)
    (setq org-pretty-entities 0)

Terminal setup

I like to just use bash:

(defun bash ()
  (interactive)
  (term "/bin/bash"))
(map!
      :desc "Start a bash shell"
      "<f6>" #'bash)

I don't like the modeline in the terminal.

(add-hook 'term-mode-hook 'hide-mode-line-mode)

Sage-math

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

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

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

Beancount

I want to launch favagtk more easily. Let's do that here:

(defun fava ()
  (interactive)
  (async-shell-command "flatpak run org.gnome.gitlab.johannesjh.favagtk"))
(map! :leader
 :desc "Start favagtk"
 "r b" #'fava)

Graphing Applications

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.

(use-package! ob-mermaid)

SVGBob

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

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

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

Fun Stuff

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

Creating Diagrams and graphs

TODO set default values using org-babel's features for that.

Securing Sensitive Files

Age.el

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

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 t)
(setq org-link-elisp-confirm-function t)
(setq enable-local-variables t)
(setq enable-local-eval 'maybe)

Org-mode for a great todo list

Making the Agenda features more efficient

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

Only include files with the hastodos tag. This section is contributed from 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.

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

Basic settings

    (setq org-log-done 'time)
    (after! org-mode
        (setq org-log-done 'time)
        (setq org-archive-location "~/org/archive.org")
        (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)
    (setq org-archive-location (concat org-directory "/archive.org::"))

Appearances

Deprecated: TODO Keywords

I like to have a few different todo keywords for different sorts of activities. Purchasing todos:

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

These settings aren't very useful for me, as I like default colors and keywords.

Deprecated: Settings for org-modern

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

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.

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

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

Export settings

(after! org
  ;; Import ox-latex to get org-latex-classes and other funcitonality
  ;; for exporting to LaTeX from org
  (use-package! ox-latex
    :init
    ;; code here will run immediately
    :config
    ;; code here will run after the package is loaded
    (setq org-latex-pdf-process
          '("pdflatex -interaction nonstopmode -output-directory %o %f"
            "bibtex %b"
            "pdflatex -interaction nonstopmode -output-directory %o %f"
            "pdflatex -interaction nonstopmode -output-directory %o %f"))
    (setq org-latex-with-hyperref nil) ;; stop org adding hypersetup{author..} to latex export
    ;; (setq org-latex-prefer-user-labels t)

    ;; deleted unwanted file extensions after latexMK
    (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))))
(setq org-latex-to-pdf-process
  '("xelatex -interaction nonstopmode %f"
     "xelatex -interaction nonstopmode %f")) ;; for multiple passes

(setq-default org-html-with-latex `dvisvgm)
(setq org-latex-pdf-process
      '("latexmk -pdflatex='pdflatex -interaction nonstopmode' -pdf -bibtex -f %f"))



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

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)

Export Function

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

We'll want a handy shortcut for this.

            (map! :leader
                    :desc "Export to html and diplay with eww"
                    "r E" #'org-export-and-open-eww)
/home/user/.config/doom/

Org-drill

Set some good keybinds for quick access:

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

ob-lilypond

(use-package! ob-lilypond)
(setq ly-arrange-mode t)

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

 (use-package! org-heatmap
	:after (org)
	:config
	(org-heatmap-mode))

Ox-hugo

(setq org-hugo-base-dir "~/org/website/")

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.

Automatic Citations with citar and org-cite

Citar is a sweet little package for managing citations. Right here we'll set it up We want a general bibliography file, a styles directory, and a default set of styles.

(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))
(after! org-mode
  (org-cite-global-bibliography '("~/org/references.bib"))
  )

(citar-org-roam-mode)

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}"
     ("\\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}"
     ("\\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}"
     ("\\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
(setq org-latex-pdf-process '("LC_ALL=en_US.UTF-8 latexmk -f -pdf -%latex -shell-escape -interaction=nonstopmode -output-directory=%o %f"     ))

Engraving Faces

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

(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
      :init (setq org-roam-directory "~/org/"))      :custom
(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: <link rel=\"stylesheet\" type=\"text/css\" href=\"css/retro.css\" />\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: <link rel=\"stylesheet\" type=\"text/css\" href=\"css/retro.css\" />\n\n\n* No Export Below This Line")
          :unnarrowed t)

         ("w" "website" plain "%?"
          :target (file+head "website/org/%<%Y%m%d-%H%M%S>.org"
                             "#+TITLE: ${title}\n")
                             :unnarrowed t))))

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

(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

                ))))
Function to pull up org-roam ui
(defun open-org-roam-ui ()
  (interactive)
  (org-roam-ui-mode)
  (async-shell-command "surf http://localhost:35901/"))

Default Browser for Export

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

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>\n")))))

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.

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

Resume template

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

Better EViL keybinds

Remapping g-j/k

(map! :n "g j" #'evil-next-visual-line)
(map! :n "g k" #'evil-previous-visual-line)

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)

Test

(require 'zmq)

Initializing shell environment variables

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