Emacs

Published 2 Feb 2025. Last update 18 Feb 2025.
Tags: .

I started using Emacs for the mu4e mail client after using and liking the mu mail indexer on the command line (read more about my mail client setup). Similarly, I was using the ledger-cli accounting system, and found the Emacs minor mode to be great. Then I got curious about Emacs Org Mode and started using it for note taking and task management. Now I’m using Emacs as my primary development environment.

I realised that configuring Emacs to my liking would be like second job, which I didn’t have the bandwidth for, so I started using the ‘distribution’ Doom Emacs. It enables Vim bindings everywhere with Evil Mode which, coming from Vim, made it much easier to get up to speed.

The Emacs philosophy is different from Vim’s, it aims to be the ‘everything program’. It is it’s own operating system: a big Lisp machine distinct from the Unix shell I’m used to working in. It’s much more configurable and extensible than Vim – plugins are written in the same language that most of the Editor is itself, Emacs Lisp. A small example of how this results in a seamless experience; in Emacs I have vertico providing fuzzy finding capabilities, which extends to built-in UI elements. For example, M-x will fuzzy match on commands I can execute. In contrast, in Neovim I use telescope to provide fuzzy searching which I have to invoke separately – I still have the normal command prompt with : but I can fuzzy search commands with <leader>fq with this binding:

vim.keymap.set('n', '<leader>fq', require('telescope.builtin').commands)

Neovim might be adding similar extensibility for fuzzy searching. It seems like with things like Evil mode and Neovim’s Lua-focused extensibility the two editors are moving towards each other somewhat.

Emacs can be slow and a bit unwieldy however, so I still use Vim sometimes, like for small edits on remote servers.

You can find my Doom Emacs configuration here.

Below are my working notes on learning and using Emacs. There are some open questions that I haven’t found time to look in to – please get in touch if you have an answer!


general

  1. C-b C-x list buffers

  2. C-b x open buffer

  3. help:

    1. variable C-h v

    2. function C-h f

    3. key C-h k

  4. M-x command

  5. C-x C-e / (gr in evil) evaluate expression selected

  6. M-: / (SPC ; in doom) evaluate expression from minibuffer

  7. key binding conventions

  8. kmacro-edit-macro to edit recorded macro

  9. X evil-mode v_g_CTRL-A

    looks like evil-numbers provides this functionality but is bound to g= in Doom Emacs

  10. view-lossage view recent history of commands invoked with key bindings

  11. O try xref (doom emacs lookup module)

  12. O search and replace in project

    https://github.com/hungyiloo/hungyi.net/blob/archive-2024/content/posts/doom-emacs-search-replace-project.org

email / mu4e

  • m move mail
  • a v open in firefox
  • C compose
  • R/W/F/C/E reply/reply-to-all/forward/compose/edit(draft)
  • Pr toggle property
    • Ptr mu4e-include-related
  • e extract attachments
    • ~/.mailcap for external openers
    • A for more options
  • blue/yellow in header view mu4e-unread-face mu4e-flagged-face
  • exit composer
    • ZZ / C-c C-c send message
    • ZD / C-c C-d save to drafts and leave
    • ZF attach
    • ZQ / C-c C-k kill the message buffer (the message remains in the draft folder)
    • ZA / C-c C-a attach a file (pro-tip: drag & drop works as well in graphical context)
    • C-c C-; switch the context
  • disable include relevant by default
  • how to add a filter to a maildir
  • how to open URL with keyboard shortcut?
    • shr-browse-url
    • RET
    • browse-url-at-point
    • M-RET mu4e--view-browse-url-from-binding
    • gx
  • cw wide reply in message view with evil mode
  • M-q format paragraph
  • . view headers
  • how to switch message from plaintext to html with a keyboard shortcut?
  • custom account completition?
  • open attachment
    • mu4e-view-mime-part-action
    • doom’s A / +mu4e-view-select-mime-part-action is currently broken
  1. O how to have m / mu4e-headers-mark-for-move pick up the context

    it seems like match-func works for replies but not this

doom macs

  • SPC h b t which key show all bindings
  • C-h in which key to search bindings
  • SPC h v help variables
  • SPC h o help symbol
  • K help
  • gd go to definition
  • map!
  • SPC f s save file
  • SPC TAB workspaces
  • SPC b buffers
  • SPC s search
  • gr evaluate lisp
  • SPC g g magit
  • SPC o m mu4e
  • SPC o t terminal
  • SPC q s / SPC q l save / load session
  • SPC p f file in project
  • in minibuffer C-s searches history
  • SPC p p opens project in new workspace
  • jumplist C-i / C-o not working in terminal?
  • Why does the help menu not stay opening when switching windows?
    • Doom’s popup window implementation
    • C-~ make popup real window
  • How to get into normal mode in emacs minibuffers?
    • (setq evil-collection-setup-minibuffer t)
  • how to edit properties in org mode?
    • SPC m o
  • how to see org mode agenda?
    • SPC o a
  • M-` does menu bar
  • SPC h w where-is command
  • S evil-surround
  • spell checker

org-mode

manual

  1. time prompt

    • - to look at past day, e.g. -sun
  2. bindings

    1. org mode key bindings

      • M-ret add entry
      • M-S-ret todo entry
      • TAB / S-TAB
        • NB S-TAB is bound to org-shifttab instead of org-global-cycle
      • M-LEFT / M-RIGHT / M-UP / M-DOWN / M-S-LEFT / M-S-RIGHT org-meta
      • RET open link
    2. evil org keybindings

      • << / >> org-meta
      • vae / vaR
      • [ h / ] h
      • gj / gk / gh / gl
      • S-UP / S-DOWN prev / next item in list
    3. doom emacs org mode bindings

      • zc / zo / zO
      • SPC m h (SPC m *) / SPC m i toggle heading / item
      • SPC m d t / org-time-stamp
      • SPC m s S subtree sort
      • SPC m s s subtree sparse
      • SPC m x toggle checkbox SPC u SPC m x add checkbox
      • SPC m + / S-LEFT / S-RIGHT cycle checkboxes
      • SPC n l store link e.g. in email / mu4e
      • SPC m l l insert link
      • C-c RET insert heading C-M-RET insert subheading https://github.com/doomemacs/doomemacs/issues/3306
      • M-S-RET insert todo heading
      • SPC m t / S-LEFT / S-RIGHT TODO
      • SPC m q / C-c C-c (on heading) set tag
      • C-c \ org-match-sparse-tree on tags
      • SPC m o set property
      • C-c C-c on property property action
      • C-c . / SPC m d t / SPC m d T org timestamp
        • SPC u SPC m d t for date time
      • SPC m c clock commands
      • TAB see drawer
      • SPC m s r refile SPC m r R refile reverse
      • SPC X capture
      • SPC m A archive
      • SPC m s a archive tag
      • SPC m a attachment
      • SPC u 3 TAB show 3 level deep headings
  3. scripting

    #+begin_src python
    a = [ 1, 2, 3 ]
    return a
    #+end_src
    
    #+RESULTS:
    | 1 | 2 | 3 |
    

    evaluate with RET

    1. add with org-insert-structure-template

  4. agenda

    • how to exclude LOOP todo items from the todo list? org-agenda-filter-by-category / sc / \ on line
    • how to filter by tag? org-agenda-filter-by-tag / st / <
    • gD select time range
  5. how to do bibtex citations?

    • biblio doom module
    • org-cite-insert
    • citar-open-notes

latex

got a project compiling using doom emacs latex module which pulls in AUCTeX

  1. synctex

    SPC m v and Ctrl+click in evince

  2. X figure out how to use internal pdf viewer (seems like +latex/viewers isn’t respected)

  3. X figure out how to get SPC m v working from another tex file (seems like the master file detection is off)

    TeX-master-file

  4. X auto reload pdf on changes

    auto-revert-mode

  5. O pdf viewer search highlight https://github.com/vedang/pdf-tools/issues/162

  6. X resize pdf frame to page width

    here

android

Using doom-emacs in Android Emacs

ledger-mode

  • [[ / ]] next / prev transaction
  • SPC m a xact
  • TAB completion
  • SPC m t clear
  • SPC m R reconciliation
  • TAB mark transaction cleared (in reconciliation)

magit

  • SPC g C git clone
  1. See log of current buffer file

    • SPC g L
  2. See diff inline

    • L -p s

lsp-mode

  1. X figure out how to not watch .gitignore files

    here

how to act on all search matches

  • embark-collect (SPC a S)

LSP from devshells

  1. O how to configure this to run?

    • currently it runs for all files (e.g. markup files in my website directory, when I only need the Haskell LSP server for editing the static site generator)
    • it also triggers if I add website org file to the agenda list

shells

  1. shell drops you into a very minimal shell

    • basically just I/O in a buffer, ANSI escape codes and such aren’t supported
  2. shell-command

    • run a shell command in your default shell
    • doesn’t support sudo as can’t read from stdin
  3. eshell a ‘shell-like’ command interpreter implemented in emacs lisp

    • e.g. an alternative to your system shell
  4. eshell-command

    • runs a command in an eshell, and supports sudo with a prompt for the password
  5. async-shell-command / M-&

    • like shell-command but doesn’t lock emacs while the command is running and opens a buffer to display the output
    • also supports sudo with a prompt for the password
  6. project-<all of these commands

    • runs these shells in the current project root directory, as opposed to the current file’s directory
  7. term / vterm

    • runs a terminal emulator in emacs
  8. what do I use?

    • I’ll default to SPC p & which runs projectile-run-async-shell-command-in-root, which as far as I can tell is basically the same as project-async-shell-command, just because it’s the default in Doom Emacs.
    • Though it seems projectile is on the way out in favour of the in-built project.
  9. O how do I stop the async shell output splitting to the side and open a new window instead?

  10. O eshell-command supports completion, but the other shell commands don’t

    emacs-bash-completion might be something to look at

find a CalDAV calendaring application

  1. ~ org-caldav

  2. ~ Khalel

    • just imports a selection into an org file, and the org format is less expressive in some ways and more expressive in others
    • we really need to deal with the iCalendar format directly
  3. X Caledonia

    • okay, I’ve done it