# Unmap all combinations starting with certain key

I am experimenting with default key mappings and am considering remapping the g key entirely. But first I would like to turn off all the existing mappings that g has. For now I am using this kind of hack:

" disable all g maps
let g:netrw_nogx = 1 " allows disabling gx
let s:chars1 = map(range(char2nr('a'), char2nr('x')), 'nr2char(v:val)')
let s:chars2 = map(range(char2nr('A'), char2nr('Z')), 'nr2char(v:val)')
let s:chars = s:chars1 + s:chars2
let s:chars = s:chars+['0','1','2','3','4','5','6','7','8','9','+','-','=','_']
let s:chars = s:chars+['~','','!','@','#','\$','%','^','&','*','(',')','/','?']
let s:chars = s:chars+['[',']','{','}','\','\|',':',';','"',"'",'<',">",'.',',']

for char in s:chars
execute 'noremap g' . char . ' <nop>'
endfor


But this is very messy and g<ctrl-_> maps are still left in.

Is there some cleaner way to accomplish this?

• I think there is no better way other than to iterate over all combinations. – Christian Brabandt Feb 27 '18 at 7:55
• Just out of curiosity: why do you need to remap all of these combinations to <nop>? Also, I agree with Christian that is probably the best way to do it. – statox Feb 27 '18 at 12:09
• Agree with @statox why not use unmap? – D. Ben Knoble Feb 27 '18 at 12:25
• @DavidBenKnoble I think what Karolis wants to do is to disable the built-in normal mode commands like gq, gU, etc while unmap would be useful to delete mappings created by the user. What I was wondering is, why does one need to disable all of these built-in commands? – statox Feb 27 '18 at 12:32
• @statox I am just experimenting with making (neo)vim maps more intuitive. For example my current experiment is to only use g prefix for "goto" commands. I.E. gg goes to top G goes to bottom, gf goes to file, gb and gB would traverse buffers, etc. No big reason to disable all g prefix maps, but it would help in a sense that I would be sure pressing g will put me into a goto context and would not do something else by accident. – Karolis Koncevičius Feb 27 '18 at 15:27

### Suppressing the built-in g

Here's a mapping that will suppress all g-prefixed bindings, and only allow custom mappings that begin with g.

function! SuppressG()
let c = nr2char(getchar())
if maparg('g'.c, 'n') != ''
return 'g'.c
else
return '\<Nop>'
endif
endfunction

nnoremap <expr> g SuppressG()


The idea is to make a top-level mapping for g itself that then reads a single character from the keyboard. If a Normal mode mapping to g followed by the input character exists, return that. Otherwise, return <Nop>. It works with chords, too.

The effect is that when you haven't defined any other mappings beginning with g, all of Vim's built-in bindings beginning with g will do nothing. For example, ge, which normally moves backwards to the end of a word, would now be a no-op.

### Creating a custom mapping

If you also defined a custom mapping to ge, then your mapping would take effect. Example:

nnoremap ge G


Now ge moves to the last line of the buffer, but all other g bindings still do nothing.

### Restoring built-ins

You can also restore the g mappings you want to keep. For example:

nnoremap gg gg


This makes gg once again move to the first line of the buffer.

• This works really well for "g" and "z" but for some reason I cannot figure out how to make it work for "ctrl". Maybe you have any tips? – Karolis Koncevičius Aug 12 '18 at 18:53
• Ctrl itself isn't mappable, it's just part of a chord. Vim sees things like Ctrl+x as a single character. – tommcdo Sep 25 '18 at 18:44
• Does it gets called immediately? Not waiting for any longer combination that could surpass it? – eyal karni Oct 23 '19 at 21:21

If your version of vim is recent enough, you could obtain all the mappings starting with g thanks to getcompletion('g', 'mapping').

However, you won't know the mode associated, you'd need to filter the list with mapcheck().

Of course, you won't obtain the default keybindings this way.

• Presumably you'd need to do this in a VimEnter autocommand (to unmap mappings added by plugins)? – Rich Mar 8 '18 at 15:02

A small generalization to tommcdo's excellent suggestion:

function! SuppressAllStartingWith(c1)
let c2 = nr2char(getchar())
if maparg(a:c1.c2, 'n') != ''
return a:c1.c2
else
return '\<Nop>'
endif
endfunction


Then you can use it like so:

nnoremap <expr> q SuppressAllStartingWith('q')
nnoremap <expr> z SuppressAllStartingWith('z')


As for motivation, in command mode I'm always fat-fingering 'z' when I'm heading for 'x', or 'q' when I'm heading for 'a', and I'm tired of that.

• Welcome to Vi and Vim! Does this prevent you from recording macros q{letter} or using the fold and other z commands (zt, etc.)? – D. Ben Knoble Feb 12 at 15:18
• Yes, it does. For certain of my editing jobs, I don't want any accidental keystrokes moving the cursor far away, or changing modes, or turning on anything. I just want local motions and text insert/delete, basically. This gets me partially there. If there's a WYSIWYG mode to vim, or a better way to achieve this, I'd love to hear about it. – Charles Feb 13 at 16:26
• Vim is WYSIWYG if what you get is plain-text, so I don't follow that. But you could look at :help -y`. – D. Ben Knoble Feb 13 at 19:37
• I was using WYSIWG in the sense of what the nano editor gives you, i.e., exactly what -y gives you in vim, thanks for that tip. But what I'd like to achieve in vim is allowing editing commands that operate on the current line, or a few lines around it, and suppressing commands that take me to other parts of the file when I mistype them. So for example I never use z because I have no use for what it does, and when I accidentally hit it, I don't want what it does. – Charles Feb 15 at 15:12