Commits

ZyX_I committed 1ae278d

Added new checks, added {sid} argument, added warn and throw functions, added plugin registration, moved feature loading code into loadplugin function

Comments (0)

Files changed (2)

 2.1. Functions                                              *frawor-functions*
 
                                                            *frawor-f-Register*
-FraworRegister(version, file, dependencies, oneload, g, F)  *FraworRegister()*
+                                                            *FraworRegister()*
+FraworRegister(version, sid, file, dependencies, oneload, g, F)
         Registers plugin sourced from {file} that has given {version} (see 
-        |frawor-t-version|).
+        |frawor-t-version|). If {oneload} is true, then plugin is considered 
+        loaded when it is registered. Arguments {g} and {F} must contain 
+        dictionaries with global and function variables.
 
 ------------------------------------------------------------------------------
 2.2. Commands                                                *frawor-commands*

plugin/frawor.vim

 endif
 "▶1 Variable initialization
 let s:F={}
+"▶2 s:g
 let s:g={}
 let s:g.pls={} " Plugin dictionaries
 let s:g.pltypes={}
                 \                'но была загружена %s',
                 \   'reqfailed': 'Не удалось загрузить зависимость %s '.
                 \                'дополнения %s',
+                \    'gnotdict': 'Ошибка регистрации %s: '.
+                \                'предпоследний аргумент FraworRegister '.
+                \                'не является словарём',
+                \    'Fnotdict': 'Ошибка регистрации %s: '.
+                \                'последний аргумент FraworRegister '.
+                \                'не является словарём (%s)',
+                \   'sidnotnum': 'Ошибка регистрации %s: второй аргумент '.
+                \                'FraworRegister не является числом',
+                \   'sidnonneg': 'Ошибка регистрации %s: второй аргумент '.
+                \                'FraworRegister должен быть '.
+                \                'либо положителен, либо '.
+                \                '(если первый аргумент равен нулю) нулём',
+                \  'nomessages': 'Глобальная переменная дополнения %s '.
+                \                'не содержит сообщений (_messages)',
+                \   'nomessage': 'Список сообщений дополнения %s '.
+                \                'не содержит сообщения %s',
             \}
 else
     let s:g._messages={
                 \  'oldversion': 'Detected too old dependency %s '.
                 \                'of a plugin %s: expected %s, but got %s',
                 \   'reqfailed': 'Failed to load dependency %s of a plugin %s',
+                \    'gnotdict': 'Error while registering %s: '.
+                \                'last but one argument to FraworRegister '.
+                \                'must be a Dictionary',
+                \    'Fnotdict': 'Error while registering %s: '.
+                \                'last argument to FraworRegister '.
+                \                'must be a Dictionary',
+                \   'sidnotnum': 'Error while registering %s: second argument '.
+                \                'to FraworRegister must be a number',
+                \   'sidnonneg': 'Error while registering %s: second argument '.
+                \                'to FraworRegister must either be positive '.
+                \                'or equal to 0 (if first argument '.
+                \                'is equal to 0 too)',
+                \  'nomessages': '%s global variable does not contain '.
+                \                '_messages',
+                \   'nomessage': '%s messages does not contain message id %s',
             \}
 endif
+"▶1 s:Eval
+function s:Eval(expr)
+    return eval(a:expr)
+endfunction
 "▶1 compareversions
 function s:F.compareversions(a, b)
     let len=max([len(a:a), len(a:b)])
     endif
 endfunction
 "▶1 newplugin
-function s:F.newplugin(version, file, dependencies, oneload, g, F)
+function s:F.newplugin(version, sid, file, dependencies, oneload, g, F)
     "▶2 plugtype, plid, plrtp, plversion
     if a:version is 0
         let plugtype='/anonymous'
         let plversion=[0, 0]
     "▶3 Verifying plugin version
     elseif type(a:version)!=type([])
-        call s:F._throw('vernotlist', plid)
+        call s:F._frawor.throw('vernotlist', plid)
     elseif len(a:version)<2
-        call s:F._throw('vershort', plid)
-    elseif !empty(filter(copy(a:version),'type(v:val)!='.type(0)).' || v:val<0')
-        call s:F._throw('vernotnum', plid)
+        call s:F._frawor.throw('vershort', plid)
+    elseif !empty(filter(copy(a:version),'type(v:val)!='.type(0).' || v:val<0'))
+        call s:F._frawor.throw('vernotnum', plid)
     "▲3
     else
         let [plugtype, plid, plrtp]=s:F.parseplugpath(a:file)
         let plversion=a:version
     endif
+    "▶2 Checking whether a:g and a:F are dictionaries and a:sid is number
+    if type(a:g)!=type({})
+        call s:F._frawor.throw('gnotdict', plid)
+    elseif type(a:F)!=type({})
+        call s:F._frawor.throw('Fnotdict', plid)
+    elseif type(a:sid)!=type(0)
+        call s:F._frawor.throw('sidnotnum', plid)
+    elseif !(a:sid>0 || (type(a:version)==type(0) && a:sid==0))
+        call s:F._frawor.throw('sidnonneg', plid)
+    endif
     "▶2 Checking for double registration
     if has_key(s:g.pls, plid)
         if s:g.pls[plid].runtimepath==#plrtp
-            call s:F._throw('doublereg', plid)
+            call s:F._frawor.throw('doublereg', plid)
         endif
         if plugtype[0]!=#'/'
-            call s:F._warn('plregistered', plid, plrtp)
+            call s:F._frawor.warn('plregistered', plid, plrtp)
         endif
         let plid.='/'
     endif
                 \ 'runtimepath': plrtp,
                 \     'version': plversion,
                 \        'file': a:file,
+                \         'sid': a:sid,
                 \'dependencies': {'plugin/frawor': 1},
-                \      'status': a:oneload ? 2 : 1,
+                \      'status': 1,
                 \    'features': {},
+                \           'F': a:F,
+                \           'g': a:g,
+                \   'intprefix': 's:g.pls['.
+                \                   substitute(string(plugdict.id),
+                \                              '\n', '''."\n".''', 'g').']',
             \}
+    let plugdict.F._frawor={}
     "▶3 Processing dependencies
     if type(a:dependencies)!=type({})
-        call s:F._throw('depnotdict', plid)
+        call s:F._frawor.throw('depnotdict', plid)
     endif
     let d={}
     for [dplid, d.Version] in items(a:dependencies)
         "▶4 Verifying dependency version
         if type(d.Version)!=type([])
-            call s:F._throw('d_vernotlist', dplid, plid)
+            call s:F._frawor.throw('d_vernotlist', dplid, plid)
         elseif empty(d.Version)
-            call s:F._throw('d_vershort', dplid, plid)
+            call s:F._frawor.throw('d_vershort', dplid, plid)
         elseif !empty(filter(copy(d.Version), 'type(v:val)!='.type(0)))
-            call s:F._throw('d_vernotnum', dplid, plid)
+            call s:F._frawor.throw('d_vernotnum', dplid, plid)
         endif
         "▲4
         let plugdict.dependencies[dplid]=d.Version
     endfor
+    lockvar! plugdict.dependencies
     "▶2 Adding plugdict to global variables
     if !has_key(s:g.pltypes, plugtype)
         let s:g.pltypes[plugtype]={plid : plugdict}
     endif
     let s:g.pls[plid]=plugdict
     "▶2 Locking plugdict
-    lockvar! plugdict
+    lockvar 1 plugdict
+    lockvar plugdict.version
     unlockvar plugdict.features
     unlockvar plugdict.status
-    "▶2 Populating features dictionary
-    for feature in values(s:g.features.index)
-        if has_key(feature, 'register')
-            let d.Result=feature.register(plugdict)
-            let plugdict.features[feature.id]=((d.Result is 0)?({}):(d.Result))
-        else
-            let plugdict.features[feature.id]={}
-        endif
-        "▶3 Locking features dictionary
-        try
-            lockvar! plugdict.features[feature.id]
-        catch /^Vim(lockvar):E743:/
-            " Ignore «variable nested too deep for (un)lock» error
-        endtry
-        "▲3
-    endfor
-endfunction
-"▶1 FraworRegister
-function FraworRegister(...)
-    return call(s:F.newplugin, a:000, {})
+    "▶2 Constructing returned dictionary
+    let r={
+                \       'type': plugdict.type,
+                \         'id': plugdict.id,
+                \'runtimepath': plugdict.runtimepath,
+            \}
+    if a:oneload
+        call s:F.loadplugin(plid)
+    endif
+    return r
 endfunction
 "▶1 loadplugin
 function s:F.loadplugin(plid)
                 let dversion=s:g.pls[dplid].version
                 "▶3 Checking dependency version
                 if d.Version[0]!=dversion[0]
-                    call s:F._throw('majmismatch', dplid, a:plid, d.Version[0],
-                                \                                 dversion[0])
+                    call s:F._frawor.throw('majmismatch', dplid, a:plid,
+                                \                         d.Version[0],
+                                \                         dversion[0])
                 elseif s:F.compareversions(d.Version, dversion)<0
-                    call s:F._throw('oldversion', dplid, a:plid,
-                                \   join(d.Version[0], '.'),
-                                \   join(dversion, '.'))
+                    call s:F._frawor.throw('oldversion', dplid, a:plid,
+                                \                        join(d.Version[0],'.'),
+                                \                        join(dversion,    '.'))
                 endif
                 "▲3
             else
-                call s:F._throw('reqfailed', dplid, a:plid)
+                call s:F._frawor.throw('reqfailed', dplid, a:plid)
             endif
         endfor
+        "▶2 Calling features
+        for feature in values(s:g.features.index)
+            "▶3 Forbid features that are not plugin dependencies
+            if !has_key(plugdict.dependencies, feature.plid)
+                continue
+            endif
+            "▶3 Feature provides constructed function
+            if has_key(feature, 'cons')
+                execute  'function plugdict.F._frawor.'.feature."(...)\n".
+                        \'    return call(s:g.features.index.'.feature.'.cons,'.
+                        \                '['.plugdict.intprefix."]+a:000,{})\n".
+                        \'endfunction'
+            endif
+            "▶3 Feature registration
+            if has_key(feature, 'load')
+                let d.Result=feature.load(plugdict)
+                let plugdict.features[feature.id]=
+                            \((d.Result is 0)?({}):(d.Result))
+            elseif has_key(feature, 'init')
+                let plugdict.features[feature.id]=deepcopy(feature.init)
+            else
+                continue
+            endif
+            "▲3
+        endfor
+        lockvar 1 plugdict.features
         "▲2
         execute 'source '.fnameescape(plugdict.file)
+        let plugdict.status=2
+        lockvar! plugdict.status
     endif
     return 1
 endfunction
+"▶1 FraworRegister
+function FraworRegister(...)
+    return call(s:F.newplugin, a:000, {})
+endfunction
+"▶1 cons.warn
+let s:g.features.index.warn={
+            \'plid': 'plugin/frawor',
+        \}
+function s:g.features.index.warn.cons(plugdict, msgid, ...)
+    if !has_key(a:plugdict.g, '_messages')
+        call s:F._frawor.throw('nomessages', a:plugdict.id)
+    elseif !has_key(a:plugdict.g._messages, a:msgid)
+        call s:F._frawor.throw('nomessage', a:plugdict.id, a:msgid)
+    endif
+    let message=a:plugdict.g._messages[a:msgid]
+    if a:0
+        let message=call('printf', [message]+a:000)
+    endif
+    let message='Frawor:'.a:plugdict.id.':'.message
+    echohl ErrorMsg
+    echomsg message
+    echohl None
+    return 0
+endfunction
+"▶1 cons.throw
+let s:g.features.index.throw={
+            \'plid': 'plugin/frawor',
+        \}
+function s:g.features.index.throw.cons(plugdict, msgid, ...)
+    call call(s:g.features.cons.warn, [a:plugdict, a:msgid]+a:000, {})
+    let throwmsg='Frawor:'.a:plugdict.id.':'.a:msgid
+    throw throwmsg
+endfunction
+"▶1 Plugin registration
+call s:F.newplugin([0, 0], s:Eval('+matchstr(expand("<sfile>"), ''\d\+'')'),
+            \      expand('<sfile>:p'), {}, 1, s:g, s:F)
 
 " vim: fmr=▶,▲ sw=4 ts=4 sts=4 et tw=80