2

When I start vim, I always use -s SCRIPT_FILE_NAME option to execute additional commands. In SCRIPT_FILE_NAME, some ex commands are written. Let COMM denote the additional commands in the file. The problem is that COMM is added to command history. For example, when I

  1. start vim and execute :echo and exit with :q
  2. and start vim again

the expected contents of the command history (which can be seen via q:) are

: 48 echo
: 49 q

but the actual contents are

: 48 echo
: 49 q
: 50 COMM1
: 51 COMM2
      ︙
: 60 COMM11

and this is truly annoying. (Assume COMM consists of a hundread of commands.)

Is there any way to avoid this?


NOTE1: Because the execution order is different between commands in .vimrc and those in SCRIPT_FILE_NAME, I cannot move COMM to .vimrc. In other words, there is a reason why I use -s option in addition to .vimrc.

NOTE2: Of course, it is possible to execute sed command between the first and second step above to remove the undesired lines. However, doing like this isn't elegant, I think. I wonder if there is a better solution supplied by vim by default.


Update:

By putting all of COMM into a function in .vimrc and calling it from SCRIPT_FILE_NAME, the number of items added to the history can be decreased to one. But I'd still like to decrease it to zero if I can.

2
  • 1
    Not sure if we can tell vim to skip the recording of a command. But :h histdel() may help. Try to put call histdel(':', -1) at the end of your function.
    – perelo
    Aug 24, 2019 at 10:35
  • @perelo Worked perfectly. Thank you :)
    – ynn
    Aug 25, 2019 at 8:56

1 Answer 1

2

I always use -s SCRIPT_FILE_NAME option to execute additional commands. In SCRIPT_FILE_NAME, some ex commands are written.

So -s {scriptin} or the equivalent :source! command are meant to read the contents of a file and execute those as Normal mode commands.

They fully reuse normal mode key processing. As such, Ex commands entered with : will be added to history. There doesn't seem to be much you can really do about that.

If you're primarily using this mechanism to run Ex commands, then turn this around. Turn it into an Ex script instead (which means you can drop the :s), then you can use the :source command to load it.

If you have parts of the script that are using Normal mode commands, you can use the :normal! command to enter them, turning that into an Ex command that you can use as part of the script.

You mentioned "putting all of COMM into a function in .vimrc and calling it from SCRIPT_FILE_NAME", so it sounds like you were able to accomplish that already, since .vimrc and function are both comprised of Ex mode commands.

Once you have your Ex script, you can then use the -c command-line option to source it:

$ vim -c 'source SCRIPT_FILE_NAME.vim' ...

Or, if you have it as a function in your .vimrc:

$ vim -c 'call MyInitFunc()' ...

That should work as expected, without polluting the Vim command history.


Also, about this:

Because the execution order is different between commands in .vimrc and those in SCRIPT_FILE_NAME, I cannot move COMM to .vimrc. In other words, there is a reason why I use -s option in addition to .vimrc.

Take a look at the VimEnter event of autocmd, it triggers once, around the same time as the -c script works. (I believe -s is a little later than both, but still close.)

If you want to always use the sequence of commands and you have only been using the external script because of the timing, then using VimEnter should solve this problem in a better way.

Use something like the following in your .vimrc:

function! MyInitFunc()
  COMM1
  COMM2
  COMM3
endfunction
augroup vimrc_initfunc
  autocmd!
  autocmd VimEnter * call MyInitFunc()
augroup END

(See also v:vim_did_enter, if you care about possibly re-running MyInitFunc() if you're reloading your .vimrc using :source during runtime.)

6
  • 1
    Thank you really much for your detailed answer. -c 'source SCRIPT' and -c 'call FUNCTION' worked as expected. And, I'm impressed by the sophisticated solution using VimEnter. That is enough in my case, so now I use VimEnter in my .vimrc and succeeded in making the bash alias for vi shorter.
    – ynn
    Aug 25, 2019 at 9:00
  • 1
    Awesome @ynn, glad I could help! Ideally you shouldn't even need a bash alias for vim (it doesn't get triggered when vim is invoked by other tools such as git for commit messages), so feel free to ask further questions about what's in your alias, we can probably help you accomplish that from within Vim itself if at all possible!
    – filbranden
    Aug 25, 2019 at 13:12
  • I'm experiencing this problem for a few years. In my environment, VimLeave doesn't help because the clipboard seems cleared after VimLeave. So I write out the clipboard contents to a file when VimLeave and by using /usr/bin/vi; LOAD, I avoid the problem where LOAD is the command to read the file into clipboard. This may be my-environment-specific and asking about that is duplicate. Since :help didn't tell me something later than VimLeave, I think the alias is needed maybe... :(
    – ynn
    Aug 25, 2019 at 13:58
  • 1
    Ah... I was really foolish. I forget the rule: more newly added autocmds are executed later. Rearranging a series of commands in .vimrc solved the problem. Both xsel and xclip worked well. (Until today, probably I tried to call LOAD before I write out to the file...) Thanks to you, today I made my .vimrc more elegant and removed three bash functions. I can't thank you enough!
    – ynn
    Aug 25, 2019 at 15:48
  • 1
    @ynn Really glad I got to help you today!
    – filbranden
    Aug 25, 2019 at 15:50

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.