Files
EmacsConfig/main.org
2025-09-04 15:42:37 -04:00

19 KiB

Universe Emacs Config

Initialization

Straight.el

Package management to be a little more fien/precise and work outside of Nix (as much as it would be nice to work inside of Nix too). This is actually contained within init.el

(defvar bootstrap-version)
(let ((bootstrap-file
       (expand-file-name
        "straight/repos/straight.el/bootstrap.el"
        (or (bound-and-true-p straight-base-dir)
            user-emacs-directory)))
      (bootstrap-version 7))
  (unless (file-exists-p bootstrap-file)
    (with-current-buffer
        (url-retrieve-synchronously
         "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
         'silent 'inhibit-cookies)
      (goto-char (point-max))
      (eval-print-last-sexp)))
  (load bootstrap-file nil 'nomessage))

This code block actually resides in init.el (so that we can perform some necessary pre-configuration)

Leaf.el

We must initialize leaf.el, which we use as a use-package replacement for defining configs and relations between packages etc.

  (eval-and-compile
    (straight-use-package 'leaf)

    (leaf leaf-keywords
      :init
      (straight-use-package 'leaf-keywords)
      :custom
      (leaf-alias-keyword-alist .'((:ensure . :straight)))
      :config
      ;; initialize leaf-keywords.el
      (leaf-keywords-init)))

  (leaf leaf-tree :ensure t)
  (leaf leaf-convert :ensure t)
  (leaf transient-dwim :ensure t
    :require t ;; Needed so that org-roam may unobstructively depend on this
    :bind (("M-=" . transient-dwim-dispatch)))

MacOS Specific

(leaf macos
  :hook (after-init hook)
  :when (eq system-type 'darwin)
  :init
  (setq mac-option-modifier 'meta))

Performance

Garbage Collection

This makes the garbage collection thresholds variable based on emacs usage. I don't know how well this plays with LSPs or similarly RAM hungry features. This was useful when I used a very restricted netbook w/ ~2GiB of RAM.

Disabled for now. (May add flags to enable on specific systems)

; (leaf gcmh :ensure t
;  :hook (after-init-hook))

Profiling

(leaf esup :disabled nil :ensure t)

Emacs Paths

Custom.el

Ensure that the custom.el resides in the users' emacs directory.

(leaf custom-el
  :leaf-defer nil
  :config
  ;; Ensure custom writes to specific file
  (setq custom-file (expand-file-name "custom.el" user-emacs-directory))
  (load custom-file 'noerror 'nomessage))

Backups

Set the backups directory to reside in the users' emacs directory.

(leaf backup
  :leaf-defer nil
  :config
  ;; Change the location of file backups/locks into the emacs.d/backups/
  (setq backup-directory-alist
	`(("." . ,(concat user-emacs-directory "backups")))))

Shell Path Preservation

Exec-path-from-shell ensures that path variable is preserved from shell.

(leaf exec-path-from-shell :ensure t
  :config
  (exec-path-from-shell-initialize))

Visual Customization

Visual Theme of Emacs config: defined in the themes directory.

(leaf visual
  :leaf-defer nil
  :doc "Visual Changes to Emacs"
  :tag "builtin" "internal"
  :custom ((menu-bar-mode . nil)
	   (tool-bar-mode . nil)
	   (scroll-bar-mode . nil))
  :custom-face ((default . '((t (:family "JuliaMono"
					 :height 150
					 :weight normal)))))
  :config
  ;; Set location of custom theme dir
  (setq custom-theme-directory (concat user-emacs-directory "themes"))
  (load-theme 'UniverseHighContrast))

Version Control

(leaf magit
  :leaf-defer nil
  :ensure t :require t)

Nix Related

Direnv

In order to support direnv (loading nix-shell / nix develop)

(leaf direnv
  :ensure t
  :global-minor-mode direnv-mode)

Nix-mode

.nix file mode

(leaf nix-mode
  :ensure t
  :mode "\\.nix\\'")

IDE Like Things

Which Key Again?

(leaf which-key
  :ensure t
  :global-minor-mode which-key-mode)

Company Completion!

We like autocomplete, it… is nice, okay?

(leaf company :ensure t
  :bind
  (("C-<tab>" . company-complete))
  :hook after-init-hook
  :global-minor-mode global-company-mode)

Language Server Protocol

We love language features that make languages nice

(leaf lsp-mode
  :ensure t
  :init
  (setq lsp-keymap-prefix "C-c l")
  :commands lsp lsp-deferred
  :hook (
  ;; which key support v v v
  (lsp-mode-hook . lsp-enable-which-key-integration)

IDE Languages

Dart/Flutter
(dart-mode . lsp-deferred)
Python
(python-mode . lsp-deferred)
C/C++
(c-mode-hook . lsp-deferred)
(c++-mode-hook . lsp-deferred)
Haskell
(haskell-mode-hook . lsp-deferred)
Java
(java-mode-hook . lsp-deferred)
Rust
(rust-mode-hook . lsp-deferred)
)

LSP Plugins:

We do want some nice to haves of course

:init
  • A pretty UI:
(leaf lsp-ui :ensure t
  :commands lsp-ui-mode)
  • Flycheck compat:
(leaf flycheck :ensure t)
  • Debugger Compatibility
(leaf dap-mode :ensure t)

Projectile (Projects)

(leaf projectile
  :commands projectile-mode
  :config
  (projectile-mode +1))

END LSP CONFIG

)

WEB

We all know the web is the future, obviously, of course.

(leaf web-mode
  :ensure t
  :mode
  "\\.p?html?\\'"
  "\\.djtml\\'"
  "\\.jsx?\\'"
  "\\.tsx?\\'")
(leaf php-mode
  :mode "\\.php\\'"
  :ensure t)
(leaf rainbow-mode
  :leaf-defer nil
  :ensure t)

D2

(leaf d2-mode
  :ensure t
  :mode "\\.d2\\'"
  )

YAML

(leaf yaml-mode
  :ensure t
  :mode "\\.yaml\\'"
  )

Python Things

Python-mode

Using python-mode is to have more up to date features (and highlighting) compared to builtin python-mode.

(leaf python-mode
  :ensure t
  :mode "\\.py\\'"
  :config
  (setq python-shell-interpreter "ipython"
	python-shell-interpreter-args "-i --simple-prompt --InteractiveShell.display_page=True"))

Poetry

For when we aren't nix'ing things, and want some nice poetry.

(leaf poetry :ensure t)

C

Who even needs C++, not me, no way, no how.

(leaf c-config
  :config
;  (leaf company-ctags :ensure t
;      :hook c-mode-hook c++-mode-hook)
;  (leaf company-c-headers :ensure t
;      :hook c-mode-hook c++-mode-hook)
;  (leaf meson-mode :ensure t
;      :hook c-mode-hook c++-mode-hook)
  )

Haskell

(leaf haskell-mode
  :ensure t
  :mode "\\.hs\\'"
  :init
  (leaf lsp-haskell :ensure t)
  (leaf company-ghci :ensure t))

Rust

(leaf rust-mode :ensure t
  :mode "\\.rs\\'"
  :init
  (leaf slint-mode :ensure t))

Minecraft??

Minecraft mcfunction support, because, it can be annoying to type this stuff otherwise.

(leaf mcf-mode
  :straight (mcf-mode :type git :host github :repo "rasensuihei/mcf"))

Lisps

Gonna need to have pretty brackets

(leaf rainbow-delimiters
  :ensure t
  :commands rainbow-delimiters-mode
  :config
  (leaf rainbow
    :hook (emacs-lisp-mode-hook . rainbow-delimiters-mode)
    (geiser-mode-hook . rainbow-delimiters-mode)))

Racket

Makes using racket so much nicer

(leaf geiser-racket :ensure t)

Clojure

For using clojure, we use both clojure-mode and for REPL we use CIDER.

(leaf clojure-mode :ensure t cider)

Org

We ensure that org is available (though it is builtin)

For Version compatibility we actually install org in init.el (to not conflict with the builtin version of Org)

(leaf org
  :require t org-tempo
  :hook
  (org-mode-hook . auto-fill-mode)
  :config
  (setq document-dir (expand-file-name (if (eq system-type 'darwin) "~/Nextcloud" "~/Documents")))
  (setq org-directory (concat document-dir "/org"))
  (when (not (file-exists-p org-directory)) (mkdir org-directory))
  (set-fill-column 100)
  (setq org-src-fontify-natively t
  	org-confirm-babel-evaluate nil
  	org-src-preserve-indentation t))
;; (tempo-define-template "Fig. Caption"
;; 			   '("" (P "Image: " image t)
;; 			     (P "Caption: " caption t)
;; 			     (P "Figure Name: " name t)
;; 			     "#+CAPTION: " (s caption) > n >
;; 			     "#+NAME: fig:" (s name) > n >
;; 			     "#+ATTR_LaTeX: :placement [H]" > n >
;; 			     "[[" (s image) "]]" > n > p >)
;; 			   "<fig" "Inserts Figure with Caption"))

We also want to set our document directory (which as it stands is OS dependent)

Citations/References

We use org-ref because it provides some niceties, like doi-utils for updating our bibliography.

(leaf org-ref :ensure t helm-bibtex pdf-tools
  :after org
  :bind*
  ("C-c ]" . org-ref-insert-link)
  :config
  (setq org-bib-dir (concat document-dir "/Bibliography"))
  (setq org-bib-file (concat org-bib-dir "/references.bib"))
  ;; Where should PDFs be stored
  (setq bibtex-completion-library-path `(,(concat org-bib-dir "/bibtex-pdfs/"))
	;; Where is the bibliography expected (org-ref & org-cite)
	bibtex-completion-bibliography (list org-bib-file)
	org-cite-global-bibliography (list org-bib-file)

	bibtex-completion-notes-path (concat org-bib-dir "/notes")
	bibtex-completion-notes-template-multiple-files "* ${author-or-editor}, ${title}, ${journal}, (${year}) :${=type=}: \n\nSee [[cite:&${=key=}]]\n"

	bibtex-completion-additional-search-fields '(keywords)
	bibtex-completion-display-formats
	'((article       . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} ${journal:40}")
	  (inbook        . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} Chapter ${chapter:32}")
	  (incollection  . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} ${booktitle:40}")
	  (inproceedings . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} ${booktitle:40}")
	  (t             . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*}"))
	bibtex-completion-pdf-open-function
	(lambda (fpath)
	  (call-process "open" nil 0 nil fpath)))
  ;; For bibtex generated keys (in-org citation format)
  (setq bibtex-autokey-year-length 4
	bibtex-autokey-name-year-separator "-"
	bibtex-autokey-year-title-separator "-"
	bibtex-autokey-titleword-separator "-"
	bibtex-autokey-titlewords 2
	bibtex-autokey-titlewords-stretch 1
	bibtex-autokey-titleword-length 5)
  (add-to-list 'org-export-before-parsing-functions 'org-ref-csl-preprocess-buffer)
  (add-to-list 'org-export-before-parsing-functions 'org-ref-refproc)
  :require org-ref org-ref-helm oc-bibtex oc-bibtex oc-csl oc-natbib org-ref-refproc)

Extra Export Options

LaTeX (Obviously)

We really do require latex

(leaf ox-latex :require t
  :after org
  :config
  (add-to-list 'org-latex-packages-alist '("" "minted"))
  (setq org-latex-listings 'minted) 
  (setq org-latex-prefer-user-labels t)
  (add-to-list 'org-latex-classes
  	       '("labtemplate" "\\documentclass{labtemplate}"
  		 ("\\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
  	       '("thesis" "\\documentclass[11pt]{ut-thesis}"
  		 ("\\part{%s}" . "\\part*{%s}")
  		 ("\\chapter{%s}" . "\\chapter*{%s}")
  		 ("\\section{%s}" . "\\section*{%s}")
  		 ("\\subsection{%s}" . "\\subsection*{%s}")
  		 ("\\subsubsection{%s}" . "\\subsubsection*{%s}"))))

HTML Export

(leaf ox-html
  :after org
  :config
  (setq org-html-head "
<style type=\"text/css\">
  pre.src {
      background-color: #000;
      color: #ccc;
      border-radius: 2ch;
  }
  pre.src:before {
      background-color: #ccc;
      color: #000;
      border-radius: 0.5ch;
  }
</style>
"))

Pandoc the Panacea of Exports

For more export formats we use pandoc:

(leaf ox-pandoc :ensure t :require t
  :after org)

Slideshows

Web based (reveal)

Writing mockup presentations can be quicker when you focus on the text of the presentation first, and prettifying later. Reveal.js is a nice in between of these.

(leaf ox-reveal :ensure t :require t
  :config
  (setq org-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js"))

LaTeX: with AuCTeX

Nicer LaTeX editing (AuCTeX):

(leaf auctex :ensure t
  :after org)

We also ma(k|d)e use of org-tempo for templating things, which can be nice. Should use the export based templating probably. Eventually.

And in case we want to make some (GNU)?plots?

(leaf gnuplot
  :ensure t)

Org Mode Agenda/Calendar Things

Agenda Location

Make it so that all files in the "

org-agenda-files
" variable (e.g. "~/Documents") will be included in the tablutation and collation of all the dates and todos etc.

(leaf org-agenda
  :after org
  :config
  (setq org-agenda-files `(,(concat org-directory))))

Capture Things

Unless specified otherwise, any captured note, date, meeting, idea, should be put into the

org-directory
.

Similarly, we have a default file for notes that we capture, in there note.org, which is where all captured things go when they aren't told to go elsewhere.

(leaf org-capture
  :after org
  :config
  (setq org-default-notes-file (concat org-directory "/notes.org")))

We also want to configure what type of things we want to capture, e.g. meetings, deadlines and whatever else:

(leaf org-capture
  :after org-capture
  :config
  (add-hook 'org-capture-mode-hook #'org-id-get-create)
  (setq org-capture-templates
	'(("t" "Todo" entry (file+headline "todos.org" "Tasks")
	   "* TODO %^{Todo?} %^G\nSCHEDULED: %^t\n:PROPERTIES:\n:ADDED: %U\n:END:\n  %i\n  %a \n%?\n")
	  ("h" "Habit" entry (file+headline "todos.org" "Habits")
	   "* TODO %^{Habit} %^G\nSCHEDULED: %^T\n:PROPERTIES:\n:STYLE: habit\n:ADDED: %U\n:END:\n%?\n")
	  ("j" "Journal" entry (file+datetree "journal.org")
	   "* %^{Journal Entry:} %^G\nEntered on %U\n  %i\n:PROPERTIES:\n:ADDED: %U\n:END:\n  %a\n%?\n")
	  ("m" "Meeting" entry (file+headline "dates.org" "Meetings")
	   "* %^{Meeting Title:} %^G\nSCHEDULED: %^t\n:PROPERTIES:\n:CATEGORY: Meeting\n:LOCATION: %^{LOCATION}\n:ADDED: %U\n:END:\n%?\n"))))

Habits

(leaf org-habit
  :after org
  :require t
  :config
  (add-to-list 'org-modules 'org-habit t)
  (setq org-habit-graph-column 80))

Org Mobile

So that we can edit and view things on the go. We could use the proper org-mobile module of org, instead we synchronize w/ Nextcloud, as to have it be the format we like when using Orgzly Revived

Org Notes (Roam)

Let alone being able to maintain dates and times and journal entries: having notes for consolidating a personal wiki (separately) is also rather useful. For this we use Org-roam, a slip-note style note taking package.

Org Roam

(leaf org-roam :ensure t
  :after org transient-dwim
  :require t
  :config
  (setq org-roam-directory (file-truename org-directory))
  (org-roam-db-autosync-mode)
  (transient-define-prefix transient--org-roam ()
    ["Org Roam"
     ("M-c" "Capture Note" org-roam-capture)
     ("M-i" "Insert Note" org-roam-node-insert)
     ("M-f" "Find Note" org-roam-node-find)])
  (transient-append-suffix 'transient-dwim-org "M-o" '("M-n" "roam" transient--org-roam))
  (setq org-roam-capture-templates
	'(("d" "default" plain "%?"
	   :target (file+head "notes/%<%Y%m%d%H%M%S>-${slug}.org"
			      "#+title: ${title}\n")
	   :unnarrowed t))))
Org Roam UI
(leaf org-roam-ui :ensure t
  :after org-roam)
Org Roam Bibtex (ORB)
(leaf org-roam-bibtex :ensure t
  :after org-roam org-ref
  :require t
  :hook (after-init-hook . org-roam-bibtex-mode))

Org Babel

(leaf org-babel
  :after org
  :config
  (org-babel-do-load-languages
   'org-babel-load-languages
   '((emacs-lisp . t)
     (python . t)
     (shell . t))))

Flutter

(leaf dart-mode :ensure t)
(leaf lsp-dart :ensure t)

BQN

(leaf bqn-mode
  :ensure (bqn-mode :type git :host github :repo "museoa/bqn-mode")
  :defer-config
  (set-face-attribute 'bqn-default nil :family 'unspecified))