h4ckt1c
h4ckt1c

Reputation: 11

How to access mapped keys in vim?

How can I access a key (for its original function) when it's already mapped in my .vimrc?

In my case: I've mapped , to comment the current line. But , is also used to continue searching, if you searched for a character in the current line using f/F/t/T. So, how can I access , in its original function (continue searching)?

Upvotes: 1

Views: 140

Answers (2)

Ingo Karkat
Ingo Karkat

Reputation: 172520

Here's a set of mappings that allow you to execute the original, built-in mappings. They rely on the fact that anything returned from a :help :map-expression is taken literally (without remapping), and so it is only necessary to pass the first key of any command through it to skip the custom mapping that overrides it.

"[count]["x]<Leader><BS>{cmd}
"<Leader><BS>[count]["x]{cmd}
"           Use the built-in, unmapped normal / visual /
"           operator-pending mode {cmd} instead of the mapping that
"           overrides the command.
"CTRL-G <BS>{cmd}   Use the built-in, unmapped insert / command-line mode
"           {cmd} instead of the mapping that overrides the command.
function! s:BuiltInCommand()
    let l:sequence = ''
    while 1
        let l:key = ingo#query#get#Char()
        if l:key ==# "\<Esc>"
            " Abort with beep.
            return l:key
        elseif l:key ==# '"'
            let l:sequence .= l:key
            " Query the register; we won't handle the expression register here.
            let l:key = ingo#query#get#Register("\<Esc>", '=')
            if l:key ==# "\<Esc>"
                " Abort with beep.
                return l:key
            endif
        elseif l:key !~# '\d'
            " This is the beginning of the built-in command; we're done.
            let l:sequence .= l:key
            return l:sequence
        endif
        " Keep querying for [count] numbers, registers, or the beginning of the
        " command.
        let l:sequence .= l:key
    endwhile
endfunction
noremap <expr> <Leader><BS> <SID>BuiltInCommand()
sunmap <Leader><BS>
noremap! <expr> <C-g><BS> ingo#query#get#Char()

This requires some functions from my ingo-library plugin. To use the original , for example, type <Leader><BS>,.

Upvotes: 0

Ingo Karkat
Ingo Karkat

Reputation: 172520

If you want to keep the original , command, you either have to map that one to a different key:

:nnoremap \\ ,

or change the mapping that overshadows the command. I know this is difficult; eventually you run out of short and memorizable keys, and tradeoffs must be made :-(

It's best to keep the , key free from conflicts, so maybe use \c. If such is already taken, ,c would also work. For the original command, there will be a short delay, as Vim needs to decide whether the , is a complete command, or the first key of the ,c mapping. If you go this route, maybe :nnoremap ,, , would be helpful. Bashing , two times is faster than waiting for the timeout.

programmatically

Though not feasible when typing interactively, you can always invoke the original, unmapped functionality via :normal! (note the !):

:normal! ,

Upvotes: 1

Related Questions