Commits

ZyX_I committed 69be1a4

@/commands: Fixed empty argument completion
@/fwc/compiler: Fixed filter created by FWC decorator
@/fwc/parser, @/fwc/topconstructs: Removed some possible infinite loop conditions
@/fwc/topconstructs: Fixed default value population for multiple {optional} section (for example, in {actions} section)
@/fwc/topconstructs: Added check for presence of all required prefixes

Comments (0)

Files changed (8)

plugin/frawor/commands.vim

         let r.args=split(a:cmdline[(len(r.range)+len(r.command)):], d.split)
         let r.curargs=split(a:cmdline[(len(r.range)+len(r.command)):(a:curpos)],
                     \       d.split)
+        if empty(a:arglead)
+            call add(r.curargs, '')
+        endif
     else
         let r.args=d.split(a:cmdline[(len(r.range)+len(r.command)):])
         let r.curargs=d.split(a:cmdline[len(r.range)+len(r.command):(a:curpos)])
             unlet a:cmd.fs
         endif
     endif
-    unlet a:cmd.funs a:cmd.augs
 endfunction
 "▶2 runcmd       :: cmd → + ?
 function s:F.runcmd(cmd, args)

plugin/frawor/fwc/compiler.vim

             \     'isnot': 'expected %s, but got %s',
             \       'anf': '`%s'' is not a valid action',
             \       'pnf': '`%s'' is not a valid prefix',
+            \ 'noreqpref': 'some required prefixes are missing',
         \}, '"Error while processing check %s for %s: ".v:val'))
 let s:_messages._types=['number', 'string', 'function reference', 'list',
             \           'dictionary']
                 \'failcal': [],
                 \ 'lavars': {},
                 \'defvals': [],
+                \'optdepth': 0,
                 \'typechanged': 0,
                 \'onlyfirst': 0,
             \})
     let vars=s:F.createvars(a:plugdict.g)
     let a=['FWCfail', a:fname, a:plugdict.id]
     let [opts, lines]=s:F.compstr(vars, a:arg[0], a:arg[1], a)
-    if opts.only
-        call map(lines, 'substitute(v:val, "@@@", "@$@args", "g")')
-        call insert(lines, 'let @$@d={"args": @@@}')
+    let rearg=(opts.only || a:arg[1] is# 'filter')
+    if rearg
+        call map(lines, 'substitute(v:val, "@@@", "@$@d.args", "g")')
+        call insert(lines, 'let @$@d={"args": copy(@@@)}')
     elseif has_key(opts, 'requiresd')
         call insert(lines, 'let @$@d={}')
     endif
-    return [128, ((opts.only)?('@$@d.args'):('@@@')), vars, lines, [], 0]
+    return [128, ((rearg)?('@$@d.args'):('@@@')), vars, lines, [], 0]
 endfunction
 "▶1 Register decorator
 call s:_f.adddecorator('FWC', s:F.makedec)

plugin/frawor/fwc/parser.vim

         call self.ungetc(c)
     endif
     "▲2
-    while self.len
+    let prevlen=-1
+    while self.len && self.len!=prevlen
+        let prevlen=self.len
         let c=self.readc()
         if c is# '|'
             call self.scanfie('pipe')

plugin/frawor/fwc/topconstructs.vim

                                 \.try()
                                     \.pushms('throwignore')
                                     \.compadescr(opt, a:idx.'.'.i.'(optional)',
-                                    \            'check', 0)
+                                    \            'check', 1)
                                     \.popms()
                                     \.let(failstr, 0)
                                     \.let(a:caidxstr, self.getlastsub())
     let addedsavemsgs=a:addedsavemsgs
     " XXX nodefs will be still 1 when compiling next adescr. It is intentional.
     let nodefs=empty(self.defvals)
+    let self.optdepth+=1
     let lopt=len(a:adescr.optional)
     if lopt>1
         let failstr=self.getlvarid('fail')
             let i+=1
         endfor
     endif
+    let self.optdepth-=1
+    if self.optdepth==0 && !empty(self.defvals)
+        call remove(self.defvals, 0, -1)
+    endif
     return [[a:caidxstr], addedsavemsgs]
 endfunction
 "▶1 prefixes
             endwhile
             unlet pref prefopts
             call self.conclose()
+            let prevlen=-1
         endif
     endwhile
     return self.conclose()
     let nextsub=[a:caidxstr]
     let preflist=[]
     let plstr=self.getfunstatvar('prefixes', preflist)
+    let reqpreflist=[]
+    let rplstr=self.getfunstatvar('reqprefixes', reqpreflist)
     let prefdictstr=self.getlvarid('prefdict')
     let base=self.argstr(0, self.subs[:-2])
     let astr=self.getlvarid('arg')
         if prefopts.alt
             call s:F.addprefix(preflist, 'no'.prefix)
         endif
+        if !prefopts.opt
+            call add(reqpreflist, prefix)
+        endif
         "▶3 Remove default value specification if any
         let hasdefault=0
         if !empty(args) && args[0][0] isnot# 'arg'
         else
             call self.up()
         endif
+        if !empty(reqpreflist)
+            call self.nextthrow('!empty(filter(copy('.rplstr.'), '.
+                        \           '"!has_key('.prefdictstr.', v:val)"))',
+                        \       'noreqpref', a:idx)
+        endif
     else
         call self.up()
     endif
         else
             let hasaction=0
             if c is# '('
-                while self.len
+                let prevlen2=-1
+                while self.len && prevlen2!=self.len
+                    let prevlen2=self.len
                     let c=self.readc()
                     if c is# ')'
                         break
 plugin/frawor/fwc/compiler:nreg
 plugin/frawor/fwc/compiler:pnf
 plugin/frawor/fwc/compiler:pnf
+plugin/frawor/fwc/compiler:noreqpref
 ::: Section <Required, optional, actions, prefixes and next composition>
 plugin/frawor/fwc/compiler:tooshort
 <<< messages

test/fwccomplete.ok

 ::: Section <Different sections/{next}+{actions}>
 ::: Section <Different sections/{prefixes}+{next}>
 ::: Section <Different sections/{optional}+{next}>
+::: Section <Different sections/{optional}+{prefixes}>
 <<< messages

test/fwccompletetests.dat

 
   @abc+
   =s:list2
+#▶2 {optional}+{prefixes}
+`[in list] {!allfolds}
+  @+
+  =s:list+["allfolds", "noallfolds"]
+
+  @abc+
+  allfolds noallfolds
 # vim: cms=#%s fmr=▶,▲ sw=2 ts=2 sts=2 et

test/fwctests.dat

 ['{abc :=(2) -}',                 'filter'], [],          [{'abc': 2}]
 ['{abc :=(2) -}',                 'filter'], ['noa'],     0
 ['{?text - ?texthl -}',           'filter'], ['text'],    [{'text': 1}]
+['{abc bool ?def bool}',          'filter'], ['def', {}], 0
 ['{*b isreg !?a}', 'filter'], ['b', 'n', 'n'], [{'b': ['n'], 'a': 0}]
 ['{*b isreg !?a}', 'filter'], ['b', 'n', 'c'], [{'b': ['n', 'c']}]
 #▶1 Required, optional, actions, prefixes and next composition
 ['<a {abc isreg} b [isreg]>', 'filter'], ['b'],             ['b']
 ['<a {abc isreg} b [isreg]>', 'filter'], ['b', ''],         ['b', '']
 ['type "" [type -0] {ab isreg} + type [] <cd bool>', 'filter'], ['', 0, 'a', '-', [1], 'c', {}], ['', 0, {'ab': '-'}, [1], 'cd', 0]
+['<a ([:=(0) bool] {?!ab})>', 'filter'], ['a', 0], ['a', 0, {}]
+['<a ([:=(0) bool] {?!+1 ab isreg})>', 'filter'], ['a', 0], ['a', 0, {}]
+['<a ([:=(0) bool] {ab :=(-1) bool !+1 cd :=(-1) bool})>', 'filter'], ['a', 0], ['a', 0, {'cd': -1, 'ab': -1}]
+['<a ([:=(0) bool]) b ([:=(1) bool])>', 'filter'], ['b'], ['b', 1]
 # vim: cms=#%s fmr=▶,▲
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.