I have the following function in an autoload file:

function! closet#FindSkeletonForFile()
    if exists('b:closet_skeleton')
        return 0

    let b:closet_skeleton = s:closet.find_skeleton_for_file(expand('%:p'), &filetype)

    if b:closet_skeleton !=# ''
        let cpopts = &cpoptions
        set cpoptions-=a
        echom "Here goes the read:"
        execute '0read '.fnameescape(b:closet_skeleton)
        let &cpoptions = cpopts
        return 1

    return 0

This is triggered by a BufNewFile autocommand, and it appears to be working. The autocmd is in my plugin/closet.vim file, and looks like this:

augroup closet
    autocmd BufNewFile * call  closet#FindSkeletonForFile()
augroup END

When I invoke vi foo.vim (a file that does not exist) I get an empty buffer, some of my earlier code identifies valid skeletons, I get a confirm dialog, the filename is returned, and the s:closet.find_skeleton_for_file(...) function returns the correct value.

My echom outputs to the message log, and when I run :mess in the new vim window, I see this:

Messages maintainer: Bram Moolenaar <Bram@vim.org>
Here goes the read:
"~/Code/aghast/vim-closet/Closet/plugin.vim" 28L, 448C
Press ENTER or type command to continue

This tells me that the dummy plugin is being read somewhere, since those line/character numbers are what I see when I edit the dummy file.

But the foo.vim buffer doesn't get changed! Since I can see the code being run correctly (many, many :echom statements) I'm pretty sure it's just down to getting that 0read statement to ... well, read!

Can someone clue me in on the obvious thing I've missed?

  • 1
    After you get an empty buffer for new file foo.vim... if you run :execute '0read '.fnameescape(b:closet_skeleton) by hand, does it properly populate the file with the contents of the intended skeleton file? – filbranden Sep 24 '19 at 23:34
  • Yes, it does. And I get the filepath in the message log with the same numbers, to boot. – aghast Sep 25 '19 at 1:04
  • And it's somewhat comforting that the b:closet_skeleton buffer variable has been set, so at least my script is getting that right. – aghast Sep 25 '19 at 1:13
  • 2
    Is it possible the 0read is actually reading but another hook is later erasing the buffer? Maybe try to test that without other plug-ins loaded to see if that works? – filbranden Sep 25 '19 at 1:43
  • 2
    @filbranden++ ! It turns out I had a hook installed that was doing find-file-if-not-exist on VimEnter, and it wasn't checking for contents. Modified that to check where the line('$') pointed to, and quit if the buffer had contents, and now all is well! Thanks. – aghast Sep 25 '19 at 2:12

Using 0read on BufNewFile actually works as expected, in fact the documentation for BufNewFile explicitly mentions using that event for loading a template or skeleton file.

If we also rule out the other things that might have gone wrong there, then the most likely explanation is that 0read is working, but the contents of the buffer are later erased by another plug-in or hook.

As we ruled out anything else from that code path specifically (the b:closet_skeleton was being set, and running the 0read from it after opening Vim was loading the file correctly), then the next course of action is to debug your vimrc file.

Following those steps, you were able to find you had a hook on VimEnter doing "find-file-if-not-exist" that was creating interference with your skeleton file hook. Updating that hook to consider previous contents of a file was enough to break that interference.

  • 1
    I too hate having resolved issues in the Unanswered section. +1! – Rich Sep 26 '19 at 8:24

Not the answer you're looking for? Browse other questions tagged or ask your own question.