[go: up one dir, main page]

Posts

  • The role of the Escape key in Emacs

    The Escape key (ESC) is legendary in vim, Emacs’s arch-rival. It’s so commonly used (mostly to switch back to normal mode and interrupt commands in progress) that you’ll find many articles on where to remap it (e.g. to Caps Lock), and there are also many keyboards that place ESC where ~ normally is, to make it more accessible.1

    In Emacs-land, however, we never really speak about ESC… Why so? Well, we use C-g to interrupt commands, and we obviously don’t have modal editing, at least not by default. Still, I think ESC has its uses in Emacs, even if they are not super obvious at first. For instance there’s the keyboard-escape-quit command, that’s described like this:

    Exit the current “mode” (in a generalized sense of the word). This command can exit an interactive command such as ‘query-replace’, can clear out a prefix argument or a region, can get out of the minibuffer or other recursive edit, cancel the use of the current buffer (for special-purpose buffers), or go back to just one window (by deleting all but the selected window).

    Basically, it’s a fancier way of doing C-g (keyboard-quit), and it’s mapped to ESC ESC ESC (triple escape). Not the most convenient keybinding, but still OK if your Escape is well positioned and you’d like to avoid holding down a modifier key.2 If you take a look at the keybinding in Emacs’s docs, though, you’ll see it’s listed as M-ESC ESC, rather than ESC ESC ESC. And this is what makes ESC really interesting - it serves as a substitute for Meta, but you don’t have to hold down ESC - instead M-something keybindings can be triggered by pressing ESC and the other key sequentially. Go ahead and try the following:

    • ESC x (same as M-x)
    • ESC g g (goto-line, same as M-g g)
    • ESC e (forward-sentence, same as M-e)

    I don’t know about you, but I think this is pretty handy, especially if you’re using macOS, where on many keyboards the Option (Meta) keys are pretty short, or one of them is even missing (the right one).

    For me using Emacs on macOS has always been a bit of a struggle, as the Meta is way more useful than Command (Super), and historically I swapped them3 because of this, but then I struggled when I had to use someone else’s keyboard. (or even my own, as I normally contained this rebinding only to Emacs). So, the ability to use ESC instead of Meta is definitely a welcome one, and I find myself doing this quite often.

    Before we wrap up consider keybindings like M->, M-! or M-% that require you to hold down both Shift and Meta when typing them. I think they way more pleasant as:

    • Esc >
    • Esc !
    • Esc %

    Admittedly, it took me a while to get used to this, as I didn’t pay much to the ESC key until I was fairly far into my Emacs journey. Topics like RSI prevention and keybinding ergonomics rarely bother young people.

    So, did you know about the role of ESC in Emacs? Are you making use of it? If you have any other tips to share on the subject I’d be happy to read them.

    That’s all I have for you today! ESC x forever!

    1. HHKB is probably the most famous example, but there are many many others that do the same. 

    2. I’m using a dual-function keybinding for what’s normally Caps Lock on most keyboards - it’s Control wwhen held down and Escape otherwise. For me that’s a good idea regardless of the editor someone’s using. 

    3. See https://batsov.com/articles/2012/10/14/emacs-on-osx/

  • Debugging Errors in Emacs

    I recently wrote an article on debugging Emacs commands. In it I mentioned M-x toggle-debug-on-error and debug-on-error briefly, but after posting the article I realized that many people probably don’t understand how this works exactly.

    The obvious thing that happens when debug-on-error is enabled is that when an error happen you’re seeing its backtrace (or stacktrace, depending on the terminology you prefer). What’s not so obvious (even, if it’s in the name) is that this buffer is actually a debugger buffer and you can do a lot with it. Here are a few examples:

    1. Navigate the Stack Trace: Move your cursor in the *Backtrace* buffer to different lines representing various stack frames.
    2. Examine Local Variables: Press v (debugger-toggle-locals) while on a stack frame to display local variables for that frame.
    3. Evaluate Expressions: Use e (debugger-eval-expression) to evaluate Lisp expressions in the context of the current frame.
    4. Step Through Code: Use d to step into function calls and evaluate expressions one by one.
    5. Continue Execution: Press c to continue normal execution. (note, that unless you change something, this will result in the error you’re trying to debug)
    6. Quit Debugging: Enter q to exit the debugger and abort the current command.
    7. View Help: Type ? to see a list of available debugger commands.
    8. Record Evaluations: Use E to evaluate an expression and save the result in the Debugger-record buffer.

    It’s important to understand that debugger runs in the environment of the error, allowing you to examine variable values precisely as they were at the time of the error. This makes it a powerful tool for understanding and fixing issues in your Emacs Lisp code.

    That debugging experience is one of the most powerful features of Lisps in general, and it’s one of the reasons why developing and debugging Emacs packages is pretty pleasant and productive experience. Provided you’re familiar with how to use the debugger in such cases that it.

    You can more help inside Emacs by pressing C-h m while in a debugger buffer.

    So, to recap - in case you run into some errors you should run the command M-x toggle-debug-on-error, re-run whatever action caused the error and then navigate the stacktrace in the debugger to figure out what went wrong exactly.

    To debug an error that happens during loading of the init file, use the option --debug-init. This binds debug-on-error to t while loading the init file, and bypasses the condition-case which normally catches errors in the init file.

    That’s all I have for you today. I hope you’ve learned something useful today and next time you run into some error you’ll be able to fix it in no time!

  • Customizing Color Themes

    Every now and then you’d be trying out a new color theme, that you really like overall, but you’d like to tweak a bit here and there to make it perfect. After all, that’s what Emacs is all about - creating the perfect editor for yourself.

    Sometimes you might be dealing with missing face definitions or configuration options that you might want to submit upstream, but most of the time the changes you’d like to see are probably quite subjective and belong in your personal config. So, how do you make those changes?

    There are 3 common ways to adjust font faces in Emacs and I’ll briefly cover all of them. Option number 1 is the tried and true classic custom-set-faces:

    (custom-set-faces
     '(region ((t (:inherit nil :background "RoyalBlue4"))))
     '(highlight ((t (:inherit region :background "dark olive green"))))
     '(hl-line ((t (:inherit highlight)))))
    

    That’s what gets generate if you’re adjusting faces with something like M-x customize-face. The bad thing about this approach is that those customizations will active regardless of your currently selected color theme and if you like to switch themes that’s not cool. Fortunately, it’s easily to narrow customizations to a particular theme with custom-theme-set-faces:

    (custom-theme-set-faces
     'zenburn
     '(region ((t (:inherit nil :background "RoyalBlue4"))))
     '(highlight ((t (:inherit region :background "dark olive green"))))
     '(hl-line ((t (:inherit highlight)))))
    

    Looking good!

    Note: custom-set-faces works by calling custom-theme-set-faces for the user theme, a special theme referring to settings made via Customize.

    Finally, you can just set a specific face using set-face-attribute like this:

    (set-face-attribute 'font-lock-builtin-face nil :weight 'bold)
    

    I’d suggest perusing the documentation of set-face-attribute (e.g. with C-h f) as it explains in great detail all the possible attributes you can configure for a font face. The number of properties you can set is truly epic, but most of the time you’ll need to tweak only a couple of them. (e.g. :foreground, :background, etc)

    Technically speaking, you can go a step further than that and define your own theme that extends the color theme you want to modify1, but that’s an overkill unless you plan to distribute this theme as a package.

    All the examples above are kind of random, so I’ll conclude here with some real modifications I do in my config to the popular Catppuccin theme:

    (use-package catppuccin-theme
      :config
      ;; or 'latte, 'macchiato, or 'mocha
      (setq catppuccin-flavor 'macchiato)
      (load-theme 'catppuccin t)
      (custom-theme-set-faces
       'catppuccin
       ;; by default the theme uses the same face as for comments, which is wrong IMO
       '(font-lock-doc-face ((t (:foreground (catppuccin-color 'green)))))
       ;; font-lock variable definitions like function definitions
       '(font-lock-variable-face ((t (:inherit font-lock-function-face))))))
    

    The example above also shows how to access the colors from the palette of some color theme outside of its definition. Usually themes provide some API like theme-name-color to get able to get the color codes easily.

    Funny enough, as I’m writing this I realized that use-package actually has built-in support for customizing faces that I could have used instead. Here’s an example of that in action:

    (use-package zenburn-theme
      :preface
      (setq my/zenburn-colors-alist
            '((fg . "#DCDCCC") (bg . "#1C1C1C") (cyan . "#93E0E3")))
      :custom-face
      (region ((t (:background ,(alist-get my/zenburn-colors-alist 'cyan)))))
      :config
      (load-theme 'zenburn t))
    

    This example also reminded me that I should expose the Zenburn colors via functions.

    So, to summarize:

    • If you’re using use-package it’s probably best to use it’s :custom-face functionality.
    • The rest of the time you most likely need custom-theme-set-faces.

    One thing is certain - with Emacs there always numerous ways to achieve something!

    Note: To see the new font faces in action you’ll either have to restart Emacs or evaluate Elisp code that sets them. (e.g. with C-x C-e)

    One final tip - if you’re wondering what’s the face used by some text, the best way to figure it out is with the M-x describe-char command. It will give you a ton of information, including something like this near the end:

    There are text properties here:
      face                 (font-lock-keyword-face markdown-code-face)
      font-lock-fontified  t
      font-lock-multiline  t
      fontified            t
      markdown-gfm-code    (2617 3092)
    

    I had placed my cursor over the word “use-package” in the code snippet above, while writing this article in markdown-mode, therefore the faces font-lock-keyword-face (coming from elisp-mode) and markdown-code-face (from markdown-mode).

    Do you have any tips on customizing color themes that you’d like share?

    That’s all I have for you today. Keep hacking!

    1. Remember that Emacs allows you load multiple themes with them stacking one upon another. 

  • Clean Unloading of Emacs Themes

    If you’re like me, you probably like playing with new Emacs color themes from time to time. Sure, I’m the person behind the Emacs ports of Zenburn and Solarized, but as much as I like them, even I get bored with them occasionally.1

    What I often do is to install a bunch of themes (e.g. using M-x package-install) and to quickly try them out by evaluating snippets like the ones below in Emacs:

    (load-theme 'catppuccin t)
    
    (load-theme 'dracula t)
    
    (load-theme 'gruvbox t)
    

    One small problem with this, though, is that Emacs themes were designed in such a way that one theme can be applied on top of another one. (loading a new theme doesn’t unload the previusly loaded one) In practice this often means that if you load a few themes one after another they’ll start to mess each other up. There are several ways to address this, the simplest being to call disable-theme every time before loading a new theme:

    (load-theme 'catppuccin t)
    
    (disable-theme 'catppuccin)
    (load-theme 'dracula t)
    
    (disable-theme 'dracula)
    (load-theme 'gruvbox t)
    

    Or you can get more adventurous and create a small command that unloads all loaded themes, effectively resetting the theme to Emacs’s default one:

    (defun er-disable-all-active-themes ()
      "Disable all currently active themes."
      (interactive)
      (dolist (theme custom-enabled-themes)
        (disable-theme theme)))
    

    Now, you can simply do M-x disable-all-active-themes when you see fit. Finally, you can consider creating a function complementary to load-theme that unloads all active themes before loading the new one:

    (defun er-load-theme (theme)
      (er-disable-all-active-themes)
      (load-theme theme t))
    
    (er-load-theme 'catppuccin t)
    
    (er-load-theme 'dracula t)
    
    (er-load-theme 'gruvbox t)
    

    Pretty neat!

    That’s all I have for you on this subject. Keep hacking!

    P.S. If you’re afraid of Elisp there are a couple of alternative approaches you might consider:

    • The built-in command M-x customize-themes
    • The consult-theme from the popular consult package

    Both are also great options for previewing themes!

    1. Zenburn is to this day my all time favorite theme, though. I rarely manage to spend more than a few days away from it. 

  • Debugging Emacs Commands

    If you’re using Emacs long enough sooner or later you’ll run into some Emacs command that’s misbehaving and you’ll need to debug it somehow.1

    If the command is just blowing up, probably you’ll be able to figure out what’s going on by looking at its backtrace. To get meaningful backtraces you can either run M-x toggle-debug-on-error or add this to your Emacs config:

    (setq debug-on-error t)
    

    Sometimes that will be enough, but other times you’ll need to dig deeper… Fortunately for us Emacs features a super powerful built-in Emacs Lisp debugger and using it is the best way to diagnose problems of any kind.2

    To debug some command you need to do the following:

    • Figure out the name of the command you want to debug (e.g. by using C-h k to see which command is associated with some keybinding)
    • Find the source of the command (e.g. by using M-x find-function RET function-name)
    • Press C-u C-M-x while in the body of the function
    • Run the command again

    At this point you’ll be dropped in the debugger and you can step forward (by pressing n) until you find the problem. The debugger is quite powerful and you can do way more than just stepping through the code, though. Here are some of the most useful commands to run in it:

    • n (next): Step over the next expression
    • d (step): Step into a function call
    • c (continue): Continue execution until the next breakpoint
    • e (eval): Evaluate a Lisp expression in the current context
    • b (break): Set a breakpoint at a specific line or function
    • u (unset): Remove a breakpoint
    • q (quit): Exit the debugger
    • r (return): Specify a return value and continue execution
    • ? (help): Shows the full list of debugger commands.

    You can read more about the debugger commands here. I would also suggest reading the short tutorial in Emacs’s manual.

    I use this approach all time and it’s very efficient. It’s also not specific to commands and works great for all Emacs Lisp code. Every Emacs user will do well to invest a bit of time into learning the basics of debugging Emacs Lisp code.

    By the way, it’s probably not super obvious but when an error happens and you’ve enabled debug-on-error (e.g. with M-x toggle-debug-on-error), you’re not just getting a backtrace, but a backtrace - that’s actually another way in which you can interact with the Emacs debugger. Press ? while in this buffer or check out this short article for more details.

    That’s all I have for you today. Keep hacking!

    1. Emacs commands are simply Emacs Lisp functions that can be invoked interactively with M-x

    2. Here’s a great crash course on using the debugger. 

Subscribe via RSS | View Older Posts