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

744 lines
19 KiB
Org Mode

#+options: ':nil *:t -:t ::t <:t H:3 \n:nil ^:t arch:headline
#+options: author:t broken-links:nil c:nil creator:nil
#+options: d:(not "LOGBOOK") date:t e:t email:nil f:t inline:t num:t
#+options: p:nil pri:nil prop:nil stat:t tags:t tasks:t tex:t
#+options: timestamp:t title:t toc:t todo:t |:t
#+title: Universe Emacs Config
#+author:
#+language: en
* 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=
#+begin_src elisp :tangle no :exports code
(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))
#+end_src
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.
#+begin_src elisp :tangle yes :exports code
(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)))
#+end_src
** MacOS Specific
#+begin_src elisp :tangle yes :exports code
(leaf macos
:hook (after-init hook)
:when (eq system-type 'darwin)
:init
(setq mac-option-modifier 'meta))
#+end_src
** 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)
#+begin_src elisp :tangle yes :exports code
; (leaf gcmh :ensure t
; :hook (after-init-hook))
#+end_src
*** Profiling
#+begin_src elisp :tangle yes :exports code
(leaf esup :disabled nil :ensure t)
#+end_src
** Emacs Paths
*** Custom.el
Ensure that the =custom.el= resides in the users' emacs directory.
#+begin_src elisp :tangle yes :exports code
(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))
#+end_src
*** Backups
Set the backups directory to reside in the users' emacs directory.
#+begin_src elisp :tangle yes :exports code
(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")))))
#+end_src
** Shell Path Preservation
Exec-path-from-shell ensures that path variable is preserved from
shell.
#+begin_src elisp :tangle yes :exports code
(leaf exec-path-from-shell :ensure t
:config
(exec-path-from-shell-initialize))
#+end_src
* Visual Customization
Visual Theme of Emacs config: defined in the =themes= directory.
#+begin_src elisp :tangle yes :exports code
(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))
#+end_src
* Version Control
#+begin_src elisp :tangle yes :exports code
(leaf magit
:leaf-defer nil
:ensure t :require t)
#+end_src
* Nix Related
** Direnv
In order to support direnv (loading =nix-shell= / =nix develop=)
#+begin_src elisp :tangle yes :exports code
(leaf direnv
:ensure t
:global-minor-mode direnv-mode)
#+end_src
** Nix-mode
=.nix= file mode
#+begin_src elisp :tangle yes :exports code
(leaf nix-mode
:ensure t
:mode "\\.nix\\'")
#+end_src
* IDE Like Things
** Which Key Again?
#+begin_src elisp :tangle yes :exports code
(leaf which-key
:ensure t
:global-minor-mode which-key-mode)
#+end_src
** Company Completion!
We like autocomplete, it... is nice, okay?
#+begin_src elisp :tangle yes :exports code
(leaf company :ensure t
:bind
(("C-<tab>" . company-complete))
:hook after-init-hook
:global-minor-mode global-company-mode)
#+end_src
** Language Server Protocol
We love language features that make languages nice
#+begin_src elisp :tangle yes :exports code
(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)
#+end_src
*** IDE Languages
**** Dart/Flutter
#+begin_src elisp :tangle yes :exports code
(dart-mode . lsp-deferred)
#+end_src
**** Python
#+begin_src elisp :tangle yes :exports code
(python-mode . lsp-deferred)
#+end_src
**** C/C++
#+begin_src elisp :tangle yes :exports code
(c-mode-hook . lsp-deferred)
(c++-mode-hook . lsp-deferred)
#+end_src
**** Haskell
#+begin_src elisp :tangle yes :exports code
(haskell-mode-hook . lsp-deferred)
#+end_src
**** Java
#+begin_src elisp :tangle yes :exports code
(java-mode-hook . lsp-deferred)
#+end_src
**** Rust
#+begin_src elisp :tangle yes :exports code
(rust-mode-hook . lsp-deferred)
#+end_src
#+begin_src elisp :tangle yes :exports code
)
#+end_src
*** LSP Plugins:
We do want some nice to haves of course
#+begin_src elisp :tangle yes :exports code
:init
#+end_src
- A pretty UI:
#+begin_src elisp :tangle yes :exports code
(leaf lsp-ui :ensure t
:commands lsp-ui-mode)
#+end_src
- Flycheck compat:
#+begin_src elisp :tangle yes :exports code
(leaf flycheck :ensure t)
#+end_src
- Debugger Compatibility
#+begin_src elisp :tangle yes :exports code
(leaf dap-mode :ensure t)
#+end_src
*** Projectile (Projects)
#+begin_src elisp :tangle yes :exports code
(leaf projectile
:commands projectile-mode
:config
(projectile-mode +1))
#+end_src
END LSP CONFIG
#+begin_src elisp :tangle yes :exports code
)
#+end_src
* WEB
We all know the web is the future, obviously, of course.
#+begin_src elisp :tangle yes :exports code
(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)
#+end_src
* D2
#+begin_src elisp :tangle yes :exports code
(leaf d2-mode
:ensure t
:mode "\\.d2\\'"
)
#+end_src
* YAML
#+begin_src elisp :tangle yes :exports code
(leaf yaml-mode
:ensure t
:mode "\\.yaml\\'"
)
#+end_src
* Python Things
** Python-mode
Using python-mode is to have more up to date features (and
highlighting) compared to builtin python-mode.
#+begin_src elisp :tangle yes :exports code
(leaf python-mode
:ensure t
:mode "\\.py\\'"
:config
(setq python-shell-interpreter "ipython"
python-shell-interpreter-args "-i --simple-prompt --InteractiveShell.display_page=True"))
#+end_src
** Poetry
For when we aren't nix'ing things, and want some nice poetry.
#+begin_src elisp :tangle yes :exports code
(leaf poetry :ensure t)
#+end_src
* C
Who even needs C++, not me, no way, no how.
#+begin_src elisp :tangle no :exports code
(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)
)
#+end_src
* Haskell
#+begin_src elisp :tangle yes :exports code
(leaf haskell-mode
:ensure t
:mode "\\.hs\\'"
:init
(leaf lsp-haskell :ensure t)
(leaf company-ghci :ensure t))
#+end_src
* Rust
#+begin_src elisp :tangle yes :exports code
(leaf rust-mode :ensure t
:mode "\\.rs\\'"
:init
(leaf slint-mode :ensure t))
#+end_src
* Minecraft??
Minecraft =mcfunction= support, because, it can be annoying to type
this stuff otherwise.
#+begin_src elisp :tangle yes :exports code
(leaf mcf-mode
:straight (mcf-mode :type git :host github :repo "rasensuihei/mcf"))
#+end_src
* Lisps
Gonna need to have pretty brackets
#+begin_src elisp :tangle yes :exports code
(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)))
#+end_src
** Racket
Makes using racket so much nicer
#+begin_src elisp :tangle yes :exports code
(leaf geiser-racket :ensure t)
#+end_src
** Clojure
For using clojure, we use both [[https://github.com/clojure-emacs/clojure-mode][clojure-mode]] and for REPL we use [[https://github.com/clojure-emacs/cider][CIDER]].
#+begin_src elisp :tangle yes :exports code
(leaf clojure-mode :ensure t cider)
#+end_src
* 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)
#+begin_src elisp :tangle yes :exports code
(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"))
#+end_src
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.
#+begin_src elisp :tangle yes :exports code
(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)
#+end_src
** Extra Export Options
*** LaTeX (Obviously)
We really do require latex
#+begin_src elisp :tangle yes :exports code
(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}"))))
#+end_src
*** HTML Export
#+begin_src elisp :tangle yes :exports code
(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>
"))
#+end_src
*** Pandoc the Panacea of Exports
For more export formats we use pandoc:
#+begin_src elisp :tangle yes :exports code
(leaf ox-pandoc :ensure t :require t
:after org)
#+end_src
*** 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.
#+begin_src elisp :tangle yes :exports code
(leaf ox-reveal :ensure t :require t
:config
(setq org-reveal-root "https://cdn.jsdelivr.net/npm/reveal.js"))
#+end_src
** LaTeX: with AuCTeX
Nicer LaTeX editing (AuCTeX):
#+begin_src elisp :tangle yes :exports code
(leaf auctex :ensure t
:after org)
#+end_src
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?
#+begin_src elisp :tangle yes :exports code
(leaf gnuplot
:ensure t)
#+end_src
** Org Mode Agenda/Calendar Things
*** Agenda Location
Make it so that all files in the " src_elisp{org-agenda-files} " variable (e.g. "=~/Documents=") will be
included in the tablutation and collation of all the dates and todos
etc.
#+begin_src elisp :tangle yes :exports code
(leaf org-agenda
:after org
:config
(setq org-agenda-files `(,(concat org-directory))))
#+end_src
*** Capture Things
Unless specified otherwise, any captured note, date, meeting, idea,
should be put into the src_elisp{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.
#+begin_src elisp :tangle yes :exports code
(leaf org-capture
:after org
:config
(setq org-default-notes-file (concat org-directory "/notes.org")))
#+end_src
We also want to configure what type of things we want to capture,
e.g. meetings, deadlines and whatever else:
#+begin_src elisp :tangle yes :exports code
(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"))))
#+end_src
*** Habits
#+begin_src elisp :tangle yes :exports code
(leaf org-habit
:after org
:require t
:config
(add-to-list 'org-modules 'org-habit t)
(setq org-habit-graph-column 80))
#+end_src
*** 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
#+begin_src elisp :tangle yes :exports code
(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))))
#+end_src
**** Org Roam UI
#+begin_src elisp :tangle yes :exports code
(leaf org-roam-ui :ensure t
:after org-roam)
#+end_src
**** Org Roam Bibtex (ORB)
#+begin_src elisp :tangle yes :exports code
(leaf org-roam-bibtex :ensure t
:after org-roam org-ref
:require t
:hook (after-init-hook . org-roam-bibtex-mode))
#+end_src
** Org Babel
#+begin_src elisp :tangle yes :exports code
(leaf org-babel
:after org
:config
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(python . t)
(shell . t))))
#+end_src
* Flutter
#+begin_src elisp :tangle yes :exports code
(leaf dart-mode :ensure t)
(leaf lsp-dart :ensure t)
#+end_src
* BQN
#+begin_src elisp :tangle yes :exports code
(leaf bqn-mode
:ensure (bqn-mode :type git :host github :repo "museoa/bqn-mode")
:defer-config
(set-face-attribute 'bqn-default nil :family 'unspecified))
#+end_src