commit b4e6eead6e787bfd7520fee3b01b2fb8c0049912
parent e2118b43554e78598a71a65bafc20485b758cd7d
Author: Ethan Long <ethandavidlong@gmail.com>
Date: Fri, 12 Dec 2025 10:28:24 +1100
Absolutely nfi what changes I have made, yet again...
Diffstat:
| M | config.org | | | 497 | +++++++++++++++++++++++++++++++++++++++++++++---------------------------------- |
| A | custom.el | | | 0 | |
| M | init.el | | | 83 | ++++++++++++++++++++++++++++++++++++------------------------------------------- |
3 files changed, 324 insertions(+), 256 deletions(-)
diff --git a/config.org b/config.org
@@ -1,106 +1,65 @@
#+Startup: overview
#+Title:My emacs config
#+Author:Ethan Long
+* What is this document/config/file?
+This is a literate config for emacs, using the built-in ~org~ package for Emacs.
* Elpaca
-The elpaca package manager is an alternative to ~use-package~ that works asynchronously in the background. Beyond the initial set-up, it is faster and more reliable than using ~package.el~. The main downside is also that it is asynchronous, as this means you need to put thought into the configuration of the rest of emacs, everything needs to be set up with ~use-package~ and a special ~elpaca-after-init-hook~ unless you want the blocking ~elpaca-wait~ function that completely defeats the purpose of elpaca.
+The Elpaca package manager is an alternative to ~use-package~ that works asynchronously in the background. Beyond the initial set-up, it is faster and more reliable than using ~package.el~.
+
+Its asynchronous nature is also what makes package initialisation a little more involved; packages that need to be set up after others must explicitly specify this. This is mostly a non-issue for my setup, and I try to avoid issues with variable declarations by using ~use-package~ whenever possible.
+
+Alternatively, if you already have a setup with extensive use of ~use-package~ with some form of synchronous package manager, then you might want to use the ~elpaca-wait~ function, which forces it to complete all package evaluation up until that point. Using this function too often will defeat the purpose of elpaca, as the asynchronicity is exactly what makes it faster than alternatives.
+
+Another thing of note, if you ever need to use ~after-init-hook~, then make sure to use ~elpaca-after-init-hook~ instead, as the regular ~after-init-hook~ can be triggered before Elpaca has finished its evaluation unless you use the afforementioned ~elpaca-wait~ function.
Elpaca is installed in =init.el=, as we need to install the latest version of org before we enter here.
-* Theme
-Catppuccin is best (dark) theme.
-#+begin_src emacs-lisp
- ;; Catppuccin Mocha theme
- (use-package catppuccin-theme)
- (unless (fboundp 'catppuccin-reload)
- (elpaca-wait))
- (load-theme 'catppuccin t)
- (setq catppuccin-flavor 'mocha)
- (catppuccin-reload)
-#+end_src
-When using emacs-plus, you can have a light and a dark theme :)
-#+begin_src emacs-lisp
- (defun ethandl/apply-theme (appearance)
- ;;"Load theme, taking current system APPEARANCE into consideration."
- (mapc #'disable-theme custom-enabled-themes)
- (pcase appearance
- ('light (setq catppuccin-flavor 'latte))
- ('dark (setq catppuccin-flavor 'mocha)))
- (catppuccin-reload))
+** ~init.el~
+#+include: "./init.el" src elisp :tangle no
+* Configuration functions
+Here I define all of my helper functions in the one place just for convenience. Unfortunately this can have the effect of breaking up some of my configuration, especially for things like ~org~.
+** General programming configuration
+Firstly, here are some convenience functions that I find useful for general programming, making the editor act the way that I want it to.
+*** Auto buffer formatting
+I quite like how the LSP (or some other kind of parser/prettifier) can automatically format the buffer. In other editors, I typically like to have this happen whenever I save.
- (add-hook 'ns-system-appearance-change-functions #'ethandl/apply-theme)
-#+end_src
-* Font & Ligature Definitions
-It's here that we pick the code font.
-#+begin_src emacs-lisp
- ;; Set the fonts
- ;; (setq code-font "Comic Code Ligatures-16")
- (setq code-font "Victor Mono-16")
- ;; (setq code-font "JuliaMono-16")
- (add-hook 'after-make-frame-functions (apply-partially #'ethandl/set-fonts code-font))
-#+end_src
-We also set the ligatures for code
-#+begin_src emacs-lisp
- (setq
- comic-code-ligs
- '(("-" (rx (+ "-"))) ("-" (rx (* "-") ">"))
- ("+" (rx (+ "+"))) ("<" (rx (+ "=")))
- ("<" (rx (+ "=") ">")) ("<" (rx (+ "~")))
- ("<" (rx (+ "~") ">")) ("<" (rx "!" (+ "-")))
- ("<" (rx (+ "-"))) ("<" (rx (+ "-") ">")) ("<" (rx "|"))
- (">" (rx (+ "="))) (">" (rx ">" (+ "=")))
- (">" (rx ">" (+ "=") ">")) (">" (rx (+ "-")))
- (">" (rx (+ "-") "<")) ("~" (rx (+ "~")))
- ("~" (rx (+ "~") ">")) ("=" (rx (* "=") ">"))
- ("=" (rx (+ (or ">" "<" "|" "/" "~" ":" "!" "="))))
- "!=" "!==" "[|" "|]" "{|" "|}" "|>" "||" "&&")
-
- victor-mono-ligs
- '("</" "</>" "/>" "~-" "-~" "~@" "<~" "<~>" "<~~" "~>" "~~" "~~>" ">=" "<="
- "<!--" "##" "###" "####" "|-" "-|" "|->" "<-|" ">-|" "|-<" "|=" "|=>"
- ">-" "<-" "<--" "-->" "->" "-<" ">->" ">>-" "<<-" "<->" "->>" "-<<" "<-<"
- "==>" "=>" "=/=" "!==" "!=" "<==" ">>=" "=>>" ">=>" "<=>" "<=<"
- "=<=" "=>=" "<<=" "=<<" ".-" ".=" "=:=" "=!=" "==" "===" "::" ":=" ":>"
- ":<" ">:" ";;" "<|" "<|>" "|>" "<>" "<$" "<$>" "$>" "<+"
- "<+>" "+>" "?=" "/=" "/==" "/\\" "\\/" "__" "&&" "++" "+++")
-
- julia-mono-ligs
- '("->" "=>" "|>" "<|" "::" "<--" "-->" "<-->"
- ("=" (rx (+ "=")))))
- (setq ligs victor-mono-ligs)
-#+end_src
-* My Custom Elisp Functions
-** General Programming Configuration
-#+begin_src emacs-lisp
- (defun ethandl/num-lines ()
- (max 1 (count-lines (point-min) (point-max))))
- (defun ethandl/base-10-len (num)
- (+ 1 (floor (log num 10))))
-#+end_src
+This functionality is especially useful for languages like Rust or Haskell where the formatting is handled quite well by the LSP.
#+begin_src emacs-lisp
(defun ethandl/format-buffer ()
(when (and eglot--managed-mode
(eglot-server-capable :documentFormattingProvider))
(eglot-format-buffer)))
#+end_src
+In the future, I may extend this function to utilise prettifiers, but I don't really have the need to at the moment.
+*** Line numbers
+Line numbering in emacs is still a bit of a third class citizen; the primary reason I say this is because the width of the line number column is prone to change for seemingly no good reason. Example: scrolling any file below 80 lines will increase the size to accomodate line numbers greater than 1oo for no reason; the same thing happens around 850 lines for numbers greater than 1000.
+
+I find that currently I am mostly satisfied by using the variable ~display-line-numbers-grow-only~. This effectively stops most of the annoyance around the width changing when scrolling up and down.
+
+Following is a function that sets up the requisite variables for the behaviour that I like:
+#+begin_src emacs-lisp
+ (defun ethandl/config-line-numbers ()
+ ;; Set line numbers to relative
+ (setq display-line-numbers 'relative
+ display-line-numbers-width 2
+ display-line-numbers-current-absolute t
+ display-line-numbers-grow-only t))
+#+end_src
+I would recommend adding this to a hook, which I have done in [[*General Emacs/Editor settings]], specifically the ~hook~ section of the ~use-package~ declaration.
+*** Code fonts
+For convenience, I have defined a helper function that can be called to configure the code fonts.
+In typical one-frame setups not using the daemon functionality of emacs, you only need to use this once with the ~default~ parameter set as ~t~.
+
+With daemon usage, it is not so simple. When using emacs as a daemon, emacs will initially read over this config file in terminal mode, which will stop it from setting the fonts correctly; the only solution to this is to set this function to run every time you create a new frame. I have this exact functionality set up in [[*Font & Ligature Definitions]].
#+begin_src emacs-lisp
- (defun ethandl/line-nums-cfg ()
- (when (derived-mode-p 'prog-mode)
- ;; Set line numbers to relative
- (setq display-line-numbers 'relative
- display-line-numbers-current-absolute t
- display-line-numbers-width (ethandl/base-10-len (ethandl/num-lines)))))
-#+end_src
-#+begin_src emacs-lisp
- (defun ethandl/set-fonts (fontname &optional frame)
- (with-selected-frame (or frame (selected-frame))
- (set-face-attribute 'default nil :font fontname)
- (set-face-attribute 'font-lock-comment-face nil :slant 'italic)
- (set-face-attribute 'font-lock-keyword-face nil :slant 'italic)))
-#+end_src
-#+begin_src emacs-lisp
- (defun ethandl/reload-config ()
- (interactive)
- (load user-init-file))
+ (defun ethandl/set-fonts (fontname &optional default)
+ (set-face-attribute 'default default :font fontname)
+ (set-face-attribute 'font-lock-comment-face default :slant 'italic)
+ (set-face-attribute 'font-lock-keyword-face default :slant 'italic)
+ (set-face-attribute 'mode-line default :font fontname))
#+end_src
+*** Tree sitter grammar compilation
+I wanted a function that, given an ~alist~ of tree sitter grammars and their associated sources, would clone, build, and set up those grammars.
+This function avoids recompiling grammars that are already installed.
#+begin_src emacs-lisp
(defun ethandl/install-treesit-grammars (lang-alist)
(require 'cl-lib)
@@ -108,12 +67,18 @@ We also set the ligatures for code
(mapc #'treesit-install-language-grammar
(cl-remove-if #'treesit-language-available-p (mapcar #'car lang-alist)))))
#+end_src
-#+begin_src emacs-lisp
- (defun ethandl/define-indents ()
- (setq-local evil-shift-width tab-width))
-#+end_src
-** Org Mode Configuration
-The following function is the base config for org-mode, it sets org to indent on section depth, sets the font to be variable pitch, turns on visual lines for wrapped lines.
+I use this function in [[*Tree Sitter Setup]].
+** Org mode configuration
+Org mode is quite ugly out of the box, at least in my opinion. I use this config, which was inspired by a config that I found online.
+
+I have used the following guides in informing this setup; it is largely based on the work of Diego Zamboni:
+ * [[https://zzamboni.org/post/beautifying-org-mode-in-emacs/][Beautifying Org Mode in Emacs by Diego Zamboni]]
+ * [[https://lepisma.xyz/2017/10/28/ricing-org-mode/][Ricing up Org Mode]]
+
+I think that the latter guide is by far the prettier, more /"aesthetically pleasing"/ setup deserving of Unixporn or something, but personally I like it slightly less minimalistic.
+
+*** Basic behavioral configuration
+For starters, I define the function ~ethandl/org-base~ as the function to set up org in the way that I generally like. Of primary concern: it sets org to indent on section depth, sets the font to be variable pitch, and turns on visual lines for wrapped lines.
#+begin_src emacs-lisp
(defun ethandl/org-base ()
(require 'org)
@@ -129,6 +94,8 @@ The following function is the base config for org-mode, it sets org to indent on
'(("^ *\\([-]\\) "
(0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•")))))))
#+end_src
+This function should be called when you are setting up org mode, personally I do it when I'm [[*
+*** Fonts
The following function is the config for org to set all the fonts. It is still a bit rough around the edges, I'd like to programatically set the heading sizes.
#+begin_src emacs-lisp
(defun ethandl/org-font ()
@@ -138,8 +105,8 @@ The following function is the config for org to set all the fonts. It is still a
((variable-font (if (x-list-fonts "ETBookOT")
'(:font "ETBookOT")
'(:family "Serif")))
- (mono-font (if (x-list-fonts code-font)
- `(:font ,code-font)
+ (mono-font (if (x-list-fonts ethandl/code-font)
+ `(:font ,ethandl/code-font)
'(:family "Mono")))
(base-font-color (face-foreground 'default nil 'default))
(headline `(:inherit default :weight bold :foreground ,base-font-color))
@@ -173,38 +140,164 @@ The following function is the config for org to set all the fonts. It is still a
'(org-tag ((t (:inherit (shadow fixed-pitch) :weight bold :height 0.8))) t "Org tag")
'(org-verbatim ((t (:inherit (shadow fixed-pitch)))) t "Verbatim"))))
#+end_src
+*** LaTeX
Some configuration for the LaTeX that appears in Org mode. We want to make sure that it's SVG, and also if we have the ability to, we should auto-render it.
#+begin_src emacs-lisp
(defun ethandl/org-latex ()
- (setq org-preview-latex-default-process 'dvisvgm)
- ;; This should not be necessary, but it seems like they are with the experimental version of org
- (add-to-list 'org-latex-packages-alist '("" "amsmath" t))
- (add-to-list 'org-latex-packages-alist '("" "amssymb" t))
- (when (>= (string-to-number (org-version)) 9.7)
- (org-latex-preview-auto-mode t)))
+ (setq org-preview-latex-default-process 'dvisvgm))
#+end_src
** Hooks
+*** Before saving
+I like to format my buffers every time that I save in other editors, for now this function just calls my other ~format-buffer~ function. Any other action that you might like to do whenever you save can be put here too.
#+begin_src emacs-lisp
(defun ethandl/before-save-hook ()
(ethandl/format-buffer))
#+end_src
+A good example of something that you might want to put here would be a ~git~ commit and push every time that you save within an Overleaf git project. This can be useful for when you're trying to avoid actually using the god-forsaken web editor of Overleaf.
+* Theme
+There are many themes for Emacs that you can use. It can be nice to spice things up every once in a while.
+One day I might make my own theme, only if I get too lost in the ricing.
+*** Catppuccin
+I use the Catppuccin theme normally.
+Unfortunately, this theme has some issues and I'm not sure whether they will ever be fixed; I have the fixes all here.
+#+begin_src emacs-lisp
+ ;; Catppuccin Mocha theme
+ (use-package catppuccin-theme
+ :config
+ (load-theme 'catppuccin t)
+ (setq catppuccin-flavor 'mocha)
+ ;;(setq catppuccin-flavor 'latte)
+ (catppuccin-reload)
+ (add-to-list 'org-src-block-faces
+ (list "" (list :foreground (catppuccin-get-color 'green))))
+ ;; HACK FIX: https://github.com/catppuccin/emacs/issues/61
+ (defun ctp/text-org-blocks ()
+ (face-remap-add-relative 'org-block (list :foreground (catppuccin-get-color 'text))))
+ ;; FIXME: Move this hook to the Org mode configuration so that it is obvious that we are adding this hook.
+ (add-hook 'org-mode-hook #'ctp/text-org-blocks)
+ (setq pdf-view-midnight-colors (cons (catppuccin-get-color 'text)
+ (catppuccin-get-color 'base))))
+#+end_src
+*** Gruber darker
+Sometimes I like to use Gruber Darker, following is an example snippet that is not tangled into my actual config.
+#+begin_src emacs-lisp :tangle no
+ (use-package gruber-darker-theme
+ :config
+ (load-theme 'gruber-darker t))
+#+end_src
+*** Emacs titlebar colour
+FIXME: Move all configuration of the titlebar colour here for all versions of emacs like the mac port and gtk+.
+It's nice to have the titlebar blend for the NS port of emacs:
+#+begin_src emacs-lisp
+ (add-to-list 'default-frame-alist '(ns-transparent-titlebar . t))
+ (add-to-list 'default-frame-alist '(ns-appearance . dark))
+#+end_src
+#+begin_src emacs-lisp
+ (add-to-list 'default-frame-alist '(mac-transparent-titlebar . t))
+#+end_src
+
+* Font & Ligature Definitions
+FIXME: Bring in the ~org~ and variable font definitions here!
+*** Code fonts
+Here I pick the code font and declare it as the variable ~ethandl/code-font~.
+#+begin_src emacs-lisp
+ (setq ethandl/code-font "Codelia Ligatures-16")
+#+end_src
+Currently I use Codelia, but I also recommend Comic Code, Julia Mono, or Victor Mono. In the end this is entirely personal preference.
+Some more examples:
+#+begin_src emacs-lisp :tangle no
+ (setq ethandl/code-font "Comic Code Ligatures-16")
+ (setq ethandl/code-font "JuliaMono-16")
+ (setq ethandl/code-font "Victor Mono-16")
+#+end_src
+
+Now we use [[*Code fonts][the font helper function that I defined earlier]] to actually set the fonts.
+#+begin_src emacs-lisp
+ ;; Set default font
+ (ethandl/set-fonts ethandl/code-font t)
+ (add-hook 'elpaca-after-init-hook (apply-partially #'ethandl/set-fonts ethandl/code-font))
+#+end_src
+**** Font supported ligatures for ~ligature.el~
+Each font has its own set of supported ligatures.
+Unfortunately on Linux systems you must use ~ligature.el~ to set ligatures, and this requires manually defining which ligatures are supported. This is either really cool or a pain in the ass.
+
+Here are some examples:
+#+begin_src emacs-lisp
+ (setq
+ comic-code-ligs
+ '(("-" (rx (+ "-"))) ("-" (rx (* "-") ">"))
+ ("+" (rx (+ "+"))) ("<" (rx (+ "=")))
+ ("<" (rx (+ "=") ">")) ("<" (rx (+ "~")))
+ ("<" (rx (+ "~") ">")) ("<" (rx "!" (+ "-")))
+ ("<" (rx (+ "-"))) ("<" (rx (+ "-") ">")) ("<" (rx "|"))
+ (">" (rx (+ "="))) (">" (rx ">" (+ "=")))
+ (">" (rx ">" (+ "=") ">")) (">" (rx (+ "-")))
+ (">" (rx (+ "-") "<")) ("~" (rx (+ "~")))
+ ("~" (rx (+ "~") ">")) ("=" (rx (* "=") ">"))
+ ("=" (rx (+ (or ">" "<" "|" "/" "~" ":" "!" "="))))
+ "!=" "!==" "[|" "|]" "{|" "|}" "|>" "||" "&&")
+
+ victor-mono-ligs
+ '("</" "</>" "/>" "~-" "-~" "~@" "<~" "<~>" "<~~" "~>" "~~" "~~>" ">=" "<="
+ "<!--" "##" "###" "####" "|-" "-|" "|->" "<-|" ">-|" "|-<" "|=" "|=>"
+ ">-" "<-" "<--" "-->" "->" "-<" ">->" ">>-" "<<-" "<->" "->>" "-<<" "<-<"
+ "==>" "=>" "=/=" "!==" "!=" "<==" ">>=" "=>>" ">=>" "<=>" "<=<"
+ "=<=" "=>=" "<<=" "=<<" ".-" ".=" "=:=" "=!=" "==" "===" "::" ":=" ":>"
+ ":<" ">:" ";;" "<|" "<|>" "|>" "<>" "<$" "<$>" "$>" "<+"
+ "<+>" "+>" "?=" "/=" "/==" "/\\" "\\/" "__" "&&" "++" "+++")
+
+ julia-mono-ligs
+ '("->" "=>" "|>" "<|" "::" "<--" "-->" "<-->"
+ ("=" (rx (+ "=")))))
+#+end_src
+In my configuration, I declare the variable ~ethandl/ligs~ to use in the ~ligature.el~ setup.
+#+begin_src emacs-lisp
+ (setq ethandl/ligs julia-mono-ligs)
+#+end_src
+
+All of this configuration is unnecessary if you don't want ligatures, or if you are using ~emacs-mac~ by Mitsuharu Yamamoto.
+* Custom Keybinds
+Here I have made a little section for setting up some additional keybinds.
+** Vim-style window navigation
+When navigating windows, I find the binding ~C-x o~ to be rather slow when you have many buffers open in different arrangements, so I have adopted a set of bindings for the ~windmove-*~ functions that are left unused in the default configuration. These binds fit in quite nicely with the ~vim~-like keybinds that I use with ~meow~.
+
+This is mostly just the work of [[https://dev.to/rajasegar/vim-style-repeatable-key-bindings-for-navigating-windows-in-emacs-5c4l][Rajasegar Chandran]].
+#+begin_src emacs-lisp
+ (global-set-key (kbd "C-x w h") 'windmove-left)
+ (global-set-key (kbd "C-x w j") 'windmove-down)
+ (global-set-key (kbd "C-x w k") 'windmove-up)
+ (global-set-key (kbd "C-x w l") 'windmove-right)
+ (repeat-mode t)
+ (defvar-keymap windmove-repeat-map
+ :repeat t
+ "h" #'windmove-left
+ "j" #'windmove-down
+ "k" #'windmove-up
+ "l" #'windmove-right)
+#+end_src
* General Emacs/Editor settings
-We can use ~use-package~ to configure emacs at startup. On MacOS we leave things mostly default because emacs-mac doesn't look fugly, but on Linux we might as well get rid of all the clutter. Also we use spaces not tabs, begone tabs.
+FIXME: Continue from here (remembering that I have other FIXMEs above)
+
+FIXME: Bring as many of these changes into standalone functions as possible to reduce fragmentation.
+We can use ~use-package~ to configure emacs at startup.
#+begin_src emacs-lisp
;; Emacs init config
(use-package emacs
:ensure nil
:hook
(prog-mode . display-line-numbers-mode)
- (display-line-numbers-mode . ethandl/line-nums-cfg)
+ (display-line-numbers-mode . ethandl/config-line-numbers)
(before-save . ethandl/before-save-hook)
- (find-file . ethandl/define-indents)
:init
- (ethandl/set-fonts code-font) ;; Set fonts
;; Get rid of default crud
(setq inhibit-startup-screen t)
- (menu-bar-mode 1)
- (tool-bar-mode 1)
+ (if (eq system-type 'darwin)
+ (menu-bar-mode 1)
+ (menu-bar-mode 0))
+ (tool-bar-mode -1)
+ (setq-default tool-bar-mode -1)
+ (add-to-list 'default-frame-alist '(tool-bar-lines . 0))
+ ;; (add-to-list 'after-make-frame-functions 'ethandl/tool-bar-padding-remove)
(when (fboundp 'scroll-bar-mode)
(scroll-bar-mode 0))
;; Note, the following two are already set in early_init.el,
@@ -217,8 +310,10 @@ We can use ~use-package~ to configure emacs at startup. On MacOS we leave things
;; Indentation
(setq-default indent-tabs-mode nil)
(setq-default tab-width 4)
- (setq-default evil-shift-width tab-width)
- (setq ring-bell-function 'ignore) ;; Get rid of the bell
+ ;; windmove wraps around
+ (setq windmove-wrap-around t)
+ ;; Get rid of the bell
+ (setq ring-bell-function 'ignore)
;; Fuck Control+Scroll to zoom, that's terrible and seems to be bound by something in emacs-plus?
(global-unset-key (kbd "<C-wheel-up>"))
(global-unset-key (kbd "<C-wheel-down>"))
@@ -230,7 +325,9 @@ We can use ~use-package~ to configure emacs at startup. On MacOS we leave things
;; Ensure that the command key is the emacs meta key
(when (eq system-type 'darwin)
(setq mac-option-modifier nil
- mac-command-modifier 'meta)))
+ mac-command-modifier 'meta))
+ ;; Emacs frame title format default is bad:
+ (setq frame-title-format "%b"))
#+end_src
* Packages
** Ivy and Counsel (Better Text Navigation)
@@ -247,13 +344,13 @@ We can use ~use-package~ to configure emacs at startup. On MacOS we leave things
Ligatures are native on =emacs-mac=, so we just call the built in helper function if we are using that. If not, we will use [[https://github.com/mickeynp/ligature.el][ligature.el]] to give ligatures with Harfbuzz.
#+begin_src emacs-lisp
;; Font ligatures:
- (if (fboundp 'mac-auto-operator-composition-mode)
+ (if (eq window-system 'mac)
;; We must be in emacs-mac
(mac-auto-operator-composition-mode)
;; Else, we're in a vanilla emacs
(use-package ligature
:config
- (ligature-set-ligatures 'prog-mode ligs)
+ (ligature-set-ligatures 'prog-mode ethandl/ligs)
(global-ligature-mode t)))
#+end_src
** Rainbow Delimiters
@@ -268,7 +365,12 @@ This modeline is supposedly sexier than the original, honestly I don't mind the
#+begin_src emacs-lisp
;; Doom modeline:
(use-package doom-modeline
- :hook (elpaca-after-init . doom-modeline-mode))
+ :hook (elpaca-after-init . doom-modeline-mode)
+ :config
+ ;; simpc-mode icon
+ (push '(simpc-mode nerd-icons-sucicon "nf-custom-c"
+ :face nerd-icons-blue)
+ nerd-icons-mode-icon-alist))
#+end_src
** Which Key?
Fix my ineptitude in this keyboard chord hell.
@@ -280,43 +382,6 @@ Fix my ineptitude in this keyboard chord hell.
:config
(setq which-key-idle-delay 0.3))
#+end_src
-** Evil mode
-Fix my ineptitude in this chord hell that is emacs. I mean seriously, chords just to navigate? I don't want even more RSI & carpel tunnel.
-#+begin_src emacs-lisp :tangle no
- ;; Evil mode :D
- (use-package evil
- :init
- (setq evil-want-integration t)
- (setq evil-want-keybinding nil)
- (setq evil-want-C-d-scroll t)
- (setq evil-want-C-u-scroll t)
- (setq evil-want-C-i-jump nil)
- (setq evil-undo-system 'undo-redo)
- (setq evil-ex-search-case 'sensitive)
- :config
- (evil-mode t)
- ;; Enabling C-g to exit from normal mode, and C-h to do what it normally does in emacs
- (define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)
- (define-key evil-insert-state-map (kbd "C-h") 'evil-delete-backward-char-and-join)
-
- ;; Use visual line motions outside of visual-line-mode buffers
- (evil-global-set-key 'motion "j" 'evil-next-visual-line)
- (evil-global-set-key 'motion "k" 'evil-previous-visual-line)
-
- ;; Set initial states to be in normal mode for some buffers
- (evil-set-initial-state 'messages-buffer-mode 'normal)
- (evil-set-initial-state 'dashboard-mode 'normal))
-#+end_src
-*** Evil Collection
-#+begin_src emacs-lisp :tangle no
- ;; Extra modes for evil, if evil is playing up this would be the first thing to check
- (use-package evil-collection
- :after evil
- :config
- (evil-collection-init))
-#+end_src
-*** Evil is being banished from this realm
-I am temporarily trying a new modal style presented by meow, I will make my own modal exiting, merging emacs, vi, kakoune, and helix all into my own abomination 😄.
** Meow
Meow takes some getting used to, but I want to try.
The beauty is that I have full control explicitly over every binding in a really simple interface, and the rest of the binds are just emacs' default with some enhancement:
@@ -408,7 +473,10 @@ The beauty is that I have full control explicitly over every binding in a really
'("Y" . meow-sync-grab)
'("z" . meow-pop-selection)
'("'" . repeat)
+ '(">" . indent-rigidly-right-to-tab-stop)
+ '("<" . indent-rigidly-left-to-tab-stop)
'("<escape>" . ignore))
+ (setq meow-keypad-leader-dispatch "C-x")
(meow-global-mode t))
#+end_src
** Corfu & Cape (Completion)
@@ -420,44 +488,37 @@ Based completion. This is an overhaul of the autocomplete. Company mode sucks be
;; Completion & Modernisation
(use-package corfu
:after cape
+ :hook
+ (meow-insert-exit . corfu-quit)
:custom
(corfu-cycle t)
(corfu-auto t)
+ (corfu-preselect 'prompt)
(corfu-scroll-margin 5)
(completion-cycle-threshold 3)
- :config
+ :init
(global-corfu-mode))
#+end_src
** Scrolling Patches
-Scrolling via cursor movement is too slow in default emacs, this fixes that.
+JDT makes a nice scroll package, this should be good regardless of the emacs build that you are using.
#+begin_src emacs-lisp
- ;; Faster scrolling:
- (use-package fast-scroll
+ (use-package ultra-scroll
+ :ensure `(ultra-scroll
+ :host github
+ :repo "jdtsmith/ultra-scroll")
+ :init
+ (setq scroll-conservatively 10
+ scroll-margin 0)
:config
- (fast-scroll-config)
- (fast-scroll-mode 1))
-#+end_src
-Here are a few more nice things for scrolling.
-#+begin_src emacs-lisp
- (unless (eq system-type 'darwin)
- ;; Change the default scroll behaviour to smooth scroll
- (pixel-scroll-precision-mode t))
- ;; Scrolling down a file only goes down a single line when reaching the bottom
- (setq scroll-step 1
- hscroll-step 1
- ;; The region that the curser needs to enter to trigger scrolling
- scroll-margin 5
- ;; Necessary to stop random jumps
- scroll-conservatively 10000)
+ (ultra-scroll-mode 1))
#+end_src
** Exec path from shell (Fix Path issues)
When running emacs as a daemon, we have a notable lack of things in our ~PATH~ because daemons are started in a minimal environment, at least on MacOS.
This solution will increase startup time, but will fix any path issues for most shells. May need tinkering. This will also only be activated when using a daemon.
#+begin_src emacs-lisp
- (when (and (fboundp 'daemonp) (daemonp))
- (use-package exec-path-from-shell
- :config
- (exec-path-from-shell-initialize)))
+ (use-package exec-path-from-shell
+ :config
+ (exec-path-from-shell-initialize))
#+end_src
** PDF-tools
#+begin_src emacs-lisp
@@ -468,24 +529,24 @@ This solution will increase startup time, but will fix any path issues for most
(setq-default pdf-view-display-size 'fit-page)
(setq pdf-annot-activate-created-annotations t))
#+end_src
-* Org Mode
-My org mode is based on [[https://orgmode.org/guide/Hyperlinks.html][a post by Diego Zamboni]]. The general idea is that we want headings to be bigger and more noticable than text, all regular text should be non-monospace, and all code should be in the regular monospace font.
-HACK fix for the catppuccin theme: (https://github.com/catppuccin/emacs/issues/61)
-#+begin_src emacs-lisp
- (add-to-list 'org-src-block-faces (list "" (list :foreground (catppuccin-get-color 'green))))
+** Emacs vterm
+In emacs' included packages, there are only 2 shells that are good to use: ~eshell~ and ~shell~.
+I have had poor experiences with ~term~, as it doesn't properly emulate all escape sequences and is a bit slow.
- (defun ctp/text-org-blocks ()
- (face-remap-add-relative 'org-block (list :foreground (catppuccin-get-color 'text))))
+The solution to this is the ~vterm~ package, which is a package written mostly in C with a much better terminal emulation. It is fast and more reliable.
+#+begin_src emacs-lisp
+ (use-package vterm)
#+end_src
+* Org Mode
+My org mode is based on [[https://orgmode.org/guide/Hyperlinks.html][a post by Diego Zamboni]]. The general idea is that we want headings to be bigger and more noticable than text, all regular text should be non-monospace, and all code should be in the regular monospace font.
The org configuration uses a lot of custom functions, see the
#+begin_src emacs-lisp
(use-package org
- :ensure nil ;; Can be removed after 9.7 is released
+ :ensure nil
:hook
(org-mode . ethandl/org-base)
(org-mode . ethandl/org-font)
- (org-mode . ethandl/org-latex)
- (org-mode . ctp/text-org-blocks))
+ (org-mode . ethandl/org-latex))
#+end_src
Other auxillary packages for Org mode:
#+begin_src emacs-lisp
@@ -516,10 +577,9 @@ LSP, the Language Server Protocol. Very nice for debugging code live as you writ
*Warning:* Some LSPs are godawful slow and can chew through CPU and memory. Be careful, tinker, and don't be afraid to disable the training wheels.
We use the built-in package eglot (requires emacs 29) if possible as there seems to occasionally be issues with installing eglot.
#+begin_src emacs-lisp
- (if (>= emacs-major-version 29)
+ (when (>= emacs-major-version 29)
(use-package eglot
- :ensure nil)
- (use-package eglot))
+ :ensure nil))
(use-package markdown-mode) ; needed for formatting the stuff in the eldoc buffers
#+end_src
** Tree Sitter Setup
@@ -543,13 +603,11 @@ Since Emacs 29, we don't need to install tree sitter separately anymore, it come
;;(haskell "https://github.com/tree-sitter/tree-sitter-haskell") ; There is no haskell-ts-mode yet
;;(ocaml "https://github.com/tree-sitter/tree-sitter-ocaml" "master" "ocaml/src") ; There is no ocaml-ts-mode
(c "https://github.com/tree-sitter/tree-sitter-c")
- (cpp "https://github.com/tree-sitter/tree-sitter-cpp")))
-
- ;; Fuck windows, compiling C on Windows is a joke.
- (setq treesit-enabled (not (eq system-type 'windows-nt)))
+ (cpp "https://github.com/tree-sitter/tree-sitter-cpp")
+ (zig "https://github.com/maxxnino/tree-sitter-zig")))
- (when treesit-enabled
- (ethandl/install-treesit-grammars treesit-language-source-alist))
+ ;; Fuck windows, this won't work on there and I don't care
+ (ethandl/install-treesit-grammars treesit-language-source-alist)
#+end_src
** Eldoc Setup
I like to have eldoc appear as a box below where I'm typing, rather than having it appear in the minibuffer. This is done with =eldoc-box=:
@@ -559,15 +617,25 @@ I like to have eldoc appear as a box below where I'm typing, rather than having
(eglot-managed-mode . eldoc-box-hover-mode))
#+end_src
** C
-We want to use tree sitter to generate syntax highlighting, so we should change the default major mode to be the tree-sitter mode.
+I was using the C treesitter mode, but that mode is still based on C-mode and is incredibly slow for large files.
+#+begin_src emacs-lisp :tangle no
+ (push '(c-mode . c-ts-mode) major-mode-remap-alist))
+#+end_src
+
+Instead, I now use Alexey Kutepov's ~simp-c~ mode, which performs far better.
#+begin_src emacs-lisp
- (when treesit-enabled
- (push '(c-mode . c-ts-mode) major-mode-remap-alist))
+ (use-package simpc-mode
+ :ensure '(simpc-mode
+ :host github
+ :repo "rexim/simpc-mode")
+ :config
+ (push '(c-mode . simpc-mode) major-mode-remap-alist))
#+end_src
** Haskell
This setup is just a combination of =haskell-mode= and the Haskell Language Server.
Haskell mode is really good for the indenting and overall behaviour of the editor, and the Haskell language server is definitely there... (It can be slow, so can be turned off on larger projects)
#+begin_src emacs-lisp
+ (executable-find "haskell-language-server-wrapper")
;; Haskell setup
(use-package haskell-mode)
(use-package eglot
@@ -587,11 +655,7 @@ Haskell mode is really good for the indenting and overall behaviour of the edito
NOTE: This is not using tree sitter, as there is no haskell-ts-mode yet or probably for a while into the future.
** Rust
Rust mode alongside LSP again. The rust LSP is very good as far as LSPs go, very helpful. Though sometimes it's better to compile and see the rustc errors as they tend to be more verbose.
-/Chad =rust-ts-mode= configuration with eglot:/
#+begin_src emacs-lisp
- (unless treesit-enabled
- (print "Cannot use rust without tree-sitter!"))
-
(use-package eglot
:ensure nil
:after eglot
@@ -605,9 +669,6 @@ Rust mode alongside LSP again. The rust LSP is very good as far as LSPs go, very
** Go
This basic LSP setup is based on the golang guide: https://cs.opensource.google/go/x/tools/+/refs/tags/gopls/v0.14.2:gopls/doc/emacs.md
#+begin_src emacs-lisp
- (unless treesit-enabled
- (print "Cannot use go without tree-sitter!"))
-
(push '("\\.go\\'" . go-ts-mode) auto-mode-alist)
(push '("\\.mod\\'" . go-mod-ts-mode) auto-mode-alist)
(defun golang/project-find-go-module (dir)
@@ -641,15 +702,11 @@ If you want a language server, maybe just use IntelliJ? I don't use Java and the
(use-package emacs
:ensure nil
:config
- (when treesit-enabled
- (push '(java-mode . java-ts-mode) major-mode-remap-alist)))
+ (push '(java-mode . java-ts-mode) major-mode-remap-alist))
#+end_src
** JavaScript/TypeScript
JavaScript and TypeScript are easy thanks to tree sitter!
#+begin_src emacs-lisp
- (unless treesit-enabled
- (print "Cannot use JS/TS without tree-sitter!"))
-
(use-package eglot
:ensure nil
:after eglot
@@ -677,8 +734,7 @@ A.K.A. the most overused and overhyped language. This language is incredibly slo
(add-to-list 'eglot-server-programs
`(python-ts-mode . ("pyright-langserver" "--stdio")))
;(push ".dir-locals.el" project-vc-extra-root-markers)
- (when treesit-enabled
- (push '(python-mode . python-ts-mode) major-mode-remap-alist)))
+ (push '(python-mode . python-ts-mode) major-mode-remap-alist))
#+end_src
The following lets me set up a venv for use with pyright (https://robbmann.io/posts/emacs-eglot-pyrightconfig/):
#+begin_src emacs-lisp
@@ -719,5 +775,24 @@ LaTeX isn't really a language, but we should set up stuff for it.
Firstly, we should get CDLaTeX:
#+begin_src emacs-lisp
(use-package cdlatex
- :hook ((latex-mode LaTeX-mode) . turn-on-cdlatex))
+ :hook ((latex-mode LaTeX-mode) . turn-on-cdlatex)
+ :hook (latex-mode . (lambda () (setq tab-width 2))))
+#+end_src
+* Native Comp
+Supress all warnings:
+#+begin_src emacs-lisp
+ (setq native-comp-async-report-warnings-errors 'silent)
+#+end_src
+
+I used to always try to compile all the emacs packages in our config, I find that this just results in a build job running forever, even when we're done. Not sure what it's doing or what package it's for, but I'm just going to make this compilation process manual.
+#+begin_src emacs-lisp :tangle no
+ (when (fboundp 'native-comp-available-p)
+ (add-hook 'elpaca-after-init-hook (lambda () (native-compile-async user-emacs-directory t))))
+#+end_src
+
+Manual compile function:
+#+begin_src emacs-lisp
+ (defun ethandl/nativecomp-all ()
+ (interactive)
+ (native-compile-async user-emacs-directory 'recursively))
#+end_src
diff --git a/custom.el b/custom.el
diff --git a/init.el b/init.el
@@ -1,9 +1,13 @@
-(defvar elpaca-installer-version 0.7)
+;; elpaca build date, CHANGE EVERY BUILD
+(setq elpaca-core-date '(20250616))
+
+;; Start elpaca bootstrap
+(defvar elpaca-installer-version 0.11)
(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
(defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
- :ref nil :depth 1
+ :ref nil :depth 1 :inherit ignore
:files (:defaults "elpaca-test.el" (:exclude "extensions"))
:build (:not elpaca--activate-package)))
(let* ((repo (expand-file-name "elpaca/" elpaca-repos-directory))
@@ -13,29 +17,30 @@
(add-to-list 'load-path (if (file-exists-p build) build repo))
(unless (file-exists-p repo)
(make-directory repo t)
- (when (< emacs-major-version 28) (require 'subr-x))
+ (when (<= emacs-major-version 28) (require 'subr-x))
(condition-case-unless-debug err
- (if-let ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
- ((zerop (apply #'call-process `("git" nil ,buffer t "clone"
- ,@(when-let ((depth (plist-get order :depth)))
- (list (format "--depth=%d" depth) "--no-single-branch"))
- ,(plist-get order :repo) ,repo))))
- ((zerop (call-process "git" nil buffer t "checkout"
- (or (plist-get order :ref) "--"))))
- (emacs (concat invocation-directory invocation-name))
- ((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
- "--eval" "(byte-recompile-directory \".\" 0 'force)")))
- ((require 'elpaca))
- ((elpaca-generate-autoloads "elpaca" repo)))
+ (if-let* ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
+ ((zerop (apply #'call-process `("git" nil ,buffer t "clone"
+ ,@(when-let* ((depth (plist-get order :depth)))
+ (list (format "--depth=%d" depth) "--no-single-branch"))
+ ,(plist-get order :repo) ,repo))))
+ ((zerop (call-process "git" nil buffer t "checkout"
+ (or (plist-get order :ref) "--"))))
+ (emacs (concat invocation-directory invocation-name))
+ ((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
+ "--eval" "(byte-recompile-directory \".\" 0 'force)")))
+ ((require 'elpaca))
+ ((elpaca-generate-autoloads "elpaca" repo)))
(progn (message "%s" (buffer-string)) (kill-buffer buffer))
(error "%s" (with-current-buffer buffer (buffer-string))))
((error) (warn "%s" err) (delete-directory repo 'recursive))))
(unless (require 'elpaca-autoloads nil t)
(require 'elpaca)
(elpaca-generate-autoloads "elpaca" repo)
- (load "./elpaca-autoloads")))
+ (let ((load-source-file-function nil)) (load "./elpaca-autoloads"))))
(add-hook 'after-init-hook #'elpaca-process-queues)
(elpaca `(,@elpaca-order))
+;; End elpaca bootstrap
;; Install use-package support
(elpaca elpaca-use-package
@@ -46,40 +51,28 @@
(elpaca-wait)
-;; If we want to use the git version of org mode, we need to download it now
+;; Install a more up-to-date version of org
+;; (use-package org
+;; :defer
+;; :ensure `(org :repo "https://code.tecosaur.net/tec/org-mode.git/"
+;; :branch "dev")
+;; :hook
+;; (org-mode . org-latex-preview-auto-mode)
+;; :config
+;; ;; Ensure that live previews are on
+;; (setq org-latex-preview-live t)
+;; (setq org-latex-preview-live-debounce 0.25))
+(use-package org)
;; There are many reasons you might want to do this, but the git version is quite unstable as well
-;;(elpaca (org :host "git.tecosaur.net" :repo "tec/org-mode"))
-;;(use-package org
- ;;:ensure (:host "git.tecosaur.net" :repo "tec/org-mode"))
-(use-package org
- :defer
- :ensure `(org
- :remotes ("tecosaur"
- :repo "https://git.tecosaur.net/tec/org-mode.git"
- :branch "dev")
- :files (:defaults "etc")
- :build t
- :pre-build
- (with-temp-file "org-version.el"
- (require 'lisp-mnt)
- (let ((version
- (with-temp-buffer
- (insert-file-contents "lisp/org.el")
- (lm-header "version")))
- (git-version
- (string-trim
- (with-temp-buffer
- (call-process "git" nil t nil "rev-parse" "--short" "HEAD")
- (buffer-string)))))
- (insert
- (format "(defun org-release () \"The release version of Org.\" %S)\n" version)
- (format "(defun org-git-version () \"The truncate git commit hash of Org mode.\" %S)\n" git-version)
- "(provide 'org-version)\n")))
- :pin nil))
+
;; We then need to wait for the download of org to complete before we can use org.
(elpaca-wait)
+
(setq ethandl/config-fname (expand-file-name "config.org" user-emacs-directory))
(when (file-readable-p ethandl/config-fname)
(org-babel-load-file ethandl/config-fname))
;; Emacs crap that it does automatically:
+(setq ethandl/custom-file (expand-file-name "custom.el" user-emacs-directory))
+(setq custom-file ethandl/custom-file)
+(load custom-file)