Commits

ZyX_I committed b6bcc4e

@/commands: Made register, bang, count and range appear in function arguments

@/checks: Made it able to pass gdict to FWC
@/options: Made it pass gdict to conschecker/consfilter

Comments (0)

Files changed (8)

 will be used to get full version of the prefix. Default matcher is 
 |FWC-m-start| with ambigious prefixes forbidden.
        {prefixes} :: "{" ("~" {matcher})? ( {prefdescr} {prefargs} )* "}"
-      {prefdescr} :: {prefopts}? {prefdefault}? ( {str} | {wordchar}+ )
+      {prefdescr} :: {prefopts}? ( {str} | {wordchar}+ ) {prefdefault}?
        {prefopts} :: ( "?" | "!" | "*" | "+" {argnum} )*
     {prefdefault} :: ":" {var}
          {argnum} :: {wordchar}+
 ------------------------------------------------------------------------------
 3.6. plugin/frawor/checks features                    *frawor-f-frawor/checks*
 
-conschecker : function ({checker})                      *frawor-f-conschecker*
+conschecker : function ({checker}[, {gdict}])           *frawor-f-conschecker*
         Creates a checker function. Constructed function takes exactly one 
         argument: |List| containing checked arguments. For {checker} 
-        description see |frawor-t-checker| >
+        description see |frawor-t-checker|. {gdict} is only used for creating 
+        checker with |frawor-f-fwc.compile| >
             let s:F.checker=s:_f.conschecker(s:F.checker)
             <...>
             " Check value contained in args variable
                 " check failed
             endif
 <
-consfilter : function ({filter})                         *frawor-f-consfilter*
+consfilter : function ({filter}[, {gdict}])              *frawor-f-consfilter*
         Like |frawor-f-conschecker|, but for filters, see |frawor-t-filter|.
 
 ------------------------------------------------------------------------------
                   Ignored if `rsplitfunc' key is present and is not 0.
         range     0, 1, "%" or Number written as string. Defines default 
                   range, see |:command-range|. 1 means `add -range without 
-                  argument'. Default: 0.
+                  argument'. Default: 0. Adds <line1> and <line2> to argument 
+                  list.
         count     0, 1 or Number written as string. Just the same as range, 
-                  but for |:command-count|. Default: 0.
-        bang, bar, register
-                  0 or 1. See |:command-bang|, |:command-bar| and 
-                  |:command-register|. Default: 1 for `bar', 0 for others.
-        buffer    0 or 1. See |:command-buffer|. Default: 0.
+                  but for |:command-count|. Default: 0. Adds <count> to 
+                  argument list.
+        bang      0 or 1, see |:command-bang|. Default: 0. Adds <bang>0  to 
+                  argument list.
+        bar       0 or 1, see |:command-bar|. Default: 1.
+        register  0 or 1, see |:command-register|. Default: 0. Adds <q-reg> to 
+                  argument list.
+        buffer    0 or 1, see |:command-buffer|. Default: 0.
         complete  Defines completion for the command. Possible values:
                   1. String, see |:command-complete|.
                   2. Function reference. Anonymous and script-local functions 
                   is for running. Latter is valid only if {cstr} is not 
                   a string. Use 0 to keep default behavior.
 
+        Order of additional arguments if any (only applicable if {cstr} is 
+        a dictionary or a function reference):
+            <bang>0, <count>, <line1>, <line2>, <q-reg>
+
 command.del : function( [ cid ] )                       *frawor-f-command.del*
         Delete command named {cid} if it was defined by this plugin. If no 
         {cid} was specified, deletes all commands defined by caller.
                     values. It is processed before `filter' if both are 
                     present. Checker must accept a list with a singe item: 
                     option being checked.
-                    Note that this key is passed to |frawor-f-addchecker| only 
-                    once for each option, then returned value is saved and 
-                    reused.
+                    Note that this key is passed to |frawor-f-conschecker| 
+                    only once for each option, then returned value is saved 
+                    and reused.
                                                             *frawor-od-filter*
         filter      Filter for an option, see |frawor-t-filter|. Will be used 
                     only for options from enviroment, not for default values. 
                     Filter must accept a list with a singe item: option being 
                     filtered, and on success return a list with a single item: 
                     filter results.
-                    Note that this key is passed to |frawor-f-addfilter| only 
+                    Note that this key is passed to |frawor-f-consfilter| only 
                     once for each option, then returned value is saved and 
                     reused.
                     Note 2: if filter key is present, option will be deep 

plugin/frawor/checks.vim

     call map(a:fdict.FWCids, 's:_f.fwc.del(v:val)')
 endfunction
 "▶1 conschecker feature
-"▶2 conschecker  :: {f}, checker → chkfunc + ?
-function s:F.conschecker(plugdict, fdict, Chk)
+"▶2 conschecker  :: {f}, checker[, gdict] → chkfunc + ?
+function s:F.conschecker(plugdict, fdict, Chk, ...)
     if type(a:Chk)==2
         if !exists('*a:Chk')
             call s:_f.throw('chkncall', a:plugdict.id)
         return a:Chk
     elseif type(a:Chk)==type('')
         let d={}
-        let [d.F, id]=s:_f.fwc.compile(a:Chk, 'check', a:plugdict.g)
+        let [d.F, id]=s:_f.fwc.compile(a:Chk, 'check',
+                    \                  get(a:000, 0, a:plugdict.g))
         call add(a:fdict.FWCids, id)
         return d.F
     else
             \                      'unload': s:F.freeres,
             \                        'init': {'FWCids': []}})
 "▶1 consfilter feature
-"▶2 consfilter  :: {f}, filter → filfunc + ?
-function s:F.consfilter(plugdict, fdict, Fil)
+"▶2 consfilter  :: {f}, filter[, gdict] → filfunc + ?
+function s:F.consfilter(plugdict, fdict, Fil, ...)
     if type(a:Fil)==2
         if !exists('*a:Fil')
             call s:_f.throw('filncall', a:plugdict.id)
         return a:Fil
     elseif type(a:Fil)==type('')
         let d={}
-        let [d.F, id]=s:_f.fwc.compile(a:Fil, 'filter', a:plugdict.g)
+        let [d.F, id]=s:_f.fwc.compile(a:Fil, 'filter',
+                    \                  get(a:000, 0, a:plugdict.g))
         call add(a:fdict.FWCids, id)
         return d.F
     else

plugin/frawor/commands.vim

                 \   'cidedef': 'команда уже определена',
                 \ 'coptsndct': 'второй аргумент не является словарём',
                 \  'invrange': '«%s» не является правильным диапозоном',
+                \  'hascount': 'нельзя использовать «range» и «count» вместе',
                 \  'invcount': '«%s» не является числом',
                 \    'invkey': 'ключ %s не принимает никаких аргументов',
                 \  'invnargs': '%s не является правильным описанием числа '.
                 \   'cidedef': 'command was already defined',
                 \ 'coptsndct': 'second argument is not a Dictionary',
                 \  'invrange': '`%s'' is not a valid range',
+                \  'hascount': 'cannot use both `range'' and `count'' '.
+                \              'for one command',
                 \  'invcount': '`%s'' is not a valid count',
                 \    'invkey': 'key %s does not accept any arguments',
                 \  'invnargs': '%s is not a valid parameter number description',
                 \  'fs': {},
                 \}
     let cmdstring=''
+    let addargs=[]
     "▶3 Process *splitfunc
     let cmd.sp=s:F.getspfunc(a:plugdict.id, a:cid, a:copts, '')
     let cmd.rsp=s:F.getspfunc(a:plugdict.id, a:cid, a:copts, 'r')
     "▶3 Create :command -options
-    for [key, value] in items(s:cmddefaults)
+    for [key, value] in sort(items(s:cmddefaults))
         if has_key(a:copts, key)
             "▶4 Completion
             if key is# 'complete'
             "▶4 Other options
             else
                 " TODO: Make unoverridable buffer=1 for filetype plugins
-                if key is# 'range' && index([0, 1, '%'], a:copts[key])==-1
-                    call s:_f.throw('invrange', a:cid, a:plugdict.id,
-                                \               string(a:copts[key]))
-                elseif key is# 'count' &&
-                            \!(a:copts[key] is 0 || a:copts[key] is 1 ||
-                            \  (type(a:copts[key])==type('') &&
-                            \   a:copts[key]=~#'^\d\+$'))
-                    call s:_f.throw('invcount', a:cid, a:plugdict.id,
-                                \   string(a:copts[key]))
+                unlet value
+                let value=a:copts[key]
+                if key is# 'range'
+                    if index([0, 1, '%'], value)==-1
+                        call s:_f.throw('invrange', a:cid, a:plugdict.id,
+                                    \               string(value))
+                    elseif has_key(a:copts, 'count')
+                        call s:_f.throw('hascount', a:cid, a:plugdict.id)
+                    elseif value isnot 0
+                        let addargs+=['<line1>', '<line2>']
+                    endif
+                elseif key is# 'count'
+                    if  !(value is 0 || value is 1 ||
+                            \(type(value)==type('') && value=~#'^\d\+$'))
+                        call s:_f.throw('invcount', a:cid, a:plugdict.id,
+                                    \               string(value))
+                    elseif value isnot 0
+                        let addargs+=['<count>']
+                    endif
                 elseif (key is# 'bang' || key is# 'bar' || key is# 'register' ||
-                            \key is# 'buffer') && !(a:copts[key] is 0 ||
-                            \                       a:copts[key] is 1)
-                    call s:_f.throw('invkey', a:cid, a:plugdict.id, key)
+                            \key is# 'buffer')
+                    if !(value is 0 || value is 1)
+                        call s:_f.throw('invkey', a:cid, a:plugdict.id, key)
+                    elseif key is# 'bang' && value
+                        let addargs+=['<bang>0']
+                    elseif key is# 'register' && value
+                        let addargs+=['<q-reg>']
+                    endif
                 elseif key is# 'nargs' && index(['0', '1', '*', '?', '+'],
-                            \                   a:copts[key])==-1
+                            \                   value)==-1
                     call s:_f.throw('invnargs', a:cid, a:plugdict.id,
-                                \               string(a:copts[key]))
+                                \               string(value))
                 endif
-                let value=a:copts[key]
             endif
             "▲4
         endif
         else
             call s:_f.throw('urepl', a:cid, a:plugdict.id)
         endif
+        let args=''
+        if !empty(addargs)
+            let args='['.join(addargs, ', ').']+'
+        endif
         if cmd.rsp is 0
-            let args='[<f-args>]'
+            let args.='[<f-args>]'
         elseif type(cmd.rsp)==type('')
-            let args='s:F.cmdsplit(<q-args>, s:commands.'.a:cid.'.rsp)'
+            let args.='s:F.cmdsplit(<q-args>, s:commands.'.a:cid.'.rsp)'
         else
-            let args='s:commands.'.a:cid.'.rsp(<q-args>)'
+            let args.='s:commands.'.a:cid.'.rsp(<q-args>)'
         endif
         if type(a:cstr)==type({})
             let cmd.cmdstring=cmdstring.

plugin/frawor/options.vim

         "▶3 `checker' and `filter' keys
         for key in ["checker", "filter"]
             if has_key(option, key)
-                let oshadow[key]=s:_f['cons'.key](option[key])
+                let oshadow[key]=s:_f['cons'.key](option[key], a:plugdict.g)
             endif
         endfor
         "▲3

test/commands-addargs.in

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

test/commands-addargs.ok

+['-def']
+[0, '-ghi']
+[0, '-jkl']
+[1, 1, '-mno']
+['-', 'pqr']
+[0, 0, '-', 'stu']
+[1, 0, 's', 'tu']

test/rtp/plugin/commands-addargs.vim

+execute frawor#Setup('0.0', {'@/commands': '0.0'}, 1)
+
+function PrintArgs(...)
+    call WriteFile(string(a:000))
+endfunction
+
+call s:_f.command.add('Abc', function('PrintArgs'), {'nargs': '1'})
+Abc-def
+
+call s:_f.command.add('Def', function('PrintArgs'), {'nargs': '1', 'bang': 1})
+Def-ghi
+
+call s:_f.command.add('Ghi', function('PrintArgs'), {'nargs': '1', 'count': 1})
+Ghi-jkl
+
+call s:_f.command.add('Jkl', function('PrintArgs'), {'nargs': '1', 'range': 1})
+Jkl-mno
+
+call s:_f.command.add('Mno', function('PrintArgs'), {'nargs': '1', 'register': 1})
+Mno-pqr
+
+call s:_f.command.add('Pqr', function('PrintArgs'), {'nargs': '1', 'register': 1,
+            \                                        'bang': 1,    'count': 1})
+Pqr-stu
+Pqr!stu
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.