new object 

public method .getopt {
  arg args, shortopts, @longopts;
  var list;

  // Ported from the Python 1.4 module of the same name
  if (type(args) == 'string) {
    args = args.explode();
  }
  list = [];
  longopts = longopts.sort();
  while (args && (args[0][1] == "-") && (args[0] != "-")) {
    if (args[0] == "--") {
      args = args.subrange(2);
      break;
    }
    if (args[0].substr(1, 2) == "--") {
      [list, args] = .do_longs(list, args[0].substr(3), longopts, args.subrange(2));
    } else {
      [list, args] = .do_shorts(list, args[0].substr(2), shortopts, args.subrange(2));
    }
  }
  return [list, args];
};

private method .do_longs() {
  arg list, opt, longopt, args;
  var i, has_arg, optarg;
  
  if ((i = stridx(opt, "="))) {
    [opt, optarg] = [opt.substr(1, i - 1), opt.substr(i)];
  } 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, t;

  optlen = opt.length();
  for i in [1..longopts.length()] {
    [x, y] = [longopts[i].substr(1, optlen - 1), longopts[i].substr(optlen)];
    if (opt != x) {
      continue;
    }
    if ((y != "") && (y != "=") && (i+1 < longopts.length())) {
      if (opt == longopts[i+1].substr(1, optlen - 1)) {
	throw(~opterr, "option --" + opt + " not a unique prefix");
      }
    }
    if (longopts[i].last() == "=") {
      return [1, longopts[i].substr(1, longopts[i].length() - 1)];
    }
    return [0, longopts[i]];
  }
  throw(~opterr, "option --" + opt + " not recongized");
};

private method .do_shorts() {
  arg list, optstring, shortopts, args;

  while (optstring != '') {
    [opt, optstring] = optstring[0], optstring.substr(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;
    
  for i in [1..shortopts.length()] {
    if ((opt == shortopts[i]) && (shortopts[i] != ':')) {
      return (shortopts.substr(i, 2) == ':');
    }
  }
  throw(~opterr, "option -" + opt + " not recognized");
};

public method .test() {
  return .getopt("-a 4 -b 12 --alpha=12", "a:b", ["alpha=", "beta"]);
};