diff --git a/autoload/maktaba/plugin.vim b/autoload/maktaba/plugin.vim index 3567e4d..aeb7129 100644 --- a/autoload/maktaba/plugin.vim +++ b/autoload/maktaba/plugin.vim @@ -180,6 +180,28 @@ function! s:FileHandleToFlagHandle(handle) abort endfunction +" Ensures {plugin}'s plugin/flags.vim file has been sourced (if it has one and +" has not already had an instant/flags.vim file sourced). +function! s:EnsureFlagsLoaded(plugin) abort + if a:plugin._loaded_flags + return + endif + try + call a:plugin.Load('flags') + " If file was loaded and called maktaba#plugin#Enter, it should now have + " PLUGIN._loaded_flags set as a side effect. + if !a:plugin._loaded_flags + call a:plugin.logger.Warn( + \ 'plugin/flags.vim seems to be missing maktaba#plugin#Enter call') + endif + catch /ERROR(NotFound):/ + " Plugin has no plugin/flags.vim file. That's totally fine if it only uses + " built-in flags like plugin[commands]. + endtry + let a:plugin._loaded_flags = 1 +endfunction + + "" " @private " Used by maktaba#library to help throw good error messages about non-library @@ -225,6 +247,10 @@ function! maktaba#plugin#Enter(file) abort let [l:plugindir, l:filedir, l:handle] = s:SplitEnteredFile(a:file) let l:plugin = maktaba#plugin#GetOrInstall(l:plugindir) let l:controller = l:plugin._entered[l:filedir] + " Check for special path plugin/flags.vim or instant/flags.vim (which gets a + " handle 'flags^' in s:SplitEnteredFile's handle syntax). + let l:is_flags_file = (l:filedir ==# 'plugin' || l:filedir ==# 'instant') + \ && l:handle ==# 'flags^' if l:filedir ==# 'ftplugin' call extend(l:controller, {l:handle : []}, 'keep') @@ -240,7 +266,12 @@ function! maktaba#plugin#Enter(file) abort return [l:plugin, 0] endif - if l:filedir !=# 'autoload' + " Only load this full file if its corresponding flag is enabled. + " For example, plugin/autocmds.vim should exit early if the user configured + " !plugin[autocmds] in their flags. + " This override mechanism has no effect for autoload files (which should be + " reloadable) or for flags files (which should never need to be disabled). + if l:filedir !=# 'autoload' && !l:is_flags_file " Check the 'plugin' or 'instant' flag dictionaries for word on the this " file, using the defaults specified in the s:defaultoff variable. let l:flag = l:plugin.Flag(l:filedir) @@ -255,6 +286,9 @@ function! maktaba#plugin#Enter(file) abort " Note that a file isn't entered when it is sourced: it is entered when this " function OKs an enter. (In other words, don't move this line up.) call add(l:controller, l:handle) + if l:is_flags_file + let l:plugin._loaded_flags = 1 + endif return [l:plugin, 1] endfunction @@ -460,6 +494,7 @@ function! s:CreatePluginObject(name, location, settings) abort \ 'Source': function('maktaba#plugin#Source'), \ 'Load': function('maktaba#plugin#Load'), \ 'AddonInfo': function('maktaba#plugin#AddonInfo'), + \ 'AllFlags': function('maktaba#plugin#AllFlags'), \ 'Flag': function('maktaba#plugin#Flag'), \ 'HasFlag': function('maktaba#plugin#HasFlag'), \ 'HasDir': function('maktaba#plugin#HasDir'), @@ -469,6 +504,7 @@ function! s:CreatePluginObject(name, location, settings) abort \ 'IsLibrary': function('maktaba#plugin#IsLibrary'), \ 'GetExtensionRegistry': function('maktaba#plugin#GetExtensionRegistry'), \ '_entered': l:entrycontroller, + \ '_loaded_flags': 0, \ } " If plugin has an addon-info.json file with a "name" declared, overwrite the " default name with the custom one. @@ -506,10 +542,10 @@ function! s:CreatePluginObject(name, location, settings) abort " These special flags let the user control the loading of parts of the plugin. if isdirectory(maktaba#path#Join([l:plugin.location, 'plugin'])) - call l:plugin.Flag('plugin', {}) + let l:plugin.flags.plugin = maktaba#flags#Create('plugin', {}) endif if isdirectory(maktaba#path#Join([l:plugin.location, 'instant'])) - call l:plugin.Flag('instant', {}) + let l:plugin.flags.instant = maktaba#flags#Create('instant', {}) endif " Load flags file first. @@ -747,6 +783,17 @@ function! maktaba#plugin#AddonInfo() dict abort endfunction + +"" +" @dict Plugin +" Returns a dictionary of @dict(Flag) handles defined on the plugin, with flag +" names as keys. +function! maktaba#plugin#AllFlags() dict abort + call s:EnsureFlagsLoaded(self) + return self.flags +endfunction + + "" " @usage {flag} " @dict Plugin @@ -757,6 +804,8 @@ endfunction " maktaba#plugin#Get('myplugin').Flag('foo') " maktaba#plugin#Get('myplugin').flags.foo.Get() " < +" except that the second version will not trigger flag loading if they haven't +" been loaded already. " " You may access a portion of a flag (a specific value in a dict flag, or " a specific item in a list flag) using a fairly natural square bracket @@ -764,7 +813,7 @@ endfunction " maktaba#plugin#Get('myplugin').Flag('plugin[autocmds]') " < " This is equivalent to: > -" maktaba#plugin#Get('myplugin').flags.plugin.Get()['autocmds'] +" maktaba#plugin#Get('myplugin').Flag('plugin')['autocmds'] " < " This syntax can be chained: > " maktaba#plugin#Get('myplugin').Flag('complex[key][0]') @@ -785,6 +834,8 @@ endfunction " maktaba#plugin#Get('myplugin').Flag('foo', 'bar') " maktaba#plugin#Get('myplugin').flags.foo.Set('bar') " < +" except that the second version will not trigger flag loading if they haven't +" been loaded already. " " Also supports dict flag syntax: > " maktaba#plugin#Get('myplugin').Flag('plugin[autocmds]', 1) @@ -792,6 +843,7 @@ endfunction " " @throws BadValue if {flag} is an invalid flag name. function! maktaba#plugin#Flag(flag, ...) dict abort + call s:EnsureFlagsLoaded(self) let [l:flag, l:foci] = maktaba#setting#Handle(a:flag) if !has_key(self.flags, l:flag) if a:0 == 0 || !empty(l:foci) @@ -808,8 +860,10 @@ endfunction "" +" @dict Plugin " Whether or not the plugin has a flag named {flag}. function! maktaba#plugin#HasFlag(flag) dict abort + call s:EnsureFlagsLoaded(self) return has_key(self.flags, a:flag) endfunction diff --git a/autoload/maktaba/setting.vim b/autoload/maktaba/setting.vim index bfce6a2..37e00c7 100644 --- a/autoload/maktaba/setting.vim +++ b/autoload/maktaba/setting.vim @@ -112,8 +112,9 @@ endfunction " Gets the flag in {plugin} relevant to the setting. " @throws NotFound if {plugin} does not define the appropriate flag. function! maktaba#setting#GetFlag(plugin) dict abort - if has_key(a:plugin.flags, self._flagname) - return a:plugin.flags[self._flagname] + let l:plugin_flags = a:plugin.AllFlags() + if has_key(l:plugin_flags, self._flagname) + return l:plugin_flags[self._flagname] endif let l:msg = 'Flag "%s" not defined in %s.' throw maktaba#error#NotFound(l:msg, self._flagname, a:plugin.name) diff --git a/doc/maktaba.txt b/doc/maktaba.txt index 26c2107..4288427 100644 --- a/doc/maktaba.txt +++ b/doc/maktaba.txt @@ -292,6 +292,10 @@ Plugin.AddonInfo() *Plugin.AddonInfo()* Otherwise, returns an empty dict. Throws ERROR(BadValue) if addon-info.json isn't valid JSON. +Plugin.AllFlags() *Plugin.AllFlags()* + Returns a dictionary of |maktaba.Flag| handles defined on the plugin, with + flag names as keys. + Plugin.Flag({flag}) *Plugin.Flag()* Returns the value of {flag}. See |maktaba#setting#Handle()| for {flag} syntax. @@ -301,6 +305,8 @@ Plugin.Flag({flag}) *Plugin.Flag()* maktaba#plugin#Get('myplugin').Flag('foo') maktaba#plugin#Get('myplugin').flags.foo.Get() < + except that the second version will not trigger flag loading if they haven't + been loaded already. You may access a portion of a flag (a specific value in a dict flag, or a specific item in a list flag) using a fairly natural square bracket syntax: @@ -309,7 +315,7 @@ Plugin.Flag({flag}) *Plugin.Flag()* < This is equivalent to: > - maktaba#plugin#Get('myplugin').flags.plugin.Get()['autocmds'] + maktaba#plugin#Get('myplugin').Flag('plugin')['autocmds'] < This syntax can be chained: > @@ -330,6 +336,8 @@ Plugin.Flag({flag}, {value}) maktaba#plugin#Get('myplugin').Flag('foo', 'bar') maktaba#plugin#Get('myplugin').flags.foo.Set('bar') < + except that the second version will not trigger flag loading if they haven't + been loaded already. Also supports dict flag syntax: > @@ -338,6 +346,9 @@ Plugin.Flag({flag}, {value}) Throws ERROR(BadValue) if {flag} is an invalid flag name. +Plugin.HasFlag({flag}) *Plugin.HasFlag()* + Whether or not the plugin has a flag named {flag}. + Plugin.MapPrefix({letter}, [throw]) *Plugin.MapPrefix()* Returns the user's desired map prefix for the plugin. If the user has not specified a map prefix, {letter} will be returned. @@ -1550,9 +1561,6 @@ maktaba#plugin#Source({file}, [optional]) *maktaba#plugin#Source()* Throws ERROR(NotAuthorized) if {file} cannot be read. Throws ERROR(NotFound) if {file} does not describe a plugin file. -maktaba#plugin#HasFlag({flag}) *maktaba#plugin#HasFlag()* - Whether or not the plugin has a flag named {flag}. - maktaba#python#ImportModule({plugin}, {name}) *maktaba#python#ImportModule()* Imports python module {name} into vim from {plugin}. Checks for {name} in the plugin's python/ subdirectory for the named module. diff --git a/vroom/fakeplugins/fullplugin/instant/flags.vim b/vroom/fakeplugins/fullplugin/plugin/flags.vim similarity index 100% rename from vroom/fakeplugins/fullplugin/instant/flags.vim rename to vroom/fakeplugins/fullplugin/plugin/flags.vim diff --git a/vroom/fakeplugins/myplugin/instant/flags.vim b/vroom/fakeplugins/legacyflagsplugin/instant/flags.vim similarity index 100% rename from vroom/fakeplugins/myplugin/instant/flags.vim rename to vroom/fakeplugins/legacyflagsplugin/instant/flags.vim diff --git a/vroom/fakeplugins/modularplugin/instant/flags.vim b/vroom/fakeplugins/modularplugin/plugin/flags.vim similarity index 62% rename from vroom/fakeplugins/modularplugin/instant/flags.vim rename to vroom/fakeplugins/modularplugin/plugin/flags.vim index 2442b11..ec8da15 100644 --- a/vroom/fakeplugins/modularplugin/instant/flags.vim +++ b/vroom/fakeplugins/modularplugin/plugin/flags.vim @@ -3,6 +3,6 @@ if !s:enter finish endif -echomsg 'The flags file is sourced immediately.' +echomsg 'The flags file is sourced on first flag access if not already loaded.' call s:plugin.Flag('plugin[optin]', 0) diff --git a/vroom/fakeplugins/myplugin/plugin/flags.vim b/vroom/fakeplugins/myplugin/plugin/flags.vim new file mode 100644 index 0000000..f463fd5 --- /dev/null +++ b/vroom/fakeplugins/myplugin/plugin/flags.vim @@ -0,0 +1,6 @@ +let [s:plugin, s:enter] = maktaba#plugin#Enter(expand('', ':p')) +if !s:enter + finish +endif + +echomsg 'Flags file sourced.' diff --git a/vroom/mappings.vroom b/vroom/mappings.vroom index f9c9009..02616c1 100644 --- a/vroom/mappings.vroom +++ b/vroom/mappings.vroom @@ -19,6 +19,7 @@ instance, if you try to load the 'mappings' file, nothing happens: @messages (STRICT) :call g:plugin.Load('mappings') + ~ The flags file is sourced on first flag access if not already loaded. @messages Unless you have EXPLICITLY enabled mappings: diff --git a/vroom/plugin.vroom b/vroom/plugin.vroom index d32bdb8..50858e4 100644 --- a/vroom/plugin.vroom +++ b/vroom/plugin.vroom @@ -44,14 +44,12 @@ ftplugin.vroom). Roughly speaking: - syntax/ files are used to highlight new filetypes - indent/ files are used to define indent rules for new filetypes -The interesting stuff usually happens in the instant/ and plugin/ directories. -- plugin/ files are sourced by vim after the vimrc file finishes -- instant/ files are sourced by maktaba IMMEDIATELY upon installation. +The interesting stuff usually happens in the plugin/ directory. plugin/ files +are sourced by vim after the vimrc file finishes. In a standard maktaba plugin, they will look something like this: -| instant/ -| flags.vim | plugin/ +| flags.vim | settings.vim | commands.vim | autocmds.vim @@ -80,12 +78,12 @@ sourced automatically EXCEPT files named mappings.vim. Maktaba policy is that users must opt-in to key mappings. (If you use custom mapping files, you should disable them by default as explained below). -You'll notice that some of these files go in the instant/ directory and others -go in the plugin/ directory. As a rule of thumb, only place files in instant/ -if you ABSOLUTELY MUST. instant/ files are loaded IMMEDIATELY when the plugin is -installed. This is usually unnecessary. Every file in plugin/ will be sourced by -vim in the usual load order. You need only use instant/ files when you need work -to be done BEFORE the .vimrc file exists. +Maktaba also currently supports an instant/ directory with files that are +sourced by maktaba IMMEDIATELY upon installation. As a rule of thumb, only place +files in instant/ if you ABSOLUTELY MUST. instant/ files are loaded IMMEDIATELY +when the plugin is installed. This is usually unnecessary. Every file in plugin/ +will be sourced by vim in the usual load order. You need only use instant/ files +when you need work to be done BEFORE the .vimrc file exists. For a vast majority of plugins, the only thing you need to do at install time is define your plugin flags. These are what users use to configure your plugin @@ -99,12 +97,7 @@ Note the order of events: The time to configure a plugin is BETWEEN installation and loading. -Notice: ANYTHING THAT YOU PUT IN THE instant/ DIRECTORY CANNOT BE CONFIGURED. - -There are some important uses for instantly loaded files, but you should use -this feature with caution. - -Almost every plugin will want an instant/flags.vim file: it's the place where +Almost every plugin will want a plugin/flags.vim file: it's the place where you define flags used to configure your plugin. This allows you to avoid subtle issues when users attempt to update complicated configurations that do not become defined until load time. If you make use of the maktaba flags framework, @@ -142,15 +135,11 @@ Now, we install the plugin by giving maktaba the full plugin path: @messages (STRICT) :let g:plugin = maktaba#plugin#Install(g:pluginpath) - ~ Flags file sourced. @messages This should generally be done by a plugin manager. -A few things have happened. First of all, notice that the flags file was sourced -immediately. (Take a look at fakeplugins/myplugin/plugin/flags.vim to see where -the message came from.) Secondly and most importantly, our plugin is now on the -runtimepath and registered with maktaba: +Our plugin is now on the runtimepath and registered with maktaba: :call maktaba#ensure#IsTrue(has_key(maktaba#rtp#LeafDirs(), 'myplugin')) :call maktaba#ensure#IsTrue(maktaba#plugin#IsRegistered('myplugin')) @@ -177,6 +166,7 @@ startup. However, if your plugin was installed after startup then it won't be loaded automatically. You can load it with the Load function: :call g:plugin.Load() + ~ Flags file sourced. ~ I shall have things my way! This will source all of the relevant plugin files. diff --git a/vroom/plugincontrol.vroom b/vroom/plugincontrol.vroom index dcb24a5..1139742 100644 --- a/vroom/plugincontrol.vroom +++ b/vroom/plugincontrol.vroom @@ -81,7 +81,10 @@ There are several other types of plugin files besides those in plugin/. Maktaba provides a concept of instant/ files, which will be activated as soon as possible after the plugin is activated. - :let g:instant_a = PluginPath(['instant', 'a.vim']) + :let g:legacyflagspath = maktaba#path#Join([g:repo, 'legacyflagsplugin']) + :let g:legacyflagsplugin = maktaba#plugin#Install(g:legacyflagspath) + :let g:instant_a = maktaba#path#Join([ + |g:legacyflagsplugin.location, 'instant', 'a.vim']) :call maktaba#ensure#IsTrue(maktaba#plugin#Enter(g:instant_a)[1]) :call maktaba#ensure#IsFalse(maktaba#plugin#Enter(g:instant_a)[1]) diff --git a/vroom/pluginfiles.vroom b/vroom/pluginfiles.vroom index 803105a..077479a 100644 --- a/vroom/pluginfiles.vroom +++ b/vroom/pluginfiles.vroom @@ -7,31 +7,33 @@ Here's what you need to know: * Functions go in autoload/, you must follow vim's naming conventions there. * ftdetect, ftplugin, indent, and syntax files go in appropriate directories. * Most other files go in the plugin/ dir, split according to functionality. -* Some very special files go in the instant/ dir. The standard maktaba plugin file split is: -| instant/ -| flags.vim | plugin/ +| flags.vim | settings.vim | commands.vim | autocmds.vim | mappings.vim -Normal plugin files (in the plugin/ directory) are sourced by vim after vimrc -time, as the last part of the vim startup sequence. plugin/mappings.vim is -opt-in, see mappings.vroom for details. All other plugin/ files are sourced -normally by vim after vimrc time. +Normal plugin files (in the plugin/ directory) are sourced by vim after vimrc +time, as the last part of the vim startup sequence, but plugin/flags.vim is +special and may be loaded as soon as plugin flags are accessed (see details +below). plugin/mappings.vim is opt-in, and mappings.vroom gives more details +about mappings files. All other plugin/ files are sourced normally by vim after +vimrc time. + +Any plugin configuration flags are defined in plugin/flags.vim (or the legacy +path of instant/flags.vim). Maktaba will ensure these are loaded before any flag +values are used so that flag defaults and hooks are applied consistently. See +pluginflags.vroom and flags.vroom for details. Files in the instant/ directory are instantloaded, and are sourced immediately upon plugin installation. This feature can be dangerous, and should be used sparingly. Make sure you understand the nuances of vim plugin loading before adding strange instant/ files. -The exception is instant/flags.vim, which is where you define your plugin -configuration flags. See flags.vroom for details. - The benefit of splitting your files up is that users can mix-and-match what they take from your plugin. In order to enable all this functionality, there's one rule: you need to have the following header at the top of all your plugin files: @@ -72,11 +74,16 @@ Now that maktaba is installed, let's get the modularplugin installed: :let g:repo = maktaba#path#Join([g:thisdir, 'fakeplugins']) :let g:path = maktaba#path#Join([g:repo, 'modularplugin']) :let g:plugin = maktaba#plugin#Install(g:path) - ~ The flags file is sourced immediately. -Note that the flags file was sourced immediately. Other plugin files won't be -loaded until we call the Load function: unless we selectively load existing -plugin files. For example, let's load the plugin settings before anything else: +Since this plugin was installed after vim startup, plugin files in the plugin/ +directory won't be loaded until we call the Load function to selectively load +them. However, maktaba will source the plugin/flags.vim file automatically if it +needs to resolve plugin flags. + + :call g:plugin.HasFlag('someflag') + ~ The flags file is sourced on first flag access if not already loaded. + +Now let's load the plugin settings before anything else: :call g:plugin.Load('settings') ~ Settings have been set. @@ -143,35 +150,31 @@ Let's examine those special flags in a bit more depth. There are two special flags in maktaba: 'plugin' and 'instant'. These correspond to the plugin/ and instant/ plugin directories. -If your plugin has these directories (as ours does) then it will have the -corresponding flags: +If your plugin has these directories then it will have the corresponding flags. +This plugin has a flag for its plugin/ directory but not instant/. - :echomsg g:plugin.HasFlag('plugin') && g:plugin.HasFlag('instant') + :echomsg g:plugin.HasFlag('plugin') && !g:plugin.HasFlag('instant') ~ 1 -However, if your plugin does not have these directories, it will not have these -flags: - - :let g:libpath = maktaba#path#Join([g:repo, 'library']) - :let g:library = maktaba#plugin#Install(g:libpath) - :echomsg g:library.HasFlag('instant') || g:library.HasFlag('plugin') - ~ 0 +You can use the 'plugin' flag to prevent certain parts of a plugin from loading. +This works great for files in the plugin/ directory. -As seen above, you can use the 'plugin' flag to prevent certain parts of -a plugin from loading. This works great for flags in the plugin/ directory. It's -quite a bit more difficult to disable files in the instant/ directory, as these -are sourced immediately when the plugin is installed: +You can also disable files in the instant/ directory using the corresponding +'instant' flag, but it's a little more difficult as these are sourced +immediately when the plugin is installed. To demonstrate, we will load a few test plugins. You may want to peruse the 'fakeplugins' directory to get an idea of what these plugins do. :let g:poisonpath = maktaba#path#Join([g:repo, 'poison']) - :call maktaba#plugin#Install(g:poisonpath) + :let g:poison = maktaba#plugin#Install(g:poisonpath) ~ You are dead. -It is, however, possible to prevent instant/ files from being loaded. To do so, -you must manually make maktaba setting objects that specify what you wish to -happen: + :echomsg g:poison.HasFlag('instant') && !g:poison.HasFlag('plugin') + ~ 1 + +It is possible to prevent instant/ files from being loaded. To do so, you must +manually make maktaba setting objects that specify what you wish to happen: :let g:settings = maktaba#setting#ParseAll('!instant[bomb]') @@ -180,5 +183,5 @@ and pass those settings to maktaba#plugin#Install: :let g:bombpath = maktaba#path#Join([g:repo, 'bomber']) :let g:bomber = maktaba#plugin#Install(g:bombpath, g:settings) -The exception is instant/flags.vim, which cannot be turned off no matter how -hard you try. +The exceptions are plugin/flags.vim and instant/flags.vim, which cannot be +turned off no matter how hard you try. diff --git a/vroom/pluginflags.vroom b/vroom/pluginflags.vroom index e0a7c1e..f6f6d7a 100644 --- a/vroom/pluginflags.vroom +++ b/vroom/pluginflags.vroom @@ -11,7 +11,7 @@ maktaba: Good. Now let's grab a plugin object: :let g:thisdir = fnamemodify($VROOMFILE, ':p:h') - :let g:path = maktaba#path#Join([g:thisdir, 'fakeplugins', 'fullplugin']) + :let g:path = maktaba#path#Join([g:thisdir, 'fakeplugins', 'myplugin']) :let g:plugin = maktaba#plugin#Install(g:path) There are two functions that you'll use to manipulate flags. The first, and the @@ -20,11 +20,10 @@ most self explanatory, is the HasFlag function. :call maktaba#ensure#IsFalse(g:plugin.HasFlag('undefined')) You'll remember from pluginfiles.vroom that plugins with instant/ and plugin/ -directories automatically get 'plugin' and 'instant' flags. Let's verify that -now: +directories automatically get 'plugin' and 'instant' flags. This one has a +plugin/ directory so it gets a 'plugin' flag automatically defined: :call maktaba#ensure#IsTrue(g:plugin.HasFlag('plugin')) - :call maktaba#ensure#IsTrue(g:plugin.HasFlag('instant')) This is all well and good, but what you really want to do is get and set flags. You do this using the Flag function. @@ -40,7 +39,8 @@ return the value of the flag: If you give it two parameters, it sets the flag (defining it if necessary), as seen above. -Note that you should only define new flags in an instant/flags.vim file. +Note that you should only define new flags in a plugin/flags.vim file (or legacy +instant/flags.vim file). @@ -67,6 +67,22 @@ maktaba#value#Focus, see value.vroom for more details. +So far, we've been setting flags after the plugin is already initialized, but +it's also possible to configure flags as part of plugin installation: + + :let g:path2 = maktaba#path#Join([g:thisdir, 'fakeplugins', 'fullplugin']) + :let g:settings = maktaba#setting#ParseAll('number+=2') + :let g:fullplugin = maktaba#plugin#Install(g:path2, g:settings) + + :echomsg g:fullplugin.Flag('number') + ~ 2 + +This approach configures the flag early in plugin setup, and is the only way to +ensure some special flags like instant[somefile] are configured before their +corresponding files are sourced. + + + Flag values are locked. You cannot change them. :call g:plugin.Flag('mylist', []) @@ -87,28 +103,34 @@ then commit the changes back with another call to Flag. The Flag function is usually sufficient for defining and manipulating flags. Sometimes, however, you need a little more power. In those cases, you can access -the flag objects directly: they live in the 'flags' dictionary on the plugin -object. +the flag objects directly: you can access them via the AllFlags method on the +plugin object. - :call maktaba#ensure#IsTrue(has_key(g:plugin, 'flags')) + :echomsg has_key(g:plugin.AllFlags(), 'mylist') + ~ 1 The objects in this dictionary are flag OBJECTS, not flag values. You can use them to get and set the flag. - :call g:plugin.flags.mylist.Set(['newlist']) - :echomsg string(g:plugin.flags.mylist.Get()) + :call g:plugin.AllFlags().mylist.Set(['newlist']) + :echomsg string(g:plugin.AllFlags().mylist.Get()) ~ ['newlist'] This allows you to use some advanced flag functionality, such as flag translators: :call g:plugin.Flag('invertme', 0) - :call g:plugin.flags['invertme'].AddTranslator('empty') + :call g:plugin.AllFlags().invertme.AddTranslator('empty') :call g:plugin.Flag('invertme', 1) :echomsg g:plugin.Flag('invertme') ~ 0 +You can also access these flags via the 'flags' dictionary on the plugin object: + + :echomsg has_key(g:plugin.flags, 'mylist') + ~ 1 + To learn about the full power of flag objects, see flags.vroom. @@ -118,7 +140,7 @@ need only interact with flags via the Flag function. Let's recap how flags are used on all the various levels: 1. All flags should be created and set to their default values in your plugin's -| instant/flags.vim file. +| plugin/flags.vim file. 2. Plugin code should access flags via the Flag function. In general, plugins | should not set their own flags: they should set defaults and leave them be. 3. Users change the values of flags, generally by interacting with commands