17 comments

[ 2.8 ms ] story [ 52.3 ms ] thread
Somehow, I was unaware of C-M-% for replacements, though I use M-% all the time for a (naive) string search then replace all instances by pressing the ! key.

This is a very neat trick, and little things like this are why I keep using Emacs. Part of me wishes there were some "universal" version of the M-: keybind for evaluating elisp expressions in any interactive command.

I'm not clear what you mean there, but it seems that C-u C-x C-e, gets a lot of the way there?
It's not exactly what you want, but "C-x ESC ESC" will bring up the last run command in lisp form and let you edit it before running it again. That's how I used to repeat M-% replacements before they added the nice history to it.
Wow! and you can C-p back to see earlier ones too! Thank you for sharing this ... to me it's similar in impact to q: in vim.
This all works in evil-mode as well, and by default you get the cool live-preview (not sure how to enable that for the vanilla C-M-%)

    :%s/\([0-9]+\))/\,(1- \#1))/
will turn

    1) one
    2) two
    3) three
into

    0) one
    1) two
    2) three

  :%s/\([0-9]\+\))/\=submatch(1)-1.')'    " vim

  perl -pe 's/([0-9]+)\)/$1-1 .")"/e'

  ruby -pe 'sub(/([0-9]+)\)/){"#{$1.to_i-1})"}'
What do you mean by live preview? My non-evil Emacs shows you the matches in the current buffer as you type. I don't think I did anything to enable it, but think it's a fairly recent thing (maybe Emacs 29).
For those wondering about why the \, is used to indicate the start a lisp expression, the backslash is used to escape all replacements and the comma recalls the lisp backquote (`) function (operator) which is like quote (‘), but allows interpolation of evaluated lisp expressions when preceded by a comma[0].

[0] https://www.gnu.org/software/emacs/manual/html_node/elisp/Ba...

I would have said that the comma recalls the way that comma is used inside backquoted expressions.
I didn't know about using elisp in the replacement! Can't wait to need to use it.

You can also do this replacement across an entire project and emacs also uses "smart" caps by default so that case is preserved from match to replacement. I wrote about it here: https://blog.gpkb.org/posts/emacs-regexp-replace/

Another way to insert counters is the keyboard macro counter (info "(emacs) Keyboard Macro Counter")

kmacro-set-counter (C-x C-k C-i)

Then <F3> to start recording the macro and <F3> again to insert the counter. <F4> to end the macro and <F4> to run it. So <F3><F3><space><F4><F4><F4><F4><...> will insert the integers starting from zero separated by a space.

This can be more useful in certain cases, for example when you need to do "structural editing" like editing a certain field in JSON where it can be easier to locate the edit point using keyboard shortcuts or search.