🪴\zansh.in\blog

39 min read / 6 for this part

VIM diary

Part: 1 | 2 | 3 | 4 | 5 | 6 | 7

While learning the basics of Vim over the course of a few months I kept a simple diary. I recorded what I had been Googling for and what I'd learned during my struggles.

# February 2024

The start of my sixth month of learning Vim.

At this point I feel like I should round-out this diary and bring things to a close. I'm learning just as much about Core Utils and tmux as I am about Vim.

I'm familar enough now that I'm as productive as I used to be. Arguably more so in most (definitely not all) cases. On the whole, learning Vim has turned out to be a lot more fun that I had expected, and fun is a great motivator for continued learning.

I certainly didn't see that coming.

# Okay, so I'm not quite done yet

My .vimrc tinkering had died down a lot and I told myself I would revisit it every 3-6 months perhaps.

Turns out that in March I did make big changes to my config, mostly to do with progressive enhancement. I really do want a config that I can drop-in anywhere and, even if I don't have the best features available because of versions or whatever, I'll have some okay fallbacks.

One of Vim's defining features is its availability on almost every platform, so to have a portable config takes maximum advantage of that.

I know this isn't the March entry, but some of the things I discovered in February would become part of this refactor: where if a plugin offered a great solution it would be preferred, otherwise a fallback would kick-in using (if possible) the same remaps.

# Every list, everywhere, all at once

Somehow I learned about all of these this month:

Things related to searching and managing search results in Vim.

My use of vim-fugitive's file-history feature would drive my interest in learning about QuickFix. I really hadn't made an effort to use it before, since things like fuzzy-finders or running find or rg directly in a buffer covered most of my needs (and still does.)

But having a dedicated window for persistent search-results was inviting, so QuickFix became a point of learning for a week or so, along with these Vim built-ins that use it: VimGrep and Grep.

The Arglist came along at the same time too.

# Grammar over Commands

One of the most useful features of both QuickFix and Arglist is being able to run commands against whatever is in the list:

" QuickFix
:cfdo %s/search/replace/g | update
" Arglist
:argdo %s/search/replace/g | update

There's no special syntax here. Whatever commands I would normally run against a single file can now be applied to many files.

Of course, in "single buffer mode" I tend to run commands one at a time, so the pipe | seems to stand-out. But it can be used to run multiple commands against a single buffer too.

This is one of the most magical things I have found about learning Vim: not so much its commands, but its grammar. Picking up a new piece of grammar suddenly opens up a huge number of possibilities I previously had no idea about, and it cost almost nothing to learn.

It takes a while to get to this point of course (here we are at month six) but how many other tools can this be said about?

# Git File History

My dependence on vim-fugitive's file-history feature would last until the middle of February when I would discover diffview.nvim, which is a much more complete and intuitive solution to the problem.

(This would eventually turn into one of those "progressive enhancements" I mentioned earlier, where diffview would be used if installed, and a fugitive based remap would be the fallack.)

# Home on the Ranges

The second week of February was about ranges in Vim and in sed.

I'd never sat down and learned the full capability of sed before. It's just that substitition command, right? Well, no: turns out there's a reason it's called a "stream editor", because that's what it is.

It has its own grammar too, where you can specify not just a pattern to match, but a start and end range, and then a command to run against that range.

sed '/pattern/'
'/pattern/cmd\'
'/pattern/cmd\ { text to pass to cmd }'
'/start/, /end/ { cmd + text }'
commands = s///g = substitute
p\ = print
a\ = append
i\ = insert
d\ = delete

What a great refactoring tool this turned out to be.

rg -l 'syncFields' \
| xargs \
| sed -i \
'/const syncFields = \[/, /\]/ {
a\
const fieldValues = Object.keys(fields)
}'

As for Vim ranges, I started here:

" Copy 5 lines, starting from -30 relative, to the current line
:-30,-25 copy .

The article linked was tough going to started with, but ended up being a great introduction.

# GNU parallel

If you've ever written a script and then afterwards found a built-in utility that does the same thing only much, much better, then you'll know how I felt when I discovered parallel.

Unsurprisingly, it runs commands in parallel:

ls *.js | parallel "prettier --write {}"

Here we pipe-in a list of files from ls and then run prettier on each one, with parallel taking care of the concurrency for us.

Notice the {} token. While not exactly defacto, this also appears in both the find and xargs commands:

ls *.md | xargs -I{} echo {}
find src/ -name '*.js' -exec echo {} \;
ls *.js | parallel "prettier --write {}"

It's configurable for xargs, but I find it curious that the documentation offers the same {} token in its examples.

# Commands Learned

Next part →

29 Feb, 2024

Google it:

🌸 find manpage 🌺 GNU parallel 🌷 Prettier 🌻 ripgrep 🌼 sed manpage 🌹 xargs manpage