2

Extremely related to this except the answer there doesn't work

I get the following error when entering command-line editing mode q: or Ctrl-F (when already in command mode)

Error detected while processing CursorHold Auto commands for "*":
E11: Invalid in command-line window; <CR> executes, CTRL-C quits:  checktime | endif

The relevant section of my .vimrc is

"automatically reload file when changes detected
set autoread "this doesn't work on it's own!

"https://unix.stackexchange.com/questions/149209/refresh-changed-content-of-file-opened-in-vim/383044#383044
"on these events, any filename... and not in command mode then check files for changes
autocmd FocusGained,BufEnter,CursorHold,CursorHoldI * if mode() != 'c' | checktime | endif

" Notification after file change
autocmd FileChangedShellPost *
  \ echohl WarningMsg | echo "File changed on disk. Buffer reloaded." | echohl None

So my question is how do I detect that I'm in the command-line window and stop that command from running there?

After a bit of reading :h command-line I tried replacing the condition with

if mode() != 'c' && getcmdwintype() == ''

but I'm still seeing the same issue.

  • I can't reproduce your issue. Could you try to put only the relevant section of your vimrc in a separate file (e.g. ~/test.vimrc), start vim with vim -u ~/test.vimrc and confirm that you still get the error. If you don't get the error maybe the problem comes from another autocmd. – statox Nov 23 '17 at 12:23
  • @statox I'm running vim 8 VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Oct 20 2017 11:15:05) Included patches: 1-1207 Modified by pkg-vim-maintainers@lists.alioth.debian.org Compiled by pkg-vim-maintainers@lists.alioth.debian.org it seems a little surprising that the other answer clearly worked for someone else but isn't for me - could be a version thing maybe – JonnyRaa Nov 23 '17 at 13:23
  • I don't think this is a version problem. Are you sure you're not using another autocmd with the CursorHold event which would cause a problem? – statox Nov 23 '17 at 14:20
  • 1
    @statox I've resolved now, see my answer. it turns out that Ale has something in there aswell, I don't think it's relevant though – JonnyRaa Nov 23 '17 at 14:43
2

Based on Luc's help I ended up going with this:

autocmd FocusGained,BufEnter,CursorHold,CursorHoldI * if !bufexists("[Command Line]") | checktime | endif

The reason this works is that the Command Line window is fairly modal so you can't have one accidentally open in the background - you will only get that buffer if you are actively editing in the command-line-window

The only caveat here is that if you save a buffer with that name, which I did accidentally at some point when messing around with this stuff - in which case the Command line window complains when it gets opened and instead gets named "[Scratch]" or something.

It's also worth noting that you should probably have something like this at the very top of your .vimrc as autocmds are just added to a list and if you are developing them you can end up with your old ones kicking around.

"clear out previous autocmds to stop them being duplicated when resourcing
"this file
autocmd!

I also learned you can list all autocmds by doing :autocmd and list for a specific event like:

:autocmd CursorHold
--- Auto-Commands ---
ALECursorGroup  CursorHold
    *         call ale#cursor#EchoCursorWarningWithDelay()
CursorHold
    *         if !bufexists("[Command Line]") | checktime | endif
Press ENTER or type command to continue
  • 2
    Regarding au!, indeed this is a good practice, but don't forget to put your autocommands in a group in order to clear only the auto-commands from this precise group. – Luc Hermitte Nov 23 '17 at 15:20
  • I second @LucHermitte. Without specifically defining a group (in the command or via :augroup), your autocmd! will delete all the autocommands in the default group, which, depending on your config, could be a lot! – Rich Nov 23 '17 at 16:13
  • @Rich is that to cover the case that there is more than one vimrc (eg a system one) introducing autocmds? – JonnyRaa Nov 23 '17 at 17:10
  • 1
    Nope. I tried it in my config and it deleted quite a few hat had been added by plugins. – Rich Nov 23 '17 at 23:09
  • 1
    The main issue doesn't occur on first run, but if you source your vimrc in an existing Vim instance (so the way you load your plugins doesn't affect things). If you want to see which autocommands it would delete, you can run the following commands in a fresh instance of Vim: 1. :redir > before.txt 2. :autocmd 3: :redir > after.txt 4. :autocmd! 5. :autocmd 6. redir END. And then quit Vim and run vimdiff before.txt after.txt – Rich Nov 24 '17 at 15:19
2

bufname('%') returns "[Command Line]" in my case. I don't know if there is another information elsewhere.

You could also listen for CmdwinEnter and CmdwinLeave events and maintain an internal state that'll tell you in which mode you are.

EDIT: Here is what I would do. Note, this is completely untested. This may not work.

" ==== file: autoload/cmdlinewindow.vim
" Initialize to 0, keep the current state if the script is reloaded
let s:is_opened = get(s:, 'is_opened', 0)

function! cmdlinewindow#_enter() abort
    call lh#assert#false(s:is_opened)
    let s:is_opened = 1
endfunction

function! cmdlinewindow#_leave() abort
    call lh#assert#true(s:is_opened)
    let s:is_opened = 0
endfunction

function! cmdlinewindow#is_opened()
    return s:is_opened
endfunction

" ==== file: plugin/cmdlinewindow.vim
aug WatchCmdLineWindow
    au!
    au CmdwinEnter * call cmdlinewindow#_enter()
    au CmdwinLeave * call cmdlinewindow#_leave()
aug END

Then, from elsewhere, you'd just have to check cmdlinewindow#is_opened() result.

NB: lh#assert#...() comes from my vim script library. They are not needed, yet they state in which state I expect to be when calling these functions.

  • Nice one with bufname, I get the same result, however if I add that to the autocmd like && bufname('%') != "[Command Line]" I still see the same error after saving and resourcing my .vimrc – JonnyRaa Nov 23 '17 at 13:28
  • In that case, it's possible you're not using the right buf-expression. Try with bufname('<abuf>') instead. I can never remember which autocommands require us to use <abuf> instead of %. – Luc Hermitte Nov 23 '17 at 13:33
  • If this still doesn't work, you can listen for the Enter/Leave events – Luc Hermitte Nov 23 '17 at 13:35
  • I couldn't get either of those working, with the events probably because of my limited understanding of vim's variables... ended up going with !bufexists("[Command Line]"). Thanks for your help – JonnyRaa Nov 23 '17 at 14:28
0

For posterity: Turns out, additionally to the mentioned approaches (which would qualify as hacks in my book) you can simply use getcmdwintype(). Credits to user micbou from the Youcompleteme maintainers. Docs:

getcmdwintype()
        Return the current |command-line-window| type. Possible return
        values are the same as |getcmdtype()|. Returns an empty string
        when not in the command-line window.
0

I am having the same issue as you. There are some discussions here and here. It seems that we can use getcmdwintype() to check if we are in command line window. Here is my working setting:

augroup auto_read
    autocmd!
    autocmd FocusGained,BufEnter,CursorHold,CursorHoldI *
                \ if mode() == 'n' && getcmdwintype() == '' | checktime | endif
augroup END

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.