10

I would like to run an autocmd in the following scenarios when I start Vim:

  • With no filename specified.
  • When the file is new.
  • When the file exists but is completely blank.

In all of the above three cases I would like to run an autocmd; specifically, I'd like to start insert mode automatically for only the above scenarios (and not when I'm opening a file that already exists & isn't blank).


UPDATE:

I've tried placing the following in my _vimrc, but no luck (plus I'm not sure whether there is a function in vim that counts the number of characters in a file (to see if it is zero) before opening it:

if @% == "" || filereadable(@%)
  autocmd BufRead,BufNewFile * startinsert
endif
  • No, this is not a duplicate. I want vi to start in insert mode ONLY FOR THE THREE SCENARIOS I HAVE MENTIONED. – John Sonderson Mar 13 '15 at 23:23
  • 3
    OKAY, I'M SORRY BUT IT REALLY LOOKED LIKE A DUPLICATE. ;-) I've edited your question a bit to make the differences clearer. – Martin Tournoij Mar 13 '15 at 23:47
  • 2
    @JohnSonderson the first link tells you how to find if no filename is given, the second can be adapted by using normal instead of exec. – muru Mar 14 '15 at 9:42
  • 1
    The vimrc file is read only once: when Vim starts. The contents of autocmd is run every time it's triggered. So the if statement should not be around the autocmd, if should be inside the autocmd, so it will be run every time the autocmd is triggered. – Martin Tournoij Mar 15 '15 at 6:42
9

This works for all 3 of your cases for me:

function InsertIfEmpty()
    if @% == ""
        " No filename for current buffer
        startinsert
    elseif filereadable(@%) == 0
        " File doesn't exist yet
        startinsert
    elseif line('$') == 1 && col('$') == 1
        " File is empty
        startinsert
    endif
endfunction

au VimEnter * call InsertIfEmpty()

These could probably be condensed into just the last check for a file being empty, since no filename or a file that doesn't exist typically start as empty buffers. However, it is probably possible that some other plugin pre-fills some stuff in one of the first two cases (like some template plugins), so it is best to check all three.

The first test you already had.

The second test needs to check filereadable against the value of zero (doesn't exist) to decide if it is new (opposite of what you had).

The last test checks that the number of the last line in the file is 1 (which is also the first line, meaning that there is only one line), and that the column number of the end of line (column after the last character in the line) is 1, which would mean there are 0 characters. If there is only 1 line with 0 characters in it, then the file must be empty.

One final note: The way you have your statements in the question can result in some surprising results. Namely, you are setting BufRead and BufNewFile only if conditions are met at startup, but then those autocommands exist for the rest of your session. So, if you were to start on an empty file, which sets these commands, every subsequent file opened (new or not, empty or not) would start in insert mode.

The autocommand VimEnter is run at the end of Vim's startup and only once for the whole session. This way, your tests only run when you start Vim and not any other time.

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.