ZyX_I avatar ZyX_I committed a3b2878

@/commands: Fixed autoloading plugin if completion is called
@/functions: Fixed s:/<SID> rewriting

Comments (0)

Files changed (43)

                      unmodified.
         splitfunc, rsplitfunc
                   Defines function that will split command-line into a list of 
-                  arguments. `splitfunc' is for completion, `rsplitfunc' is 
-                  for running. Latter is valid only if {cstr} is not a string. 
-                  Use 0 to keep default behavior.
+                  arguments. `splitfunc' is for FWC completion, `rsplitfunc' 
+                  is for running. Latter is valid only if {cstr} is not 
+                  a string. Use 0 to keep default behavior.
 
 command.del : function( [ cid ] )                       *frawor-f-command.del*
         Delete command named {cid} if it was defined by this plugin. If no 

plugin/frawor/commands.vim

 "▶1 Header
 scriptencoding utf-8
-execute frawor#Setup('0.0', {'@/functions': '0.0',
-            \             '@/autocommands': '0.0',}, 1)
+execute frawor#Setup('0.0', {'@/autocommands': '0.0',
+            \                '@/fwc/compiler': '0.0',}, 1)
 "▶1 Define messages
 if v:lang=~?'ru'
     let s:_messages={
     endif
     if fstr[:1] is# 's:'
         let fstr='<SNR>'.a:sid.'_'.fstr[2:]
-    elseif fstr[:4] is# '<SID>'
+    elseif fstr[:4] ==? '<SID>'
         let fstr='<SNR>'.a:sid.'_'.fstr[5:]
     endif
     return fstr
 endfunction
+"▶1 wrapfunc     :: cmd, fname, fdict → + :function
+function s:F.wrapfunc(cmd, fname, fdict)
+    let a:cmd.f[a:fname[2:]]=call(a:cmd.wrapfunc, [a:fdict], {})
+    execute      "function ".a:fname."(...)\n"
+                \"    return call(s:commands.".a:cmd.id.".f.".a:fname[2:].", ".
+                \                "a:000, {})\n".
+                \"endfunction"
+endfunction
 "▶1 add_commands :: {f} → + p:_commands
 function s:F.add_commands(plugdict, fdict)
     if !has_key(a:plugdict.g, '_commands') ||
     endif
     if !empty(a:cmd.funs)
         call map(remove(a:cmd.funs, 0, -1),
-                    \'s:_f.addextfunctions({v:val[0]:v:val[1]})')
+                    \'s:F.wrapfunc(a:cmd, v:val[0], v:val[1])')
+        if empty(a:cmd.f)
+            unlet a:cmd.f
+        endif
     endif
+    unlet a:cmd.funs a:cmd.augs
 endfunction
 "▶2 runcmd       :: cmd → + ?
 function s:F.runcmd(cmd, args)
                 \'plid': a:plugdict.id,
                 \'augs': [],
                 \'funs': [],
+                \   'f': {},
                 \}
     let cmdstring=''
     "▶3 Process *splitfunc
                 let cmd.compfname='s:Complete'.cmd.id
                 "▶5 Use function
                 if tcomplete==2
-                    let fname=s:F.rewritefname(a:copts.complete)
+                    let fname=s:F.rewritefname(a:plugdict.sid, a:copts.complete)
                     if fname=~#'^\d'
                         let cmd.compfunc=d.complete
                         let intfname='s:commands.'.cmd.id.'.compfunc'
                 "▶5 Use function described by dictionary
                 elseif tcomplete==type({})
                     let fpattern='*'.(s:_sid).'_'.(cmd.compfname[2:])
+                    if !exists('*a:plugdict.g._f.wrapfunc')
+                        call s:_f.throw('nowrapfunc', a:cid, a:plugdict.id)
+                    endif
+                    let cmd.wrapfunc=a:plugdict.g._f.wrapfunc
                     if a:plugdict.status!=2
                         let augname=s:compaugprefix.(cmd.id)
                         call s:_f.augroup.add(augname,
-                                    \         ['FuncUndefined', fpattern, 0,
-                                    \          [s:F.loadplugin, cmd]])
+                                    \         [['FuncUndefined', fpattern, 0,
+                                    \           [s:F.loadplugin, cmd]]])
                         call add(cmd.augs, augname)
                         call add(cmd.funs, [cmd.compfname, d.complete])
                     else
-                        call s:_f.addextfunctions({cmd.compfname : d.complete})
+                        call s:F.wrapfunc(cmd, cmd.compfname, d.complete)
                     endif
                     let cmdstring.='-complete=customlist,'.(cmd.compfname).' '
                 "▶5 Use FWC string
                     let [cmd.compfunc, cmd.FWCid]=
                                 \call(s:_f.fwc.compile, compargs, {})
                     let intfname = 's:commands.'.cmd.id.'.compfunc'
-                    let args     = 's:commands.'.cmd.id.'.splitfunc(a:000)'
+                    let args     = '[call(s:F.splitfunc, '.
+                                \        'a:000'.
+                                \        ((cmd.sp is 0)?
+                                \           (', '):
+                                \           ('+[s:commands.'.cmd.id.'.sp], ')).
+                                \        '{}).curargs]'
                     execute      "function ".cmd.compfname."(...)\n".
                                 \"    return call(".intfname.",".args.",{})\n".
                                 \"endfunction"
         if has_key(a:fdict[cid], 'FWCid')
             call s:_f.fwc.del(a:fdict[cid].FWCid)
         endif
+        if has_key(a:fdict[cid], 'f')
+            for fname in keys(a:fdict[cid].f)
+                execute 'delfunction s:'.fname
+            endfor
+        endif
         unlet s:commands[cid]
         unlet a:fdict[cid]
         execute 'delcommand' cid

plugin/frawor/functions.vim

     endif
     if fstr[:1] is# 's:'
         let fstr='<SNR>'.a:sid.'_'.fstr[2:]
-    elseif fstr[:4] is# '<SID>'
+    elseif fstr[:4] ==? '<SID>'
         let fstr='<SNR>'.a:sid.'_'.fstr[5:]
     endif
     return fstr
             call s:_f.throw('foptsnotdict', fname, a:plugdict.id)
         endif
         "▶2 Replace s: prefix with <SNR>{SID}_
-        if fname[:1] is# 's:'
-            let fstr='<SNR>'.a:sid.'_'.fstr[2:]
-        endif
+        let fstr=s:F.rewritefname(a:plugdict.sid, fname)
         "▶2 Check function name
         if fname!~#'^\%(\h:\w\+\|[A-Z_]\w*\)$'
             call s:_f.throw('invfname', fname, a:plugdict.id)

test/commands-completion-twoload.in

+:let &rtp.=",".escape($TESTDIR, ',\').'/rtp'
+:let g:testfile="plugin/".g:curtest.".vim"
+:source test.vim
+:set wc=<Tab> wcm=<Tab>
+:Abc a	
+:call FraworUnload(g:testfile[:-5])
+:source test.vim
+:Abc b	

test/commands-completion-twoload.ok

+>>> messages
+First load
+Second load
+<<< messages
+aa
+>>> messages
+First load
+Second load
+<<< messages
+bb

test/commands-completion.in

+:let &rtp.=",".escape($TESTDIR, ',\').'/rtp'
+:let g:testfile="plugin/".g:curtest.".vim"
+:source test.vim
+:set wcm=<Tab> wc=<Tab>
+:W- complete: String
+:Abc g:te	
+:W- complete: Function: global
+:Def ab	
+:W- complete: Function: script
+:Ghi def	
+:W- complete: Function: anonymous
+:Jkl def	
+:W- complete: FWC: 1
+:Mno a	
+:W- complete: FWC: 2
+:Pqr d	

test/commands-completion.ok

+- complete: String
+g:testfile
+- complete: Function: global
+abab
+- complete: Function: script
+fed
+- complete: Function: anonymous
+deffed
+- complete: FWC: 1
+abc
+- complete: FWC: 2
+def

test/commands-twoload.in

+:let &rtp.=",".escape($TESTDIR, ',\').'/rtp'
+:let g:testfile="plugin/".g:curtest.".vim"
+:source test.vim
+:call FraworUnload(g:testfile[:-5])
+:source test.vim

test/commands-twoload.ok

+$ Abc
+$ Abc
+:let &rtp.=",".escape($TESTDIR, ',\').'/rtp'
+:let g:testfile="plugin/".g:curtest.".vim"
+:source test.vim
+:call FraworUnload(g:testfile[:-5])
+:source test.vim
+- String + no options
+$ Abc
+- nargs
+caught E471
+$ WF
+- range
+1
+4
+1
+1
+- count
+2
+2
+- bang
+bang: 0
+bang: 1
+- bar
+1 | Pqr 2
+3
+4
+- Fref + no options
+$ Abc
+- rsplitfunc: regex
+abc
+def
+ghi
+abc def
+- rsplitfunc: function
+abc
+def
+ghi
+abc def
+- rsplitfunc: 0
+abc:def:ghi
+abc
+def
+ghi
+- String + no options
+$ Abc
+- nargs
+caught E471
+$ WF
+- range
+1
+4
+1
+1
+- count
+2
+2
+- bang
+bang: 0
+bang: 1
+- bar
+1 | Pqr 2
+3
+4
+- Fref + no options
+$ Abc
+- rsplitfunc: regex
+abc
+def
+ghi
+abc def
+- rsplitfunc: function
+abc
+def
+ghi
+abc def
+- rsplitfunc: 0
+abc:def:ghi
+abc
+def
+ghi

test/invalid-commands.in

+:let &rtp.=",".escape($TESTDIR, ',\').'/rtp'
+:let i=1
+:while filereadable("rtp/plugin/".g:curtest.".".i.".vim") | let g:testfile="plugin/".g:curtest.".".i.".vim" | source test.vim | let i+=1 | endwhile

test/invalid-commands.ok

+.1: plugin/frawor/commands:cidnstr
+.2: plugin/frawor/commands:invcid
+.3: plugin/frawor/commands:cidedef
+.4: plugin/frawor/commands:urepl
+.5: plugin/frawor/commands:urepl
+.6: plugin/frawor/commands:invnargs
+.7: plugin/frawor/commands:invnargs
+.8: plugin/frawor/commands:invrange
+.9: plugin/frawor/commands:invcount
+.10: plugin/frawor/commands:invkey
+.11: plugin/frawor/commands:invkey
+.12: plugin/frawor/commands:invkey
+.13: plugin/frawor/commands:invkey
+.14: plugin/frawor/commands:ucomp
+.15: plugin/frawor/commands:invsp
+.16: plugin/frawor/commands:invsp
+.17: plugin/frawor/commands:nowncid
+.18: plugin/frawor/commands:nowncid
+.19: plugin/frawor/commands:dcidnstr
+.20: plugin/frawor/commands:ciddef
+.21: plugin/frawor/commands:coptsndct
+.22: plugin/frawor/commands:1nstr
+.23: plugin/frawor/commands:invclen
+.24: plugin/frawor/commands:invsreg
+.25: plugin/frawor/commands:invsreg

test/reload-frawor.ok

 load: plugin/writefile-feature
 unloadpre: autoload/frawor
 unloadpre: plugin/frawor/commands
+unloadpre: plugin/frawor/functions
 unloadpre: plugin/frawor/lua
 unloadpre: plugin/frawor/mappings
 unloadpre: plugin/frawor/perl
 unloadpre: plugin/frawor/ruby
 unloadpre: plugin/frawor/tcl
 unloadpre: plugin/ignoredeps-feature
-unloadpre: plugin/frawor/functions
 unloadpre: plugin/frawor/options
 unloadpre: plugin/writefile-feature
 unloadpre: plugin/frawor/autocommands
 unloadpre: plugin/frawor/decorators/altervars
 unloadpre: plugin/frawor/checks
 unloadpre: plugin/frawor/fwc/compiler
+unloadpre: plugin/frawor/decorators
 unloadpre: plugin/frawor/fwc/constructor
 unloadpre: plugin/frawor/fwc/parser
 unloadpre: plugin/frawor/fwc/intfuncs
 unloadpre: plugin/frawor/fwc/topconstructs
-unloadpre: plugin/frawor/decorators
 unloadpre: plugin/frawor/os
 unloadpre: plugin/frawor/resources
 unloadpre: plugin/frawor
 unload: autoload/frawor
 unload: plugin/frawor/commands
+unload: plugin/frawor/functions
 unload: plugin/frawor/lua
 unload: plugin/frawor/mappings
 unload: plugin/frawor/perl
 load: plugin/frawor/fwc/intfuncs
 register: plugin/frawor/fwc/topconstructs
 load: plugin/frawor/fwc/topconstructs
-register: plugin/frawor/functions
-load: plugin/frawor/functions
 register: plugin/frawor/fwc/compiler
 load: plugin/frawor/fwc/compiler
 register: plugin/writefile-feature
 load: plugin/frawor/mappings
 register: plugin/frawor/lua
 load: plugin/frawor/lua
+register: plugin/frawor/functions
+load: plugin/frawor/functions
 register: plugin/frawor/commands
 load: plugin/frawor/commands

test/rtp/plugin/commands-completion-twoload.vim

+if !exists('s:_pluginloaded')
+    execute frawor#Setup('0.0', {'@/commands': '0.0', '@/functions': '0.0'}, 0)
+    let s:rdict={}
+    call s:_f.command.add('Abc', 'call WriteFile(<q-args>)',
+                \         {'complete': s:rdict, 'nargs': '1'})
+    echom 'First load'
+    finish
+elseif s:_pluginloaded
+    echom 'Third load'
+    finish
+endif
+echom 'Second load'
+function s:rdict.function(a, c, p)
+    return [a:a.a:a]
+endfunction

test/rtp/plugin/commands-completion.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+
+call s:_f.command.add('Abc', 'call WriteFile(<q-args>)',
+            \         {'complete': 'var', 'nargs': '1'})
+
+function Complete(a, c, p)
+    return [a:a.a:a]
+endfunction
+call s:_f.command.add('Def', 'call WriteFile(<q-args>)',
+            \         {'complete': function('Complete'), 'nargs': '1'})
+
+function s:Complete(a, c, p)
+    return [join(reverse(split(a:a, '\v.@=')), '')]
+endfunction
+call s:_f.command.add('Ghi', 'call WriteFile(<q-args>)',
+            \         {'complete': function('s:Complete'), 'nargs': '1'})
+
+function s:F.complete(a, c, p)
+    return [a:a.join(reverse(split(a:a, '.\@=')), '')]
+endfunction
+call s:_f.command.add('Jkl', 'call WriteFile(<q-args>)',
+            \         {'complete': s:F.complete, 'nargs': '1'})
+
+let s:list=['abc']
+call s:_f.command.add('Mno', 'call WriteFile(<q-args>)',
+            \         {'complete': ['in list'], 'nargs': '1'})
+
+let s:list2=['def']
+call s:_f.command.add('Pqr', 'call WriteFile(<q-args>)',
+            \         {'complete': ['in list2', 'complete'], 'nargs': '1'})

test/rtp/plugin/commands-twoload.vim

+if !exists('s:_pluginloaded')
+    execute frawor#Setup('0.0', {'@/commands': '0.0', '@/functions': '0.0'}, 0)
+    let s:rdict={}
+    call s:_f.command.add('Abc', s:rdict, {})
+    Abc
+    finish
+elseif s:_pluginloaded
+    finish
+endif
+function s:rdict.function()
+    W$ Abc
+endfunction

test/rtp/plugin/commands.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+
+W- String + no options
+function Abc()
+    W$ Abc
+endfunction
+let s:_functions+=['Abc']
+call s:_f.command.add('Abc', 'call Abc()', {})
+Abc
+
+W- nargs
+call s:_f.command.add('WF', 'call WriteFile(<q-args>)', {'nargs': '+'})
+try
+    WF
+catch
+    call WriteFile('caught '.matchstr(v:exception, 'E\d\+'))
+endtry
+WF$ WF
+
+W- range
+call s:_f.command.add('Def', 'call WriteFile(<line1>, <line2>)', {'range': '%'})
+if line('$')==1
+    call append('.', ['', '', ''])
+endif
+Def
+.Def
+
+W- count
+call s:_f.command.add('Ghi', 'call WriteFile(<line1>, <line2>)',{'count': '20'})
+2Ghi
+
+W- bang
+call s:_f.command.add('Jkl', 'call WriteFile("bang: ".<bang>0)', {'bang': 1})
+Jkl
+Jkl!
+
+W- bar
+call s:_f.command.add('Mno', 'call WriteFile(<q-args>)', {'nargs': '1',
+            \                                             'bar': 0})
+call s:_f.command.add('Pqr', 'call WriteFile(<q-args>)', {'nargs': '1'})
+Mno 1 | Pqr 2
+Pqr 3 | Mno 4
+
+W- Fref + no options
+call s:_f.command.add('Stu', function('Abc'), {})
+Stu
+
+W- rsplitfunc: regex
+call s:_f.command.add('Vwx', function('WriteFile'), {'rsplitfunc': '-'})
+Vwx abc-def-ghi
+Vwx abc def
+
+W- rsplitfunc: function
+function Rsplit(cmdline)
+    return split(a:cmdline, ':')
+endfunction
+let s:_functions+=['Rsplit']
+call s:_f.command.add('Yz', function('WriteFile'),
+            \         {'rsplitfunc': function('Rsplit')})
+Yz abc:def:ghi
+Yz abc def
+
+W- rsplitfunc: 0
+call s:_f.command.add('Zy', function('WriteFile'), {'rsplitfunc': 0,
+            \                                       'nargs': '+'})
+Zy abc:def:ghi
+Zy abc def ghi

test/rtp/plugin/invalid-commands.1.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add(0, 'call Abc()', {})
+

test/rtp/plugin/invalid-commands.10.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Abc', 'call Abc()', {'bang': ''})
+

test/rtp/plugin/invalid-commands.11.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Abc', 'call Abc()', {'bar': ''})
+

test/rtp/plugin/invalid-commands.12.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Abc', 'call Abc()', {'register': ''})
+

test/rtp/plugin/invalid-commands.13.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Abc', 'call Abc()', {'buffer': ''})
+

test/rtp/plugin/invalid-commands.14.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Abc', 'call Abc()', {'complete': 1})
+

test/rtp/plugin/invalid-commands.15.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Abc', 'call Abc()', {'splitfunc': 1})
+

test/rtp/plugin/invalid-commands.16.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Abc', 'call Abc()', {'rsplitfunc': 1})
+

test/rtp/plugin/invalid-commands.17.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Abc', 'call Abc()', {})
+let s:g={}
+call FraworRegister(0, s:_sid, 'xxx', {'@/commands': [0]}, 1, s:g)
+call s:g._f.command.del('Abc')
+call s:_f.command.del('Abc')
+

test/rtp/plugin/invalid-commands.18.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.del('Abc')
+

test/rtp/plugin/invalid-commands.19.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.del(0)
+

test/rtp/plugin/invalid-commands.2.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('xxxinvalidusercommand', 'call Abc()', {})
+

test/rtp/plugin/invalid-commands.20.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Ghi', 'call Abc()', {})
+call s:_f.command.add('Ghi', 'call Abc()', {})
+

test/rtp/plugin/invalid-commands.21.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Def', 'call Abc()', 0)
+

test/rtp/plugin/invalid-commands.22.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Def', 'call Abc()', {'complete': [0]})
+

test/rtp/plugin/invalid-commands.23.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Def', 'call Abc()', {'complete': ['path','complete','']})
+

test/rtp/plugin/invalid-commands.24.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Def', 'call Abc()', {'splitfunc': '\v('})
+

test/rtp/plugin/invalid-commands.25.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Def', 'call Abc()', {'rsplitfunc': '\v('})
+

test/rtp/plugin/invalid-commands.3.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('W', 'call Abc()', {})
+

test/rtp/plugin/invalid-commands.4.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Abc', 0, {})
+

test/rtp/plugin/invalid-commands.5.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Abc', function('s:Eval'), {})
+

test/rtp/plugin/invalid-commands.6.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Abc', 'call Abc()', {'nargs': 1})
+

test/rtp/plugin/invalid-commands.7.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Abc', 'call Abc()', {'nargs': '0x10'})
+

test/rtp/plugin/invalid-commands.8.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Abc', 'call Abc()', {'range': []})
+

test/rtp/plugin/invalid-commands.9.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+call s:_f.command.add('Abc', 'call Abc()', {'count': ''})
+
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.