Camel to Snake in Vim

Here’s another useful refactoring shortcut. At work, we use React/JavaScript on the front end and Ruby on Rails on the back end. In Ruby, you make variable names with “snake case”, e.g. foo_bar_baz. In JavaScript, you generally use “camel case”, e.g. fooBarBaz. These aren’t hard and fast rules, but the usual conventions. Sometimes you need to convert between the two. I’ve made a couple of shortcuts that will do that. Unlike the macro-type shortcuts I made in the previous article, these will make use of regex to to search and replace.

1
2
3
4
" turn a snake into a camel
nnoremap <Leader>+ mmviw:s/\%V_\(.\)/\U\1/g<CR>:nohlsearch<CR>`m
" turn a camel into a snake
nnoremap <Leader>_ mmviw:s/\%V\(\u\)/_\L\1/g<CR>:nohlsearch<CR>`m

I’ll break it down step by step.

First, each mapping starts with mm and ends with \m`. This sets a mark at your current position before doing anything, and then returns to that position when you’re done. Little details like that make commands like this much nicer.

Then I do viw or “visual inside word”. This visually selects the current word the cursor is on.

Then the substitution, which has the format s/.../.../g. Replace what’s in the first part with what’s in the second. g means global, not just the first match. First, I put in a \%V. This restricts the search to the current visual selection which we did in the last step. I’m looking for an underscore followed by any other character. That would be _. But I want to capture that second character so I can uppercase it. So we’d say _(.). But I need to escape those parens, so it’s _\(.\). OK, that’s our search. I want to replace it with that captured second charcter, which would be \1. But I want to uppercase that character. So it’s \U\1. Finally, a carriage return to execute the substitution. <CR>.

If you have your Vim configured to show highlighted searches, this search will leave anything else that matches that search highlighted. In that file or any other open file. So I say :nohlsearch<CR> to cancel that.

That turns a snake-cased word into a camel-cased one. The reverse is pretty similar.

We want to search for any upper case character - \u in the currently visually selected word, and capture it. \%V\(\u\).

And we want to replace that upper case character with an underscore, plus that same character, lower-cased. _\L\1.

All the rest is the same. I’ve mapped these to <Leader>+ and <Leader>-, but do whatever works for you.

Refactoring in Vim

Pretty much anything you can do manually in Vim, you can also directly script and turn into some kind of command, function or simple mapping. This is one of its great powers. If you find yourself doing something on a regular basis, you can just make a shortcut to do that complex thing in a couple of keystrokes.

For example, in my job, we do a lot of React, using ES6. There’s tons of legacy code that creates class methods like this:

1
2
3
4
5
class Foo {
doStuff() {
// does some stuff
}
}

Or sometimes just some standalone function like this:

1
2
3
function doStuff() {
// does stuff
}

But sometimes those functions are used as callbacks or in other ways that mess up the scope. So I need to turn them into closures, like this:

1
2
3
4
5
class Foo {
doStuff = () => {
// does some stuff
}
}

Or:

1
2
3
const doStuff = () => {
// does stuff
}

Making those changes is very straightforward. Replace function with const if it exists, find the opening ( and insert the = before it, find the closing ) and insert the => after it. After doing it several times, I came up with a shortcut:

1
nnoremap <Leader>( :s/function/const/e^Mf(i = ^[f)a =>^[

Walking through it. First we replace function with const. :s/function/const/e. The e at the end ignores any errors. In this case, if it doesn’t find the word function. I wanted the single macro to work for regular functions as well as class methods, which don’t use the word function.

The ^M there is a return character. If you were just typing this command in command mode, you’d have to hit enter to do the substitution.

Note! You can’t just type the characters ^ and M here. And you won’t be able to copy and paste the code from this page into your Vim config. ^M is a special control code. You enter it by typing Control-v Control-m.

Now the replacement is done, if it needed to be.

Then we find the opening paren: f(. We go into insert mode and enter the equals sign: i =.

Then we need to escape out of insert mode. That’s done with another escape code: ^[. You get that by typing Control-v Control-[.

Finally, you find the closing paren, append, enter the fat arrow and escape again. f)a =>^[.

I’ve saved this as <Leader>(. Works great.

To create these types of mappings, you can just mentally walk through the steps and try to insert the right characters. But there’s an easier way - with macros.

A macro allows you to record everything you do and then play it back. You start a macro by typing q plus another character. Say, qa to make a macro called a. I did this and then just did the transformation that I’d normally do. Did the function to const substitution, found each paren and inserted stuff before and after.

When you’re done with your macro, hit q again to save it. Now you can re-run that macro by typing @a. By default, though, macros are not saved beyond the session you are in. There are ways to save your current macros and reload them, but I wanted to get the contents of the macro to use in a shortcut.

Macros are stored in registers. You can see the contents of any register or paste it into your buffer.

For macro a, type :reg: a and you’ll see the code that you just recorded. Which is exactly what I just showed you in the above mapping. You can even paste the content of a macro. Just type " plus the register of the macro, a in this case, plus p. So, "ap.

So, once you have a macro and have verified that it does what you want it to do, go into your Vim config, type your mapping, like nnoremap <Leader>( and then paste the macro in, as per the above. Note that it will have all the correct escape characters, etc. Wonderful. You can even edit it further from there if you need to.

Search and Replace in Vim

Search and replace is pretty straightforward in Vim. But it’s done in command mode rather than with a nifty little search and replace dialog. Type : to get into command line, and then if you want to replace foo with bar, you do:

1
:s/foo/bar/

However, this simple syntax is very limited. It will just replace the first occurrence of foo with bar - on the current line you’re on. If you want to replace all the instances of foo on the line, add a g at the end:

1
:s/foo/bar/g

A more common use case is that you want to replace every occurrences of foo in the current file with bar. To do that, use %s:

1
:%s/foo/bar/g

That’s a lot to remember and type. OK, it’s not really that much, but if we can make it easier, why not? Here’s a mapping that makes it a little better, IMO:

1
nnoremap <Leader>rr :%s//g<Left><Left>

This is mostly a straight up and really simple macro-type mapping. It just takes you into command line and then types out everything you need except the terms you want to find and replace. And then it adds two <Left>s that move the cursor back in between the two forward slashes. After typing the shortcut, you just need to type the search word, a forward slash and the replace word. Pretty simple.

But we can go one further. Since the word you want to replace is usually right there in front of you, it would be great if we could grab it out of the buffer, rather than retyping it by hand. We do that with a special control key combo, <c-r><c-w>. This stands for the word currently under the text cursor in the current buffer. Here’s that in use:

1
nnoremap <Leader>rw :%s/<c-r><c-w>//g<left><left>

This is essentially the same as the first, but it auto-inserts the search term that your cursor is on, and the middle forward slash. All you need to do now is type the word you want to replace it with and hit enter.

Spell checking in Vim

Another article discussing prose editing in Vim. You might want to check out this one and this one as well.

Spell checkers in code editors are useless. There are so many different programming languages, each with their own key words. And you, yourself, will be creating functions and variable names that aren’t valid English words. Some editors try to get smart and only spell-check words in strings, the theory being that these will all be proper English. Not a great theory.

However, if you start using Vim as more of a wordprocessor, spell-checking would be a nice thing to have. Initially, I assumed that this would require some kind of plugin. But it turns out that spell-checking is built right into Vim.

You’ll need to configure two options. I put these in my config:

1
2
set spelllang=en_us
set spellfile=~/Dropbox/vimspell/en.utf-8.add

The first just sets the language. Obvious. The second is a link to the file where you will store your own custom added words. It should be in the format shown there: en.utf-8.add. You can have different spell files for different languages by changing the first part of that.

You can store the spell file wherever you want. I put mine in Dropbox so it syncs across my machines and the words I’ve added are availble anywhere.

Now, how do you turn on (and off) spell checking?

On, just type:

1
:set spell

Off:

1
:set nospell

Simple enough. As mentioned in this post, I use the plugins Goyo and Limelight to set up a nice wordprocessing environment. It makes sense to me to have spell check automatically turned on when I enter Goyo, and turned off when I leave. Well, that post I just mentioned tells us just how to do that. So I added these two lines:

1
2
autocmd! User GoyoEnter set spell
autocmd! User GoyoLeave set nospell

This is the same thing I did to turn Limelight on and off in sync with Goyo. Now it gives me auto-spell-check mode as well!

Now, if you type a word that Vim doesn’t know, it will underline it. You can also jump between spelling errors with the shortcuts ]s to go to the next error, and [s to go to the previous error.

That’s good in itself, but real processors will suggest corrections too. With the cursor on the offending word, press z=. This opens up a list of possible corrections. It looks like this:

Not quite as pretty as Microsoft Word, but it gets the job done. Press the number of the word you want to use to replace your error, and hit enter. Or just hit enter to get out of the list.

If what you have typed is some specialized word that you’ll likely use again in other documents, you can add it to the spell file we created earlier. Do that by putting the cursor on the word and typing zg. Now Vim knows that word. At least as long as you keep that spell file around.

There’s another useful option. If there’s a word that Vim doesn’t know and you’d like to tell Vim it’s OK, but you don’t want to permanently add it to your main spell file, type zG instead. This adds the word to a temporary internal word list. This word list is deleted when you exit Vim.

There are lots of other options for spell checking type :help spell to read about all of them.

Editing text with Vim, Goyo and Limelight

When you are really comfortable with the Vim way of doing things, using any other text editor can be painful. Your writing may end up filled with stray h, j, k, l, i characters or end with :wq. So, whenever I need to write more than a sentence or two in any other editor, I’ll usually do all the initial composition in Vim, and then copy it over to whatever it will wind up in for final editing.

There are a couple of plugins I use to make prose editing in Vim an even nicer experience. Goyo and Limelight. Both are written by the same person, and they work great together. Let’s see them in action. Here’s a screenshot of a draft of this very page in Vim:

As you can see, it’s not quite as nice as using a dedicated wordprocessor. The line numbers are distracting. The full width text is really hard to scan. And because each paragraph often ends up being one or two lines long, It’s really hard to visually group them. I’ve also got a tab bar up at the top and a status bar down at the bottom that don’t really add to the experience of writing long form text.

So here is the same page with Goyo and Limelight turned on:

All distractions are gone - line numbers, tab bar, status bar, color column. There are healthy margins on all four sides of the text. This narrows the actual text width, making the paragraphs look more like… paragraphs. That’s all Goyo in action. (Note that I do still have a tmux status bar down at the bottom. I can live with that.)

Also notice that the paragraph I’m currently editing is much brighter than all the other paragraphs, which have been dimmed down. This is the functionality of Limelight. It puts what you’re currently focusing on… in the limelight.

To get this setup, install the two plugins from the links above. I’ll assume you’re using some kind of plugin manager or have otherwise figured out how to install and manage plugins manually.

Now you need a way to turn them on and off. As great as this setup is for general text editing, you don’t want to use it for coding.

Goyo can be toggled by typing :Goyo. If it’s off, that’ll turn on, and vice versa. So I’ve set up a mapping in my config like so:

1
nnoremap <Leader>gy :Goyo<CR>

I also only want Limelight on when I’m using Goyo. I could set up a toggle shortcut for that too, but it’d be great if I could tie the two together. Fortunately, that’s easy. There are events that you can use to trigger actions when you enter or leave Goyo mode. We can tie those to commands to turn Limelight on and off. Looks like this:

1
2
autocmd! User GoyoEnter Limelight
autocmd! User GoyoLeave Limelight!

Now, when you turn Goyo on, it turns Limelight on. Turn it off, they both go off. One other tweak you might want to play around with is setting the color Limelight uses for the dimmed text. I have this:

1
let g:limelight_conceal_ctermfg = 240

This makes all dimmed text a medium gray color. I think it’s pretty close to whatever the default is anyway. But if you don’t want it quite so dim, or maybe you want it some other color entirely, that’s where you set it.

When you’re in Goyo mode, you’ll almost certainly want to adjust your vertical navigation keys as I described in this article.

In another article, I’ll talk about using spell-checking in Vim, which goes hand-in-hand with using Goyo for long form text editing.

Better cursor movement in Vim

OK, you’ve been using Vim long enough where you’re used to h, j, k, and l for navigation. And maybe you mostly write code. And you’re probably a good coder who respects line length so you don’t have a lot of line wrapping. So those j and k keys work pretty well for you for moving up and down in your text.

But then you start getting annoyed whenever you’re typing in some other editor or word processor and you decide to use Vim as an editor not just for code, but for freeform prose. And you run into a problem because now you have paragraphs. But Vim sees each paragraph as a single line. I’m assuming you have line wrapping on here (set wrap). So when you start using j and k to move up and down, you are navigating by paragraph. You’re positioned at the bottom of a paragraph and you hit k and suddenly you are at the top.

So you start moving through using h or l to move through the paragraph letter by letter. Or, hopefully, w or b or e to move word by word. Or maybe you’re a real pro and you’re using ( or ) to move through by sentences.

Whatever you’re doing, it’s a real pain when the character you’re on is directly underneath the character you want to be on, and you can’t just move there. But you can! Just prepend your vertical motion key with g!

gj moves up one visible line and gk moves down one visible line.

Problem solved? Yes, but no. It’s still a pain to press two keys with two different fingers on two hands to move upwards or downwards through a paragraph. So I just remapped j and k to gj and gk.

1
2
3
" move by one line
nnoremap j gj
nnoremap k gk

Now j and k work just like the up and down arrow keys in any other text editor. At first I just did this mapping when I was working on long form text, but I left it on and I haven’t seen any downside in having it there all the time for code editing too. However, if you want to have the behavior toggle-able, you can set up a mapping like this:

1
2
nnoremap <Leader>gg :nnoremap j gj<CR>:nnoremap k gk<CR>
nnoremap <Leader>gx :nunmap j<CR>:nunmap k<CR>

Use whatever trigger works for you. One of them does the two mappings I already mentioned. The other one calls nunmap - normal mode unmap - to remove those mappings.

Increment/Decrement Numbers in Vim

Vim is primarily a code editor, though once you get acclimatized to it, you’ll find yourself wanting to use it for any and all text editing. But when you’re editing code, you’re probably going to have numbers somewhere in your code. Sometimes you’re going to want to change those numbers. Maybe you’ll need to completely replace a number with another number, but other times you’re going to want to nudge that number up or down.

Take CSS for example. You have a margin that is set at 10px and it needs to be a bit larger. You can position your cursor over the 0 and press r to replace and 1 to change the total value to 11px. See how it looks, do the same thing to change it to 12 or 13. Hmm… Maybe it would be better smaller. Delete the whole 13 and replace it with 8.

There’s an easier way. And an even easier one.

Put your cursor on the line in question - anywhere before the number, and hit Control-A. The cursor jumps to the next number in that line and increments it. Continue hitting Control-A and the number keeps going up one-by-one. And Control-X does the same thing in reverse - decrementing the next number on the current line.

As useful as that is, a mapping can make it even easier.

1
2
3
" increment/decrement numbers
nnoremap + <C-a>
nnoremap - <C-x>

Really simple one. Normal mode mapping of + to Control-A for increment and - for Control-X for decrement. Makes things a lot more convenient. Of course, you might want to choose some other keys - < and > maybe. Whatever works for you.

Managing your Vim config

I find myself going in and out of two main modes since I’ve been using Vim full time. I’ll go deep messing with my Vim config and trying out new plugins. And then I’ll get it to a point I’m really happy with and I won’t mess with it for a while - just use it. After a week or two of use, I’ll start tweaking things again.

When I’m in tweak mode, I’m editing my Vim config and reloading it constantly. So it helps to have some shortcuts to do that easily.

Here’s what I have in my Vim config to do that:

1
2
3
4
5
" edit .vimrc
nnoremap <Leader>ev :e ~/.vimrc<CR>

" source .vimrc
nnoremap <Leader>sv :so ~/.vimrc<CR>

Breaking it down…

nnoremap means this mapping only applies to normal mode (n), and will not change any functionality of any existing commands (noremap).

<Leader>ev is what I need to press to trigger the shortcut. The leader key is a specially defined key in Vim. By default it is the forward slash /. I have mine remapped to use the comma key ,. Some people like to use the space bar. It’s all personal preference.

Change that to whatever works for you in your Vim config as well:

1
let mapleader = ","

Then comes what will happen when this shortcut is triggered:

:e ~/.vimrc<CR> is exactly as if you had typed that in within Vim. : puts you in command mode. e means edit. Then there’s the path to the .vimrc file, followed by a carriage return (enter) <CR>.

All in all, this opens up your Vim config file for editing. After you’ve edited it, you’ll need to reload it, or “source” it. The next mapping does that with the shortcut <Leader>sv. Again, command mode with : and then so is short for source. Then the path to the config file and enter. Now whatever you just typed and saved in your config is live.

Actually, I use neovim, so my config file is ~/.config/nvim/init.vim. Thus, my actual mappings are:

1
2
3
4
5
" edit init.vim 
nnoremap <Leader>ev :e ~/.config/nvim/init.vim<CR>

" source init.vim
nnoremap <Leader>sv :so ~/.config/nvim/init.vim<CR>

Another thing you might want to try is :vs or :sp rather than :e for editing. This will open the config file in a vertical or horizontal split, alongside whatever else you were already editing.

init()

Oh, hello there. Gonna try a little experiment here. Sharing some (very) short form tech tips. Mini/micro blog format. I also wanted to try out one of these “static site generators”. I’m going with Hexo. Pretty straightforward stuff. Well documented, with a bunch of useful videos embedded in their docs. I was pretty amazed at how quick and easy it was to set up and publish a site.

I’ve been diving heavily into Vim in the past few months. So the initial posts will probably be focused on Vim tips - key mappings, useful settings, plugins I’m trying, etc. And from there, who knows?