5

When I start vim with an ex-command as command line parameter, it won't show up in vim's command history. Why? Can I tell vim to do so?

Minimal example:

vim -c 'execute "help -c"'

Why I'm asking:

After grepping (with rg) in the command line, sometimes I want to open the results in vim. That's why I made a script that opens vim with the last ripgrep search as parameter, for example:

nvim -c 'execute "RgRaw failed --glob !lib"'

After closing the search (inside vim), I would like to simply repeat (and maybe adapt) this search via :up.

  • This specific workflow needs ripgrep, fzf, fzf.vim, vim-agriculture to be installed.
  • I use nvim here, because vim (8.2.2398) shows a warning (twice): "E994: Not allowed in a popup window"
MaxGyver
  • 231
  • 1
  • 8

1 Answers1

3

When I start vim with an ex-command as command line parameter, it won't show up in vim's command history. Why?

Presumably because only commands that are typed interactively while Vim is running are remembered:

  • Only commands that are typed are remembered. Ones that completely come from mappings are not put in the history.

That's not the case of commands executed via the -c flag; those are not typed interactively; they're processed before VimEnter:

The commands given with the |-c| and |+cmd| arguments are executed.


Can I tell vim to do so?

Try this:

augroup CustomHistory | au!
    au VimEnter * eval v:argv
        \ ->copy()
        \ ->filter({i, v -> i > 0 && v:argv[i - 1] == '-c'})
        \ ->map({_, v -> histadd('cmd', v)})
augroup END

For more info, see:

user938271
  • 5,947
  • 1
  • 15
  • 24
  • Awesome! It works. Thanks a lot. I just noticed that "execute" will be added to the history, too. Then I noticed that I can drop it completely: vim -c "RgRaw failed --glob !lib". Is there any reason why I should use "execute" for this use case? – MaxGyver Jan 24 '21 at 13:00
  • This works fine in vim. But in neovim, I get this warning: E492: Not an editor command: eval v:argv ->copy() ->filter({i, v -> i > 0 && v:argv[i - 1] == '-c'}) ->map({_, v -> histadd('cmd', v)}). Any idea why? – MaxGyver Jan 24 '21 at 13:17
  • Is there any reason why I should use "execute" for this use case? I don't see any reason to use :execute here. Any idea why? Because this uses Vim 8.2 syntaxes, and Neovim is a fork of Vim 7.4. I don't use Neovim anymore, but try this (untested): call map(filter(copy(v:argv), {i, v -> i > 0 && v:argv[i - 1] == '-c'}), {_, v -> histadd('cmd', v)}). – user938271 Jan 24 '21 at 14:25
  • Well, this did not work: E121: Undefined variable: v:argv. Thanks anyway. I've opened an issue for the other error (E994), I get only in vim. – MaxGyver Jan 24 '21 at 15:33
  • That's because of netrw which executes :windo on VimEnter. :windo needs to temporarily focus other windows, but that's disallowed while a popup terminal is active. You need to either: 1. remove netrw directory handler with autocmd VimEnter * if exists("#FileExplorer") | exe "au! FileExplorer *" | endif; or 2. disable netrw interface entirely with let g:loaded_netrwPlugin = 1; or 3. delay :Rg with a timer: vim -c 'call timer_start(0, {-> execute("Rg")})'. – user938271 Jan 24 '21 at 16:27
  • FWIW, Vim provides matchfuzzypos() since 8.2.1726 which lets you build your own fuzzy commands. This might not be as powerful as fzf(1), but it definitely gives you much more control than a compilation of third-party plugins. – user938271 Jan 24 '21 at 16:27
  • Wow, you know a lot about vim! You need to either: ... I guess option 1 and 2 don't play well with vim-vinegar. But option 3 works well! Thanks again. Vim provides matchfuzzypos() This sounds interesting (and like a lot of work)! But I'm fine with using ripgrep + fzf. I have these installed anyway. – MaxGyver Jan 24 '21 at 19:28
  • After trying this in practice I noticed: When I run vim -c "call timer_start(0, {-> execute('Rg')})", I get a fzf list but I can't open a match with "Enter" anymore! – MaxGyver Jan 25 '21 at 13:54