I'm trying to unmap some key sequences mapped by python filetype plugin. While I know a better way, I'm still curious if it can be done with autocommands. Here's what I've got so far:

augroup python_ftplugin
    autocmd!
"\       for m in ['[[', '[]', '[m', '[M', ']]', '][', ']m', ']M']
    autocmd BufNewFile,BufRead *.py
\       for m in ['[[']
\           | if !empty(maparg(m, 'n'))
\               | execute 'nunmap <buffer> ' . m
\               | echom expand('%') . ': unmapped ' . m
\           | else
\               | echom expand('%') . ': not unmapped ' . m
\           | endif
\       | endfor
augroup END

The thing is, when I do :lvimgrep ... *.py, filetype plugin gets executed after my autocommand for the first matched file. Is there a way to remedy this?

  • You might want to share what lvim is – D. Ben Knoble Dec 9 at 2:27
  • @D.BenKnoble See updated question. – x-yuri Dec 9 at 3:10
  • Could you change your title from Event after :lvimgrep has opened the first file to something more specific Unmap python filetype mappings? – Hotschke Dec 9 at 9:30
  • @Hotschke The thing is, I'm particularly interested in why using BufNewFile,BufRead is not enough or wrong in this case. I saw the other question where there's a hint (not only hint now) at solving my X (of XY) problem. But from what I can see now, I most likely used the wrong events. FileType event is most likely to be used in this case. I'm also interested in why in this particular case filetype plugin executed after BufRead, but the answer probably: "That's just the way it works." – x-yuri Dec 9 at 14:18
  • 1
    I had a look into the order of events and yes it is unfortunately somewhat unexpected: there is a difference between opening a single python file versus running :lvimgrep. See details in my answer. – Hotschke Dec 10 at 8:55
up vote 3 down vote accepted

Unmap via autocmd Filetype python

augroup python_ftplugin
    autocmd!
    autocmd Filetype python
\       for m in ['[[', '[]', '[m', '[M', ']]', '][', ']m', ']M']
\       | execute('silent! unmap <buffer> '.m)
\       | endfor
augroup END

I have used unmap instead of nunmap because there are also xmap and omap which you might also want to unmap.

Order of events and when $VIMRUNTIME/ftplugin/python.vim is sourced

augroup python_ftplugin
    autocmd!
    autocmd Filetype python echom "Event Filetype python"
    autocmd BufNewFile,BufRead *.py echom "Event BufNewFile,BufRead *.py"
augroup END

and add following echom to $VIMRUNTIME/ftplugin/python.vim:

" Vim filetype plugin file
" Language: python
" ...

echom "Sourcing $VIMRUNTIME/ftplugin/python.vim"

It is very interesting to see that there is a difference between

$ vim myfile.py

enter image description here

:lvimgrep class *.py

enter image description here

Sato Katsura has expressed this as following

Contrary to the popular belief, the order of applying autocmds across multiple files is not well-defined.

Unmap in ~/.vim/after/ftplugin/python.vim

However, if you have many autocommands, filetype is tested for each autocommand, which is not efficient. Furthermore, you replicate something that Vim already does automatically anyway (see the reddit post where_to_put_filetype_specific_stuff by romainl).

Therefore, it is recommended to do this in ~/.vim/after/ftplugin/python.vim

for m in ['[[', '[]', '[m', '[M', ']]', '][', ']m', ']M']
  execute('silent! unmap <buffer> '.m)
endfor

Add variable to $VIMRUNTIME/ftplugin/python.vim to disable mappings

Actually, $VIMRUNTIME/ftplugin/python.vim should follow the recommendation given in

:h write-filetype-plugin

The user must have a chance to disable the mappings in a filetype plugin, without disabling everything. Here is an example of how this is done for a plugin for the mail filetype: >

" Add mappings, unless the user didn't want this.
if !exists("no_plugin_maps") && !exists("no_mail_maps")
  " Quote text by inserting "> "
  if !hasmapto('<Plug>MailQuote')
    vmap <buffer> <LocalLeader>q <Plug>MailQuote
    nmap <buffer> <LocalLeader>q <Plug>MailQuote
  endif
  vnoremap <buffer> <Plug>MailQuote :s/^/> /<CR>
  nnoremap <buffer> <Plug>MailQuote :.,$s/^/> /<CR>
endif

If you can convince the current maintainer (https://github.com/tpict/vim-ftplugin-python) to make the mappings optional, you only have to place let no_python_maps = 1 to your vimrc.

Do you really need the builtin [[,[],]],][,[m,[M,]m,]M for python?

I would highly appreciate if you could add a python code snippet to your question illustrating where you want to use the builtin motions. Otherwise I consider your question unmotivated. Do you know the motions [{ and ]}?

For an illustration what the mappings of the filetype plugin python do, see here End of python block motion. IMHO they are very useful not only for python.

Update: Convenient Cycling Through Quickfix/Location List

As it has turned out the OP is using [ and ] to cycle through the location list. As I said in the comments I would not advice to use them for this because they are namespace keys similar to z and g.

Suggested alternatives:

  1. vim-unimpaired [l and ]l ([q and ]q for quickfix) (maybe with repmo-vim)
    Pros: no known conflicts with others
    Cons: too much weak finger movement and keys
  2. vim-qf <C-Home> and <C-End> (<Home> and <End> for quickfix)
    Pros: no known conflicts with others
    Cons: too much hand movement
  3. http://vim.wikia.com/wiki/Short_mappings_for_common_tasks#Quickfix (function key)
    Pros: common scheme (e.g. F3 in PyCharm & F4 in Sublime Text) and less conflicts
    Cons: too much hand movement

  4. ale-inspired

    nmap <silent> <C-k> :lprevious<CR>
    nmap <silent> <C-j> :lnext<CR>
    

    Pros: home row keys (in particular when capslock is remapped to ctrl)
    Cons: already used by others (e.g. ale, switch between splits, vim-tmux-navigator/pilot, edgemotion)

    vim-syntastic does not dare to suggest any specific mapping (except mentioning vim-unimpaired) but certainly sees a motivation for this.

  5. Leader to space plus j/k (or n/p)

    let mapleader = "\<space>"
    nnoremap <leader>j :lnext<CR>
    nnoremap <leader>k :lprevious<CR>
    

    Pros: space bar by strongest finger and jk are home row keys
    Cons: possibly already used but others are also available (e.g. ln/lp)

  6. macOS:

    • MacVim: <Ctrl-Cmd-Left/Right> for quickfix (default)
      <Alt-Cmd-Left/Right> for location list (add to gvimrc)
    • Xcode-inspired: <Ctrl-Cmd-G>/<Ctrl-Shift-Cmd-G> Find next/previous in workspace
  • These [[ motions are indeed look pretty interesting. But I'm a heavy user of :lvimgrep, and up until now I've been using [ and ] to cycle through the matches. And these extra motions added by Python plugin were in the way. After pressing [ it waited if I were to press [ or something, or that's it. I wonder why builtin motions didn't lead to this though. So, cycling through matches in Python files became a drag. But they are indeed interesting, I've got to give them a try. But you know, the number of keyboard keys is limited. It's hard to decide what to use, and what not... – x-yuri Dec 9 at 14:36
  • Thanks for the details. You did not mention that you have remapped [ and ] to a custom command. BTW, you also have to do this for ruby, vimscript and a few others. I would not recommend this. There are even more builtin square bracket motions. Please have a look at :h [. I count 23 pairs of builtin mappings which you all remove. I really like the plugin vim-unimpaired which adds even more. You might be interested in [l and ]l. – Hotschke Dec 9 at 14:57
  • Also you might like repeating them with ; and ,: vi.stackexchange.com/questions/18162/repeat-complicated-motions – Hotschke Dec 9 at 14:58
  • 1
    I would also recommend to you to read chapter 29.3 of the vim user manual. This might convince you not to change the meaning of [ and ]: :help 29.3 – Hotschke Dec 9 at 15:15
  • 1
    I have added a few suggestions for mappings to conveniently cycyle through the location list. However, if you have engraved them in your memory muscle, it will take effort to change to others. – Hotschke Dec 9 at 16:12

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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