Posts
-
expreg: Expand Region, Reborn
expand-region is one of my all time favorite Emacs packages. I’ve been using it since forever – press a key, the selection grows to the next semantic unit, press again, it grows further. Simple, useful, and satisfying. I’ve mentioned it quite a few times over the years, and it’s been a permanent fixture in my config for as long as I can remember.
But lately I’ve been wondering if there’s a better way. I’ve been playing with Neovim and Helix from time to time (heresy, I know), and both have structural selection baked in via tree-sitter – select a node, expand to its parent, and so on. Meanwhile, I’ve been building and using more tree-sitter major modes in Emacs (e.g. clojure-ts-mode and neocaml), and the contrast started to bother me. We have this rich AST sitting right there in the buffer, but expand-region doesn’t know about it.
The fundamental limitation is that expand-region relies on hand-written, mode-specific expansion functions for each language. Someone has to write and maintain
Read Moreer/mark-ruby-block,er/mark-python-statement,er/mark-html-tag, and so on. Some languages have great support, others get generic fallbacks. And when a new language comes along, you’re on your own until someone writes the expansion functions for it. -
Soft Wrapping Done Right with visual-wrap-prefix-mode
Emacs has always offered two camps when it comes to long lines: hard wrapping (inserting actual newlines at
fill-columnwithM-qorauto-fill-mode) and soft wrapping (displaying long lines across multiple visual lines withvisual-line-mode).1Hard wrapping modifies the buffer text, which isn’t always desirable. Soft wrapping preserves the text but has always had one glaring problem: continuation lines start at column 0, completely ignoring the indentation context. This makes wrapped code and structured text look terrible.
Emacs 30 finally solves this with
visual-wrap-prefix-mode.What it does
When enabled alongside
visual-line-mode,visual-wrap-prefix-modeautomatically computes awrap-prefixfor each line based on its surrounding context. Continuation lines are displayed with proper indentation — as if the text had been filled withM-q— but without modifying the buffer at all.The effect is purely visual. Your file stays untouched.
Basic setup
As usual, you can enable the mode for a single buffer:
(visual-wrap-prefix-mode 1)Or globally:
(global-visual-wrap-prefix-mode 1)You’ll likely want to pair it with
visual-line-mode:(global-visual-line-mode 1) (global-visual-wrap-prefix-mode 1)Note that with
visual-line-modesoft wrapping happens at the window edge. If you’d like to control the extra indentation applied to continuation lines, you can tweakvisual-wrap-extra-indent(default0):;; Add 2 extra spaces of indentation to wrapped lines (setq visual-wrap-extra-indent 2)Before and after
Without
visual-wrap-prefix-mode(standardvisual-line-mode):Some deeply indented text that is quite long and wraps to the next line without any indentation, which looks terrible and breaks the visual structure.With
visual-wrap-prefix-mode:Some deeply indented text that is quite long and wraps to the next line with proper indentation, preserving the visual structure nicely.A bit of history
If this sounds familiar, that’s because it’s essentially the
adaptive-wrappackage from ELPA — renamed and integrated into core Emacs. If you’ve been usingadaptive-wrap-prefix-mode, you can now switch to the built-in version and drop the external dependency.Closing Thoughts
As mentioned earlier, I’m not into soft wrapping myself - I hate long lines and I prefer code to look exactly the same in every editor. Still, sometimes you’ll be dealing with some code you can’t change, and I guess many people don’t feel as strongly about cross-editor consistency as me. In those cases
visual-wrap-prefix-modewill be quite handy!I have to admit I had forgotten about
auto-fill-modebefore doing the research for this article - now I’m wondering why I’m not using it, as pressingM-qall the time can get annoying.That’s all I have for you today. Keep hacking!
-
I’ve always been in the
M-qcamp. ↩
-
-
Preview Regex Replacements as Diffs
If you’ve ever hesitated before running
query-replace-regexpacross a large file (or worse, across many files), you’re not alone. Even experienced Emacs users get a bit nervous about large-scale regex replacements. What if the regex matches something unexpected? What if the replacement is subtly wrong?Emacs 30 has a brilliant answer to this anxiety:
replace-regexp-as-diff.How it works
Run
M-x replace-regexp-as-diff, enter your search regexp and replacement string, and instead of immediately applying changes, Emacs shows you a diff buffer with all proposed replacements. You can review every single change in familiar unified diff format before committing to anything.If you’re happy with the changes, you can apply them as a patch. If something looks off, just close the diff buffer and nothing has changed.
Multi-file support
It gets even better. There are two companion commands for working across files:
multi-file-replace-regexp-as-diff— prompts you for a list of files and shows all replacements across them as a single diff.dired-do-replace-regexp-as-diff— works on marked files in Dired. Mark the files you want to transform, run the command, and review the combined diff.
The Dired integration is particularly nice — mark files with
m, run the command from the Dired buffer, and you get a comprehensive preview of all changes.Note to self - explore how to hook this into Projectile.
A practical example
Say you want to rename a function across your project. In Dired:
- Mark all relevant files with
m(or% mto mark by regexp) - Run
dired-do-replace-regexp-as-diff - Enter the search pattern:
\bold_function_name\b - Enter the replacement:
new_function_name - Review the diff, apply if it looks good
No more sweaty palms during large refactorings.1
Closing Thoughts
I have a feeling that in the age of LLMs probably few people will get excited about doing changes via patches, but it’s a pretty cool workflow overall. I love reviewing changes as diffs and I’ll try to incorporate some of the commands mentioned in this article in my Emacs workflow.
That’s all I have for you today. Keep hacking!
-
Assuming you’re still doing any large-scale refactorings “old-school”, that is. And that you actually read the diffs carefully! ↩
-
So Many Ways to Work with Comments
I’ve been using Emacs for over 20 years and I still keep discovering (and rediscovering) comment-related commands and variables. You’d think that after two decades I’d have comments figured out, but it turns out there’s a surprising amount of depth hiding behind a few keybindings.
What prompted this article was my recent work on neocaml, a tree-sitter based major mode for OCaml. OCaml uses
Read More(* ... *)block comments – no line comments at all – and that unusual syntax forced me to dig deeper into how Emacs handles comments internally. I learned more about comment variables in the past few months than in the previous 20 years combined. -
Hide Minor Modes in the Modeline in Emacs 31
Most Emacs users run a tone of minor modes and many of them contribute something (usually useless) to the modeline. The problem is that the modeline is not infinite and can quickly get quite cluttered. That’s why for the longest time I’ve been using the third-party
diminishpackage and I have something like this in my config:(use-package diminish :config (diminish 'abbrev-mode) (diminish 'flyspell-mode) (diminish 'flyspell-prog-mode) (diminish 'eldoc-mode))diminishgets the job done, but it’s a bit annoying that you need a third-party package for something so basic. Fortunately that’s about to change…I just learned that in Emacs 31 it’s finally possible to hide minor modes in the modeline using built-in functionality! Here’s how you can do the above:
(setq mode-line-collapse-minor-modes '(abbrev-mode flyspell-mode flyspell-prog-mode eldoc-mode))And here’s how you can hide all minor modes (probably a bad idea, though, as some add useful info to the modeline):
(setq mode-line-collapse-minor-modes '(not))For more info on what you can do with this new functionality see
C-h v mode-line-collapse-minor-modes. After all, they don’t call Emacs the “self-documenting editor” for no reason.From the docs you’ll learn that hidden mode “lighters” (Emacs lingo for a mode’s modeline indicator) get compressed into one. It’s
...by default, but it can be customized via the variablemode-line-collapse-minor-modes-to.Apart from
diminish, there are also the newerdelightandminionspackages that tackle more or less the same problem. As explained here forminions, they might still be useful, depending on your use-cases. One of the great aspects of Emacs is having options and when it comes to dealing with the minor mode lighters we have plenty of options!That’s all I have for you today. Happy Christmas holidays! Keep hacking!
Subscribe via RSS | View Older Posts