new object getopt: $root;
public method .getopt {
arg args, shortopts, @longopts;
var list;
// Ported from the Python 1.4 module of the same name
longopts = (| longopts[1] |) || [];
if (type(args) == 'string) {
args = args.explode();
}
list = [];
longopts = longopts.sort();
while (args && args[1][1] == "-" && args[1] != "-") {
if (args[1] == "--") {
args = args.subrange(2);
break;
}
if (args[1][2] == "-") {
[list, args] = .do_longs(list, args[1].subrange(3), longopts, args.subrange(2));
} else {
[list, args] = .do_shorts(list, args[1].subrange(2), shortopts, args.subrange(2));
}
}
return [list, args];
};
private method .do_longs() {
arg list, opt, longopts, args;
var i, has_arg, optarg;
if ((i = stridx(opt, "="))) {
[opt, optarg] = [opt.subrange(1, i - 1), opt.subrange(i + 1)];
} else {
optarg = 0;
}
[has_arg, opt] = .long_has_args(opt, longopts);
if (has_arg) {
if (optarg == 0) {
if (!args) {
throw(~opterr, "option --" + opt + " requires argument");
}
[optarg, args] = args;
}
} else if (optarg) {
throw(~opterror, "option --" + opt + " must not have an argument");
}
list = [@list, ["--" + opt, optarg || ""]];
return [list, args];
};
private method .long_has_args() {
arg opt, longopts;
var optlen, i, x, y;
optlen = opt.length();
for i in [1 .. longopts.length()] {
[x, y] = (| [longopts[i].subrange(1, optlen), longopts[i].subrange(optlen+1)] |) || [longopts[i], ""];
if (opt != x) {
continue;
}
if (y != "" && y != "=" && i + 1 < longopts.length()) {
if (opt == longopts[i + 1].subrange(1, optlen)) {
throw(~opterr, "option --" + opt + " not a unique prefix");
}
}
if (longopts[i].last() == "=") {
return [1, longopts[i].subrange(1, longopts[i].length() - 1)];
}
return [0, longopts[i]];
}
throw(~opterr, "option --" + opt + " not recongized");
};
private method .do_shorts() {
arg list, optstring, shortopts, args;
var opt, optarg;
while (optstring != "") {
[opt, optstring] = [optstring[1], optstring.subrange(2)];
if (.short_has_arg(opt, shortopts)) {
if (optstring == "") {
if (!args) {
throw(~opterr, "option -" + opt + " requires argument");
}
[optstring, @args] = args;
}
[optarg, optstring] = [optstring, ""];
} else {
optarg = "";
}
list = [@list, ["-" + opt, optarg]];
}
return [list, args];
};
private method .short_has_arg() {
arg opt, shortopts;
var i;
if (i = opt in shortopts) {
return (| shortopts[i+1] == ":" |) || 0;
}
throw(~opterr, "option -" + opt + " not recognized");
};
public method .test() {
return .getopt("-a 4 -b --alpha=12 -- --beta foo", "a:b", ["alpha=", "beta"]);
};