2

When wanting to edit another file, I'm a big fan of typing

:e 

then tab (or a few characters before) to see the wildmenu pop up.

Problem is that the way it works, arrows keys up and down go 'down' or 'up' in the hierarchy and left and right lets you navigate through file within the same hierarchy level.

This is very unintuitive for me as I would like the up and down arrows to select file and the side arrows to change hierarchical level.

I know how to remap keys in general, but I never had to remap keys specifically for one command and I'm unsure how to do it the proper way.

4

You can do this by mapping the keys to behave differently when the wildmenu is visible:

set wildcharm=<C-Z>
cnoremap <expr> <up> wildmenumode() ? "\<left>" : "\<up>"
cnoremap <expr> <down> wildmenumode() ? "\<right>" : "\<down>"
cnoremap <expr> <left> wildmenumode() ? "\<up>" : "\<left>"
cnoremap <expr> <right> wildmenumode() ? " \<bs>\<C-Z>" : "\<right>"

These use an expression mapping that checks whether the wildmenu is showing with the wildmenumode() function returning the altered keystroke if that it is, and returning the regular keystroke if it isn't (so that the keys still work normally when you're not using the wildmenu).

There is a slight complication in the mapping for the right arrow key, which is that it appears that the "go into subdirectory" behaviour is implemented internally as a macro that does something along the lines of <space><bs><tab>, but because 'wildchar' cannot be used in a macro, the <tab> is instead inserted literally in the command line, appearing as CTRL-I: ^I.

I've worked around this by using 'wildcharm' and mapping to that instead of directly to <down>.

To make the mappings more precise, you can also check the current contents of the command-line to make sure it's an :e command:

set wildcharm=<C-Z>
cnoremap <expr> <up> getcmdline()[:1] is 'e ' && wildmenumode() ? "\<left>" : "\<up>"
cnoremap <expr> <down> getcmdline()[:1] is 'e ' && wildmenumode() ? "\<right>" : "\<down>"
cnoremap <expr> <left> getcmdline()[:1] is 'e ' && wildmenumode() ? "\<up>" : "\<left>"
cnoremap <expr> <right> getcmdline()[:1] is 'e ' && wildmenumode() ? " \<bs>\<C-Z>" : "\<right>"

If you also need the mappings to work for the other variants of the :e command: :ed, :edi, and :edit, you can instead use a regular expression:

set wildcharm=<C-Z>
let edit_re = 'e\%[dit] '
cnoremap <expr> <up> getcmdline() =~# edit_re && wildmenumode() ? "\<left>" : "\<up>"
cnoremap <expr> <down> getcmdline() =~# edit_re && wildmenumode() ? "\<right>" : "\<down>"
cnoremap <expr> <left> getcmdline() =~# edit_re && wildmenumode() ? "\<up>" : "\<left>"
cnoremap <expr> <right> getcmdline() =~# edit_re && wildmenumode() ? " \<bs>\<C-Z>" : "\<right>"

Unfortunately, I couldn't find any way of checking whether the wildmenu is completing filenames (complete_info() only appears to work for insert mode completion, and I couldn't find a similar function for command-line completion), so there doesn't appear to be a better method of applying it to all filename wildmenu completions.

If you need this, you will have either use the original version which applies regardless of what the wildmenu is completing, or use a more complicated regular expression to check for all the commands where you need the mappings to be in effect.

| improve this answer | |
  • This works like a charm for navigating between files in the same level, but I'm not able to properly navigate to a subdirectory. It prints ^I in the command line after pressing right arrow and pressing tab again doesn't register the directory change as it shows me the options of the same level. Any idea on how to fix this? – Delhirio Jan 22 at 15:41
  • @Delhirio See my most recent edit for an explanation and solution. It should now work like a (wild)charm for navigating to subdirectories, too! – Rich Jan 22 at 16:11
  • It does seems to work flawlessly now! Thank you! – Delhirio Jan 22 at 16:30
  • @Delhirio Glad I could help! – Rich Jan 22 at 16:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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