Table of Contents
- Different themes per buffer
- RSS with Elfeed
- Lazy loading manually
- The Profiler
- After thoughts
The most appealing feature of Emacs is to enable every single user to enjoy a very customized experience and this is possible through a very powerful infrastructure a.k.a Elisp Interpreter and by lots of community contribution around packages and code fragments to accomplish the most varied tasks.
All of it can be summarized by the relationship between an Emacs user and she’s configuration setup.
Over the years I wrote a lot of customized
.emacs.d folders and even
added to my 2021 resolutions to stick with my current one for a longer
run. I tried to study the configs and explore possibilities, also I
enjoy the feeling of “crafting my own tool” behind it.
Let’s talk about some of these experiments.
I don’t even use this setup in my daily activities but I invested a lot of time in crafting this beauty. The setup uses EXWM as my Window Manager and lots of customization around desktop activities such as screenshots, multi-monitor support, audio, etc.
- Link: github
- Style: Literate Programming in Org-mode
- Goal: Emacs all the way down!
- Rate: 7/10
- Bad aspects: Eventual hanging during Garbage Collection
I learned a lot about literate programming style and how awesome Org Mode can be to accomplish that, but there are a couple of interesting things in this config I want to call out.
Different themes per buffer
Add this code to your
load-path and you can use the function
load-theme-buffer-local to customize it such as this example:
(load-theme-buffer-local 'deeper-blue (get-buffer "*wttr.in - São Paulo*"))
English is not my first language, therefore I use a lot of resources to spell-check, find meanings, translation, synonyms for common words, etc. I use this same setup for ages.
RSS with Elfeed
Yeah, I enjoyed a lot to do all this customization with Elfeed. Specially the portion about scoring each RSS entry to match content I would be more interesting in reading first.
Also, you see the power of literate programming in Org-mode using this anchors.
(require 'elfeed) (require 'cl-lib) (require 'elfeed-search) (require 'elfeed-db) <<elfeed-basic-config>> <<elfeed-mode-disabled>> <<elfeed-newsletters>> <<elfeed-scoring>> <<elfeed-filters>> <<elfeed-automatic-update>> <<elfeed-starred>> <<elfeed-youtube>>
Lazy loading manually
I always understood in theory how lazy loading works, but I never gave much attention to it. I tend to not close my Emacs session that often, therefore startup time was rarely an issue for me (which is usually the main motivation I see around for lazy loading)
However, as I stared digging deeper in Emacs and look at what packages were loaded at a time, I wondered “why does CIDER (clojure interactive development environment) is loaded when I only want to write some essays in Org-mode?” (I made up this example to illustrate the point, can’t remember which package was the trigger)
Then I started a new config to manage to understand this situation.
- Link: github
- Style: Small separate modules
- Goal: Only load modules when I actually need them
- Rate: 8/10
- Bad aspects: Too manual
I noticed that I had started my own “framework” and I even wrote some specialized functions to handle some activities such as load, update, list, and delete packages.
The bulk of the work is here:
(defun bk/add-load-path (pkg subdir) "If PKG/SUBDIR exist add it to `load-path'. Return non-nil if successful." (let* ((path (concat (file-name-as-directory (expand-file-name pkg user-emacs-directory)) (concat "pkgs/" subdir)))) (when (file-readable-p path) (add-to-list 'load-path path)))) (defun bk-auto-loads (file &rest func-or-ext-with-func) "`autoload' and `auto-mode-alist' for packages in the FILE. FUNC-OR-EXT-WITH-FUNC are the triggers of the package activation. After any of the functions is called, the whole package is loaded in memory." (dolist (x func-or-ext-with-func) (autoload (if (consp x) (cdr x) x) file "Undocumented `autoload'." t) (when (consp x) (add-to-list 'auto-mode-alist x))))
With this two functions you can “register” the entrypoint functions to your modules or functionalities that will be the triggers to load the full module afterwards.
;; * cider mode ;; - History ;; - 2020-08-14 Created ;; - 2020-08-18 Adding key binding to cider-jack-in (when (bk/add-load-path "langs/clojure" "cider") (bk-auto-loads "cider" #'cider-jack-in #'cider-connect #'cider-jack-in-clj&cljs))
In the case above, if you open your Emacs and hit
M-x cider- the only
options you will see are those three functions registered as
entrypoint. To contrast with my current setup (which I just found out
and really don’t like that much), I haven’t used Clojure today at all
and if I hit
M-x cider- there are hundreds of functions available.
(use-package cider :ensure t :commands (cider cider-connect cider-jack-in cider-jack-in-clj) :config (add-hook 'cider-mode-hook #'eldoc-mode) (add-hook 'cider-mode-hook #'whitespace-cleanup-mode) (add-hook 'cider-repl-mode-hook #'eldoc-mode) (add-hook 'cider-repl-mode-hook #'paredit-mode))
use-package I expected that only the functions specified in
:commands key were available to me. (Another fight, for another
I thought about continuing evolving this configuration to improve the very bad aspect of “manual installation” of packages and its dependencies through git submodules. Who knows, I might come back to it some day.
My idea was to leverage chemacs to build very isolated configurations to specific tasks. For example, I might open my “clojure toolbox” that only is concerned with Clojure and nothing else.
- Link: github
- Style: Separate folders per “goal”
- Goal: Provide specific configuration schemes for your goals
- Rate: 8/10
- Bad aspects: Not too bad if you live in the terminal
The idea was to provide a configuration file (the same from chemacs actually was pretty good) and be able to lunch your own instances as you need. The cost of startup time is decreased by loading all the instances as emacs servers when you log in.
(("default" . ((user-emacs-directory . "~/emacs/profile/default"))) ("clojure" . ((user-emacs-directory . "~/emacs/profile/clojure"))) ("roam" . ((user-emacs-directory . "~/emacs/profile/roam"))) ("ledger" . ((user-emacs-directory . "~/emacs/profile/ledger"))))
And a set of aliases to help you out.
# GUI instances alias emacs="emacsclient -c -s default" alias emacs.default="emacsclient -c -s default" alias emacs.clojure="emacsclient -c -s clojure" alias emacs.roam="emacsclient -c -s roam" alias emacs.ledger="emacsclient -c -s ledger" # terminal instances alias et="emacsclient -t -s default" alias et.default="emacsclient -t -s default" alias et.clojure="emacsclient -t -s clojure" alias et.roam="emacsclient -t -s roam" alias et.ledger="emacsclient -t -s ledger"
I still like this idea.
I like how much I learned by writing each one of this configuration files and I am definitely proud to be able to go through my own ideas and explore Emacs landscape. But the underlying principle here is how flexible Emacs actually is.
My current configuration setup is this one which I am aiming to learn
more about how to leverage
The term Emacs Bankruptcy is very famous in the community, but I don’t believe this is the only reason you would be willing to “re-write” your configurations. I definitely encourage you to experiment.
You will notice that some pieces of code will follow you whatever you go :)