Files
EmacsConfig/main.org

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

(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
    (customize-set-variable
     'package-archives '(("org" . "https://orgmode.org/elpa/")
  		       ("melpa" . "https://melpa.org/packages/")
  		       ("gnu" . "https://elpa.gnu.org/packages/")))
    (package-initialize)
    (unless (package-installed-p 'leaf)
      (package-refresh-contents)
      (package-install '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

(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
  :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
  :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
  :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 :ensure t :require t)

Nix Related

Direnv

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

(leaf direnv
  :ensure t
  :config
  (direnv-mode))

Nix-mode

.nix file mode

(leaf nix-mode :ensure t)

IDE Like Things

Which Key Again?

(leaf which-key :ensure t
  :config (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
  :config (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

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

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
  :ensure t)
(leaf rainbow-mode
  :ensure t)

D2

(leaf d2-mode :ensure t)

YAML

(leaf yaml-mode :ensure t)

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
  :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)
(leaf lsp-haskell :ensure t)
(leaf company-ghci :ensure t)

Rust

(leaf rust-mode :ensure t
  :init
  (leaf slint-mode :ensure t))

Minecraft??

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

(leaf mcf-mode
  :el-get 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"))
  (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-hook 'org-export-before-parsing-functions 'org-ref-csl-preprocess-buffer)
  :require org-ref org-ref-helm oc-bibtex oc-bibtex oc-csl oc-natbib)

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) 

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

  (setq org-latex-pdf-process
	'("%latex -shell-escape -interaction nonstopmode -output-directory %o %f"
	  "%latex -shell-escape -interaction nonstopmode -output-directory %o %f"
	  "bibtex %b"
	  "%latex -shell-escape -interaction nonstopmode -output-directory %o %f"
	  "%latex -shell-escape -interaction nonstopmode -output-directory %o %f")))

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

(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 "todo.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 "todo.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
  :el-get "museoa/bqn-mode"
  :defer-config
  (set-face-attribute 'bqn-default nil :family 'unspecified))