commit c96358c02c46cba428de2502235e36ae3c09eb91
parent 8fc92b518721a177c47c8f6e52dc99e4b2f211b4
Author: Ethan Long <ethandavidlong@gmail.com>
Date: Sat, 20 Jun 2026 02:10:10 +1000
Implemented a rather ludicrous optimisation
I was able to get rid of the blocking (elpaca-wait) call by setting up
my own async queuing system w/ the async package.
Check it out if you're interested, but there are two queues; one has
eagrely defined functions, and the other has lazy functions that are
evaluated only just before execution by `async`. Really this solution is
a very overkill way of being able to use `async-inject-variables`
without the `async` package being in-scope.
This could be drastically simplified by just using a list of tuples,
with the fn being on one branch of the tuple and the inject-vars rules
being on the other, but that would be too easy... And simple...
Damn it.
Diffstat:
| M | config.org | | | 84 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------- |
1 file changed, 69 insertions(+), 15 deletions(-)
diff --git a/config.org b/config.org
@@ -254,7 +254,7 @@ To define our desired fonts, we create functions as we did before in [[Code font
Use HEIGHT to specify the font height in px, VAR as the variable-pitch
font family, and MONO as the monospace font family. If HEIGHT is nil,
- uses a height of 155. If VAR or MONO are nil, selects the first
+ uses a height of 140. If VAR or MONO are nil, selects the first
available font for each from a predefined list."
(setq ethandl/org-mono-font-name
(or mono
@@ -274,7 +274,7 @@ To define our desired fonts, we create functions as we did before in [[Code font
"Times New Roman"
"DejaVu Serif"))))
(setq ethandl/org-font-ht
- (or height 155)))
+ (or height 140)))
#+end_src
Next, we define a way to easily apply these fonts.
@@ -305,19 +305,20 @@ This is not as simple as it should be, because ~variable-pitch-mode~ takes over
Finally, we apply these fonts every time we enter org mode.
#+begin_src emacs-lisp
- (ethandl/set-org-fonts)
(add-hook 'org-mode-hook #'ethandl/set-org-fonts)
#+end_src
** Theme
I like the Catppuccin theme, but the official one kinda stinks. As such, I use the ~batppuccin~ theme:
#+begin_src emacs-lisp
(elpaca batppuccin
+ (require 'batppuccin)
(load-theme 'batppuccin-mocha t))
#+end_src
Another nice theme is ~gruber-darker~ by tsoding, one can use it similarly:
#+begin_src emacs-lisp :tangle no
(elpaca gruber-darker-theme
+ (require 'gruber-darker-theme)
(load-theme 'gruber-darker t))
#+end_src
* Emacs behaviour
@@ -350,6 +351,7 @@ For smooth mouse and faster document scrolling, I use the package ~ultra-scroll~
This works on all emacs builds to my knowledge, and is by far the best scrolling package.
#+begin_src emacs-lisp
(elpaca ultra-scroll
+ (require 'ultra-scroll)
(ultra-scroll-mode 1)
(add-hook 'ultra-scroll-hide-functions #'org-modern-mode))
#+end_src
@@ -363,7 +365,50 @@ For debugging purposes, you can disable the tangling of this block:
** Asyncronous commands
The package ~async~ allows for us to run long, blocking commands in separate Emacs processes.
#+begin_src emacs-lisp
- (elpaca async)
+ (setq ethandl/async-fn-queue nil)
+ (setq ethandl/lazy-async-fn-queue nil)
+ (setq ethandl/async-fn-evaluated nil)
+
+ (defun ethandl/eval-async-fn-queue ()
+ ;; Evaluate regular async fns
+ (push (mapcar #'async-start ethandl/async-fn-queue)
+ ethandl/async-fn-evaluated)
+ (setq ethandl/async-fn-queue nil)
+
+ ;; Generate lazy async fns and evaluate
+ (let ((fns (mapcar #'funcall ethandl/lazy-async-fn-queue)))
+ (push (mapcar #'async-start fns)
+ ethandl/async-fn-evaluated))
+ (setq ethandl/lazy-async-fn-queue nil))
+
+ (defun ethandl/async-fn-queue-add (form &optional inject-vars)
+ (if inject-vars
+ (push (lambda ()
+ `(lambda ()
+ ,(async-inject-variables inject-vars)
+ ,form))
+ ethandl/lazy-async-fn-queue)
+ (push `(lambda () ,form) ethandl/async-fn-queue)))
+
+ (elpaca async
+ (require 'async)
+ (ethandl/eval-async-fn-queue)
+ (run-with-idle-timer 30 t 'ethandl/eval-async-fn-queue))
+#+end_src
+** Ahead-of-time nativecomp
+After just installing this Emacs config, things can be a little stuttery. We can speed this up by telling Emacs to nativecomp everything.
+
+Here is a simple convenience function to compile everything in this config, including all packages installed with ~elpaca~:
+#+begin_src emacs-lisp
+ (defun ethandl/nativecomp-aot ()
+ (interactive)
+ (native-compile-async user-emacs-directory t))
+#+end_src
+
+We add this to the ~elpaca-after-init-hook~ so that everything is compiled after initial installation. Any subsequent compilation can occur at runtime.
+#+begin_src emacs-lisp
+ (add-hook 'elpaca-after-init-hook
+ #'ethandl/nativecomp-aot)
#+end_src
* Org mode
** Section numbering
@@ -384,6 +429,7 @@ I lied: this package is just for beauty because Org is somewhat ugly by default.
Unfortunately, this package conflicts with ~visual-wrap-prefix-mode~, so we need to explicitly disable that for org mode with a hook function.
#+begin_src emacs-lisp
(elpaca org-modern
+ (require 'org-modern)
(add-hook 'org-mode-hook #'org-modern-mode)
(add-hook 'org-agenda-finalize-hook #'org-modern-agenda)
(add-hook 'org-mode-hook (lambda () (visual-wrap-prefix-mode 0))))
@@ -420,35 +466,40 @@ If we want images generated by the output of ~org-babel~ to automatically render
#+end_src
This will save a ~C-c C-x C-v~ invocation every time we want to display newly generated images.
* The programming environment
-** Org babel env init
-Throughout these subsections, I will add languages to a list of languages that Org can evaluate in code blocks. The default list includes elisp, but we will rebuild it from scratch in the following sections:
+** Org babel
+In addition to being a useful Markdown alternative, Org mode can also serve as a literate programming environment and (shitty) Jupyter replacement.
+
+The intended configuration for ~org-babel~ involves defining your list of languages to support all at once using the ~org-babel-do-load-languages~ function.
+To allow for the language list (contained in ~ethandl/org-babel-langs~) to be defined dynamically (even in environment), the following function is defined:
#+begin_src emacs-lisp
(setq ethandl/org-babel-langs nil)
(defun ethandl/org-babel-load-langs ()
(org-babel-do-load-languages
'org-babel-load-languages
ethandl/org-babel-langs))
+#+end_src
+This list is then evaluated dynamically every time an Org document is opened through the ~org-mode-hook~:
+#+begin_src emacs-lisp
(add-hook 'org-mode-hook #'ethandl/org-babel-load-langs)
#+end_src
** The ~vterm~ terminal emulator
-To make emacs a useful development environment, we need a good terminal. Instead of using a separate terminal emulator like a Unix puritan, we use the ~vterm~ package:
+To make emacs a useful development environment, we need a good terminal.
+In addition to using separate (good) terminals, we can use the cromulent ~vterm~ package:
#+begin_src emacs-lisp
(elpaca vterm)
#+end_src
** Treesitter grammar async install
Treesitter grammar installation is slow and blocks up the emacs process. The following allows for asyncronous treesitter grammar installation on separate processes:
#+begin_src emacs-lisp
- (elpaca-wait)
(defun ethandl/treesit-install-async (lang)
(unless (treesit-language-available-p lang)
- (async-start
- `(lambda ()
- ,(async-inject-variables "\\`treesit-language-source-alist\\'")
- (treesit-install-language-grammar ',lang))
- 'ignore)))
+ (ethandl/async-fn-queue-add
+ `(treesit-install-language-grammar ',lang)
+ "\\`treesit-language-source-alist\\'")))
#+end_src
** Markdown mode
-Emacs comes with ~markdown-ts-mode~, which utilises treesitter to provide highlighting for markdown. This means that we need the treesitter grammar installed:
+Emacs comes with ~markdown-ts-mode~, which utilises treesitter to provide highlighting for markdown.
+To use this mode, we just install the treesitter grammar(s):
#+begin_src emacs-lisp
(add-to-list 'treesit-language-source-alist
'(markdown "https://github.com/tree-sitter-grammars/tree-sitter-markdown" "split_parser" "tree-sitter-markdown/src"))
@@ -459,11 +510,14 @@ Emacs comes with ~markdown-ts-mode~, which utilises treesitter to provide highli
(ethandl/treesit-install-async 'markdown-inline)
#+end_src
** Emacs Lisp
-Not much needs to be done here. For verbosity, I will specify that we want Org to be able to run elisp:
+Not much needs to be done here.
+For verbosity, I will specify that we want Org babel to be able to evaluate elisp ~src~ blocks:
#+begin_src emacs-lisp
(add-to-list 'ethandl/org-babel-langs '(emacs-lisp . t))
#+end_src
** Python
+There are two python modes installed by default with Emacs.
+From my (admittedly limited) experience, ~emacs-ts-mode~ tends to have
#+begin_src emacs-lisp
(add-to-list 'treesit-language-source-alist
'(python "https://github.com/tree-sitter/tree-sitter-python"))