dotfiles/notes/vim/vim_batch_editing.md

114 lines
3 KiB
Markdown
Raw Normal View History

2022-10-07 01:17:16 -06:00
# Quick help
```bash
for f in *.html; do nvim -Nes "$f" < ex_commands; done
for f in "$(rg -l homu)"; do nvim -Nes "$f" < ex_commands; done
for f in $(fd -tf -e html); do
nvim -Nes <<'EX'
g/^Stl/exe "norm! cStyle: new\<CR>\<esc>"
$ | a
# ex: ff=unix:
.
wq
EX
done
```
# Batch editing with ex
Ever needed to apply the same edit to several files? Well ex-mode is the only
generalized solution for this
Ex-mode is vim's equivalent of `ed` and `ex` is symlinked as `vim -e` on many
systems. Use the `-N` flag for a more familiar experience. Enter this mode while
in vim with `gQ`. Using the `ex` executable is slightly different from neovim's
implementation, notably neovim doesn't echo back with `nu` and `p`
```bash
ex file
vim -Nes file
```
Ex-mode uses vim's command-mode syntax, which is similar though different from
visual mode
```
:21 Goes to line 21. ^ and $ are for the first and last line
:10,20d Deletes lines 10 through 20, inclusive on both ends
:u[ndo] Undoes the last action
:g/re/p Globally exectute a command on lines with /re/
:v/re/p Inverse of :g. Executes on all lines without /re/
:3,6co$ Copy lines [3,6] to the end of the document
:3m6 Move line 3 to line 6
:z=3 Pretty print lines in [-2,+2]
```
Several commands can be chained with `|`, similar to `;` in bash
```
:g/bash/exe "normal! cfish\<esc>" | undo | nu
```
Changes every line with "bash" to "fish", undoes that, then prints the line
:g/string/nu | g/num/nu
Does NOT print all the lines with `string` or `num`. This prints all the lines
with `string` then reprints them if they also have `num`. `:g` only uses a new
line to delimit its commands from the next set!
## Batch editing styles:
1. Here-string: For only one command, here-strings are a quick and easy choice
```bash
for f in $(find ~/); do nvim -Nes <<<"%s/re/p | wq"; done
```
2. Here-ansi-c-string: Allows including c-style escape sequences
```bash
for f in $(find ~/); do vim -Nes <<< $'%s/re/nu\nwq'; done
```
3. Here-documents: The best choice for quick batch edits
```bash
for file in $(fd -at type subs_); do
nvim -Nes $file <<'DOC'
g/^Stl/exe "norm! cStyle: new\<CR>\<esc>"
$ | a
# ex: ff=unix:
.
wq
DOC
done
```
```bash
for file in ~/.bash*; do vim -Nes $file <<EOF
a
# ex: set syntax=bash:ff=unix:
.
wq
EOF
done
```
4. Sourced documents: Better for recurring batch edits. Similar to `nvim -S`
```bash
fd -a subs_ -x ex < change_font
fd -a subs_ -x nvim -Nes < change_font
for f in *.html; do nvim -Nes "$f" < ex_commands; done
for f in "$(rg -l homu)"; do nvim -Nes "$f" < ex_commands; done
```
## Best practices
Use `-t file` in `fd`, otherwise `ex` may stop when it hits a directory
Unless you're really confident, always use files to store commands, then first
try them out on copies of files you'd like to edit. It's often hard to debug an
edit in advance and there's no undo
## Batch editing manually
This isn't really a batch edit... though it's worth mentioning
```bash
fd -t file . -X rg --files-with-matches 'ex:' | xargs -o vim
```