Packages: best practices?

164 views
Skip to first unread message

Nicola

unread,
Mar 25, 2016, 3:16:19 PM3/25/16
to vim...@googlegroups.com
I would like to start using Vim's new package feature, but first I want to make
sure that I have understood how it is supposed to be used. Is it too early to
ask for tips about that?

First let me summarize what I have understood about packages (please correct
anything wrong):

- every package must be inside a directory called `pack` (`~/.vim/pack`).

- Each package should have (at least one of) two subdirectories: `start` and
`opt`.

- Plugins and ftplugins that must be available at launch time must go inside
`start`. What actually happens is that *any* directory under `start` is added
to `runtimepath` at startup independent of its content (much like Pathogen
does). Besides, if a directory contains a `plugin/foo.vim` file, that file is
sourced.

- Plugins and ftplugins that you want to be loaded lazily/manually go inside
`opt`. These may be loaded with `:packadd`. This is not exactly like loading
a plugin at startup, though, because if a plugin does something on VimEnter,
that something must be triggered manually.

- The `colorscheme` command searches both `pack/*/start` and `pack/*/opt/`
(beside `runtimepath`), so it does not matter where a colorscheme is.

If the above is accurate, I would give the following recommendations:

- Always put filetype plugins (no `plugin/foo.vim`) inside `start`. I see no
reason why you would want to do otherwise (unless you have a filetype
that you
seldom use and you really want to keep `runtimepath` as small as possible).
This type of plugin does not cause any file to be loaded at startup, unless
there is an `ftdetect/xyz.vim` file.

- Always put colorschemes inside `opt`. This avoid cluttering
`runtimepath`, and
they are found anyway.

For a concrete example of migration, let's say I am using Pathogen and I have
the following:

bundle/surround <-- regular plugin
bundle/youcompleteme <-- regular plugin
bundle/solarized <-- colorscheme
bundle/zenburn <-- colorscheme
bundle/ledger <-- filetype plugin
bundle/pgsql <-- filetype plugin
bundle/swift <-- filetype plugin

I might then move them to:

pack/bundle/start/surround
pack/bundle/start/ledger
pack/bundle/opt/youcompleteme
pack/languages/start/pgsql
pack/languages/start/swift
pack/themes/opt/solarized
pack/themes/opt/zenburn

Then, everything should work as before, with the exception of YCM, which must
now be loaded manually. To do so, I need

:packadd youcompleteme

but also

:call youcompleteme#Enable()

because :packadd does not trigger VimEnter.

Does what I said make sense? Am I missing something?

Nicola


Nicola

unread,
Mar 26, 2016, 11:29:49 AM3/26/16
to vim...@googlegroups.com

I have implemented the schema above, using the following directory structure:


pack/

  bundle/

    start/

    opt/

  themes/

    opt/


All seems fine. For colorschemes things are not as simple as I have described

above, because they may contain autoload directories, with (typically) stuff for

Airline/Lightline or for GUI Vim. Since I don't use those, for me it's fine to

have colorschemes inside `opt`, but in general some colorschemes would better go

inside `start`.


Plugins that I had blacklisted in Pathogen are now in bundle/opt. Pathogen lives

in bundle/opt, too: I still use it as a fallback when packages are not available.


A positive note is that the startup time has improved ~25% (now it's ~60ms).


Then, everything should work as before, with the exception of YCM, which must

now be loaded manually. To do so, I need


:packadd youcompleteme


but also


:call youcompleteme#Enable()


because :packadd does not trigger VimEnter.


This is a bit a of a pain. How about having `:packadd` trigger an event that

plugins may hook to?


Nicola


Bram Moolenaar

unread,
Mar 26, 2016, 1:56:44 PM3/26/16
to Nicola, vim...@googlegroups.com

Nicola wrote:

> > Then, everything should work as before, with the exception of YCM, which must
> > now be loaded manually. To do so, I need
> >
> > :packadd youcompleteme
> >
> > but also
> >
> > :call youcompleteme#Enable()
> >
> > because :packadd does not trigger VimEnter.
>
> This is a bit a of a pain. How about having `:packadd` trigger an event that
> plugins may hook to?

I'm not sure what you mean. Doesn't youcompleteme do its initialization
when it is being loaded?

Hmm, maybe it relies on being sourced early, and has a VimEnter
autocommand to trigger initialization?

I suppose there is no easy way to know if VimEnter already fired.
Perhaps we need a flag that indicatest this, so you can do:

if v:vim_did_enter
call s:init()
else
au VimEnter * call s:init()
endif

Something like that?

--
All true wisdom is found on T-shirts.

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

Nicola

unread,
Mar 26, 2016, 2:31:48 PM3/26/16
to vim...@googlegroups.com
On 2016-03-26 17:56:34 +0000, Bram Moolenaar said:

> Nicola wrote:
>
>>> Then, everything should work as before, with the exception of YCM, which must
>>> now be loaded manually. To do so, I need
>>>
>>> :packadd youcompleteme
>>>
>>> but also
>>>
>>> :call youcompleteme#Enable()
>>>
>>> because :packadd does not trigger VimEnter.
>>
>> This is a bit a of a pain. How about having `:packadd` trigger an event that
>> plugins may hook to?
>
> I'm not sure what you mean. Doesn't youcompleteme do its initialization
> when it is being loaded?
>
> Hmm, maybe it relies on being sourced early, and has a VimEnter
> autocommand to trigger initialization?

Exactly. See:

https://github.com/Valloric/YouCompleteMe/blob/master/plugin/youcompleteme.vim#L166


It has:

autocmd VimEnter * call youcompleteme#Enable()

> I suppose there is no easy way to know if VimEnter already fired.
> Perhaps we need a flag that indicatest this, so you can do:
>
> if v:vim_did_enter
> call s:init()
> else
> au VimEnter * call s:init()
> endif
>
> Something like that?

For YCM, that would work. I don't know what else a plugin can do at
startup that
would not do if loaded at a later time (other types of autocmds?).

Nicola


Andy Wokula

unread,
Mar 26, 2016, 2:54:03 PM3/26/16
to vim...@googlegroups.com
if has("vim_starting")
" init on VimEnter
else
" init immediately
endif

--
Andy

Nicola

unread,
Mar 26, 2016, 3:06:51 PM3/26/16
to vim...@googlegroups.com
On 2016-03-26 18:53:44 +0000, Andy Wokula said:

> if has("vim_starting")
> " init on VimEnter
> else
> " init immediately
> endif

That works, thanks!

Nicola


Gary Johnson

unread,
Mar 26, 2016, 4:02:19 PM3/26/16
to vim...@googlegroups.com
That's a very odd application of has().

The has() function is clearly intended to indicate presence or
absence of some feature that is compiled in, or in the case of
"gui_running", available only under certain unchanging conditions.
I would never think to look among features for a flag indicating the
startup state. Even Bram did not find it.

It's probably too late to change it, but I think it would make more
sense to expose that state as a variable such as v:vim_starting or
v:vim_did_enter or as a function such as vim_starting().

Regards,
Gary

Bram Moolenaar

unread,
Mar 26, 2016, 4:24:43 PM3/26/16
to Andy Wokula, vim...@googlegroups.com
Ah, forgot about that one. And couldn't find it, it doesn't have a help
tag (added one).

Turns out it's very close to v:vim_did_enter. Should we revert adding
v:vim_did_enter ?

--
There are three kinds of persons: Those who can count and those who can't.

Andy Wokula

unread,
Mar 28, 2016, 3:50:50 PM3/28/16
to vim...@googlegroups.com
Am 26.03.2016 um 21:03 schrieb Gary Johnson:
> On 2016-03-26, Andy Wokula wrote:
>> if has("vim_starting")
>> " init on VimEnter
>> else
>> " init immediately
>> endif
>
> That's a very odd application of has().
>
> The has() function is clearly intended to indicate presence or
> absence of some feature that is compiled in, or in the case of
> "gui_running", available only under certain unchanging conditions.
> I would never think to look among features for a flag indicating the
> startup state. Even Bram did not find it.

Proper linking in the help should be enough?

> It's probably too late to change it, but I think it would make more
> sense to expose that state as a variable such as v:vim_starting or
> v:vim_did_enter or as a function such as vim_starting().
>
> Regards,
> Gary

It has been there for a long time (Vim 5.7 or earlier).

There are other "dynamic" items:
has("multi_byte_encoding")
has("syntax_items")
...

--
Andy
Reply all
Reply to author
Forward
0 new messages