Make vim more powerful by customizing it with your own commands! I recently had a problem that was pretty easy to solve with a few vim commands. After sorting it out, I realized that I might need to solve this problem again in the future; this was not premature optimization, I promise. After years of using vim, I still wasn’t confident in writing my own commands. Turns out it’s a lot easier than I had expected once I took the time to learn. Here’s a simple breakdown through example of what it takes to start adding your own custom commands to your vim experience.
Step 0: The Problem
I prefer spaces over tabs. I was writing
css files with a
tabstop of four spaces and realized I would like each file to only have two
spaces per tab. I updated my filetype settings so all new files would have the
correct tab spacing. Then I decided to find a solution to update all the
existing files to my liking.
Step 1: The Solution
Stack Overflow to the rescue. I quickly found an answer that solved my problem. All I had to do was open each file and enter the following commands.
:set ts=4 sts=4 noet :retab! :set ts=2 sts=2 et :retab
Perfect. I tested it out. All my 4 space tabs turned into 2 space tabs. I opened the next file, pressed the up arrow several times, pressed enter a few times and repeated the necessary commands to adjust the tabs once again.
Then I decided this was boring. I wanted a quick reusable solution.
Step 2: Turn the Solution into a Function
Vim allows you to write your own functions. For now, just place them in your
- Vimscript functions must start with a capital letter if they are unscoped!
- Add a bang (!) to the function definition in order to overwrite any existing definitions.
- Functions can take parameters. And commands can pass params to functions.
- Assign local variables with
function! ChangeTabStops(current, new) let &l:tabstop = a:current let &l:softtabstop = a:current set noexpandtab retab! let &l:tabstop = a:new let &l:softtabstop = a:new set expandtab retab endfunction
And here’s the short version.
fu! ChangeTabStops(c, n) let &l:ts = a:c | let &l:sts = a:c | set noet ret! let &l:ts = a:n | let &l:sts = a:n | set et | ret endf
Cool! I prefer the longer version. Vim script is arcane enough as it is. Either way, now it’s a lot simpler to update each file. All we have to do is:
:call ChangeTabStops(4, 2)
But we can do even better.
Step 3: Turn the Function into a Command
By adding a command that calls our new function, it will be even easier to update each file. The following line creates the command that will pass all the arguments to the function we made:
command! -nargs=* ChangeTabStops call ChangeTabStops(<f-args>)
Now to update a file, I just have to type:
:ChangeTabStops 4 2
If this command ends up being used all the time, we could assign a mnemonic
mapping to call it with even less keystrokes. How about
nnoremap <leader>ct :ChangeTabStops 4 2<CR>
That’s it. It’s really pretty simple to create your own commands/functions that
will supercharge your vim experience. I don’t recommend running out and writing
a function for every little thing you do. When you notice that you’re spending a
lot of time doing something or always repeating the same actions over and over,
take a step back see if there’s a better way to achieve the result. Don’t be
afraid to dive into vim’s
:help system. If you can streamline something you do
over and over again it can really pay dividends in the long run.