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.

" 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.