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"]); };