How to define parameter with arity 0 or 1 - jcommander

I'm using jcommander 1.72 to handle commands in a REPL (not directly from the command line). I have a parameter that can optionally take a value; if a value is provided, the value is set. If no value is provided, then the current value is printed. E.g.:
> myCmd --foo 5
set foo = 5
> myCmd --foo
current value of foo = 5
I tried this:
#Parameter(names = {"-f", "--foo"}, variableArity=true)
List<String> foo = new ArrayList<>()
But I get this error:
com.beust.jcommander.ParameterException: Expected a value after parameter --foo
at com.beust.jcommander.JCommander.processFixedArity(JCommander.java:886)
at com.beust.jcommander.JCommander.processVariableArity(JCommander.java:859)
at com.beust.jcommander.JCommander.parseValues(JCommander.java:705)
at com.beust.jcommander.JCommander.parse(JCommander.java:340)
at com.beust.jcommander.JCommander.parseValues(JCommander.java:787)
at com.beust.jcommander.JCommander.parse(JCommander.java:340)
at com.beust.jcommander.JCommander.parse(JCommander.java:319)
...
How can I accomplish this in jcommander?

Related

Generate variable name with string and value in Lua

Is there a function in Lua to generate a variable name with a string and a value?
For example, I have the first (string) part "vari" and the second (value) part, which can vary. So I want to generate "vari1", "vari2", "vari3" and so on. Something like this:
"vari"..value = 42 should then be vari1 = 42.
Thanks
Yes, but it most likely is a bad idea (and this very much seems to be an XY-problem to me). If you need an enumerated "list" of variables, just use a table:
local var = { 42, 100, 30 }
var[4] = 33 -- add a fourth variable
print(var[1]) -- prints 42
if you really need to set a bunch of variables though (perhaps to adhere to some odd API?), I'd recommend using ("..."):format(...) to ensure that your variables will be formatted as var<int> rather than var1.0, var1e3 or the like.
Th environment in Lua - both the global environment _G and the environment of your script _ENV (in Lua 5.2), which usually is the global environment, are just tables in the end, so you can write to them and read from them the same way you'd write to and read from tables:
for value = 1, 3 do
_ENV[("vari%d"):format(value)] = value^2
end
print(var3) -- prints 3*3 = 9
-- verbose ways of accessing var3:
print(_ENV.var3) -- still 9
print(_ENV["var"]) -- 9 as well
Note that this is most likely just pollution of your script environment (likely global pollution) which is considered a bad practice (and often bad for performance). Please outline your actual problem and consider using the list approach.
Yes. Call:
rawset(table, key, value)
Example:
rawset(_G, 'foo', 'bar')
print(foo)
-- Output: bar
-- Lets loop it and rawget() it too
-- rawset() returns table _G here to rawget()
-- rawset() is executed before rawget() in this case
for i = 1, 10 do
print(rawget(rawset(_G, 'var' .. i, i), 'var' .. i))
end
-- Output: 10 lines - First the number 1 and last the number 10
See: https://lua.org/manual/5.1/manual.html#pdf-rawset
Putting all together and create an own function...
function create_vars(var, start, stop)
for i = start, stop do
print(var .. i, '=>', rawget(rawset(_G, var .. i, i), var .. i))
end
end
And use it...
> create_vars('var', 42, 42)
var42 => 42
> print(var42)
42

Can I introspect a variable to directly discover what subset it was declared with?

Is there a way to introspect a variable to directly find out what subset it was declared with? Here I create a subset, but introspection points me to its base type:
> subset Prime of Int where .is-prime
(Prime)
> my Prime $x = 23
23
> $x.WHICH
Int|23
I know it has to store the information somewhere, because if I try to reassign a value that doesn't match the subset, it fails:
> $x = 24
Type check failed in assignment to $x; expected Prime but got Int (24)
in block <unit> at <unknown file> line 1
I tried searching through the code, but I quickly get down into files like container.c and perl6_ops.c where the C code makes my eyes glaze over. I thought that X::TypeCheck::Assignment might help (see core/Exception.pm), but it's not clear to me where the expected value comes from. (see also this commit)
I feel like I'm missing something obvious.
I can check that something matches a subset, but that doesn't tell me if it were declared with a particular subset:
> my Int $y = 43;
43
> $y ~~ Prime;
True
I'm using Rakudo Star 2017.01
Inspired by a Zoffix's use of subsets in a recent post.
The value that you stored in $x is an Int. It is acceptable to the container (which you typed to Prime) because Prime is a subtype of Int.
So what you're interested in, is not the value in the container, but the type of the container. To get at the container, Perl 6 has the .VAR method. And that has an .of method to get at the type:
$ 6 'subset Prime of Int where .is-prime; my Prime $x; dd $x.VAR.of'
Prime

Understanding string.gsub in Lua

I'm trying to print a gsub string (in Lua) to stdout here how my code look like.
print('string.gsub(\'VEECTORY\',\'EE\',\'I\') =>', string.gsub('VEECTORY','EE','I'))
Everytime I run this, although I get the desired result but I see 1 appearing in the output.
So, the output look like this.
string.gsub('VEECTORY','EE','I') => VICTORY 1
I'm unable to understand what does that 1 stand for but if I used a variable I don't see that 1 anymore.
local replace_string = string.gsub('VEECTORY','EE','I')
print('string.gsub(\'VEECTORY\',\'EE\',\'I\') =>',replace_string)
I get output as
string.gsub('VEECTORY','EE','I') => VICTORY
I also notice that when I run the above code in Lua console
i.e this code
local replace_string = string.gsub('VEECTORY','EE','I')
print('string.gsub(\'VEECTORY\',\'EE\',\'I\') =>',replace_string)
I get the output as nil
What am I missing ?
string.gsub has two return values. The first is result string, while the second is the total number of matches that occurred.
In your example:
string.gsub('VEECTORY','EE','I')
The second return value is 1 because the substitution happened once.
When you assign the result as:
local replace_string = string.gsub('VEECTORY','EE','I')
The first return value is assigned to replace_string, while the second return value is discarded.
You can get the second return value explicitly by:
local replace_string, num = string.gsub('VEECTORY','EE','I')
Finally, in interactive mode, each line is a chunk by itself, so the local variables are out of scope in the next line, therefore you saw replace_string becomes nil. If you use global variables:
replace_string = string.gsub('VEECTORY','EE','I')
print('string.gsub(\'VEECTORY\',\'EE\',\'I\') =>',replace_string)
The output will be as expected in interactive mode as well.

Unnamed parameter with commander.js (positional arguments)

I am currently taking a look at commander.js as I want to implement a CLI using Node.js.
Using named parameters is easy, as the example of a "pizza" program shows:
program
.version('0.0.1')
.option('-p, --peppers', 'Add peppers')
.option('-P, --pineapple', 'Add pineapple')
.option('-b, --bbq', 'Add bbq sauce')
.option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')
.parse(process.argv);
Now, e.g., I can call the program using:
$ app -p -b
But what about an unnamed parameter? What if I want to call it using
$ app italian -p -b
? I think this is not so very uncommon, hence providing files for the cp command does not require you to use named parameters as well. It's just
$ cp source target
and not:
$ cp -s source -t target
How do I achieve this using commander.js?
And, how do I tell commander.js that unnamed parameters are required? E.g., if you take a look at the cp command, source and target are required.
With the present version of commander, it's possible to use positional arguments. See the docs on argument syntax for details, but using your cp example it would be something like:
program
.version('0.0.1')
.arguments('<source> <target>')
.action(function(source, target) {
// do something with source and target
})
.parse(process.argv);
This program will complain if both arguments are not present, and give an appropriate warning message.
You get all the unnamed parameters through program.args. Add the following line to your example
console.log(' args: %j', program.args);
When you run your app with -p -b -c gouda arg1 arg2 you get
you ordered a pizza with:
- peppers
- bbq
- gouda cheese
args: ["arg1","arg2"]
Then you could write something like
copy args[0] to args[1] // just to give an idea
program.argument('<myarg>') + program.namedArgs as of 9.4.1 for positional arguments
Tested as of commander 9.4.1 the best option for positional arguments seems to be the .argument function.
This method achieves the basic features you'd expect from a decent library:
gives an error if mandatory arguments are not passed
allows you to set defaults and do custom parsing/checks e.g. integer conversion
give an error if there are too many positional with program.allowExcessArguments(false) (shame not the default)
We use program.namedArgs because program.args ignores myParseInt or defaults.
TODO built-in way to
access positional arguments by their name (e.g. program.processedArgs.arg1) rather than by index (program.processedArgs[0])
Sample usage:
positional.js
function myParseInt(value, dummyPrevious) {
const parsedValue = parseInt(value, 10);
if (isNaN(parsedValue)) {
throw new commander.InvalidArgumentError('Not a number.');
}
return parsedValue;
}
const commander = require('commander');
const program = commander.program
program.option('-m --myopt <myopt>', 'doc for myopt', 'myopt-default');
program.argument('<arg1>', 'doc for arg1');
program.argument('<arg2>', 'doc for arg2');
program.argument('[arg3]', 'doc for arg3', myParseInt, 1);
program.allowExcessArguments(false);
program.parse(process.argv);
const [arg1, arg2, arg3] = program.processedArgs
const opts = program.opts()
// Use the arguments.
console.error(`arg1: ${arg1} (${typeof arg1})`);
console.error(`arg2: ${arg2} (${typeof arg2})`);
console.error(`arg3: ${arg3} (${typeof arg3})`);
console.error(`myopt: ${opts.myopt} (${typeof opts.myopt})`);
Sample calls:
$ ./positional.js
error: missing required argument 'arg1'
$ ./positional.js a
error: missing required argument 'arg2'
$ ./positional.js a b
arg1: a (string)
arg2: b (string)
arg3: 1 (number)
myopt: myopt-default (string)
$ ./positional.js a b c
error: command-argument value 'c' is invalid for argument 'arg3'. Not a number.
$ ./positional.js a b 2
arg1: a (string)
arg2: b (string)
arg3: 2 (number)
myopt: myopt-default (string)
$ ./positional.js a b 2 c
error: too many arguments. Expected 3 arguments but got 4.
$ ./positional.js -m c a b 2
arg1: a (string)
arg2: b (string)
arg3: 2 (number)
myopt: c (string)
$ ./positional.js a b 2 -m c
arg1: a (string)
arg2: b (string)
arg3: 2 (number)
myopt: c (string)
$ ./positional.js -h
Usage: positional [options] <arg1> <arg2> [arg3]
Arguments:
arg1 doc for arg1
arg2 doc for arg2
arg3 doc for arg3 (default: 1)
Options:
-m --myopt <myopt> doc for myopt (default: "myopt-default")
-h, --help display help for command

DSL with groovy -> passing values to metaClass methods

I'm trying to write a mini DSL for some specific task. For this purpose I've been trying to solve a problem like this below (without using parantheses):
give me 5 like romanLetter
give me 5 like word
where the first line would return "V" and the second "five"
My definitions for the first part give me 5 look like this
def give = { clos -> clos() }
def me = { clos -> [:].withDefault { it
println it}
}
and then give me 5 prints 5
The problem is how to add more metaclass methods on the right. E.g.
give me 5 like romanLetter -> prints V OR
give me 5 like word -> prints five
my intuition is that I define like as
Object.metaClass.like = {orth -> if (orth.equals("roman")){ println "V"}
else {println "five"} }
this metaClass method like works only if there is a returned value from the left to be applied to, right? I tried adding a return statement in all of the closures which are on the left side but I always receive
groovy.lang.MissingPropertyException: No such property: like
for class: com.ontotext.paces.rules.FERulesScriptTest ...
do you have an idea how shall I do?
========================================
Here is the application of what I'm asking for.
I want to make a rule as follows
add FEATURE of X opts A,B,C named Y
where add is a closure, of, opts and named are MetaClass methods (at least that's how i imagine it), X, A, B, C, Y are parameters most probably strings and FEATURE is either a MetaClass property, or a closure without arguments or a closure with arguments.
If FEATURE does not take arguments then it is enough that add takes FEATURE as argument and returns a value on which
Object.metaClass.of will be executed with parameter X
Object.metaClass.opts will be executed on the returned by OF value with parameters A, B, C
Object.metaClass.named will be executed on the returned by opts value with parameter Y
each one of these metaclass methods sets its parameter as a value in a map, which is passed to a JAVA method when named is called.
I'm not sure this is the best solution for such a problem, but it seems to me such for the moment. The problem is if FEATURE is not a property itself but a closure which takes argument (e.g. feature1 ARG1). Then
add feature1 ARG1 of X opts A,B,C named Y
and this is the case which I'm stuck with. add feature1 ARG1 is the give me 5 part and I'm trying to add the rest to it.
========================================================
EXAMPLES:
I need to have both of the following working:
add contextFeature "text" of 1,2,3 opts "upperCase" named "TO_UPPER"
add length named "LENGTH"
where in the first case by parsing the rule, whenever each metaclass method of, opts, named is called I fill in the corresponding value in the following map:
params = [feature: "text",
of: 1,2,3,
opts: "upperCase",
named: "TO_UPPER"]
ones this map is filled in, which happens when named is parsed, I call a java method
setFeature(params.of, params.named, params.opts, params.feature)
In the second case length is predefined as length = "length", params values will be only
params = [feature : length,
of: null,
opts: null,
named: "LENGTH"]
and since of is null another java method will be called which is addSurfaceFeature(params.feature, params.named). The second case is more or less streight forward, but the first one is the one I can't manage.
Thanks in advance! Iv
You can do this sort of thing... Does that get you close?
def contextFeature( type ) {
"FEATURE_$type"
}
// Testing
new IvitaParser().parse {
a = add text of 1,2,3 opts "upperCase" named "TO_UPPER"
b = add length named "LENGTH"
c = add contextFeature( "text" ) of 1,2,3 opts "upperCase" named "TO_UPPER"
}
assert a == [feature:'text', of:[1, 2, 3], opts:'upperCase', named:'TO_UPPER']
assert b == [feature:'length', of:null, opts:null, named:'LENGTH']
assert c == [feature:'FEATURE_text', of:[1, 2, 3], opts:'upperCase', named:'TO_UPPER']
// Implementation
class IvitaParser {
Map result
def parse( Closure c ) {
c.delegate = this
c.resolveMethod = Closure.DELEGATE_FIRST
c()
}
def propertyMissing( String name ) {
name
}
def add( String param ) {
result = [ feature:param, of:null, opts:null, named:null ]
this
}
def of( Object... values ) {
result.of = values
this
}
def named( String name ) {
result.named = name
result
}
def opts( String opt ) {
result.opts = opt
this
}
}
You can even get rid of the quotes on the definition:
a = add text of 1,2,3 opts upperCase named TO_UPPER
b = add length named LENGTH
As the propertyMissing method just converts unknown properties into a String of their name

Resources