1

I have a plugin (c.vim) which includes a lot of maps (all with leader key). I changed my leader key to space, which I like, but the problem is that the maps also apply to insert mode. I would like to disable all imaps containing <Space>, so space in insert doesn't cause a delay (and sometimes a command).

I tried :iunmaping specific maps using what I saw in :imap, but that said E31: No such mapping.

I also tried using .vim/after/plugin/map.vim and autocmd VimEnter * imapclear, neither of which worked.

1
  • 3
    What is the c.vim plugin?
    – Maxim Kim
    Jul 9, 2020 at 6:55

4 Answers 4

3

If your insert mode mappings are filetype specific then .vim/after/plugin/map.vim and autocmd VimEnter * imapclear would not work as they are executed before fitetype creates them. Also imapclear deletes all insert mode mappings including default ones.

You can try to apply imapclear <buffer> on bufread/filetype event though:

using after/ftplugin

create .vim/after/ftplugin/c.vim:

imapclear <buffer>

using autocommands

put it into your vimrc:

augroup cvim_imapclear | au!
    au BufRead,BufNewFile *.c imapclear <buffer>
augroup end

PS, although I would challenge your c.vim plugin if it has other means of tuning it/turning those off.

PPS, what is the :imap output? Can you see those mappings?

2
  • imap example i <Space>hm @<C-C>:call C_Help("m")<CR>.
    – Not me
    Jul 9, 2020 at 19:12
  • There is smth wrong with this c.vim. It should provide non-intrusive buffer local insert mode mappings.
    – Maxim Kim
    Jul 10, 2020 at 7:37
3

You can try to analyze the result of split(execute('imap <buffer> <space>'), "\n")

From there, keep only the second field (IIRC). => ->map({k,v -> split(v)[1]}), and generate the clearing commands, => prefer ->map({k,v -> 'iunmap <buffer> '.split(v)[1]})

And finally ->execute().

TL;DR

:call execute('imap <buffer> <space>')
\ ->split("\n")
\ ->map({k,v -> 'iunmap <buffer> '.split(v)[1]})
\ ->execute()

I guess it should be done in ~/.vim/after/ftplugin/c/clear-imaps.vim

PS: I don't user (local/)leader in insert mode mappings in lh-cpp ^^'

6
  • Could you loop over maparg results, unmapping them?
    – D. Ben Knoble
    Jul 9, 2020 at 13:05
  • @D.BenKnoble, the problem is that maparg() returns only one result and it has to receive the exact key sequence. maparg('<space>', 'i') won't return anything in OP's case. mapcheck() will work on a partial match, but again, only a single result will be returned. They can't be exploited to answer OP's question. Jul 9, 2020 at 13:16
  • Maybe i was looking at the wrong function, so it’s mapcheck that does partial matches. But if you do something like while mapcheck != empty | iunmap (pseudocode)? Surely that could give you all of them?
    – D. Ben Knoble
    Jul 9, 2020 at 13:26
  • @D.BenKnoble. May be. But as I don't like loops (slow and painful to debug), I prefer the functional approach. ^^' Beside, as we cannot have ` while (m = mapcheck(...); !empty(m))` in Vimscript language, the loops will be clumsy with repeated lines. Jul 9, 2020 at 14:09
  • 1
    @D.BenKnoble There are risks indeed: 1. I don't know whether newlines can appears in a mapping. I don't see how. 2. The output format of :map may change in the future. In an ideal world mapcheck() would have another parameter to return all matches. Jul 9, 2020 at 14:36
1

This should work to clear all Insert-mode mappings starting with space:

let l:map = mapcheck(' ', 'i')
while !empty(l:map)
  execute 'iunmap' l:map
  let l:map = mapcheck(' ', 'i')
endwhile

Unfortunately, there is no way to restrict mapcheck to buffer-local mappings only; however, the ugly loop does let us sidestep parsing command output, which may be brittle and break if the output ever changes or contains something unexpected.

1

I ended up combining bits of solutions provided by Luc and Maxim, ending up with the following in my .vimrc:

" clear all mappings starting with space in insert mode
" based on https://vi.stackexchange.com/a/26385/40274
" and https://vi.stackexchange.com/a/26384/40274
function! ClearInsertLeaders() abort
        let s:mappings = execute('imap <space>')
        \ ->split('\n')
        \ ->map({k,v -> split(v)[1]})
        for mapping in s:mappings
                " needed in case of no mappings
                if mapping != 'mapping'
                        execute('iunmap '.mapping)
                endif
        endfor
endfunction
    
augroup clear_insert_leaders
        autocmd!
        autocmd BufRead,BufNewFile * call ClearInsertLeaders()
augroup END
1

Your Answer

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

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