vim-plug icon indicating copy to clipboard operation
vim-plug copied to clipboard

Make automatic installation script in wiki tips compatible with Neovim

Open clebs opened this issue 1 year ago • 9 comments

When using the snippet to auto install everything on Neovim it does not recognise PlugInstall as a command without restarting. To solve this I added one line to the suggested tip to source Plug right after downloading it.

It now looks as follows (in lua):

local data_dir = fn.stdpath('data')
if vim.fn.empty(vim.fn.glob(data_dir .. '/site/autoload/plug.vim')) == 1 then
	vim.cmd('silent !curl -fLo ' ..
		data_dir ..
		'/site/autoload/plug.vim --create-dirs  https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim')
	vim.cmd('source ' .. data_dir .. '/site/autoload/plug.vim')
	vim.cmd('autocmd VimEnter * PlugInstall --sync | source $MYVIMRC')
end

Would it be possible to add this solution for those who get the error that PlugInstall is not a command on first setup with this tip?

NVIM v0.9.5
Build type: Release
LuaJIT 2.1.1703358377
  • Type:
    • [ ] Bug
    • [x] Enhancement
    • [ ] Feature Request
    • [ ] Question
  • OS:
    • [x] All/Other
    • [ ] Linux
    • [ ] macOS
    • [ ] Windows
  • Vim:
    • [ ] Terminal Vim
    • [ ] GVim
    • [x] Neovim

clebs avatar Mar 05 '24 18:03 clebs

I've faced this issue as well and this does solve it.

jtmr05 avatar Mar 06 '24 15:03 jtmr05

Any idea why the command is not recognized?

Because plug.vim is in autoload directory, the file is automatically loaded when you call any of its plug#... functions. Your configuration file should have both plug#begin and plug#end so they will trigger the load then you have :PlugInstall command. autocmd VimEnter is triggered after Vim finished processing the configuration file, so at that point, :PlugInstall must be available.

I have tested the code without the source line in this init.lua file and it works just fine.

local data_dir = vim.fn.stdpath('data')
if vim.fn.empty(vim.fn.glob(data_dir .. '/site/autoload/plug.vim')) == 1 then
	vim.cmd('silent !curl -fLo ' ..
		data_dir ..
		'/site/autoload/plug.vim --create-dirs  https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim')
	vim.cmd('autocmd VimEnter * PlugInstall --sync | source $MYVIMRC')
end

local vim = vim
local Plug = vim.fn['plug#']

vim.call('plug#begin')
Plug('junegunn/vim-easy-align')
vim.call('plug#end')

junegunn avatar Mar 07 '24 14:03 junegunn

That is interesting, I do have a plug#begin/end block right after what I just pasted exactly as you wrote. Yet without sourcing it explicitly, I do get the mentioned error. This behaviour is also consistent between MacOS and Linux.

Might be something specific to neovim? I have not tried with regular vim.

clebs avatar Mar 07 '24 15:03 clebs

With regular vim there seems to be no issue

jtmr05 avatar Mar 07 '24 17:03 jtmr05

I ran into the same problem with Neovim 0.9.5 and init.vim (not init.lua), but OP solved it.

This script works as expected;

" Automatic installation of vim-plug
let s:data_dir = stdpath('data') . '/site'
if empty(glob(s:data_dir . '/autoload/plug.vim'))
  silent execute '!curl -fL --create-dirs '
    \. '-o ' . s:data_dir . '/autoload/plug.vim '
    \. 'https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
  execute 'source ' . s:data_dir . '/autoload/plug.vim'
  autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
endif

@junegunn Could you retry in a fresh environment? This problem occurs on the first run as the OP mentioned.

it does not recognise PlugInstall as a command without restarting.

I tried your init.lua with Neovim 0.9.5 in a new Docker container, and got this error;

Error detected while processing /home/rust/.config/nvim/init.lua:
E5113: Error while calling lua chunk: Vim:E117: Unknown function: plug#begin
stack traceback:
        [C]: in function 'call'
        /home/rust/.config/nvim/init.lua:12: in main chunk
Error detected while processing VimEnter Autocommands for "*":
E492: Not an editor command: PlugInstall --sync | source $MYVIMRC
Press ENTER or type command to continue

mamekoro avatar Mar 25 '24 23:03 mamekoro

Okay, after removing all the directories related to Neovim, I was able to reproduce the problem, and it seems like a bug of Neovim.

The gist of the problem is this: Neovim does not pick up autoload files if ~/.local/share/nvim/site directory was not present when it was started.

rm -rf ~/.config/nvim ~/.local/share/nvim
mkdir -p ~/.config/nvim # ~/.local/share/nvim/site # FIXME: uncomment this part
cat << "EOF" > ~/.config/nvim/init.vim
call mkdir(stdpath('data') . '/site/autoload', 'p')
call writefile(['function! foobar#it()', 'echom 123', 'endfunction'], stdpath('data') . '/site/autoload/foobar.vim')
call foobar#it()
EOF
nvim
E117: Unknown function: foobar#it
Press ENTER or type command to continue

However, if we create the directory before starting Neovim, the autoload script is loaded as expected and prints 123.

rm -rf ~/.config/nvim ~/.local/share/nvim
mkdir -p ~/.config/nvim ~/.local/share/nvim/site # NOTE: uncommented
cat << "EOF" > ~/.config/nvim/init.vim
call mkdir(stdpath('data') . '/site/autoload', 'p')
call writefile(['function! foobar#it()', 'echom 123', 'endfunction'], stdpath('data') . '/site/autoload/foobar.vim')
call foobar#it()
EOF
nvim

I don't know if this is intentional, but I wouldn't call this a feature. Maybe they were trying to speed up processing by remembering which directories existed, so they could ignore non-existent directories afterwards.

Anyway, manually sourcing the plug.vim file seems to be the only workaround we can think of now. But this can't really be an ideal solution, because other autoload functions are also unavailable during the start-up.

rm -rf ~/.config/nvim ~/.local/share/nvim
mkdir -p ~/.config/nvim # ~/.local/share/nvim/site
cat << "EOF" > ~/.config/nvim/init.vim
call mkdir(stdpath('data') . '/site/autoload', 'p')
call writefile(['function! foobar#it()', 'echom 123', 'endfunction'], stdpath('data') . '/site/autoload/foobar.vim')
call writefile(['function! barfoo#it()', 'echom 456', 'endfunction'], stdpath('data') . '/site/autoload/barfoo.vim')
source ~/.local/share/nvim/site/autoload/foobar.vim
call foobar#it() " This works
call barfoo#it() " This doesn't
EOF
nvim
E117: Unknown function: barfoo#it

But after Neovim starts, call barfoo#it() works.

junegunn avatar Mar 26 '24 02:03 junegunn

That is an interesting finding. Will report it there and see what the answer is: https://github.com/neovim/neovim/issues/28128

Thanks for the detailed analysis!

clebs avatar Mar 31 '24 15:03 clebs

The workaround (resetting runtimepath) shown in https://github.com/neovim/neovim/issues/28128 works, so,

local data_dir = vim.fn.stdpath('data')
if vim.fn.empty(vim.fn.glob(data_dir .. '/site/autoload/plug.vim')) == 1 then
  vim.cmd('silent !curl -fLo ' .. data_dir .. '/site/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim')
  vim.o.runtimepath = vim.o.runtimepath
  vim.cmd('autocmd VimEnter * PlugInstall --sync | source $MYVIMRC')
end

-- An example of vim-plug section --------------------------------------------
local vim = vim
local Plug = vim.fn['plug#']

vim.call('plug#begin')
Plug('junegunn/seoul256.vim')
vim.call('plug#end')

vim.cmd('silent! colorscheme seoul256')

junegunn avatar Jun 05 '24 01:06 junegunn