Olaf Dabrunz wrote:
> > > > > On 09-Feb-16, Bram Moolenaar wrote:
> > > > > >
> > > > > > I had another idea. Currently when installing a plugin or support
> > > > > > for
> > > > > > a language, the files are scattered over different directories under
> > > > > > $VIMRUNTIME. That makes it hard to update them.
> > > > > >
> > > > > > How about this: use $VIMRUNTIME/bundles. Below that will be the
> > > > > > directories that are usually directly under $VIMRUNTIME. For
> > > > > > example,
> > > > > > netrw would be installed in the directories:
> > > > > > $VIMRUNTIME/bundles/netrw/plugin
> > > > > > $VIMRUNTIME/bundles/netrw/autoload
> > > > > > $VIMRUNTIME/bundles/netrw/syntax
> > > > > > It doesn't need an "indent" directory.
> > > > >
> > > > > I like the idea.
> > > > >
> > > > > But it should be easily possible to enable or disable plugins.
> > > > >
> > > > > E.g., I enable some of my Vundle plugins conditionally depending on
> > > > > the
> > > > > features in the vim version that I start:
> > > > >
> > > > > if has('iconv')
> > > > > Plugin 'mbbill/fencview'
> > > > > endif
> > > > >
> > > > > if has("python") || has("python3")
> > > > > Plugin 'SirVer/ultisnips'
> > > > > else
> > > > > Plugin 'MarcWeber/vim-addon-mw-utils'
> > > > > Plugin 'tomtom/tlib_vim'
> > > > > Plugin 'garbas/vim-snipmate'
> > > > > endif
> > > > >
> > > > > This is esp. relevant on Fedora, where "vi" is a tiny build of vim (I
> > > > > believe), and "vim" is a huge build of vim (I believe).
> > > >
> > > > Why does every user need to take care of this? The plugin should check
> > > > for features and skip if it is missing something.
> > >
> > > Because I may prefer using plugin A, but when plugin A does not work, I
> > > may want to use plugin B instead.
> > >
> > > A plugin cannot know my preferences about this.
> > >
> > > Also, when A and B are alternatives that cannot both be loaded (one
> > > excludes the other), as in Gary's 'netrw' example, the user may need to
> > > choose between A and B, depending on Vim's version or features.
> >
> > OK, but this should be an exception and not happen very often. We
> > should not say "it happens anyway so let's just let plugins mess about".
> > In other words: plugins should be encourage to make it easier for the
> > user.
>
> Yes, this should be an exception (in my case for 18% of the plugins,
> mostly for code snippet plugins and their libraries), and yes, we should
> definitely encourage plugins to get their feature and version checks
> right.
>
> In my suggestion to load plugins according to a dependency graph, the
> graph will mostly be empty, and Vim will load the plugins just as it
> used to do it, letting the plugins decide if they can load successfully.
>
> For the cases where fallbacks need to be specified, Vim will still
> attempt to load plugin A, and only if that fails it will attempt to load
> plugin B. So decisions are still based on the plugin's go/no go
> assessment.
Hmm, I didn't intend to replace a plugin manager, but assuming that the
user doesn't have one, or the plugin isn't made to be used by one, it
would be nice if the plugin writer can say "load this other plugin".
And that other plugin would then only be loaded when being asked to.
So, besides the "plugin bundles" that would always be loaded when found,
we could have "optional bundles" that are only loaded on request.
This would then also fulfill your ask for loading a plugin depending on
some conditions, from your .vimrc:
if some_condition
loadplugin thatPlugin
endif
I know some plugin writers have debugging stuff that is only enabled
when being asked for. So they could do something like:
if g:xxx_want_debug
" try loading plugin with XxxDebug command, may fail if the
" plugin can't be found.
loadplugin xxxdebug
endif
if exists(':XxxDebug')
XxxDebug "got there"
endif
Obviously there is no automatic downloading or updating. And it raises
the question of how the optional plugins are made available. One can
assume they are used by more than one plugin by the same author. Would
be nice if you can update them all at once... Can't think of a solution
that doesn't add another directory level (bundle of bundles). Perhaps
not go that way.
> > > But I agree that plugins generally should refuse to load when they
> > > cannot work with the version of Vim that tries to load them.
> > >
> > > Still, an experienced user or a plugin packager should be able to make
> > > better decisions than the plugin writer, because getting all the
> > > conditions right under which a plugin works can be a challenge, and some
> > > conditions may only become apparent in some specific setup.
> > >
> > > And when more conditions are figured out by users or plugin
> > > packagers, tried and tested, these could be forwarded to the plugin
> > > author. (Unless they are very specific to some distribution or
> > > setup.)
> >
> > Anything we can do to make it easier for plugin authors? A big
> > improvement would be if plugins would write tests that we can run
> > against different Vim configurations. I haven't seen plugins with tests
> > though...
> >
> > > It may be possible to specify plugin dependencies to Vim, so Vim can try
> > > to load plugins in the order dictated by a dependency graph, so that if
> > > plugin A does not load or is disabled, it attempts to load plugin B.
> > > And some plugin C is only loaded when plugin B has been loaded.
> > >
> > > To make this work, Vim also needs a reliable way to find out if a plugin
> > > has loaded correctly.
> > >
> > > Maybe like this: when during plugin loading the plugin does *not*
> > > use 'finish', then Vim can consider the plugin loaded.
> > >
> > > But some plugins load in stages, e.g. the taglist.vim plugin, so
> > > they use 'finish' even when loading successfully...
> >
> > This is for a large part the work of a plugin manager. If you have
> > dependencies you also need a way to download and install plugins
> > (otherwise you can only give error messages).
> >
> > And if plugin writers are so bad at bailing out when it won't work on
> > the current Vim, you can't really expect them to define dependencies
> > properly.
> >
> > > > I would also prefer Plugins run by default, and have some way to disable
> > > > them when you don't want them. Most plugins should just be used, only
> > > > in some cases would you want to skip one.
> > >
> > > If we find a way to specify plugin disable/enable information and plugin
> > > dependencies to Vim, and a way to check if a plugin loaded successfully,
> > > then this and the issues above could all be covered.
> >
> > I think you are describing a plugin manager.
>
> Yes, this is part of a plugin manager.
>
> Plugin managers currently use &runtimepath to implement conditional
> loading of plugins, based on conditions specified by the user.
>
> If we want to clean up &runtimepath, and take fallback actions (that is,
> load other plugins) based on the failure or success of loading plugins,
> we need some other way to specify the fallbacks to Vim.
>
> If we don't offer some other way to specify fallbacks, and to
> disable/enable plugins, plugin managers will continue to resort to using
> &runtimepath.
>
> Using &runtimepath means the decision to load A or B and C has to be
> made when &runtimpath is set up, which is before plugin loading is
> attempted. So in fallback cases the user has to figure out and specify
> the conditions when to load each plugin.
>
> Which is something I would like to change. Let Vim load A, and only if
> that fails load B and C.
>
> Admittedly, fallback handling is not needed in many cases. But what can
> plugin managers do except for using &runtimepath to cover such cases?
Yeah, I think I've given up on cleaning up 'runtimepath'. I don't think
I make users happy by breaking their snippets plugin or plugin manager.
I might be able to convince authors of plugin managers to change how it
works, but there will be users who upgrade Vim without updating the
plugin manager.
So we probably have to accept that 'runtimepath' is a mess and find
another solution.
> Please see below for a suggestion.
>
> > > > > Also, the compatibility issues need to be addressed.
> > > > >
> > > > > Some of them may go away simply by using a different subdirectory
> > > > > name,
> > > > > such as "plugpacks" instead of "bundles". Old plugins and plugin
> > > > > managers can use the old and known subdirectories, together with the
> > > > > known &runtimepath methods of including them.
> > > > >
> > > > > It should be possible to find out if a plugin is compatible with the
> > > > > new
> > > > > "plugpacks" subdirectory scheme. This is the difficult part, because
> > > > > how do we do this without requiring a flag in the plugin, which must
> > > > > be
> > > > > present in all future versions as well?
> > > > >
> > > > > It may not be so bad to have a flag, it can just become part of the
> > > > > boilerplate template for a plugin.
> > > > >
> > > > > But a standard boilerplate template for a vim plugin does not exist
> > > > > yet,
> > > > > to my knowledge. Google tried to make one, but AFAIK it did not catch
> > > > > on.
> > > >
> > > > I'm afraid that if we want to be backwards compatible with plugins that
> > > > depend on the runtime file layout we might be stuck in a sub-optimal
> > > > situation. And every plugin manager finds its own way, making it even
> > > > worse in the long run.
> > > >
> > > > I think it's not too bad to support the proposed directory layout. In
> > > > most cases everything will just keep working. In case some plugin needs
> > > > to find other plugins, and can only find other plugins from
> > > > 'runtimepath', then we can make that plugin add itself to 'runtimepath'.
> > > > Worst case all of them, using globpath(&runtimepath, 'bundles/*').
> > > >
> > > > I do think we need to get rid of adding lots of directories to
> > > > 'runtimepath'. It's supposed to be an option set by the user. The only
> > > > reason plugin managers use it is because there is no alternative.
> > >
> > > Cleaning up &runtimepath is one thing I like about this idea. The other
> > > thing is that each plugin lives in its own little directory subtree, so
> > > it is easy to install, remove and update.
> > >
> > > Also, in many cases we can try to load a plugin to see if the plugin can
> > > work with the current Vim.
> >
> > Right, that's what I was trying to make possible. Sort of a manual
> > plugin management.
> >
> > > Now if we also can specify plugin disable/enable information and plugin
> > > dependencies (between each other and on Vim features) to Vim, and find
> > > out when a plugin loaded successfully, and if all this can be done in a
> > > simple and reliable way, this could be an alternative to &runtimepath.
> >
> > I think that's too much for the Vim distribution to support. Unless we
> > include a plugin manager.
>
> Hm, I was also thinking that it may be too much. Maybe it is.
>
>
> Here is an idea of what it would look like:
>
> Vim can remember the success of loading a plugin in
> v:scripts[<scriptname>]. This stores the value the plugin has given
> with :finish <value>.
>
> Typically 0 or 1, -1 if no value was given, and -2 if the plugin did
> not execute :finish. (A plugin can only specify values >= 0.)
>
> This should cover most current uses of :finish correctly, and gives
> plugins a way to be exact about loading successfully in the future.
> Special (legacy) cases can be dealt with by plugin managers, please
> see below.
>
> <scriptname> is the full path name of the plugin.
>
> Additionally, there are indices for the plugin base names, that is
> the names without path and without trailing .vim:
>
> v:scripts[<basename>] = ['<scriptname1>', '<scriptname2>', ...]
>
> (There can be no collisions, <basename> cannot contain path
> separators, <scriptname> must contain at least a leading path
> separator.)
>
> In .vimrc, the user can say
>
> :plugdep "<basename>" "<condition>" or
> :plugdep "<scriptname>" "<condition>"
>
> and the condition can use the v:scripts dictionary, or just 0.
>
> The "<condition>" is eval()'ed by Vim before Vim tries to load the
> plugin <scriptname>. If the result is false, Vim skips the plugin.
>
> Plugins with dependencies are considered last, and in the order of the
> :plugdep commands.
>
> Example:
>
> :function PluginLoaded(name)
> : " ':finish' -> not loaded, no ':finish' -> loaded
> : " (and below: ':finish <value>' -> loaded if <value> > 0)
> : let loaded = {-1: 0, -2: 1}
> : if !has_key(v:scripts, a:name)
> : return 0 " unknown -> not loaded
> : endif
> : let val = v:scripts[a:name]
> : if type(val) == type(1)
> : " a:name is full plugin path
> : return get(loaded, val, val) > 0
> : endif
> : " plugin basename: has loaded if loaded from any path
> : return max(
> : \ map(val, 'get(loaded, v:scripts[v:val], v:scripts[v:val])')
> : \ ) > 0
> :endfunction
> :
> :plugdep 'vim-addon-mw-utils' '!PluginLoaded("ultisnips")'
> :plugdep 'tlib_vim' '!PluginLoaded("ultisnips")'
> :plugdep 'vim-snipmate' '!PluginLoaded("ultisnips")'
> :
> :plugdep 'test_me' '0' " disabled
>
>
> Example for netrw (Gary):
>
> :plugdep $HOME.'/.vim/plugin/netrwPlugin.vim'
> : \ 'v:version > 703 || (v:version == 703 && has("patch465"))'
> :plugdep 'netrwPlugin' '!PluginLoaded("netrwPlugin")'
>
> netrw always sets its g:loaded_netrwPlugin variable, even if it does
> not load successfully. If it would set g:loaded_netrwPlugin only
> when loading successfully, then several attempts could be made to
> try loading different versions of it, and we would only need to
> specify order of precedence here (= order of :plugdep commands):
>
> :plugdep $HOME.'/.vim/netrw/netrwPlugin.vim' '1'
> :plugdep 'netrwPlugin' '1' " or
> '!PluginLoaded("netrwPlugin")'
>
> And maybe there should be a way to suppress netrw's error message
> for unsuccessful loads.
>
>
> Too much, maybe. But maybe not?
>
> There still is the assumption that ':finish' (without value) means 'not
> loaded'. But that's usually true, and where it is not, the plugin
> manager can make a list of such plugins and use special checks on the
> plugin's g:..._loaded variables (in the PluginLoaded() function).
>
> With this in place, I believe &runtimepath does not need to be changed
> by plugin managers.
>
> And in all cases the decision of whether a plugin loads successfully is
> left to the plugin to decide. Unless the user *really* wants to
> override this.
I think this is expecting too much of plugin authors. Too many things
to understand, too many mistakes that can be made.
It should not use the whole path, only the name of the plugin. The user
may install plugins in several directories. There can be system-wide
plugins with per-user override (that's what I have at work).
We can keep track of which plugins we tried to load. Whether that
succeeded or not is already getting a bit tricky, it depends on the
plugin writer. The load could also work partially.
One thing we know: If one plugin depends on another plugin, it knows why
it depends on it. So it can check if loading that plugin worked by
checking for that dependency. Above I used a user command as an
example.
Perhaps all we need is:
- 'pluginpath' - list of directories that contain plugin bundles that
are always loaded. User puts them there.
- 'optionalpluginpath' - list of directories that contain plugin bundles
that can be loaded when wanted (needs a better name).
- ":loadplugin" - loads an optional plugin and remembers that Vim tried
to load it, won't load it a second time.
When loading a plugin from 'pluginpath' or 'optionalpluginpath' that
directory is added to 'runtimepath'. That hopefully keeps existing
plugins and plugin managers working.
--
hundred-and-one symptoms of being an internet addict:
227. You sleep next to your monitor. Or on top of it.
/// Bram Moolenaar -- [email protected] -- 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 ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.