1

The twist here, is that I'm using IdeaVim inside PhpStorm, so I'm looking for something simple, that works both in Vim (~/.vimrc) and PhpStorm (~/.ideavimrc).

I'm actually using Neovim (LazyVim), but I would like a solution that works in regular Vim if possible. This isn't a must, though.

The mission

Go to the next uppercase character, ideally using E (shift+e) and B (shift+b). So for a word like this: theQuickBrownFoxJumpsOverTheLazyDog.
Then I can set the cursor in the beginning of the word and type: EEE (and then the cursor is at the F).
Followed by Shift+e Shift+e h (selecting FoxJumps). Press x to delete it and then press i (insert mode) and write a replacement.

Solution attempt 1: noremap in ~/.vimrc

I tried this:

noremap <silent> E :set nohlsearch<CR>/\u<CR>:set nohlsearch<CR>
noremap <silent> B :set nohlsearch<CR>?\u<CR>:set nohlsearch<CR>

The :set nohlsearch is because the files can be long, and it adds a delay, if it momentarily should select all uppercase letters, for large files.

That works in normal mode, for both Vim and PhpStorm (IdeaVim).

But I can't modify that, so it works in visual-mode.

Solution attempt 2: A function

I tried something like this:

function! CamelForward()
    call search('\u', 'W')
endfunction

function! CamelBackward()
    call search('\u', 'bW')
endfunction

nnoremap <silent> E :call CamelForward()<CR>
nnoremap <silent> B :call CamelBackward()<CR>

And that works in Vim, but not in PhpStorm (IdeaVim).

And even so, then the select-part doesn't work either, even if I add something like this:

vnoremap <silent> E :<C-u>call CamelForward()<CR>
vnoremap <silent> B :<C-u>call CamelBackward()<CR>

Solution attempt 3: Add a global toggle shortcut

It would also be a solution, if there is a global shortcut (such as <leader>c that toggles "CamelCase mode" on and off. And if it's on, then e and b goes to previous/next uppercase letter.

But this involves a function as well, making it not work in IdeaVim.
And I also can't get the visual mode to work in regular Vim either.

2
  • 1
    Just to have the same understanding: you're aware that E and B already do something out of the box and you want to override the default behavior for your "CamelCase mode"? Commented 22 hours ago
  • 2
    Yep, I would like to override the default behavior. :) Commented 22 hours ago

4 Answers 4

2

When you create a <silent> mapping, all error messages are suppressed. This makes it almost impossible to debug mappings. The generally recommended way is to:

  1. make it work
  2. suppress errors (if needed at all)

Let's debug the mapping. As you already observed, it works fine in Normal mode, but not in Visual mode. When we remove the <silent> and run your mapping in Visual mode, we first run

:'<,'>set nohlsearch

which triggers E481: No range allowed.

The solution is to either throw away the range with (old) <C-U> or use (new) <Cmd> which will work in any mode as explained in :help :map-cmd:

:noremap E <Cmd>set nohlsearch<CR>/\u<CR><Cmd>set hlsearch<CR>

I also took the liberty of changing the trailing nohlsearch to hlsearch to switch it on after the search is done. But that will highlight everything again, possibly slowing things down.

I'd consider just switching off the highlights immediately after the search with :nohlsearch:

:noremap E /\u<CR><Cmd>nohlsearch<CR>

As for your "CamelCase mode", I'd conditionally create or remove mappings.

This answer was tested in Vim.

1

To make the first solution working in visual mode I would do:

function! SearchForward()
  execute "normal /\\u\<C-m>"
endfunction
vnoremap E <Cmd>set nohlsearch<Bar>call SearchForward()<Bar>set nohlsearch<Cr>

function! SearchBackward()
  execute "normal ?\\u\<C-m>"
endfunction
vnoremap B <Cmd>set nohlsearch<Bar>call SearchBackward()<Bar>set nohlsearch<Cr>

More information with: :help <Cmd>

I suppose it is not an option for PhpStorm but for Vim or Neovim you could be interested by the following CamelCaseMotion plugin.

1

IdeaVim has an undocumented/non-standard camel case motion [w to move to the start of the next capital letter of a camel case word and [b to move back. There's also ]w and ]w.

Unfortunately, this is only a motion and not a text object. I have long intended to create an extension to emulate Vim's CamelCaseMotion plugin, which would provide motion and text object, at which point this non-standard mapping would go away. See VIM-1984.

New contributor
citizenmatt is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
1
  • Welcome to Vi and Vim and thank you for posting an answer. Nice avatar, by the way. Commented 2 hours ago
0

A basic solution for visual mode is:

noremap <silent> E :set nohlsearch<CR>/\u<CR>:set nohlsearch<CR>
noremap <silent> B :set nohlsearch<CR>?\u<CR>:set nohlsearch<CR>

vnoremap <silent> E :<C-u>set nohlsearch<CR>gv/u<CR>:<C-u>set nohlsearch<CR>gv
vnoremap <silent> B :<C-u>set nohlsearch<CR>gv?u<CR>:<C-u>set nohlsearch<CR>gv

Where:

  • <C-u> deletes the range part generated by the switch to command mode (:)
  • gv restore the selection lost in the switch to command mode

Remark: I have added this solution since it relies only on basic Vim key commands (no functions, no special command mapping <Cmd>)

I have tested the solution successfully on:

  • Vim
  • Neovim
  • IdeaVim

Your Answer

By clicking โ€œPost Your Answerโ€, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.