reddit / emacs
Emacs <==> vi/vim "Rosetta Stone"?
techn0mad · 2022-12-15 02:55
Are there any lists of translations of common vi/vim idioms to Emacs?
I am a longtime vi user trying to migrate back to Emacs, but sometimes I struggle when I want to do something that I've done thousands of times in vi.
For example:
:g/foo/s/bar/baz/
e.g. "For each line containing the pattern 'foo', replace the string 'bar' with the string 'baz'."
Usually a bit of google-fu yields a solution, but this one seems difficult.
TheDamnGondolaMan · 2022-12-15 03:32
I currently know of no such list, but I'd maybe like to make sure: are you using evil mode? And if not, why not? It makes you able to do everything you can do in vi/vim exactly as you do it in vi/vim. It's what I use, and I would highly recommend.
techn0mad · 2022-12-15 03:37
I am aware of evil mode, and I'm sure it works, but my quest is to learn how to do things the Emacs way and to stop doing things the vi/vim way.
[deleted] · 2022-12-15 03:40
[deleted]
jmite · 2022-12-15 03:41
The emacs way is to do it your own way. You'll find a lot of people making their own keybindings and such. The beauty is that emacs is flexible enough that it can act like vim without losing its power.
[deleted] · 2022-12-15 03:41
[deleted]
GrimeOfTheAncients · 2022-12-15 03:44
query-replace-regexp usually bound to C-M-%
If on the first match you hit "? for help" you get...
```Query replacing regexp switch with bah.
Type Space or ‘y’ to replace one match, Delete or ‘n’ to skip to next,
RET or ‘q’ to exit, Period to replace one match and exit,
Comma to replace but not move point immediately,
C-r to enter recursive edit (C-M-c to get out again),
C-w to delete match and recursive edit,
C-l to clear the screen, redisplay, and offer same replacement again,
! to replace all remaining matches in this buffer with no more questions,
^ to move point back to previous match,
u to undo previous replacement,
U to undo all replacements,
E to edit the replacement string.
In multi-buffer replacements type ‘Y’ to replace all remaining
matches in all remaining buffers with no more questions,
‘N’ to skip to the next buffer without replacing remaining matches
in the current buffer.
```
Hitting bang will do what you vi thing did.
theunixman · 2022-12-15 04:47
There’s a built in tutorial that I used to get started after vim that was really helpful. Then I went down the elisp rabbit hole and, well, damn. 40 years on….
fabiopapa · 2022-12-15 04:54
I had never used vi/vim before switching to emacs (except casually/by mistake from the command line) and I learned vi/vim modal editing and ex commands, etc. in emacs. I would never go back. It just works well with my brain.
Emacs is *not* a text editor, it is an environment for creating your ideal text editor. If that includes vi bindings then there’s no need to learn some other system, especially not to learn the emacs way, since the emacs way is *your* way.
I remember learning this lesson when first switching to emacs and asking (here) if it was considered emacs-y to use snippets. I hope this helps!
7890yuiop · 2022-12-15 05:17
> For example:
>
> `:g/foo/s/bar/baz/`
>
> e.g. "For each line containing the pattern 'foo', replace the string 'bar' with the string 'baz'."
>
> Usually a bit of google-fu yields a solution, but this one seems difficult.
I imagine `evil` implements that specifically (it would be a rather simple elisp loop), but FWIW I'd do this as a two-step process, using `occur` to find lines matching `foo` and then `occur-edit-mode` to do the search and replace.
techn0mad · 2022-12-15 05:24
I knew that obviously there was a regexp replace command, but the catch is, AFAIK, that vi, as a descendent of ed, is a line-oriented editor, whereas (again, AFAIK) Emacs is a buffer-oriented editor. So to me the tricky part here is trying to get Emacs to do something on a line-by-line basis rather than on a buffer basis. My crude pseudo-code interpretation of the original vi command
```
:g/foo/s/bar/baz/
```
is
```
for each line in the open file
if the line contains the pattern 'foo'
replace a string 'bar' in the line with the string 'baz'
```
I assume that the `query-replace-regexp` with the `!` option would replace all instances, not just those on lines containing the desired pattern.
noman_032018 · 2022-12-15 05:27
You would indeed have to get clever with the regex and possibly have to use substitution groups.
For more info: [(info "(emacs) Regexp Replace")](https://www.gnu.org/software/emacs/manual/html_node/emacs/Regexp-Replace.html)
Something like `^(whatever-pattern-i-want)(.*)$ -> whatever-new-thing \2`
edit: You'll have to backslash the parens too, in most cases.
algalgal · 2022-12-15 05:28
I don’t think there’s a directly corresponding emacs command.
Fwiw, I’d do it with a regex. I’d call query-replace-regexp with a query something like “foo\(.*\)bar” replacing it with “foo\1baz”.
This is clearly less elegant than the dedicated vim command! I’d write my own command if I found myself doing it every few days, but I don’t think I’ve ever done such a replace.
deafpolygon · 2022-12-15 05:37
Evil mode.
centzon400 · 2022-12-15 05:49
> The emacs way is to do it your own way.
The 80s were very 'perlish' 😀
`query-replace-regexp` is typically `C-M-%`, which is just horrible, IMHO.
I've that aliased so that `M-x rr <RET>` gets me there.
JohnDoe365 · 2022-12-15 06:19
This is not stack overflow but - this would be the obvious and somewhat best matching equivalent to the vim :g/ command
MitchellMarquez42 · 2022-12-15 06:46
https://github.com/noctuid/evil-guide
Primarily discusses evil-mode, which is the best vim implementation in Emacs. As an evil user and occasional hacker I can confirm that they do a good job of bridging the gap between emacs and vim concepts - "states" vs "modes", "kill/yank" vs "delete/yank/put" (yes, yank means opposite things).
16rlut3Br · 2022-12-15 07:21
It's a multi step process:
- filter with occur
- make occur buffer editable
- query-replace-regexp the replacements
GrimeOfTheAncients · 2022-12-15 07:51
You can use occur-mode ie.
M-x list-matching-lines
C-x-o to other window
e to edit occur
query-replace-regexp
Atemu12 · 2022-12-15 08:31
I use Spacemacs in Hybrid mode. It's got full vim bindings for normal mode but, in insert mode, all keybinds are "the Emacs way".
wonko7 · 2022-12-15 10:38
> I am aware of evil mode, and I'm sure it works, but my quest is to learn how to do things the Emacs way and to stop doing things the vi/vim way.
evil is the way man. it's just sane defaults so you can build your own interface.
FrozenOnPluto · 2022-12-15 13:32
A recorded macro perhaps? C-x ( iirc, then C-s isearch for match, return to break search, then the replace, and C-x ) close macro. Execute as needed or save for later.
publicvoit · 2022-12-15 13:40
It was in the 90s when I initially wrote my vim-Emacs-Cheatsheet of freezing hell because I was starting to work with both:
https://karl-voit.at/unmaintained/vim-emacs-cheatsheet_of_freezing_hell.txt
Excellent-Pattern119 · 2022-12-15 13:54
I'm a user of EMACS and curiously I know how to do this on vi but not on EMACS...I would just write a ELISP script or record a macro and edit it to repeat until the end.
Different_Access · 2022-12-15 14:07
This is the way
CowboyBoats · 2022-12-15 14:29
I didn't know about that command pattern in vim, thanks.
From a quick trial on my [Doom Emacs](https://github.com/doomemacs/doomemacs) (a wonderful configuration of emacs that's built with evil mode as the default), it seems to work fine.
techn0mad · 2022-12-15 16:13
I concur, even though it's not a "one liner", to me this seems like the most direct mapping from the vi command to Emacs. Thanks u/GrimeOfTheAncients!
techn0mad · 2022-12-15 16:18
I had assumed that someone had been looking for the same sort of information that I was. Thank you u/publicvoit!
pathemata · 2022-12-15 17:13
I would use `consult-ripgrep` and `embark` for this, easy and with visual feedback.
flylikeabanana · 2022-12-15 17:59
I switched from vim to emacs and used evil mode so I could get productive quickly. I was an advanced-intermediate vim user and haven't found anything that vim could do that evil can't. I've gotten pretty good at emacs (command/package knowledge, navigating help, writing elisp, etc.) and still don't really know many of the default bindings. What's "write the file?" C-x something or the other. Never bothered with it.
karthink · 2022-12-15 21:52
Here are four ways you could do this. As is generally the case with Emacs, none of these methods are as elegant as Vim:
1. Shell out to awk (or equivalent): `C-x h`, `M-1 M-|`, `awk '/foo/ { sub("bar","baz") } {print}'`
2. Use occur and occur-edit: `M-s o`, `foo`, `e`, replace-regexp bar with baz, `C-c C-c` to confirm changes.
3. Use `consult-focus-lines` (requires Consult to be installed): `M-x consult-focus-lines`, `foo`, replace-regexp bar with baz across the buffer, call `consult-focus-lines` again to reveal all the text.
4. Write some elisp and call `replace-in-matching-lines` when required.
Something like this will work:
(defun replace-in-matching-lines (containing from-regexp to-regexp)
(interactive (list
(read-from-minibuffer "Containing: ")
(read-from-minibuffer "From: ")
(read-from-minibuffer "To : ")))
(save-excursion
(goto-char (point-min))
(while (re-search-forward containing nil t)
(replace-regexp-in-region from-regexp to-regexp
(line-beginning-position)
(line-end-position)))))
FreeAd7233 · 2022-12-16 00:34
I don’t think there will be many people mention this, so I will mention it here.
Emacs doesn’t have native tab concept until recent version. Emacs has two modes of tabs. The “tab” in tab-bar-mode is almost exactly the same as the “tab” in vim. Evil uses tab-bar-mode to emulate vim’s tabs too. The “tab” in tab-line-mode is more similar to the “tab” in GUI applications like vscode, it is actually a drawer of “buffers”
FreeAd7233 · 2022-12-16 00:41
You can use evil to do the exactly same thing “:g” stuffs. Evil perfectly emulates it. What’s more, you can use evil’s “:g” to do both vim commands and even evaluate s-expression.
So you have two forms:
“:g/PAT/normal fgcawab”
“:g/PAT/s/PAT2/REPEX/g”
“:g/PAT/(s-expression arg1 arg2)”
To me sometimes I feel evil is even superior than vim as you can’t imagine how much magic lies behind evil.
GrimeOfTheAncients · 2022-12-16 01:12
I will add one final thought.
Although the way I have outlined has several advantages, like being able to see what the result of the selection regex is and decide whether the query & replace is doing the right thing etc. etc.
One of the super powers is the ability to introspect.
​
C-h f query-replace-regexp takes you to....
```query-replace-regexp is an interactive byte-compiled Lisp function in
‘replace.el’.
It is bound to C-M-%, <menu-bar> <edit> <replace>
<query-replace-regexp>.
(query-replace-regexp REGEXP TO-STRING &optional DELIMITED START END
BACKWARD REGION-NONCONTIGUOUS-P)
Replace some things after point matching REGEXP with TO-STRING.
As each match is found, the user must type a character saying
what to do with it. Type SPC or ‘y’ to replace the match,
DEL or ‘n’ to skip and go to the next match. For more directions,
type C-h at that time.
.....
```
but that "replace.el" is a hyperlink that takes you to the actual elisp for that function.
There is nothing to stop you from literally copying and pasting that function, giving it a new name and an extra parameter and a few tweaks implementing the one liner version without the intermediate footwork of the occur-mode route.
In this particular case I'm not sure it's worth the bother, but it's a very nifty idea to keep in your back pocket.
Lisp is in some senses super easy to read super simple syntax..., it's (function-name arg1 arg2 arg3 ...) and if you find any function that you don't know, C-h f will take you to it.
The other nifty superpower, if you know sed or perl or ruby oneliners... select the text you want to mangle Esc-| and enter your one liner... Did that do the right thing? Ok, C-u Esc-| and it replaces that region with the result of the one liner.
schmooser · 2022-12-16 20:04
For a given example: occur, search for foo, then “e” to enable occur-edit-mode, then replace regexp (M-S-% or like, I have bound it to S in meow-normal-mode).
Regarding other idioms, I use fewer and fewer vim commands, they are not that useful after all, especially those with numbers and `ciw`, `sat` and similar - I’m bad with counting. Instead, I use expand-region or C-M-u|n|p|f|d, those are really handy after I configured a separate key to send C-M on my Keyboardio Model 100 and on Planck.