Vim: Converting to JavaCase to ruby_case

This morning I was in a mode to do a regex kata and thought it would be interesting to see if I can substitute CamelCase (I call it JavaCase for fun) to underscore_separated_words (I did a search and could not find a good word for this so) I will call it ruby_case.

Here is how I started (note in my setting of vim you have to escape parens \):

:%s/\([a-z]\)\([A-Z]\)/\1_\2/gc

The above matches lowercase letter followed by uppercase letter and captures them then replaces them with underscore between them.

:%s/\(\l\)\(\u\)/\1_\2/gc

I found that Vim has metacharacters for upper (\u) and lowercase (\l). So above become cleaner version of the previous, call it refactoring. (JavaCase => Java_Case)

:%s/\(\l\)\(\u\)/\1_\L\2/gc

I found how to change an uppercase capture to lowercase. But this was leaving first character of the word still uppercase (JavaCase => Java_case)

:%s/\(\<\u\).*\(\l\)\(\u\)/\L\1\2_\L\3/gc

In this attempt to capture the first letter and lower case it I lost the letters in between. (JavaCase => ja_case)

:%s/\(\<\u.*\)\(\l\)\(\u\)/\L\1\2_\L\3/gc

Finally, I got what I wanted. (JavaCase => java_case) Hurray!

But I notice the match is greedy, so if there are multiple CamelCase on the same line this would fail.

For now I will leave this as an exercise for the reader as I am out of time for now, when I have a solution I will add it here.

This was a fun little exercise and I enjoyed it very much. Now I can find and solve a problem like this every morning it will jump start the day.

Reference: Vim Regular Expression 101 (http://www.geocities.com/volontir/)

Cheers!