39 min read / 10 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.
# January 2024
The start of a "ramping up" to using Vim/Neovim on a regular basis.
Before Christmas my hand was forced by permissions issues with my work laptops. The only thing that I was able to code in was Vim. It was a stressful blessing, but a blessing nonetheless, and the need to "git good" bore down pretty strong just before the Holidays.
But I had to get back into it before that would happen.
Time away from something that clearly requires regular and consistent practice has noticably taken its toll, and I discovered that many of the more complex commands teetered beyond the edge of memory.
I was now grateful to have started working on this diary. It was a great aid in these halting moments of trying to get back into the flow.
# New Toys
Learning Vim is one thing, but what surprised me were all the peripherals that go along with it: Namely all the CLI stuff you get to use more regularly and get better at.
I had been a regular Linux user in the distant past, using it a lot at work on servers that hosted and managed video. I used an Ubuntu/Gentoo combination for my home setup for a few years, wrote the odd script, and thought I was fairly comfortable with the terminal in general.
This was false confidence. I realise now I was a mere tinkerer, and all sorts of goodies have opened up since becoming a baby Vim'er.
For example, I am now doing things like:
# Copy files from one branch to another
git diff dev --name-only \
| grep utils \
| while read file; do cp ../feature/${file} ./${file}; done
And...
# Search/replace with multi-file confirmation using fzf
find src/ -name '*.js*' -print0 \
| xargs -0 grep -l "${search}" \
| fzf -m --print0 \
| xargs -0 sed -i "s/${search}/${replacement}/g"
And and even...
# Append new lines of code
rg -l 'syncFields' \
| xargs sed -i \
'/const syncFields = \[/, /\]/ {
a\
const fieldValues = Object.keys(fields)
}'
sed syntax used above:
- Range part:
/start/, /end/ - Group part:
{ ... }(stuff to run against the pattern) - Append command:
a\(followed immediately by text to append)
I wasn't just keeping these things in a scratch-pad to copy-and-paste when I needed them (although I certainly did that) but I was conjuring up commands like these ad-hoc, and with less and less need to refer to manpages or Stackoverflow. It's quite the power-up, because all of this stuff is usable both within and without Vim.
# git worktree is amazing
It took since the 2nd week of December to get used to worktrees, but there's no way of going back to a single-branch workflow ever again.
For a surprise free experience, do not be tempted to use --bare repos with
your worktrees as some tutorials seem to propound. Instead, clone your first
branch into a subfolder:
git clone https://github.com/shuckster/repo.git ./repo/master
cd ./repo/master
Then create your worktrees from there:
# New branch from current
git worktree add -b fix/issue ../fix-issue
# Clone existing branch
git worktree add ../local-branch remote-branch
ls ../
master fix-issue local-branch
There is a trade-off of course: Because worktrees are contained within distinct folders you have to go through your installation and config prerequisites each time you create one.
cp ../dev/.env.local . ; npm ci ; npm run build:config
Not a dealbreaker, but it does make me miss using pnpm when at work.
Apparently ThePrimagen has written a plugin to permit a Neovim'er to easily
add/remove and switch between worktrees, but for me I'll be sticking (for now)
with cd'ing and nvim'ing in and out from the CLI. Or just having a few
terminal windows open for each worktree.
The following snippet lifted from Stackoverflow works great with the above workflow. It auto saves/loads the session based on the current working dir you started Neo/Vim from:
let g:sessiondir = has('nvim')
\ ? '~/.config/nvim/sessions'
\ : '~/.vim/sessions'
function! MakeSession(overwrite)
call mkdir(g:sessiondir, 'p')
let l:sessionfile = g:sessiondir . '/session.vim'
if a:overwrite == 0 && filereadable(l:sessionfile)
return
endif
exe 'mksession! ' . l:sessionfile
endfunction
function! LoadSession()
let l:sessionfile = g:sessiondir . '/session.vim'
if filereadable(l:sessionfile)
exe 'source ' . l:sessionfile
else
echo 'No session loaded.'
endif
endfunction
if (argc() == 0)
au VimEnter * nested :call LoadSession()
au VimLeave * :call MakeSession(1)
else
au VimLeave * :call MakeSession(0)
endif
" Manually save a session
nnoremap <leader>ss :call MakeSession(1)<CR>
Later in the month I intended to start learning tmux, which I expected would
make switching between multiple sessions easier. At home, at least. I'm afraid
tmux is not available in Windows outside of WSL, and I did not want to use
WSL just yet.
# Keyboard
Somehow the prospect of typing an extra 10-20 words per minute was enticing enough to go shopping, so I did. I won't turn this into a review, but the long story short is:
I'm really used to typing on an Apple Mac keyboard.
That's pretty much it. My own typing speed is not fast, perhaps 80 average, with 100 in bursts depending on what is being typed. But since I was "doing more" already by just using Vim, I decided not to put myself through the ordeal of retraining my fingers.
I returned the keyboard.
# Regression
Towards the end of the second week I was becoming frustrated with not having an editor where I could just CTRL+V like I always could. (I was still regularly forgetting that Neovim does in fact support this.) The issue arises whenever I find myself messing around with online playgrounds, or sharing code across a chat system.
I disabled the Vim Extension in VSCode so I could nave a Vim-free scratch-pad.
It didn't last long. The next time I hopped over to VSCode I had a complete brain block. It wasn't even that I had thoughts about which motions were suddenly no longer available - I couldn't even begin. I was just staring at the pasted code wondering how on earth I could do anything in VSCode.
I enabled the Vim extension once again.
I should say that this block happened in Windows, where my muscle memory for the default editing shortcuts has long atrophied. On Mac I can still do stuff without Vim motions.
The whole experience of feeling my old habits tugging at me once again made me question why I was doing this. I felt a powerful draw back to my old ways. I mean, I had got this far without Vim, right? I don't need this crap at this stage of my professional life, do I? But once I put myself back in that world I found I missed the Vim motions even more than CTRL+V. It's all very peculiar.
# Moving on
Into the 3rd week of January it seems like productivity is steadily going up and I'm a bit more comfortable getting things done. I'm making decent progress on the Great Refactor at work and light flickered at the end of the tunnel. For that project I mean, not Vim.
I wanted to run Google searches from within Vim, so I wrote a Bash script to
do it. It's tiny and uses jq:
# No arguments? Read from stdin
if [ ${#} -eq 0 ]; then
read query
else
query="${*}"
fi
# Replace spaces with plus signs
query=$(echo "${query}" | sed 's/ /+/g')
# Run the search and format into a Markdown list
curl -s "https://www.googleapis.com/customsearch/v1?\
key=YOUR_GOOGLE_API_KEY\
cx=I_FORGET_WHAT_THIS_IS\
q=${query}" \
| jq -r '.items[].link' \
| sed 's/^"\(.*\)"$/- \1/'
Doing things like this makes me feel better.
It was a nice antidote to - the same day - learning on
Reddit
that cil is not a Vim text-object, but something provided by a plugin
installed along with LazyVim.
(I'm still subbornly trying to stick to remaps created by myself rather than
plugins - although vim-abolish has
since made it back into my plugins.)
Three things brought January to a close for me:
vim-airline- Re-watching Let Vim do the Typing
- Learning about ranges
# vim-airline
This was a real love/hate moment.
You see this plugin (and things like it) all the time in screenshots you see on the social medias. People are constantly asking about how it was achieved or the colourschemes used, whether it's tmux or Neo/Vim and such.
My own (first) installation of vim-airline didn't even last 24 hours. I
immediately hated it for how busy things suddenly got. It is configurable,
but I didn't give it a chance in the first day.
Except for the optional "tabbed" buffer line. I liked that, and it inspired me
to come up with some remaps for previous/next buffer to accompany those I had
already come up with for tabs: [b ]b and [t ]t respectively.
# Let Vim do the Typing
I already watched this video in my second month of starting with Vim. I rewatched it with a completely different set of eyes this time, and found it much more memorable.
I took some notes:
<C-r> <register> put from register in INSERT mode. Already knew
about this one, but didn't know about the `.`
special register that pastes the last inserted
text from the previous INSERT mode operation.
<C-a> In INSERT mode, this is a shortcut for <C-r>.
<C-x> INSERT mode completion stuff. Most useful thing
from this part of the talk was pointing out that,
after hitting N or P (as you might do <C-n> or <C-p>
for regular completion) the <C-x> mode "remembers"
where the completion came from. With this context,
you can keep hitting <C-x>n or p to bring in
everything *from* that context.
<C-x>l (lowercase L) brings in the whole next line.
# Commands Learned
:tab splitopens your current split in a new tab, essentially "maximising" it. I use it all the time.- Learned how to move Tabs around:
:tabm[ove] -/+n, can also specify 0-index absolute values with:tabm 0. gtcan be prefixed with a number to move to that particular tab. I would later forget about this and remap my prev/next tabs shortcuts to[tand]trespectively.- Discovered Telescope can pop results into the QuickFix list with
<C-q>. - Learned about
\vto put regexes into a "normal" mode for things like:%s/\v//g. In other words, you have to escape the characters that have special regex meaning if you want to search for them literally. :windo diffthisrun this while you have a vertical-split to perform a diff between them.:windo diffoffdisables diff-mode (but will not close the window.) Was reminded of[cand]c.<C-w>tjump to the top-left window. Handy for getting toundotreefrom a split on the far-right.- Jumping to the start/end points of folds:
[z]z - Got 4 whole lines in tmux.conf! Vim navigation and 1-based tab-switching.
31 Jan, 2024