14

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
John Sonderson
  • 617
  • 1
  • 6
  • 14
  • 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
  • 4
    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
  • Related: https://vi.stackexchange.com/questions/239/how-do-i-make-vim-use-a-default-filename-when-not-given-any-filenames, https://vi.stackexchange.com/questions/258/how-do-i-run-a-command-on-creation-of-a-new-file – muru Mar 14 '15 at 00:13
  • Well, @muru, the first link is irrelevant to my question, and the second link's answers show how to run a Unix command when a file is created, but I need to run a vim command ('i'), and need to run it in the other two cases as well. – John Sonderson Mar 14 '15 at 09:12
  • 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 09:42
  • Please see my updated post, still not sure if there's a way to do what I'm looking for. – John Sonderson Mar 14 '15 at 21:54
  • 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 06:42

1 Answers1

12

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.

John O'M.
  • 8,552
  • 2
  • 42
  • 58