YouCompleteMe is quite heavy (causes an extra 180ms in loading time on a fast i7 machine; much slower on older machines). I'd like to have it load on demand. Here is what I found:
If I use 'on' command, I get something like the following, no matter which ycm command I try:
Error detected while processing function <SNR>2_lod_cmd:
line 2:
E492: Not an editor command: YcmCompleter
If I use 'L' to load YouCompleteMe in the PlugStatus page, it'll show the plugin as OK but the YCM commands will not be available with error messages like this:
E492: Not an editor command: YcmCompleter
It seems to work with 'for' filetype triggers on startup (e.g. vim whatever.ch if I have 'on': 'chill') only. It doesn't work with ':e whatever.ch' though, so I can't load the plugin during a session.
That's probably because YCM calls youcompleteme#Enable() only during VimEnter. So if you want to load it after Vim started, you have to manually call that function. The following example shows how you can defer loading of YCM until you enter insert mode.
https://github.com/junegunn/vim-plug/wiki/faq#loading-plugins-manually
If you want to load it on a specific command, you have to define your own proxy command like follows (I haven't checked if it really works, but you'll get the idea)
Plug 'Valloric/YouCompleteMe', { 'on': [] }
command! YcmCompleter call plug#load('YouCompleteMe') | call youcompleteme#Enable() | YcmCompleter
Thanks for the reply, Junegunn. The explicit enable workaround indeed works.
However, I think a better solution seems to be adding an 'after' option to the Plugin command, which is contain the commands to execute (in this case the plugin specific Enable command) after the plugin is loaded. With this option, we can make the 'on', 'for' and 'L' all work properly for such plugins.
I understand. But vim-plug labels itself as "A minimalist Vim plugin manager" and we indeed believe that "less is better". So we try very hard to keep it as simple as possible. (If you're looking for more features, there are a couple of alternatives) I don't disagree with the suggested after option per se, but the thing is, YCM is the only popular plugin I'm aware of that requires the option, and I don't think it's a right call to add an option just for a very exception plugin, which is YCM. I'll consider it later when we get to see more plugins that would benefit from it.
By the way, I personally don't understand why YCM uses VimEnter event in the first place.
I'm glad that you care about your minimalist goal. However adding this particular option will save you many more times of answering the YCM issue, with only a few lines of code, given the popularity of the plugin. IMO, if you're trying to be minimalist, you'd get rid of the many lines of code that deals with multi-threaded update of the plugins, which is cool but nothing minimalist about it. I'd prefer it simply updating the plugins one by one and echo _all_ the output in the buffer. Comparing to the plugin update feature, the 'after' option solves a real problem in a minimalist way :)
However adding this particular option will save you many more times of answering the YCM issue
We have FAQ page and I can just point to the older issues. And generally, more options/features lead to more questions. And more importantly, why don't we just fix YCM instead? Have you tried contacting the author?
you'd get rid of the many lines of code that deals with multi-threaded update of the plugins
Well, what's the point of vim-plug if we remove parallel update, why would you use it when we already have other plugin managers? vim-plug is minimalist in the sense that it has very concise, straightforward API with the minimal set of necessary options for the cases for which no workaround exists, and it just works better than the others (parallel update) without forcing you to spend time learning it.
If you get rid of PlugUpdate and even PlugInstall, vim-plug will be truly minimalist with a focus on plugin loading management to ensure the best startup time for most occasions. I moved from pathogen, solely due to the on demand loading feature, which makes vim-plug faster than pathogen for all my use cases. In fact, I chose vim-plug, _despite_ the parallel update with its quirky URL requirements that wasted me much more time than necessary for the move. Who install/update their plugins every day? (which BTW is already trivial for typical vim users). A vim user (vs emacs users) starts vim countless time everyday, so startup time (snappiness) matters a lot more than install/update.
Who install/update their plugins every day?
Well, I do, and that's the reason I wrote vim-plug in the first place. Not technically every day though, I start a day with a sip of coffee, looking at the flow of the characters on vim-plug update screen. :coffee: And we seem to have very different definitions of "plugin manager". I'm not going to call something a plugin manager if it can't install or update plugins. In my view, it's just a runtimepath manager. And it's definitely not what vim-plug is trying to be. So we'll have to agree to disagree.
Although I added on-demand loading feature to vim-plug, fundamentally, it's just a stopgap solution to the problem. A plugin properly using autoload and ftplugin should load instantly and the right approach I believe is to fix plugins that take too long to load, not to find workarounds.
Back to the YCM issue, I'll tell you what you can do. Fork the plugin and remove the use of VimEnter event. And your problem's gone.
Well, most people think that pathogen is a minimalist plugin manager, which doesn't do install and update. The 'after' option (and 'before') would be useful for other things as well. e.g. log/notify the plugin loading events for 3rd-party plugin/tool/service integration etc. IMO, a well behaved plugin should do one thing really well and include mechanisms to integrate with other services for other features.
I'm finding out why Val doesn't simply call ycm enable after the plugin is loaded. OTOH, I'm really tempted to fork vim-plug (add 'before' and 'after' and remove PlugInstall/Update, which should really happen asynchronously, when I'm not using vim itself) as a really minimalist plugin manager :)
@vicaya can I ask you how many plugin do you have?
I have 28 at the moment, I'd like to collect stats (among other things) how much I use them via 'before'/'after' :)
I have 28 at the moment
And you would not care to update them faster?
I'm actually against this before/after thing because it seems to bring almost zero value to vim-plug.
With this option, we can make the 'on', 'for' and 'L' all work properly for such plugins.
I'm really curious to know which are this plugins except YCM (which I'm currently testing for removing the VimEnter autocmd)
Well, most people think that pathogen is a minimalist plugin manager, which doesn't do install and update.
Well apparently most people can't read: directly from the vim-pathogen repo
pathogen.vim: manage your runtimepath
which means that is no plugin manager, a great tool (I used it myself before switching) but not a plugin manager.
log/notify the plugin loading events for 3rd-party plugin/tool/service integration etc.
To me this sounds like the Plugfile all over again, namely a cool idea that no one used.
Although I added on-demand loading feature to vim-plug, fundamentally, it's just a stopgap solution to the problem. A plugin properly using autoload and ftplugin should load instantly and the right approach I believe is to fix plugins that take too long to load, not to find workarounds.
That is the key point that most people do not understand. Vim already has the right functionality for doing the base minimum during the startup, see ftplugin, autoload etc etc, but most people think that using the lazy loading is the only thing to do for speed up vim startup. For example the worst thing one can do with the lazy loading is lazy loading syntax plugin for "rarely used" filetype. That is because usually a syntax file for a filetype also has a ftdetect file, and if you lazy load the plugin, vim will not be able to read such ftdetect file, so the plugin manager has to force sourcing that file and load the rest later. Well vim would be able to do all of that for free, so one think that [s]he's been speeding vim up when instead [s]he's been slowing it down.
@vicaya At this point, it's clear to me that you should be checking out NeoBundle instead of vim-plug.
I have solved it in another way: by patching
function! PatchAndBuildYcm(info)
!sed -i 's/^augroup youcompletemeStart$/call youcompleteme\#Enable()\n&/' plugin/youcompleteme.vim
!git update-index --assume-unchanged plugin/youcompleteme.vim
if a:info.status == 'installed' || a:info.force
!./install.sh
endif
endfunction
Plug 'Valloric/YouCompleteMe', { 'for' : [ 'c', 'cpp' ], 'do' : function('PatchAndBuildYcm') }
@m42e See #231 #232. Now you can write
function! BuildYCM(info)
if a:info.status == 'installed' || a:info.force
!./install.sh
endif
endfunction
Plug 'Valloric/YouCompleteMe', { 'for' : [ 'c', 'cpp' ], 'do': function('BuildYCM') }
EDIT: We no longer need youcompleteme#Enable().
Thanks @junegunn
Is the InsertEnter autocommand manual loading still the most practical way (currently) to defer loading of YCM?
It depends. I don't always need YCM, so I enable it only for a few file types.
Plug 'Valloric/YouCompleteMe',
\ { 'for': ['c', 'cpp', 'go'], 'do': './install.py --clang-completer --gocode-completer' }
I like the idea of deferring loading a heavyweight plugin like that until insert mode usage, so it's working pretty well for me so far.
I also do like to use YCM for its buffer based symbol completion.
But being able to defer it from spooling up the daemon till vim actually begins editing a buffer is really sweet. it means it never has to be loaded if vim is used just to view a file, for example.
(to be clear to onlookers, i am using the https://github.com/junegunn/vim-plug/wiki/faq#loading-plugins-manually instructions)
Whatever works best for you. I use YcmCompleter GoTo command for browsing source code, so I need it in normal mode as well. I could additionally set up 'on': 'YouCompleter', but I don't really mind the delay that much.
let g:YouCompleteMeLazyLoaded = 0
function! LazyLoadingYMC()
if g:YouCompleteMeLazyLoaded == 0
g:YouCompleteMeLazyLoaded = 1
call plug#load('YouCompleteMe') | call youcompleteme#Enable()
endif
endfunction
autocmd InsertEnter * call LazyLoadingYMC()
For anyone who is annoyed by the YMC loading time, I wrote one function here for copy and paste!
@Piping
let g:YouCompleteMeLazyLoaded = 0 function! LazyLoadingYMC() if g:YouCompleteMeLazyLoaded == 0 g:YouCompleteMeLazyLoaded = 1 call plug#load('YouCompleteMe') | call youcompleteme#Enable() endif endfunction autocmd InsertEnter * call LazyLoadingYMC()For anyone who is annoyed by the YMC loading time, I wrote one function here for copy and paste!
Change g:YouCompleteMeLazyLoaded = 1 to let g:YouCompleteMeLazyLoaded = 1 work well!
When I use the method above, vim hangs for a second when entering insert mode. Is there any way to avoid it?
For now the best I could achieve is:
Plug 'Valloric/YouCompleteMe', { 'do': './install.sh --go-completer --js-completer', 'on': [] }
let g:YouCompleteMeLazyLoaded = 0
function! LazyLoadingYMC()
if g:YouCompleteMeLazyLoaded == 0
let g:YouCompleteMeLazyLoaded = 1
call plug#load('YouCompleteMe') | call youcompleteme#Enable()
endif
endfunction
autocmd BufWinEnter * call timer_start(1, {id->execute('call LazyLoadingYMC()')} )
Most helpful comment
For now the best I could achieve is: