Posts
Relative Line Numbers
Relative line numbers (relative to the current line) are super popular in the world of Vim, because there it’s super easy to move
n
lines up or down wihtj
andk
. In the world of Emacs most of us tend to just go some line usingM-g g
using a absolute line number or usingavy
(avy-goto-line
).That being said, relative line numbers are easy to enable in Emacs and quite handy if you’re into
evil-mode
:(setq display-line-numbers-type 'relative) (global-display-line-numbers-mode +1)
Relative line numbers are useful with the Emacs core commands
forward-line
(C-n
) andprevious-line
(C-p
) as well. Just trigger them with the universal prefixC-u
and you can move quickly around:C-u 5 C-n
(move 5 lines forward)C-u 10 C-p
(move 10 lines backward)
Easy-peasy!
That’s all I have for you today! Keep hacking!
You have no idea how powerful isearch is!
isearch
is probably one of the most widely known Emacs commands. Every Emacs user knows that they can run it usingC-s
(to search forward) andC-r
to search backwards. Everyone also knows they can keep pressingC-s
andC-r
to go over the list of matches in the current buffer. Even at this point that’s a very useful command. But that doesn’t even scratch the surface of whatisearch
can do!After you’ve started
isearch
you can actually do a lot more than pressingC-s
andC-r
:- Type
DEL
to cancel last input item from end of search string. - Type
RET
to exit, leaving point at location found. - Type LFD (
C-j
) to match end of line. - Type
M-s M-<
to go to the first match,M-s M->
to go to the last match. (super handy) - Type
C-w
to yank next word or character in buffer onto the end of the search string, and search for it. (very handy) - Type
C-M-d
to delete character from end of search string. - Type
C-M-y
to yank char from buffer onto end of search string and search for it. - Type
C-M-z
to yank from point until the next instance of a specified character onto end of search string and search for it. - Type
M-s C-e
to yank rest of line onto end of search string and search for it. - Type
C-y
to yank the last string of killed text. - Type
M-y
to replace string just yanked into search prompt with string killed before it. - Type
C-q
to quote control character to search for it. - Type
C-x 8 RET
to add a character to search by Unicode name, with completion. C-g
while searching or when search has failed cancels input back to what has been found successfully.C-g
when search is successful aborts and moves point to starting point.
You can also toggle some settings write
isearch
is active:- Type
M-s c
to toggle search case-sensitivity. - Type
M-s i
to toggle search in invisible text. - Type
M-s r
to toggle regular-expression mode. - Type
M-s w
to toggle word mode. - Type
M-s _
to toggle symbol mode. - Type
M-s '
to toggle character folding.
Type
M-s SPC
to toggle whitespace matching. In incremental searches, a space or spaces normally matches any whitespace defined by the variablesearch-whitespace-regexp
; see also the variablesisearch-lax-whitespace
andisearch-regexp-lax-whitespace
.Type
M-s e
to edit the search string in the minibuffer. That one is super useful!Also supported is a search ring of the previous 16 search strings:
- Type
M-n
to search for the next item in the search ring. - Type
M-p
to search for the previous item in the search ring. - Type
C-M-i
to complete the search string using the search ring.
Last, but not least - you can directly search for the symbol/thing at point:
- Type
M-s .
to search for the symbol at point. (useful in the context of programming languages) - Type
M-s M-.
to search for the thing (e.g. word or symbol) at point.
One of the most useful parts of that is the fact that a region is a thing. So you can mark a region (e.g. with
expand-region
ormark-*
) andM-s M-.
to immediately search for other instances of that text. Powerful stuff!Tip: You don’t really have to remember all those keybindings - just remember you can press
C-h b
to show them. (after you’ve startedisearch
)Most of the above text is coming straight from the docstring of
isearch
. It’s funny that I’ve been using Emacs for almost 20 years, I useisearch
numerous times every day and I still often forget about much of its functionality.There’s more to
isearch
, though. Did you know it’s widely customizable as well? If you check its options withM-x customize-group isearch
you’ll see there are over 30 (!!!) options there! Admittedly, I never used any of them, but you’ve got quite a lot of opportunities to tweak the behavior ofisearch
if you want to. Here’s an example of a customization some of you might find useful:;; When isearching, enable M-<, M->, C-v and M-v to skip between matches ;; in an intuitive fashion. Note that the `cua-selection-mode' bindings ;; for C-v and M-v bindings are not supported. (setq isearch-allow-motion t isearch-motion-changes-direction t)
I hope you learned something useful today! Keep searching (the Emacs docs)!
- Type
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. toCaps Lock
), and there are also many keyboards that placeESC
where~
normally is, to make it more accessible.1In Emacs-land, however, we never really speak about
ESC
… Why so? Well, we useC-g
to interrupt commands, and we obviously don’t have modal editing, at least not by default. Still, I thinkESC
has its uses in Emacs, even if they are not super obvious at first. For instance there’s thekeyboard-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 toESC 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 asM-ESC ESC
, rather thanESC ESC ESC
. And this is what makesESC
really interesting - it serves as a substitute forMeta
, but you don’t have to hold downESC
- insteadM-something
keybindings can be triggered by pressingESC
and the other key sequentially. Go ahead and try the following:ESC x
(same asM-x
)ESC g g
(goto-line
, same asM-g g
)ESC e
(forward-sentence
, same asM-e
)
I don’t know about you, but I think this is pretty handy, especially if you’re using
macOS
, where on many keyboards theOption
(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 thanCommand
(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 useESC
instead ofMeta
is definitely a welcome one, and I find myself doing this quite often.Before we wrap up consider keybindings like
M->
,M-!
orM-%
that require you to hold down bothShift
andMeta
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!-
HHKB is probably the most famous example, but there are many many others that do the same. ↩
-
I’m using a dual-function keybinding for what’s normally
Caps Lock
on most keyboards - it’sControl
wwhen held down andEscape
otherwise. For me that’s a good idea regardless of the editor someone’s using. ↩
Debugging Errors in Emacs
I recently wrote an article on debugging Emacs commands. In it I mentioned
M-x toggle-debug-on-error
anddebug-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:- Navigate the Stack Trace: Move your cursor in the
*Backtrace*
buffer to different lines representing various stack frames. - Examine Local Variables: Press
v
(debugger-toggle-locals
) while on a stack frame to display local variables for that frame. - Evaluate Expressions: Use
e
(debugger-eval-expression
) to evaluate Lisp expressions in the context of the current frame. - Step Through Code: Use
d
to step into function calls and evaluate expressions one by one. - 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) - Quit Debugging: Enter
q
to exit the debugger and abort the current command. - View Help: Type
?
to see a list of available debugger commands. - 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 bindsdebug-on-error
tot
while loading the init file, and bypasses thecondition-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!
- Navigate the Stack Trace: Move your cursor in the
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 withcustom-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 callingcustom-theme-set-faces
for theuser
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. withC-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 facesfont-lock-keyword-face
(coming fromelisp-mode
) andmarkdown-code-face
(frommarkdown-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!
-
Remember that Emacs allows you load multiple themes with them stacking one upon another. ↩
- If you’re using
Subscribe via RSS | View Older Posts