Commits

ZyX_I committed b9cab52

@/functions: Added functions autoloading support. Untested
Autoloading is done from separate files now. It is superior to
plain old vim autoload#functions only because it allows to hide
used functions from global scope and adds autoloaded plugins as
a dependency to plugin that requested a function.

Comments (0)

Files changed (2)

autoload/frawor/functions.vim

 "▶1 Header
 scriptencoding utf-8
-execute frawor#Setup('0.0', {'@/decorators': '0.0',
+execute frawor#Setup('0.1', {'@/decorators': '0.0',
             \              '@/autocommands': '0.0',})
 "▶1 _messages
 if v:lang=~?'ru'
                 \        'fdef': 'функция уже определена',
                 \      'nofunc': 'описание функции не содержит '.
                 \                'ключа «function»',
-                \        'nref': 'ключ «%s» не является ссылкой на функцию',
+                \        'nref': 'ключ «%s» не является ссылкой на функцию '.
+                \                'или списком',
+                \       'n3len': 'ключ «function» должен иметь ровно три '.
+                \                'элемента',
+                \      '02nstr': 'один из элементов «function» '.
+                \                'не является строкой',
+                \       '1nver': 'второй элемент «function» должен быть '.
+                \                'списком неотрицательных целых чисел',
                 \   'invdecret': 'декоратор %s вернул неверное значение',
                 \     'decndep': 'дополнение, определившее декоратор %s, '.
                 \                'не находится в списке зависимостей',
                 \        'fdef': 'function was already defined',
                 \      'nofunc': 'function description lacks '.
                 \                '`function'' key',
-                \        'nref': 'key `%s'' is not a function reference',
+                \        'nref': 'key `%s'' is not a function reference '.
+                \                'or a list',
+                \       'n3len': 'function key must have exactly two items',
+                \      '02nstr': 'one of the items in function key '.
+                \                'is not a string',
+                \       '1nver': 'second element of `function'' key must be '.
+                \                'a list of non-negative integers',
+                \       'nodep': 'plugin %s must depend on @/functions',
+                \       'nodep': 'no function %s in s:_aufunctions of %s',
                 \   'invdecret': 'decorator %s returned invalid value',
                 \     'decndep': 'plugin that defined decorator %s '.
                 \                'is not in dependency list',
     endif
     return fstr
 endfunction
-"▶1 refunction      :: sid, Funcref, throwargs → Funcref
-function s:F.refunction(sid, Fref, ...)
+"▶1 refref          :: sid, Funcref → Funcref
+function s:F.refref(sid, Fref)
     let fstr=s:F.rewritefname(a:sid, a:Fref)
     if string(+fstr) is# fstr
         return a:Fref
     else
         if !exists('*'.fstr)
+            call s:_f.throw('uref', a:plugdict.id, 'function', a:fname)
             call call(s:_f.throw, a:000, {})
         endif
         return function(fstr)
     endif
 endfunction
+"▶1 fundef          :: plugdict, funopts, fundef, fname → Funcref
+function s:F.fundef(plugdict, funopts, fundef, fname)
+    let fundefext=copy(a:funopts)
+    if type(a:funopts.function)==type([])
+        if len(a:funopts.function)!=3
+            call s:_f.throw('n3len', a:fname, a:plugdict.id)
+        elseif          type(a:funopts.function[0])!=type('')
+                    \|| type(a:funopts.function[2])!=type('')
+            call s:_f.throw('02nstr', a:fname, a:plugdict.id)
+        elseif          type(a:funopts.function[1])!=type([])
+                    \|| !empty(filter(copy(a:funopts.function[1]),
+                    \                    'type(v:val)!='.type(0).
+                    \                 '|| v:val<0'))
+            call s:_f.throw('1nver', a:fname, a:plugdict.id)
+        endif
+        call a:plugdict.g._f.require(a:funopts.function[0],
+                    \                a:funopts.function[1], 1)
+        if !has_key(s:aufunctions, a:funopts.function[0])
+            call s:_f.throw('nodep', a:fname, a:plugdict.id,
+                        \   a:funopts.function[0])
+        elseif !has_key(s:aufunctions[a:funopts.function[0]].functions,
+                    \   a:funopts.function[2])
+            call s:_f.throw('nofun', a:fname, a:plugdict.id,
+                        \   a:funopts.function[2], a:funopts.function[0])
+        endif
+        call extend(fundefext, s:aufunctions[a:funopts.function[0]].functions)
+        let sid=s:aufunctions[a:funopts.function[0]].sid
+    else
+        let sid=a:plugdict.sid
+    endif
+    let fundefext.function=s:F.refref(sid, fundefext.function)
+    call extend(a:fundef, fundefext, 'keep')
+    return a:fundef
+endfunction
 "▶1 delfunction     :: sid, Funcref → + :delfunction
 function s:F.delfunction(sid, Fref)
     let fstr=s:F.rewritefname(a:sid, a:Fref)
     "▶2 Check a:funopts
     if !has_key(a:funopts, 'function')
         call s:_f.throw('nofunc', a:fname, a:plugdict.id)
-    elseif type(a:funopts.function)!=2
+    elseif type(a:funopts.function)!=2 && type(a:funopts.function)!=type([])
         call s:_f.throw('nref', a:fname, a:plugdict.id, 'function')
     endif
     "▲2
     let fdicts.nextid+=1
     let fdicts[fundef.id]=fundef
     "▶2 Add `function' key
-    let fundef.function=s:F.refunction(a:plugdict.sid, a:funopts.function,
-                \                      'uref', a:plugdict.id, 'function',
-                \                              a:fname)
+    let fundef=s:F.fundef(a:plugdict, a:funopts, fundef, a:fname)
     "▲2
     let decs=map(filter(keys(a:funopts), 'v:val[0] is# "@"'),
                 \'s:_r.getdecorator(v:val[1:])')
                         \['endfunction']
         endif
         "▲2
-        execute join(s:F.beatycode(func), "\n")
+        " execute join(s:F.beatycode(func), "\n")
+        execute join(func, "\n")
         if fname isnot# 'fundef.cons'
             let fundef.cons=function(fname)
         endif
             unlet s:{a:fdict.fundictsname}[fundef.id]
         endif
     endfor
+    if has_key(s:aufunctions, a:plugdict.id)
+        unlet s:aufunctions[a:plugdict.id]
+    endif
 endfunction
 "▶1 loadplugin      :: fdict → + fdict, …
 function s:F.loadplugin(plid, fdict)
     let a:fdict.fundicts[fundef.id]=fundef
     return fundef.cons
 endfunction
+let s:aufunctions={}
+function s:F.wrapfunc_register(plugdict, fdict)
+    if !has_key(a:plugdict.g, '_aufunctions') ||
+                \type(a:plugdict.g._aufunctions)!=type({})
+        let a:plugdict.g._aufunctions={}
+    endif
+    let s:aufunctions[a:plugdict.id]={'functions': a:plugdict.g._aufunctions,
+                \                     'sid': a:plugdict.sid}
+endfunction
 call s:_f.newfeature('wrapfunc', {'cons': s:F.wrapfunc_cons,
             \                   'unload': s:F.delfunctions,
+            \                 'register': s:F.wrapfunc_register,
             \                     'init': {'fundictsname': 'wrappedfuncs',
             \                                  'fundicts': {}}})
 "▶1
-call frawor#Lockvar(s:, 'extfunctions,wrappedfuncs,lastdid')
+call frawor#Lockvar(s:, 'extfunctions,wrappedfuncs,lastdid,aufunctions')
 " vim: fmr=▶,▲ sw=4 ts=4 sts=4 et tw=80
         plugin and create requested function.
                                                            *frawor-f-wrapfunc*
 wrapfunc : function ({funcdescr})
+         + load + s:_aufunctions
          + unload
         Creates a function out of given {funcdescr} (see 
         |frawor-t-funcdescr|). Is useful to wrap some function with 
         except `function' are optional):
         Key        Description ~
                                                           *frawor-fd-function*
-        function   Function reference. Determines function that will be 
-                   called.
+        function   Function reference or list. Determines function that will 
+                   be called. In case of function reference referenced 
+                   function will be called. List must have another syntax: 
+                   [{plid}, {version}, {key}], in this case when function is 
+                   created the following is done:
+                   1. {plid} is loaded using |frawor-f-require|. It must 
+                      depend on @/functions.
+                   2. Dictionary {key} from |s:_aufunctions| dictionary of 
+                      plugin with given {plid} is merged with the current 
+                      dictionary, overriding keys in the latter. Load event of 
+                      |frawor-f-wrapfunc| feature is responsible for this.
+                                                        *frawor-fd-thisplugin*
+        thisplugin If this key is present, then plugin dictionary is taken 
+                   from the plugin that defined it last. Useful for decorators 
+                   in case |frawor-fd-function| contains a list.
                                                           *frawor-fd-redefine*
         redefine   If this key is present, then it will try to redefine 
                    function if it exists, if it is not and function with given 
                                   script-local functions or their names. Is 
                                   used by |frawor-f-delfunctions| and set by 
                                   |frawor#Setup()|.
+*s:_aufunctions*   @/functions      Dictionary containing functions that are 
+                                  required by another plugins, see 
+                                  |frawor-f-wrapfunc| (feature using this 
+                                  dictionary) and |frawor-fd-function|.
 *s:_r*             @/resources      Dictionary containing resources posted by 
                                   plugins listed in dependencies. Is set by 
                                   |frawor-f-addresource|.
     0.1: Added folds |frawor-av-special|
 @/python:
     1.0: Removed _r.py resource, made it handle python and python3 separately.
+@/functions:
+    0.1: Added ability to have [{plid}, {version}, {key}] in 
+         |frawor-fd-function| and |frawor-fd-thisplugin|.
 
 vim: ft=help:tw=78
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.