RSS Amplifier

cleberg.net · Feb 2, 2026

Emacs Carnival: Completion

0
Sign in to vote or save

Christian Cleberg <hello@cleberg.net> · cleberg.net

· My response to the Emacs Carnival prompt for February 2026.

I'm having a great time with the Emacs Carnival, as it has inspired me to write two posts in such a short time. It's been a much-needed inspiration to write during my busy season at work.

Anyway, let's get to it. The topic today is Completion: the magical thing that turns someone like me, who cannot remember long lists of commands to save my life, from an illiterate to a literate programmer.

1. Defining Custom Abbreviations

While you can define abbrevs dynamically in the buffer with C-x a g (which generally saves abbrevs to /.emacs.d/abbrev_defs), I prefer to define my abbreviations directly within my config.el file.

This allows for better portability between my machines, as well as clearer configuration for myself.

To create a new abbrev, I simply open ~/.config/doom/config.el and add a new one to the list below.

;; Abbreviations
(setq-default abbrev-mode t)
(define-abbrev-table 'global-abbrev-table
  '(
    ;; ("abbreviation" "expansion")
    ("omw" "on my way")
    ("eml" "hello@cleberg.net")
    ("shrg" "¯\_(ツ)_/¯")
    ("teh" "the")
    ("xtoday" "" (lambda () (insert (format-time-string "%Y-%m-%d %H:%M:%S"))))
    ("xnow" "" (lambda () (insert (format-time-string "%H:%M:%S"))))
    ))

Now, I can type something like xtoday in my buffer and get the fully formatted time string, like so: 2026-02-02 21:52:55.

¯\_(ツ)_/¯

This comes in handy most at work, where I need to constantly use acronyms and take shorthand notes to fill out phrases that I'm, unfortunately, required to reuse constantly. Looking at you, "completeness and accuracy of the data".

2. Doom Configuration

I have played around with a few different completion options for my purposes and have settled on the following packages.

Here is how I have my :completion, :tools, and :lang modules toggled in ~/.config/doom/init.el:

(doom! :input
       :completion
       (corfu +orderless)  ; complete with cap(f), cape and a flying feather!
       vertico             ; the search engine of the future
        :checkers
       syntax              ; tasing you for every semicolon you forget
       (spell +flyspell)   ; tasing you for misspelling mispelling
       grammar             ; tasing grammar mistake every you make
       :tools
       (lsp +eglot)        ; M-x vscode
       :lang
       data                ; config/data formats
       emacs-lisp          ; drown in parentheses
       json                ; At least it ain't XML
       javascript          ; all(hope(abandon(ye(who(enter(here))))))
       markdown            ; writing docs for people to ignore
       (org +dragndrop     ; drag & drop images/files into org
            +journal       ; daily logging
            +noter         ; for annotating PDFs (great for research)
            +roam2)        ; Zettelkasten note-taking
       python              ; beautiful is better than ugly
       sh                  ; she sells {ba,z,fi}sh shells on the C xor
       :config
       (default +bindings +smartparens))

With this setup, I am able to get a wonderful IDE-level experience within Emacs and without the bloat of a traditional IDE. It's the perfect balance of speed and power for my work and hobbies.

2.1. vertico + marginalia

Vertico is wonderful for finding files (SPC .) or running commands (SPC :). It provides a clean, vertical interface for the minibuffer.

Marginalia works wonderfully with Vertico, as it provides marginalia to the minibuffer commands within the command selection buffer.

Vertico: Command
Figure 1: Vertico: Command
Vertico: Files
Figure 2: Vertico: Files

2.2. orderless

Orderless is a game changer. As I mentioned above, I'm terrible with memorization. Therefore, I use this package and am able to search with multiple out-of-order terms to find a result in my Vertico searches.

Orderless
Figure 3: Orderless

2.3. corfu

For code completion, I’ve swapped out Company mode for Corfu. It’s faster, stays out of my way until I need it, and uses a small popup that feels right at home in a terminal or a GUI.

Corfu
Figure 4: Corfu

2.4. eglot

To actually "know" what my code is doing, I use LSP (Language Server Protocol). I've enabled the +eglot flag in Doom because Eglot is now built into Emacs core and tends to be a bit more stable and performant for my Python and JavaScript workflows.

2.5. flyspell

Flyspell is the last piece to my puzzle, as it allows for easy help in correcting grammar errors within the buffer. I combine flyspell + syntax + grammar for ultimate writing guidance. Whether or not I choose to follow that guidance is another story entirely.

Flyspell
Figure 5: Flyspell

3. Looking Forward

I know this is just the tip of the iceberg, so I've made a list of packages I want to dive into deeper in the future:

  • tempel
  • yasnippet
  • consult
  • embark
  • cape
  • kind-icon
  • prescient.el

Completion and expansion utilities are phenomenal and have been one of the larger tools in my development and writing.

Want to participate in the Emacs Carnival or read more posts? Visit the main Carnival page on the Emacs Wiki to learn more.

...or, comment on this post on Bubbles!

Read the original on cleberg.net

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.