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

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)

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

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