Search code examples
cvimctagsnon-interactive

Efficient non-interactive use of vim


I use vim to non-interactively write a single C language function to a file. First a tags file is created with ctags. To write the main() function to file func.c I then use

vim -R -U NONE -u NONE -c ":ta main" -c ":.,/^}/w!func.c" -c :q

In other words this runs 3 vim commands non-interactively:

  1. :ta main to jump to main()
  2. :.,/^}/w!func.c to write from the current line to the next closing curly at the start of a line
  3. :q to quit

I have tried to make this efficient by not wasting time reading user or system startup files (-U NONE -u NONE) and avoiding .swp file creation (-R).

There are two snags remaining I couldn't get rid of:

  1. If this is run as part of a pipe I get the Vim: Warning: Output is not to a terminal warning and (apparently) a one second delay.
  2. If I save the stdout of this command I still see lots of terminal escape sequences being used, and messages such as "func.c" 58 lines, 1707 characters written being generated.

Is there a way to avoid each of these?


Solution

  • This sounds like silent batch mode (:help -s-ex) could work for your use case. Else, you can't get around full automation (with some of the downsides that you describe).

    Silent Batch Mode

    For very simple text processing (i.e. using Vim like an enhanced 'sed' or 'awk', maybe just benefitting from the enhanced regular expressions in a :substitute command), use Ex-mode.

    REM Windows
    call vim -N -u NONE -n -i NONE -es -S "commands.ex" "filespec"
    

    Note: silent batch mode (:help -s-ex) messes up the Windows console, so you may have to do a cls to clean up after the Vim run.

    # Unix
    vim -T dumb --noplugin -n -i NONE -es -S "commands.ex" "filespec"
    

    Attention: Vim will hang waiting for input if the "commands.ex" file doesn't exist; better check beforehand for its existence! Alternatively, Vim can read the commands from stdin. You can also fill a new buffer with text read from stdin, and read commands from stderr if you use the - argument.

    Full Automation

    For more advanced processing involving multiple windows, and real automation of Vim (where you might interact with the user or leave Vim running to let the user take over), use:

    vim -N -u NONE -n -c "set nomore" -S "commands.vim" "filespec"
    

    Here's a summary of the used arguments:

    -T dumb           Avoids errors in case the terminal detection goes wrong.
    -N -u NONE        Do not load vimrc and plugins, alternatively:
    --noplugin        Do not load plugins.
    -n                No swapfile.
    -i NONE           Ignore the |viminfo| file (to avoid disturbing the
                    user's settings).
    -es               Ex mode + silent batch mode -s-ex
                    Attention: Must be given in that order!
    -S ...            Source script.
    -c 'set nomore'   Suppress the more-prompt when the screen is filled
                    with messages or output to avoid blocking.