Skip to content

calstad/emacs-config

Repository files navigation

Colin’s Emacs Configuration

Emacs Configuration

This is my “dot emacs” configuration using org-mode.

Global Configuration

File Paths

These are file paths that are used throughout the configuration

Where we persist files between emacs sessions.

(setq calstad/persistence-dir
      (expand-file-name "persistence/" user-emacs-directory))

The directory that will sync files across all machines.

(setq calstad/sync-dir "~/files")

The directory for all things org-mode related.

(setq calstad/org-dir (expand-file-name "org" calstad/sync-dir))

Where we keep capture templates for org-mode and related packages.

(setq calstad/org-capture-templates
      (expand-file-name "org_capture_templates/" user-emacs-directory))

The location of my reference library including bibliographies and PDFs.

(setq calstad/ref-lib-dir (expand-file-name "library" calstad/sync-dir)
      calstad/lib-bib (expand-file-name "library.bib" calstad/ref-lib-dir)
      calstad/lib-docs (expand-file-name "documents/" calstad/ref-lib-dir))

Directory where we keep all of the org-roam files.

(setq calstad/org-roam-dir
      (expand-file-name "roam" calstad/org-dir))

User details

Emacs will normally pick this up automatically, but this way I can be sure the right information is always present.

(setq user-full-name "Colin Alstad"
      user-mail-address "colin.alstad@gmail.com")

Packages

We use the straight package manager to take care of dependency management. The straight package is bootstrapped in the init file so that the wrong version of org-mode is not loaded.

Next we setup straight to use the use-package macro for package configuration.

;; Use straight to install use-package
(straight-use-package 'use-package)
;; Tell use-package to always install from straight
(setq straight-use-package-by-default t)

This tells straight how to find my forks of packages on github.

(setq straight-host-usernames
      '((github . "calstd")))

UI

Skip splash screen on startup

(setq initial-buffer-choice t)

GUI options

(when window-system
  (setq frame-title-format '(buffer-file-name "%f" ("%b")))
  (tooltip-mode -1)       ; dont need mouse tootips!
  (mouse-wheel-mode t)    ; stupid mice
  (blink-cursor-mode -1)  ; about to give me seizures
  (tool-bar-mode -1))

Terminal options

(menu-bar-mode -1)

Set a color theme

(use-package zenburn-theme
  :config (load-theme 'zenburn t))

;; (use-package spacemacs-theme
;;   :config (load-theme 'spacemacs-light))

Turn off visual and audio bells

(setq visible-bell t
      ring-bell-function 'ignore)

Add indication at bottom of buffer for empty lines

(set-default 'indicate-empty-lines t)

Turn off bookmark fringe marker

Turn off the orange fringe marker for bookmarks introduced in Emacs 28.1.

(setq bookmark-set-fringe-mark nil)

Mode line settings

(line-number-mode t)
(column-number-mode t)
(size-indication-mode t)

Enable y/n answers

(fset 'yes-or-no-p 'y-or-n-p)

Confirm exiting Emacs

(setq confirm-kill-emacs 'y-or-n-p)

Editing

Key bindings

Miscellaneous editing keybindings

(global-set-key (kbd "RET") 'newline-and-indent)
(global-set-key (kbd "C-;") 'comment-or-uncomment-region)
(global-set-key (kbd "C-+") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)

Marking text

Be able to write over the marked region and also highlight the marked region.

(delete-selection-mode t)
(transient-mark-mode t)

Filling

Add auto fill to certain modes
(add-hook 'text-mode-hook 'visual-line-mode)
Unfill a region
(defun calstad/unfill-region ()
  (interactive)
  (let ((fill-column (point-max)))
    (fill-region (region-beginning) (region-end) nil)))

Spell check

Use ispell as the spell checker

(setq ispell-program-name "ispell")

Check spelling on the fly

(add-hook 'text-mode-hook 'flyspell-mode)
(add-hook 'prog-mode-hook 'flyspell-prog-mode)

Use a shared dictionary

(setq ispell-personal-dictionary (expand-file-name "flyspell_dictionary" calstad/org-dir))

Remap keybinding

(eval-after-load 'flyspell
  '(define-key flyspell-mode-map (kbd "C-;") nil))

Death to tabs

(setq-default indent-tabs-mode nil)

Highlight matching parens and auto pair

(show-paren-mode t)
(setq show-paren-style 'parenthesis)
(electric-pair-mode)

Enable Disabled commands

These commands are disabled by default and I would like to use them.

(put 'upcase-region 'disabled nil)
(put 'downcase-region 'disabled nil)

Windows and Buffers

Use better buffer list

IBuffer is a more feature rich buffer list than Buffer Menu.

(global-set-key (kbd "C-x C-b") 'ibuffer)

Go to previous window

(global-set-key (kbd "C-x O") 'previous-multiframe-window)

Swap windows

If I have two windows open, it swaps them.

(defun calstad/swap-windows ()
  (interactive)
  (if (/= (count-windows) 2)
      (message "You need exactly 2 windows to do this.")
    (let* ((w1 (first (window-list)))
           (w2 (second (window-list)))
           (b1 (window-buffer w1))
           (b2 (window-buffer w2))
           (s1 (window-start w1))
           (s2 (window-start w2)))
      (set-window-buffer w1 b2)
      (set-window-buffer w2 b1)
      (set-window-start w1 s2)
      (set-window-start w2 s1)))
  (other-window 1))
Keybinding
(global-set-key (kbd "C-c s") 'calstad/swap-windows)

Kill other buffers

Kills all the buffers but the current one. Doesent mess with earmuffed buffers.

(defun calstad/kill-other-buffers ()
  (interactive)
  (dolist (buffer (buffer-list))
    (unless (or (eql buffer (current-buffer)) (not (buffer-file-name buffer)))
      (kill-buffer buffer))))

Kill the buffer and delete file

Kills the current buffer and deletes the file it is visiting.

(defun calstad/delete-file-and-buffer ()
  (interactive)
  (let ((filename (buffer-file-name)))
    (when filename
      (delete-file filename)
      (message "Deleted file %s" filename)))
  (kill-buffer))

Revert buffers automatically when underlying files change

(global-auto-revert-mode t)
Keybinding
(global-set-key (kbd "C-c C-k") 'calstad/delete-file-and-buffer)

Rename buffers

(global-set-key (kbd "C-c r") 'rename-buffer)

Unique buffer names

Make it so that buffers have unique names if the files dont.

(require 'uniquify)
(setq uniquify-buffer-name-style 'forward
      uniquify-separator "/"
      uniquify-after-kill-buffer-p t ; rename after killing uniquified
      uniquify-ignore-buffers-re "^\\*" ; don't muck with special buffers
      )

Encrypting/Decrypting Files

Enable the EasyPG package

(epa-file-enable)

Specify the GPG key to use to encrypt/decrypt files.

(setq epa-file-encrypt-to "me@colinalstad.com")

Specify which GPG program to use.

(setq epg-gpg-program "gpg2")
(setf epa-pinentry-mode 'loopback)

Persistence Files

Several Emacs major modes use files for persistence between sessions and I keep them all in the same directory.

(unless (file-exists-p calstad/persistence-dir)
  (make-directory calstad/persistence-dir t))

Save settings from Customize into seperate file

By default, settings changed through the Customize UI are added to the init.el file. This saves those customizations into a separate file.

(setq custom-file (expand-file-name "custom.el" calstad/persistence-dir))
(unless (file-exists-p custom-file)
  (write-region "" nil custom-file))
(load custom-file)

Recently accessed files

(setq recentf-save-file (expand-file-name "recentf" calstad/persistence-dir))

Bookmarks

(setq bookmark-default-file (expand-file-name "bookmarks" calstad/persistence-dir))

URL Cache, Cookies, and History

(setq url-configuration-directory (expand-file-name "url/" calstad/persistence-dir))

Tramp Connections

(setq tramp-persistency-file-name (expand-file-name "tramp" calstad/persistence-dir))

Forget backup and temporary files

Dont create backup or temporary files

(setq make-backup-files nil
      backup-directory-alist `((".*" . ,temporary-file-directory))
      auto-save-file-name-transforms `((".*" ,temporary-file-directory t))
      auto-save-list-file-prefix nil)

System Specific Configuration

Mac OS X

Set meta to apple key

(setq mac-command-modifier 'meta)

Set font

(if window-system
    (setq default-frame-alist '((font . "-*-Monaco-medium-r-normal--15-0-72-72-m-0-iso10646-1"))))

Setup path for GUI emacs

(use-package exec-path-from-shell
  :config (exec-path-from-shell-initialize))

Fix Native Compiliation

(when (eq system-type 'darwin) (customize-set-variable 'native-comp-driver-options '("-Wl,-w")))

Mode and Language Specific Configuration

All the Icons

(use-package all-the-icons)

Anki

(use-package anki-editor
  :straight (anki-editor :type git :host github :repo "anki-editor/anki-editor")
  :after org-noter
  :config
  (setq anki-editor-create-decks 't))

Company

company-mode is a text completion framework for Emacs. The name stands for “complete anything”. It uses pluggable back-ends and front-ends to retrieve and display completion candidates.

(use-package company
  :bind (("<C-return>" . company-complete)
         :map company-active-map ("M-d" . company-show-doc-buffer))
  :init (add-hook 'after-init-hook 'global-company-mode))

Dired

Use a to reuse dired buffer

The command dired-find-alternate-file is disabled by default so we enable it which allows us to use the a key to reuse the current dired buffer

(put 'dired-find-alternate-file 'disabled nil)

Human readable file sizes

(setq dired-listing-switches "-alh")

Docker

(use-package dockerfile-mode)

Eglot

Emacs Polyglot is a LSP client for Emacs.

;; (use-package eglot)

Emacs Lisp

Add hooks for navigation and documentation

(use-package elisp-slime-nav
  :init
  (dolist (hook '(emacs-lisp-mode-hook ielm-mode-hook))
    (add-hook hook 'turn-on-elisp-slime-nav-mode)))

(use-package paredit
  :init
  (add-hook 'emacs-lisp-mode-hook 'enable-paredit-mode))

(add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)

Key bindings

(define-key read-expression-map (kbd "TAB") 'lisp-complete-symbol)
(define-key lisp-mode-shared-map (kbd "RET") 'reindent-then-newline-and-indent)

Eshell

Start eshell or switch to it if it’s active.

(global-set-key (kbd "C-x m") 'eshell)

Start a new eshell even if one is active.

(global-set-key (kbd "C-x M")
                (lambda ()
                  (interactive)
                  (eshell t)))

Save eshell persistence files out of the way

(setq eshell-directory-name (expand-file-name "eshell/" calstad/persistence-dir))

Env Files

Major mode for editing .env files, which are used for storing environment variables.

(use-package dotenv-mode
  :mode "\\.env\\..*\\'")

Helm

Helm is an Emacs framework for incremental completions and narrowing selections. There is a good tutorial here and the wiki is also very helpful. The old ido and smex configuration can be found at commit 667cbdc.

(use-package helm
  :bind (("M-x" . helm-M-x)
         ("C-x C-f" . helm-find-files)
         ("C-x b" . helm-mini)
         ("C-s" . helm-occur)
         ("C-x r b" . helm-filtered-bookmarks))
  :custom
  (helm-move-to-line-cycle-in-source nil)
  :config
  (helm-mode 1)
  (helm-autoresize-mode 1))

Helm BibTex

Helm-bibtex is a Helm interface for managing BibTex bibliographies.

(use-package helm-bibtex
  :straight (helm-bibtex :type git :host github :repo "calstad/helm-bibtex")
  :custom
  (bibtex-completion-bibliography calstad/lib-bib)
  (bibtex-completion-library-path calstad/lib-docs)
  (bibtex-completion-pdf-symbol "")
  (bibtex-completion-notes-symbol "")
  (bibtex-completion-additional-search-fields '(keywords)))

Sort BibTex entries in order they are in the BibTex file

(advice-add 'bibtex-completion-candidates
            :filter-return 'reverse)

Jupyter

emacs-jupyter is an interface to communicate with Jupyter kernels with built-in REPL and org-mode frontends.

(use-package jupyter)

Latex

AUCTeX

AUCTeX is a comprehensive customizable integrated environment for writing input files for TeX/LaTeX/ConTeXt/Texinfo using Emacs.

(use-package tex
  :straight auctex
  :custom
  ;; Treat environments defined in other packages as math envs
  (TeX-parse-self 't)
  ;; Follow underscores and carets by brackets
  (TeX-electric-sub-and-superscript 't))

CDLaTex

CDLaTex is a minor mode for fast input methods for LaTex environments and math.

(use-package cdlatex
  :init
  (add-hook 'org-mode-hook 'turn-on-org-cdlatex))

Auto pair “$”

(add-hook 'TeX-mode-hook
          #'(lambda ()
              (define-key LaTeX-mode-map (kbd "$") 'self-insert-command)))

Macaulay2

Tell emacs where to find the Macaulay2 elisp files.

(when (file-directory-p "/opt/homebrew/share/emacs/site-lisp/macaulay2")
  (progn
    (add-to-list 'load-path "/opt/homebrew/share/emacs/site-lisp/macaulay2")
    (load "M2-init")))

Disable company-mode in Macaulay2 buffers.

(setq company-global-modes '(not M2-mode))

Remap key binding for evaluating a Macaulay2 buffer.

(eval-after-load 'M2
  '(define-key M2-mode-map (kbd "C-c C-c") 'M2-send-to-program))

org-babel support for Macaulay2

(straight-use-package '(ob-M2 :type git :host github :repo "d-torrance/ob-M2"))

Magit

(use-package magit
  :bind ("C-x g" . magit-status)
  :config
  ;; Keep file revert warning from showing everytime magit starts
  (setq magit-last-seen-setup-instructions "1.4.0"))

Markdown

(use-package markdown-mode)

Olivetti

(use-package olivetti)

Org

org-mode is one of the most powerful and amazing features of Emacs. I use it for task managment, notes, journal, habit tracker, latex, and development environment.

(use-package org
  :bind (("C-c a" . org-agenda)
         ("C-c b" . org-iswitchb)
         ("C-c c" . org-capture)
         ("C-c l" . org-store-link)
         ("C-c i" . org-id-get-create))
  :custom
                                        ; UI
  (org-startup-indented t)
  ;; (org-hide-emphasis-markers t)
  (org-emphasis-alist '(("*" bold)
                        ("/" italic)
                        ("_" underline)
                        ("=" org-verbatim verbatim)
                        ("~" org-code verbatim)
                        ("+" (:strike-through nil))))
  (org-startup-folded t)
                                        ; Behavior
  (org-list-allow-alphabetical t)
  (org-insert-heading-respect-content t)
                                        ; File locations
  (org-archive-location "%s_archive::datetree/")
  (org-id-locations-file (expand-file-name "org-id-locations" calstad/persistence-dir))
  (org-persist-directory (expand-file-name "org-persist" calstad/persistence-dir))
  (org-attach-id-dir (expand-file-name "attachements" calstad/org-dir))
  :hook
  (org-mode . visual-line-mode))

UI

;; (use-package org-modern-mode)
(use-package org-bullets
    :config
    (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))
(custom-theme-set-faces
 'user
 '(variable-pitch ((t (:family "CMU Serif" :height 1.25 :weight thin)))))
;; (let* ((variable-tuple
;;         (cond ((x-list-fonts "ETBembo")         '(:font "ETBembo"))
;;               ((x-list-fonts "Source Sans Pro") '(:font "Source Sans Pro"))
;;               ((x-list-fonts "Lucida Grande")   '(:font "Lucida Grande"))
;;               ((x-list-fonts "Verdana")         '(:font "Verdana"))
;;               ((x-family-fonts "Sans Serif")    '(:family "Sans Serif"))
;;               (nil (warn "Cannot find a Sans Serif Font.  Install Source Sans Pro."))))
;;        (base-font-color     (face-foreground 'default nil 'default))
;;        (headline           `(:inherit default :weight bold :foreground ,base-font-color)))

;;   (custom-theme-set-faces
;;    'user
;;    `(org-level-8 ((t (,@headline ,@variable-tuple))))
;;    `(org-level-7 ((t (,@headline ,@variable-tuple))))
;;    `(org-level-6 ((t (,@headline ,@variable-tuple))))
;;    `(org-level-5 ((t (,@headline ,@variable-tuple))))
;;    `(org-level-4 ((t (,@headline ,@variable-tuple :height 1.1))))
;;    `(org-level-3 ((t (,@headline ,@variable-tuple :height 1.25))))
;;    `(org-level-2 ((t (,@headline ,@variable-tuple :height 1.5))))
;;    `(org-level-1 ((t (,@headline ,@variable-tuple :height 1.75))))
;;    `(org-document-title ((t (,@headline ,@variable-tuple :height 2.0))))))
;; (use-package mixed-pitch)

Agenda

Set where agenda items are pulled from

(setq org-agenda-files (list (expand-file-name "tasks" calstad/org-roam-dir)))

Have todo items with no associated timestamp show up at the top of the agenda view above the time slots instead of below.

(setq org-agenda-sort-notime-is-late nil)

Don’t duplicate a task in the deadline section if it is scheduled

(setq org-agenda-skip-deadline-prewarning-if-scheduled t)

org-agenda-skip-deadline-prewarning-if-scheduled

Default the agenda view to the daily instead of weekly view.

(setq org-agenda-span 'day)

Show breadcrumbs for nested headline todos in the agenda views.

;; (setq org-agenda-prefix-format
;;       '((agenda . " %i %-12:c%?-12t% s")
;;         (timeline . "  % s")
;;         (todo .
;;               " %i %-12:c %(concat \"[ \"(org-format-outline-path (org-get-outline-path)) \" ]\") ")
;;         (tags .
;;               " %i %-12:c %(concat \"[ \"(org-format-outline-path (org-get-outline-path)) \" ]\") ")
;;         (search . " %i %-12:c")))

Configure how the time grid is shown in the daily agenda view

(setq org-agenda-time-grid
      '((daily today require-timed remove-match)
        (700 730 800 830 900 930 1000 1030 1100 1130 1200 1230 1300 1330
             1400 1430 1500 1530 1600 1630 1700 1730 1800 1830 1900 1930
             2000 2030 2100 2130 2200 2230 2300)
        "......" "----------------"))

Remove time slots from the agenda if they fall into the range of one of the agenda items’ timestamps. This code is modified from this StackExchange post.

(defun calstad/org-time-to-minutes (time)
  "Convert an HHMM time to minutes"
  (+ (* (/ time 100) 60) (% time 100)))

(defun calstad/org-time-from-minutes (minutes)
  "Convert a number of minutes to an HHMM time"
  (+ (* (/ minutes 60) 100) (% minutes 60)))

(defun calstad/extract-time-window (line)
  "Gets the start and end times of each block in the agenda"
  (let ((start (get-text-property 1 'time-of-day line))
        (dur (get-text-property 1 'duration line)))
    (cond
     ((and start dur)
      (cons start
            (calstad/org-time-from-minutes
             (truncate
              (+ dur (calstad/org-time-to-minutes start))))))
     (start start)
     (t nil))))

(defun calstad/remove-spanned-time-slots (orig-fun &rest args)
  "Removes time slots that fall within a scheduled block"
  (let* ((list (car args))
         (windows (delq nil (mapcar 'calstad/extract-time-window list)))
         (org-agenda-time-grid
          (list
           (car org-agenda-time-grid)
           (cl-remove-if
            (lambda (time)
              (cl-find-if (lambda (w)
                            (if (numberp w)
                                (equal w time)
                              (and (>= time (car w))
                                   (< time (cdr w)))))
                          windows))
            (cadr org-agenda-time-grid) )
           (caddr org-agenda-time-grid)
           (cadddr org-agenda-time-grid)
           ))
         (res (apply orig-fun args)))
    res))

(advice-add 'org-agenda-add-time-grid-maybe :around #'calstad/remove-spanned-time-slots)

Change the agenda sort order to implement time block planning. The idea for this came from this StackExchange thread.

(setq org-agenda-sorting-strategy '((agenda habit-down time-up ts-down
                                            priority-down category-keep)
                                    (todo priority-down category-keep)
                                    (tags priority-down category-keep)
                                    (search category-keep)))

Todo Items

Todo States
(setq org-todo-keywords
      '((sequence "TODO(t)" "IN-PROGRESS(p)" "WAITING(w@/!)" "|" "DONE(d!)" "CANCELLED(c@)")))

Log state changes into a property drawer

(setq org-log-into-drawer t)

Add a CLOSED timestamp to todo items

(setq org-log-done t)

Add ability to bulk remove todo keywords from the agenda view, which is useful when I don’t want the tasks to be moved to an archive file, but also don’t want them junking up the DONE view. Code taken from this stackexchange post.

(setq org-agenda-bulk-custom-functions '((?R (lambda nil (org-agenda-todo "")))))
Enable Inline Tasks
(require 'org-inlinetask)
(setq org-inlinetask-min-level 10)
Enable Habit Tracking
(add-to-list 'org-modules 'org-habit)
Reset Checkboxes for Repeating Tasks

The code below was taken from this StackExchange post.

(defun calstad/org-reset-checkbox-state-maybe ()
  "Reset all checkboxes in an entry if the `RESET_CHECK_BOXES' property is set"
  (interactive "*")
  (if (org-entry-get (point) "RESET_CHECK_BOXES")
      (org-reset-checkbox-state-subtree)))

(defun calstad/org-reset-checkbox-when-done ()
  (when (member org-state org-done-keywords)
    (calstad/org-reset-checkbox-state-maybe)))

(add-hook 'org-after-todo-state-change-hook 'calstad/org-reset-checkbox-when-done)

org-crypt

org-crypt is used for encrypting the text of headline.

(require 'org-crypt)
(org-crypt-use-before-save-magic)
(setq org-tags-exclude-from-inheritance (quote ("crypt")))
(setq org-crypt-key "me@colinalstad.com")

org-ref

Org-ref is a library for org-mode that provides rich support for citations, labels, and cross-references in org-mode.

(use-package org-ref
  :custom
  (org-ref-insert-link-function 'org-ref-insert-link-hydra/body)
  (org-ref-insert-cite-function 'org-ref-cite-insert-helm)
  (org-ref-insert-label-function 'org-ref-insert-label-link)
  (org-ref-insert-ref-function 'org-ref-insert-ref-link)
  (org-ref-cite-onclick-function (lambda (_) (org-ref-citation-hydra/body)))
  (org-ref-latex-bib-resolve-func #'expand-file-name)
  (org-ref-clean-bibtex-entry-hook '(org-ref-bibtex-format-url-if-doi
                                     orcb-key-comma
                                     org-ref-replace-nonascii
                                     orcb-&
                                     orcb-%
                                     org-ref-title-case-article
                                     orcb-clean-year
                                     orcb-key
                                     orcb-clean-doi
                                     orcb-clean-pages
                                     org-ref-sort-bibtex-entry
                                     orcb-fix-spacing
                                     orcb-download-pdf))
  :bind
  ("<f6>" . org-ref-cite-insert-helm)
  (:map org-mode-map
        ("C-c ]" . org-ref-insert-link-hydra/body)))
(require 'org-ref-helm)

Update the color of org-ref cite links to be the same as other org-mod links instead of white.

;; (set-face-foreground
;;  'org-ref-cite-face
;;  (cdr (assoc "zenburn-yellow-2" zenburn-default-colors-alist)))

org-roam

(use-package emacsql-sqlite3)

(use-package org-roam
  :straight (:host github :repo "org-roam/org-roam"
                   :files (:defaults "extensions/*"))
  :custom
  (org-roam-v2-ack t)
  (org-roam-directory (file-truename calstad/org-roam-dir))
  (org-roam-database-connector 'sqlite3)
  (org-roam-db-location (expand-file-name "org-roam.db" calstad/persistence-dir))
  (org-roam-mode-sections
   (list #'org-roam-backlinks-section
         #'org-roam-reflinks-section
         ;; #'org-roam-unlinked-references-section
         ))
  (org-roam-capture-templates
   '(("d" "default" plain "%?"
      :if-new (file+head "evergreen/%<%Y%m%d%H%M%S%2N>.org"
                         "#+TITLE: ${title}\n")
      :unnarrowed t)
     ("b" "bibliography reference" plain "%?"
      :if-new (file+head "reference/%<%Y%m%d%H%M%S%2N>.org"
                         "#+TITLE: ${title}
#+AUTHOR: ${author-or-editor}

* Notes
:PROPERTIES:
:CUSTOM_ID: ${citekey}
:AUTHOR: ${author-or-editor}
:NOTER_DOCUMENT: %(orb-process-file-field \"${citekey}\")
:NOTER_PAGE:
:END:")
      :unnarrowed t)))
  (org-roam-capture-ref-templates
   '(("r" "ref" plain "%?" :target
     (file+head "reference/%<%Y%m%d%H%M%S%2N>.org" "#+TITLE: ${title}")
     :unnarrowed t)))

  :bind (("C-c n l" . org-roam-buffer-toggle)
         ("C-c n f" . org-roam-node-find)
         ("C-c n g" . org-roam-graph)
         ("C-c n i" . org-roam-node-insert)
         ("C-c n c" . org-roam-capture))
  :config
  (require 'org-roam-protocol)
  (org-roam-db-autosync-mode)

  (cl-defmethod org-roam-node-doom-filetitle ((node org-roam-node))
    "Return the value of \"#+title:\" (if any) from file that NODE resides in.
If there's no file-level title in the file, return empty string."
    (or (if (= (org-roam-node-level node) 0)
            (org-roam-node-title node)
          (org-roam-get-keyword "TITLE" (org-roam-node-file node)))
        ""))

(cl-defmethod org-roam-node-doom-hierarchy ((node org-roam-node))
  "Return hierarchy for NODE, constructed of its file title, OLP and direct title.
  If some elements are missing, they will be stripped out."
  (let ((title     (org-roam-node-title node))
        (olp       (org-roam-node-olp   node))
        (level     (org-roam-node-level node))
        (filetitle (org-roam-node-doom-filetitle node))
        (separator (propertize " > " 'face 'shadow)))
    (cl-case level
      ;; node is a top-level file
      (0 filetitle)
      ;; node is a level 1 heading
      (1 (concat (propertize filetitle 'face '(shadow italic))
                 separator title))
      ;; node is a heading with an arbitrary outline path
      (t (concat (propertize filetitle 'face '(shadow italic))
                 separator (propertize (string-join olp " > ") 'face '(shadow italic))
                 separator title)))))

  ;; (cl-defmethod org-roam-node-hierarchy ((node org-roam-node))
  ;;   "Return the hierarchy for the node."
  ;;   (let* ((title (org-roam-node-title node))
  ;;          (olp (mapcar (lambda (s) (if (> (length s) 10) (concat (substring s 0 10)  "…") s)) (org-roam-node-olp node)))
  ;;          (level (org-roam-node-level node))
  ;;          (filetitle (org-roam-node-file-title node))
  ;;          (shortentitle (if (> (length filetitle) 20) (concat (substring filetitle 0 20)  "...") filetitle))
  ;;          (separator (concat " " (all-the-icons-material "chevron_right") " "))
  ;;          )
  ;;     (cond
  ;;      ((>= level 1) (concat (all-the-icons-material "list" :face 'all-the-icons-green :v-adjust 0.02 :height 0.8) " "
  ;;                            (propertize shortentitle 'face 'org-roam-dim)
  ;;                            (propertize separator 'face 'org-roam-dim)
  ;;                            title))
  ;;      ((> level 1) (concat (all-the-icons-material "list" :face 'all-the-icons-dpurple :v-adjust 0.02 :height 0.8)
  ;;                           " "
  ;;                           (propertize (concat shortentitle separator (string-join olp separator)) 'face 'org-roam-dim)
  ;;                           (propertize separator 'face 'org-roam-dim)
  ;;                           title))
  ;;      (t (concat (all-the-icons-faicon "file-text-o" :face 'all-the-icons-lyellow :v-adjust 0.02 :height 0.7) " " title))
  ;;      )
;;     ))

(cl-defmethod org-roam-node-category ((node org-roam-node))
  "Return the currently set category for the NODE."
  (cdr (assoc-string "CATEGORY" (org-roam-node-properties node))))

(setq org-roam-node-display-template
      "${doom-hierarchy:*} ${category:10} ${tags:10}"))

org-roam-ui

org-roam-ui is a frontend for exploring and interacting with org-roam notes.

(use-package org-roam-ui
  :straight
  (:host github :repo "org-roam/org-roam-ui" :branch "main" :files ("*.el" "out"))
  :after org-roam
  :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))

org-roam-bibtex

(use-package org-roam-bibtex
  :after org-roam
  :demand t
  :hook (org-roam-mode . org-roam-bibtex-mode)
  :custom
  (orb-insert-interface 'helm-bibtex)
  (orb-note-actions-interface 'helm)
  (orb-roam-ref-format 'org-ref-v3)
  (orb-preformat-keywords
   '(("citekey" . "=key=") "file" "author-or-editor" "year"))
  :bind (("C-c n r" . orb-insert-link))
  :config
  (require 'org-ref)
  (org-roam-bibtex-mode))

org-journal

org-journal is a package to maintain a simple personal diary / journal using org-mode.

(defun calstad/insert-journal-body ()
  (save-excursion
    (goto-char (point-max))
    (insert "\n** Time Block Plan\n** Journal\n")))

(use-package org-journal
  :bind
  ("C-c n j" . org-journal-new-entry)
  ("C-c n J" . org-journal-new-scheduled-entry)
  :custom
  (org-journal-file-format "%Y%m%d_week_%V.org")
  (org-journal-dir (expand-file-name "journal" calstad/org-roam-dir))
  (org-journal-enable-cache t)
  (org-journal-enable-agenda-integration t)
  (org-journal-file-type 'weekly)
  (org-journal-file-header "#+CATEGORY: journal\n#+TITLE: %Y - Week %W")
  (org-journal-time-prefix "*** ")
  :config
  (setq org-journal--cache-file (expand-file-name "org-journal.cache" calstad/persistence-dir))
  :init
  (add-hook 'org-journal-after-header-create-hook #'calstad/insert-journal-body)
  )

org-noter

(use-package org-noter
  :custom
  (org-noter-doc-property-in-notes t)
  (org-noter-always-create-frame nil)
  (org-noter-auto-save-last-location t))

elfeed-org

(use-package elfeed-org
  :custom
  (rmh-elfeed-org-files
   (list (expand-file-name "feeds.org" calstad/org-dir)))
  :config
  (elfeed-org))

org-chef

org-chef is a package for managing recipes in org-mode. One of the main features is that it can automatically extract recipes from websites like allrecipes.com

(use-package org-chef)

Capture

(setq org-default-notes-file (expand-file-name "roam/tasks/inbox.org" calstad/org-dir))
(setq org-capture-templates
      '(("c" "OrgProtocol capture" entry (file+headline org-default-notes-file "Links")
         "* [[%:link][%:description]]\n%i"
         :immediate-finish t)
        ("t" "Task" entry (file+headline org-default-notes-file "Tasks")
         "* TODO %i%?")))

Refile

(setq org-refile-targets '((nil :maxlevel . 3)
                           (org-agenda-files :maxlevel . 3)))
(setq org-outline-path-complete-in-steps nil)         ; Refile in a single go
(setq org-refile-use-outline-path t)                  ; Show full paths for refiling


(defun calstad/verify-refile-target ()
  "Exclude task headings from refile target list"
  (or (not (member (nth 2 (org-heading-components)) org-todo-keywords)))
  (save-excursion (org-goto-first-child)))

(setq org-refile-target-verify-function 'calstad/verify-refile-target)

LaTeX

Highlight LaTeX source in org documents

(setq org-highlight-latex-and-related '(latex entites))

Use this tip to increase the scale of inline LaTeX images

(plist-put org-format-latex-options :scale 1.5)

Save all LaTeX preview images in the same temp directory.

(setq org-preview-latex-image-directory "/tmp/org_latex_prevs/")

Automatically preview LaTeX when opening an org-mode file.

;; (setq org-startup-with-latex-preview t)

Automatically toggle LaTeX fragments when the cursor enters/leaves a fragment.

(use-package org-fragtog
  :custom
  (org-fragtog-preview-delay 0.5)
  :hook
  (org-mode . org-fragtog-mode))

Load these LaTeX packages by default in all org-mode documents.

(add-to-list 'org-latex-packages-alist '("" "amsthm" t))
(add-to-list 'org-latex-packages-alist '("" "tikz-cd" t))
(setq org-preview-latex-default-process 'imagemagick)

Don’t treat angle brackets as matching delimiters like parenthesis. Code taken from this stackexchange thread.

(defun org-syntax-table-modify ()
  "Modify `org-mode-syntax-table' for the current org buffer."
  (modify-syntax-entry ?< "." org-mode-syntax-table)
  (modify-syntax-entry ?> "." org-mode-syntax-table))

(add-hook 'org-mode-hook #'org-syntax-table-modify)

org-babel

Babel is Org-mode’s ability to execute source code within Org-mode documents.

Language Support
(org-babel-do-load-languages
 'org-babel-load-languages
 '((emacs-lisp . t)
   (shell . t)
   (latex . t)
   (M2 . t)
   (python . t)
   (jupyter . t)))

(use-package ob-sagemath
  :custom
  (org-babel-default-header-args:sage '((:session . t)
                                        (:results . "output"))))
Syntax highlighting for code blocks
(setq org-src-fontify-natively t)
Don’t confirm executing source blocks
(setq org-confirm-babel-evaluate nil)
Tangle Source Blocks

According to this reddit post, this needs to be done to allow setting :tangle no as a header-args property for sub-headings.

(setq org-use-property-inheritance t)
Inline Images

Display images generated by source blocks.

(setq org-startup-with-inline-images t)
(add-hook 'org-babel-after-execute-hook 'org-redisplay-inline-images)

Importing

org-pandoc-import converts all types of buffers to org-mode buffers so I never have to leave org-mode!

(use-package org-pandoc-import
  :straight (:host github
                   :repo "tecosaur/org-pandoc-import"
                   :files ("*.el" "filters" "preprocessors")))

Exporting

Only export “ab” as a subscript instead of “a_b”.

(setq org-export-with-sub-superscripts '{})
Beamer

Have earmuffs be bold like normal instead of alert.

(defun calstad/beamer-bold (contents backend info)
  (when (eq backend 'beamer)
    (replace-regexp-in-string "\\`\\\\[A-Za-z0-9]+" "\\\\textbf" contents)))
(add-to-list 'org-export-filter-bold-functions 'calstad/beamer-bold)
LaTex

Define the command to use for creating PDFs

;; (setq org-latex-pdf-process '("latexmk -pdflatex='%latex -shell-escape -bibtex -interaction nonstopmode' -pdf -output-directory=%o -f %f"))
;; (setq org-latex-pdf-process (list "latexmk -shell-escape -bibtex -output-directory=%o -cd -f -pdf %f"))
;; (setq org-latex-pdf-process (quote ("texi2dvi -p -b -V %f")))
(setq org-latex-pdf-process (list "latexmk -pdflatex='%latex -shell-escape -bibtex -interaction nonstopmode' -pdf -output-directory=%o %f"))

Use the tabularx package for exporting org-mode tables

(add-to-list 'org-latex-packages-alist '("" "tabularx"))
Markdown
GitHub Flavor

This package allows for GitHub flavored markdown

(use-package ox-gfm
  :after ox)
Hugo Flavor

This package allows for exporting org-mode to Hugo flavored markdown

(use-package ox-hugo
  :after ox)
Pandoc

ox-pandoc is an org-mode exporter backend that utilizes pandoc for exporting to multiple formats.

(use-package ox-pandoc
  :after ox)

External Applications

Tell org-mode to open certain file types using an external application.

(mapcar
 (lambda (file-type) (add-to-list 'org-file-apps file-type :append))
 '(("\\.docx" . default)
   ("\\.pptx" . default)))

Saving Org Buffers

Use advice to save all the current org-mode buffers before/certain actions are taken.

(setq calstad/org-save-funcs
      '((:before . (org-agenda-quit))
        (:after . (org-todo
                   org-store-log-note
                   org-deadline
                   org-schedule
                   org-time-stamp
                   org-refile
                   org-archive-subtree))))

In order to apply the advice to save all org-mode buffers to interactivce functions, we need all to allow the save function to take arbitrary arguments. See this SO answer for more details.

(defun calstad/org-save-all-org-buffers (&rest _ignore)
  "Apply `org-save-all-org-buffers' ignoring all arguments."
  (org-save-all-org-buffers))

Now we use our custom save function to advise the previously specified org-mode functions.

(defun calstad/advise-org-funcs (org-func-alist)
  (mapcar
   (lambda (elem)
     (let ((action (car elem))
           (org-funcs (cdr elem)))
       (mapcar (lambda (org-func)
                 (advice-add org-func action 'calstad/org-save-all-org-buffers))
               org-funcs)))
   org-func-alist))

(calstad/advise-org-funcs calstad/org-save-funcs)

Save buffers after capture has finished

(add-hook 'org-capture-after-finalize-hook 'org-save-all-org-buffers)

PDF Tools

PDF Tools is, among other things, a replacement of DocView for PDF files. The key difference is that pages are not pre-rendered by e.g. ghostscript and stored in the file-system, but rather created on-demand and stored in memory.

(use-package pdf-tools
  :straight (pdf-tools :type git :host github :repo "vedang/pdf-tools")
  :mode ("\\.pdf\\'" . pdf-view-mode)
  :config (pdf-tools-install)
  :custom (pdf-view-continuous nil))

Pyvenv

Use pyvenv to manage python and conda virtual environments.

(setenv "WORKON_HOME" "/usr/local/Caskroom/miniforge/base/envs")
(use-package pyvenv
  :config
  (pyvenv-mode 1))

Rest Client

Restclient is a major mode for exploring HTTP REST web services.

(use-package restclient
  :mode ("\\.http\\'" . restclient-mode))

SageMath

Sage is an open source mathematics software system that wraps a lot of different math packages.

(use-package sage-shell-mode
  :custom
  (sage-shell:sage-executable "/usr/local/bin/sage"))

YAML

(use-package yaml-mode)

YASnippet

yasnippet is a template system for Emacs that allows type an abbreviation and automatically expand it into function templates.

Load yasnippet on programming langauge major modes.

(use-package yasnippet
  :config
  (setq yas-snippet-dirs '("~/.emacs.d/snippets"))
  (yas-global-mode 1))

Emacs Server

Start the emacs server so that clients can connect

(server-start)
(require 'org-protocol)

About

My personal dot-emacs

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published