Jeff
Jeff

Reputation: 1857

camelCase to underscore in vi(m)

If for some reason I want to selectively convert camelCase named things to being underscore separated in Vim, how could I go about doing so?

Currently I've found that I can do a search /s[a-z][A-Z] and record a macro to add an underscore and convert to lower case, but I'm curious as to if I can do it with something like:

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

Thanks in advance!

EDIT: I figured out the answer for camelCase (which is what I really needed), but can someone else answer how to change CamelCase to camel_case?

Upvotes: 45

Views: 20725

Answers (8)

Betheev
Betheev

Reputation: 35

I would like to add my two cents to this old question. If you don't want to install additional plugins, you can add the following mappings:

nnoremap <expr> <leader>cc 'ciw' . substitute(expand("<cword>"), "\\(_\\)\\([a-z]\\)", "\\u\\2", "g") . '<esc>b'
nnoremap <expr> <leader>sc 'ciw' . substitute(expand("<cword>"), "[a-z]\\@<=[A-Z]", "_\\l&", "g") . '<esc>b'

Type <leader>cc to change the word under the cursor from snake_case to camelCase and <leader>sc to change the word under the cursor from camelCase to snake_case. Furthermore, if you have Tim Pope's vim-repeat plugin installed, use the following mappings to repeat the action using the . command:

nnoremap <expr> <Plug>SnakeCaseToCamelCase 'ciw' . substitute(expand("<cword>"), "\\(_\\)\\([a-z]\\)", "\\u\\2", "g") . '<esc>b:call repeat#set("\<Plug>SnakeCaseToCamelCase")<cr>'
nnoremap <silent> <leader>cc <Plug>SnakeCaseToCamelCase

nnoremap <expr> <Plug>CamelCaseToSnakeCase 'ciw' . substitute(expand("<cword>"), "[a-z]\\@<=[A-Z]", "_\\l&", "g") . '<esc>b:call repeat#set("\<Plug>CamelCaseToSnakeCase")<cr>'
nnoremap <silent> <leader>sc <Plug>CamelCaseToSnakeCase

An advantage of these mappings is that the cursor remains on the word.

Upvotes: 1

Jeff
Jeff

Reputation: 1857

I suppose I should have just kept trying for about 5 more minutes. Well... if anyone is curious:

%s/\(\l\)\(\u\)/\1\_\l\2/gc does the trick.

Actually, I realized this works for camelCase, but not PascalCase, which could also be useful for someone.

Upvotes: 17

Ela Dute
Ela Dute

Reputation: 846

For the camelCase:

%s/\v<([a-z_]+)([A-Z][a-zA-Z]+)>/\1_\l\2/gc

You may need to run this command multi times.

Upvotes: 1

Raimondi
Raimondi

Reputation: 5303

This is a bit long, but seems to do the job:

:%s/\<\u\|\l\u/\= join(split(tolower(submatch(0)), '\zs'), '_')/gc

Upvotes: 43

Chiedo
Chiedo

Reputation: 7544

I whipped up a plugin that does this. https://github.com/chiedojohn/vim-case-convert

To convert the case, select a block of text in visual mode and the enter one of the following (Self explanatory) :

:CamelToHyphen :CamelToSnake :HyphenToCamel :HyphenToSnake :SnakeToCamel :SnakeToHyphen

To convert all occerences in your document then run one of the following commands:

:CamelToHyphenAll :CamelToSnakeAll :HyphenToCamelAll :HyphenToSnakeAll :SnakeToCamelAll :SnakeToHyphen

Add a bang (eg. :CamelToHyphen!) to any of the above command to bypass the prompts before each conversion. You may not want to do that though as the plugin wouldn't know the different between variables or other text in your file.

Upvotes: 9

Luc Hermitte
Luc Hermitte

Reputation: 32926

I have an API for various development oriented processing. Among other things, it provides a few functions for transforming names between (configurable) conventions (variable <-> attribute <-> getter <-> setter <-> constant <-> parameter <-> ...) and styles (camelcase (low/high) <-> underscores). These conversion functions have been wrapped into a plugin.

The plugin + API can be fetch from here: https://github.com/LucHermitte/lh-dev, for this names conversion task, it requires lh-vim-lib

It can be used the following way:

  • put the cursor on the symbol you want to rename
  • type :NameConvert + the type of conversion you wish (here : underscore). NB: this command supports auto-completion.
  • et voilà!

Upvotes: 0

nelstrom
nelstrom

Reputation: 19542

You might want to try out the Abolish plugin by Tim Pope. It provides a few shortcuts to coerce from one style to another. For example, starting with:

MixedCase

Typing crc [mnemonic: CoeRce to Camelcase] would give you:

mixedCase

Typing crs [mnemonic: CoeRce to Snake_case] would give you:

mixed_case

And typing crm [mnemonic: CoeRce to MixedCase] would take you back to:

MixedCase

If you also install repeat.vim, then you can repeat the coercion commands by pressing the dot key.

Upvotes: 72

michaelmichael
michaelmichael

Reputation: 14125

For the CamelCase case:

%s#(\<\u\|\l)(\l+)(\u)#\l\1\2_\l\3#gc

Tip: the regex delimiters can be altered as in my example to make it (somewhat) more legible.

Upvotes: 2

Related Questions