I want to write a command, this command would have this format:
[range]MyCMD[!] [count] [oneArg] [flags]
or
[range]MyCMD[!] [oneArg] [count] [flags]
similiar to
:[range]P[rint] [count] [flags]
or
:[range]d[elete] [x] {count}
The command MyCMD
eventually will call a function to do some work. I wrote this line (won't work)
command! -nargs=+ -range -bang -count=0 MyCMD <line1>,<line2>call MyFUNC(<q-args>, "<bang>","<count>", .... ..)
Here the problem is, how to handle those arguments:
problem 1 I read about the help, -range
and -count
cannot not be used at same time, but I need them both. I also took a look some vim commands, like :delete, :print, when we use those commands, we could give both range
and count
. Also I found that vim doc has two entries of same command if a {count}
or [count]
is available. like:
:[range]d[elete] [x]
:[range]d[elete] [x] {count}
or
:[range]p[rint] [flags]
:[range]p[rint] {count} [flags]
why is that? why not just with [count]
? (this would be another small question)
problem 2 from my design, all those arguments are optional, they have default values(see the table below). How can I pass those arguments to function (I checked <q-args> and <f-args>
) and how can I distinguish which user-inputs are for which argument? for example user gives
:MyCMD 5 g
here is the default values for args:
argName | Default value | description
-------------------------------------
range | current line | this could be get by function xxx ( ) range
count | 0 | this could be get by <count>
bang | "" | this is easy too, with <bang>
arg | " " | this argument could have space
flags | "" | no space allowed for flags
-------------------------------------
thanks.
For your complex custom command, you cannot rely solely on Vim's limited parsing options; you can have it handle the range with -range
, but have to parse your combination of arguments yourself.
:command! -nargs=* -range -bang MyCMD <line1>,<line2>call MyFUNC(<bang>0, <q-args>)
Inside MyFUNC
(which should probably be defined with :function MyFUNC( ... ) range
to be invoked only once), split()
the arguments on whitespace. Alternatively, you could define the function to use a variable number of arguments and use <f-args>
, but note that the number of function arguments is limited (to 20 IIRC).
The <bang>0
is a nice trick to transform the bang into a boolean, which is usually what you need.
Have to ask tough questions. I don't really have any solutions but here are my findings.
:command! -range -bang -nargs=* MY echo [<bang>0, <line1>, <line2>, <count>, <q-args>]
After running the following scenarios:
:MY
[0, 3, 3, -1, '']
:MY!
[1, 3, 3, -1, '']
:%MY
[0, 1, 10, 10, '']
:%MY 4
[0, 1, 10, 10, '4']
:MY 4
[0, 3, 3, -1, '4']
:%MY flag
[0, 1, 10, 10, 'flag']
:MY flag
[0, 3, 3, -1, 'flag']
:%MY 4 flag
[0, 1, 10, 10, '4 flag']
Now with -count
instead of -range
:command! -count -bang -nargs=* MY echo [<bang>0, <line1>, <line2>, <count>, <q-args>]
Results:
:MY
[0, 3, 1, 0, '']
:MY!
[1, 3, 1, 0, '']
:%MY
[0, 1, 10, 10, '']
:%MY 4
[0, 1, 4, 4, '']
:MY 4
[0, 3, 4, 4, '']
:%MY flag
[0, 1, 10, 10, 'flag']
:MY flag
[0, 3, 1, 0, 'flag']
:%MY 4 flag
[0, 1, 4, 4, 'flag']
As you can see it doesn't easy. My suggestion would be to use -range
with your command. And then parse the <q-args>
looking for a number via \d\+
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With