#+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-" . 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 >) ;; " pre.src { background-color: #000; color: #ccc; border-radius: 2ch; } pre.src:before { background-color: #ccc; color: #000; border-radius: 0.5ch; } ")) #+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