#+date: [2026-02-02 Mon 18:40:21] #+title: Emacs Carnival: Completion #+description: My response to the Emacs Carnival prompt for February 2026. #+slug: emacs-carnival-2026-02-completion #+filetags: :emacs:personal: 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 [[https://www.emacswiki.org/emacs/CategoryCompletion][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. * Defining Custom Abbreviations While you can define [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Abbrevs.html][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. #+begin_src elisp ;; 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")))) )) #+end_src 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". * 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~: #+begin_src elisp (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)) #+end_src 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. ** [[https://github.com/minad/vertico][vertico]] + [[https://github.com/minad/marginalia][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. #+caption: Vertico: Command [[https://img.cleberg.net/blog/20260202-emacs-carnival-2026-02-completion/vertico-commands.webp]] #+caption: Vertico: Files [[https://img.cleberg.net/blog/20260202-emacs-carnival-2026-02-completion/vertico-files.webp]] ** [[https://github.com/oantolin/orderless][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. #+caption: Orderless [[https://img.cleberg.net/blog/20260202-emacs-carnival-2026-02-completion/orderless.webp]] ** [[https://github.com/minad/corfu][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. #+caption: Corfu [[https://img.cleberg.net/blog/20260202-emacs-carnival-2026-02-completion/python.webp]] ** [[https://github.com/joaotavora/eglot][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. ** [[https://github.com/leotaku/flycheck-aspell?tab=readme-ov-file][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. #+caption: Flyspell [[https://img.cleberg.net/blog/20260202-emacs-carnival-2026-02-completion/suggestions.webp]] * 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. #+begin_quote Want to participate in the Emacs Carnival or read more posts? Visit the main [[https://www.emacswiki.org/emacs/Carnival][Carnival]] page on the Emacs Wiki to learn more. #+end_quote