0

I use vim for coding. I have a disability where some of my fingers hurt and I have trouble holding down shift and a letter to produce uppercase. The same goes for parentheses.

How can I convert lowercase text to camel case?

For instance:

  • ccw: change function name to camel case (first letter in lowercase)
  • cccw: change class name to camel case (first letter capitalized)

Here are some camelCase examples:

For function names

  • lowercase: retrieveelementsbycriterion
  • camel case: retrieveElementsByCriterion

For class name

  • lowercase: parentawaretree
  • camel case: ParentAwareTree
1

4 Answers 4

1

There are a few plugins out there that do the job. And, shameless plug, I got mine: lh-style.

In particular, you'll be interested in the command :NameConvert upper_camel_case (or lower...).

As such the command requires capitalization for the first N (then tab completion can do the rest), and of course it won't suit you as is. Fortunately you can always map it to whatever feels comfortable (and doesn't conflict with other shortcuts you are using). For instance:

:nnoremap <silent> ccw  :<c-u>NameConvert lower_camel_case<cr>
:nnoremap <silent> cccw :<c-u>NameConvert upper_camel_case<cr>

There is no AI behind it, only regexes, and as such it'll need a way to know what should be capitalized: with this solution, you'll have to start from identifiers in snake_case.

Note: the plugin does a few other things. In particular, it provides functions you could use from snippets you would use to generate classes or functions -- but then it will require a little bit of scripting. The two functions of interest are lh#naming#to_lower_camel_case() and lh#naming#to_upper_camel_case()

For the sake of completeness, these two functions rely on the following regex substitutions:

" Function:lh#naming#to_upper_camel_case(identifier)   {{{3
function! lh#naming#to_upper_camel_case(identifier) abort
  " to_uppercase the first letter, and every letter after a _
  let identifier = substitute(a:identifier, '\%(^\|_\)\(\a\)', '\u\1', 'g')
  return identifier
endfunction

" Function:lh#naming#to_lower_camel_case(identifier)   {{{3
function! lh#naming#to_lower_camel_case(identifier) abort
  " to_uppercase every letter after a _
  let identifier = substitute(a:identifier, '_\(\a\)', '\u\1', 'g')
  " make sure the first letter is in lowercase
  let identifier = substitute(identifier, '^\(\a\)', '\l\1', '')
  return identifier
endfunction
0

This answer focuses on easy solutions that work out of the box and completely ignores the AI requirement (sorry in advance). Speaking of AI, I think the way to go would be to use GitHub Copilot (which can be used through a Vim plugin) and ask it to do what you want. You would have to pay to use Copilot, though. AI results are non-deterministic in nature. Reading your examples, it seems your interested in a very deterministic solution.

Changing case is such a common operation that Vim offers a couple of ways to do so. See :help case. Depending on your keyboard layout, some of these may already be useful. If not, they can be made accessible by creating a mapping or an abbreviation (two important mechanisms to tweak Vim to personal preferences and needs).

Some notable commands to change case are:

  • ~ to switch case of the letter under the cursor
  • gU{motion} convert {motion} to upper case.
  • :substitute/pattern/\U& change "pattern" to upper case (see :h s/\U)

Now gU already contains an upper case letter which was chosen for obvious reasons but is unlucky in this case. You could create a mapping using e.g. your leader key like this

:nnoremap <leader>u gU
:nnoremap <leader>uu gUl

To create snakeCase names from lower case, I think it's easiest to use markers to indicate which letters should be capitalized. In the example below, a minus is used but this can be tweaked by changing the replace pattern.

:nnoremap ccw <Cmd>substitute/-\(\l\)/\U\1/g<CR>

This will capitalize any lower case letter (\l) that was prefixed by a minus - (and remove it).

To pick one of your examples, you would write

class -parent-aware-tree
{
    int retrieve-elements-by-criterion()

And - after pressing ccw on lines 1 and 3 - you would get:

class ParentAwareTree
{
    int retrieveElementsByCriterion()

When it comes to parentheses, I'd play around with :iabbrev or :inoremap to create convenient sequences that will be turned into opening or closing parentheses. The difference is that :iabbrev works on whole words (i.e. you have to press Space to make it happen) while :inoremap suppresses output while you type, which can be slightly annoying.

Since a comma is usually followed by a space, you might try and get started mappings for opening and closing parentheses like these:

:inoremap ,o (
:inoremap ,c )
0

My preferred plugin is tpope/vim-abolish. While it also includes handy substitution and abbreviation mechanisms, I primarily use its coercion features to convert between various programming cases.

From the docs:

Abolish's case mutating algorithms can be applied to the word under the cursor
using the cr mapping (mnemonic: CoeRce) followed by one of the following
characters:

  c:       camelCase
  p:       PascalCase
  m:       MixedCase (aka PascalCase)
  _:       snake_case
  s:       snake_case
  u:       SNAKE_UPPERCASE
  U:       SNAKE_UPPERCASE
  k:       kebab-case (not usually reversible; see |abolish-coercion-reversible|)
  -:       dash-case (aka kebab-case)
  .:       dot.case (not usually reversible; see |abolish-coercion-reversible|)

For example, cru on a lowercase word is a slightly easier to type equivalent
to gUiw.

I missed some of the context of starting with applecat and getting appleCat—that probably would be hard to get right. But if you can type apple-cat or apple.cat comfortably (none of which require Shift on my keyboard layout), then crc or crp should work (as long as either - or . is in 'iskeyword', unfortunately).

0

FWIW, it is practically impossible to reliably convert:

retrieveelementsbycriterion

to:

retrieveElementsByCriterion

because the word boundaries can't be known without a very large dictionary that would account for every possible typo. And even then, the computation would probably be very expensive.

Of course, none of the proposed solutions addresses that part of your question… because they simply can't. What they can work with, though, is something like:

retrieve-elements-by-criterion

where word boundaries are explicit.

Alternatively, you can press the Caps Lock key, press the desired key, and press the Caps Lock key again. That's three keystrokes for a B which, considering your situation, is not too bad.


There is a pattern emerging from your questions: you are looking for Vim-specific solutions to non-Vim-specific problems. This is a misguided approach, as you will have to repeat the process over and over again.

Case in point: you need to type camelCase words in Vim, but also in browser textfields and in Teams or Slack or whatever. Solving the problem in Vim won't solve it in your browser or your collaboration tools.

You are having difficulties using your keyboard. That is the problem to which you should find a solution. And that solution is to use a more suitable keyboard, not to cobble together fragile workarounds.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.