// Generated by CoffeeScript 1.9.1
(function() {
  var Argument, BranchPattern, Command, Dict, DocoptExit, DocoptLanguageError, Either, LeafPattern, OneOrMore, Option, Optional, OptionsShortcut, Pattern, Required, Tokens, any, docopt, enumerate, extras, formal_usage, parse_argv, parse_atom, parse_defaults, parse_expr, parse_long, parse_pattern, parse_section, parse_seq, parse_shorts, print, transform, zip,
    indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
    slice = [].slice,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;

  print = function() {
    return console.log([].join.call(arguments, ' '));
  };

  enumerate = function(array) {
    var i, item, j, len, results;
    i = 0;
    results = [];
    for (j = 0, len = array.length; j < len; j++) {
      item = array[j];
      results.push([i++, item]);
    }
    return results;
  };

  any = function(array) {
    return indexOf.call(array, true) >= 0;
  };

  zip = function() {
    var args, arr, i, j, length, lengthArray, ref, results;
    args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
    lengthArray = (function() {
      var j, len, results;
      results = [];
      for (j = 0, len = args.length; j < len; j++) {
        arr = args[j];
        results.push(arr.length);
      }
      return results;
    })();
    length = Math.min.apply(Math, lengthArray);
    results = [];
    for (i = j = 0, ref = length; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
      results.push((function() {
        var len, q, results1;
        results1 = [];
        for (q = 0, len = args.length; q < len; q++) {
          arr = args[q];
          results1.push(arr[i]);
        }
        return results1;
      })());
    }
    return results;
  };

  String.prototype.partition = function(separator) {
    var parts, self;
    self = this;
    if (self.indexOf(separator) >= 0) {
      parts = self.split(separator);
      return [parts[0], separator, parts.slice(1).join(separator)];
    } else {
      return [String(self), '', ''];
    }
  };

  String.prototype.startsWith = function(searchString, position) {
    position = position || 0;
    return this.lastIndexOf(searchString, position) === position;
  };

  String.prototype.endsWith = function(searchString, position) {
    var lastIndex, subjectString;
    subjectString = this.toString();
    if (position === void 0 || position > subjectString.length) {
      position = subjectString.length;
    }
    position -= searchString.length;
    lastIndex = subjectString.indexOf(searchString, position);
    return lastIndex !== -1 && lastIndex === position;
  };

  String.prototype._split = function() {
    return this.trim().split(/\s+/).filter(function(i) {
      return i !== '';
    });
  };

  String.prototype.isUpper = function() {
    return /^[A-Z]+$/g.exec(this);
  };

  Number.isInteger = Number.isInteger || function(value) {
    return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
  };

  DocoptLanguageError = (function(superClass) {
    extend(DocoptLanguageError, superClass);

    function DocoptLanguageError(message) {
      this.message = message;
      DocoptLanguageError.__super__.constructor.call(this, this.message);
    }

    return DocoptLanguageError;

  })(Error);

  DocoptExit = (function(superClass) {
    extend(DocoptExit, superClass);

    function DocoptExit(message) {
      this.message = message;
      DocoptExit.__super__.constructor.call(this, this.message);
    }

    return DocoptExit;

  })(Error);

  Pattern = (function(superClass) {
    extend(Pattern, superClass);

    function Pattern() {
      return Pattern.__super__.constructor.apply(this, arguments);
    }

    Pattern.prototype.fix = function() {
      this.fix_identities();
      this.fix_repeating_arguments();
      return this;
    };

    Pattern.prototype.fix_identities = function(uniq) {
      var c, flat, i, j, k, len, len1, q, ref, ref1, ref2;
      if (uniq == null) {
        uniq = null;
      }
      "Make pattern-tree tips point to same object if they are equal.";
      if (!this.hasOwnProperty('children')) {
        return this;
      }
      if (uniq === null) {
        ref = [{}, this.flat()], uniq = ref[0], flat = ref[1];
        for (j = 0, len = flat.length; j < len; j++) {
          k = flat[j];
          uniq[k] = k;
        }
      }
      ref1 = enumerate(this.children);
      for (q = 0, len1 = ref1.length; q < len1; q++) {
        ref2 = ref1[q], i = ref2[0], c = ref2[1];
        if (!c.hasOwnProperty('children')) {
          console.assert(uniq.hasOwnProperty(c));
          this.children[i] = uniq[c];
        } else {
          c.fix_identities(uniq);
        }
      }
      return this;
    };

    Pattern.prototype.fix_repeating_arguments = function() {
      "Fix elements that should accumulate/increment values.";
      var c, child, counts, e, either, j, len, len1, len2, mycase, q, r, ref;
      either = (function() {
        var j, len, ref, results;
        ref = transform(this).children;
        results = [];
        for (j = 0, len = ref.length; j < len; j++) {
          child = ref[j];
          results.push(child.children);
        }
        return results;
      }).call(this);
      for (j = 0, len = either.length; j < len; j++) {
        mycase = either[j];
        counts = {};
        for (q = 0, len1 = mycase.length; q < len1; q++) {
          c = mycase[q];
          counts[c] = (counts[c] ? counts[c] : 0) + 1;
        }
        ref = (function() {
          var len2, results, u;
          results = [];
          for (u = 0, len2 = mycase.length; u < len2; u++) {
            child = mycase[u];
            if (counts[child] > 1) {
              results.push(child);
            }
          }
          return results;
        })();
        for (r = 0, len2 = ref.length; r < len2; r++) {
          e = ref[r];
          if (e.constructor === Argument || e.constructor === Option && e.argcount) {
            if (e.value === null) {
              e.value = [];
            } else if (e.value.constructor !== Array) {
              e.value = e.value._split();
            }
          }
          if (e.constructor === Command || e.constructor === Option && e.argcount === 0) {
            e.value = 0;
          }
        }
      }
      return this;
    };

    return Pattern;

  })(Object);

  transform = function(pattern) {
    "Expand pattern into an (almost) equivalent one, but with single Either.\n\nExample: ((-a | -b) (-c | -d)) => (-a -c | -a -d | -b -c | -b -d)\nQuirks: [-a] => (-a), (-a...) => (-a -a)\n";
    var c, child, children, e, groups, index, j, len, parents, ref, result, t;
    result = [];
    groups = [[pattern]];
    while (groups.length) {
      children = groups.shift();
      parents = [Required, Optional, OptionsShortcut, Either, OneOrMore];
      if (any((function() {
        var j, len, results;
        results = [];
        for (j = 0, len = parents.length; j < len; j++) {
          t = parents[j];
          results.push(indexOf.call(children.map(function(c) {
            return c.constructor;
          }), t) >= 0);
        }
        return results;
      })())) {
        child = ((function() {
          var j, len, ref, results;
          results = [];
          for (j = 0, len = children.length; j < len; j++) {
            c = children[j];
            if (ref = c.constructor, indexOf.call(parents, ref) >= 0) {
              results.push(c);
            }
          }
          return results;
        })())[0];
        index = children.indexOf(child);
        if (index >= 0) {
          children.splice(index, 1);
        }
        if (child.constructor === Either) {
          ref = child.children;
          for (j = 0, len = ref.length; j < len; j++) {
            c = ref[j];
            groups.push([c].concat(children));
          }
        } else if (child.constructor === OneOrMore) {
          groups.push((child.children.concat(child.children)).concat(children));
        } else {
          groups.push(child.children.concat(children));
        }
      } else {
        result.push(children);
      }
    }
    return new Either((function() {
      var len1, q, results;
      results = [];
      for (q = 0, len1 = result.length; q < len1; q++) {
        e = result[q];
        results.push(new Required(e));
      }
      return results;
    })());
  };

  LeafPattern = (function(superClass) {
    "Leaf/terminal node of a pattern tree.";
    extend(LeafPattern, superClass);

    function LeafPattern(name1, value1) {
      this.name = name1;
      this.value = value1 != null ? value1 : null;
    }

    LeafPattern.prototype.toString = function() {
      return this.constructor.name + "(" + this.name + ", " + this.value + ")";
    };

    LeafPattern.prototype.flat = function(types) {
      var ref;
      if (types == null) {
        types = [];
      }
      types = types instanceof Array ? types : [types];
      if (!types.length || (ref = this.constructor, indexOf.call(types, ref) >= 0)) {
        return [this];
      } else {
        return [];
      }
    };

    LeafPattern.prototype.match = function(left, collected) {
      var a, increment, left_, match, pos, ref, same_name;
      if (collected == null) {
        collected = null;
      }
      if (collected === null) {
        collected = [];
      }
      ref = this.singleMatch(left), pos = ref[0], match = ref[1];
      if (match === null) {
        return [false, left, collected];
      }
      left_ = left.slice(0, pos).concat(left.slice(pos + 1));
      same_name = (function() {
        var j, len, results;
        results = [];
        for (j = 0, len = collected.length; j < len; j++) {
          a = collected[j];
          if (a.name === this.name) {
            results.push(a);
          }
        }
        return results;
      }).call(this);
      if (Number.isInteger(this.value) || this.value instanceof Array) {
        if (Number.isInteger(this.value)) {
          increment = 1;
        } else {
          increment = typeof match.value === 'string' ? [match.value] : match.value;
        }
        if (!same_name.length) {
          match.value = increment;
          return [true, left_, collected.concat(match)];
        }
        if (Number.isInteger(this.value)) {
          same_name[0].value += increment;
        } else {
          same_name[0].value = [].concat(same_name[0].value, increment);
        }
        return [true, left_, collected];
      }
      return [true, left_, collected.concat(match)];
    };

    return LeafPattern;

  })(Pattern);

  BranchPattern = (function(superClass) {
    "Branch/inner node of a pattern tree.";
    extend(BranchPattern, superClass);

    function BranchPattern(children) {
      this.children = children instanceof Array ? children : [children];
    }

    BranchPattern.prototype.toString = function() {
      var a;
      return this.constructor.name + "(" + (((function() {
        var j, len, ref, results;
        ref = this.children;
        results = [];
        for (j = 0, len = ref.length; j < len; j++) {
          a = ref[j];
          results.push(a);
        }
        return results;
      }).call(this)).join(', ')) + ")";
    };

    BranchPattern.prototype.flat = function(types) {
      var child, ref;
      if (types == null) {
        types = [];
      }
      types = types instanceof Array ? types : [types];
      if (ref = this.constructor, indexOf.call(types, ref) >= 0) {
        return [this];
      }
      return ((function() {
        var j, len, ref1, results;
        ref1 = this.children;
        results = [];
        for (j = 0, len = ref1.length; j < len; j++) {
          child = ref1[j];
          if (child instanceof Pattern) {
            results.push(child.flat(types));
          }
        }
        return results;
      }).call(this)).reduce((function(pv, cv) {
        return [].concat(pv, cv);
      }), []);
    };

    return BranchPattern;

  })(Pattern);

  Argument = (function(superClass) {
    extend(Argument, superClass);

    function Argument() {
      return Argument.__super__.constructor.apply(this, arguments);
    }

    Argument.prototype.singleMatch = function(left) {
      var j, len, n, pattern, ref, ref1;
      ref = enumerate(left);
      for (j = 0, len = ref.length; j < len; j++) {
        ref1 = ref[j], n = ref1[0], pattern = ref1[1];
        if (pattern.constructor === Argument) {
          return [n, new Argument(this.name, pattern.value)];
        }
      }
      return [null, null];
    };

    Argument.parse = function(source) {
      var name, value;
      name = /(<\S*?>)/ig.exec(source)[1];
      value = /\[default:\s+(.*)\]/ig.exec(source);
      return new Argument(name, value ? value[1] : null);
    };

    return Argument;

  })(LeafPattern);

  Command = (function(superClass) {
    extend(Command, superClass);

    function Command(name1, value1) {
      this.name = name1;
      this.value = value1 != null ? value1 : false;
    }

    Command.prototype.singleMatch = function(left) {
      var j, len, n, pattern, ref, ref1;
      ref = enumerate(left);
      for (j = 0, len = ref.length; j < len; j++) {
        ref1 = ref[j], n = ref1[0], pattern = ref1[1];
        if (pattern.constructor === Argument) {
          if (pattern.value === this.name) {
            return [n, new Command(this.name, true)];
          } else {
            break;
          }
        }
      }
      return [null, null];
    };

    return Command;

  })(Argument);

  Option = (function(superClass) {
    extend(Option, superClass);

    function Option(short1, long1, argcount1, value) {
      var ref;
      this.short = short1 != null ? short1 : null;
      this.long = long1 != null ? long1 : null;
      this.argcount = argcount1 != null ? argcount1 : 0;
      if (value == null) {
        value = false;
      }
      console.assert((ref = this.argcount) === 0 || ref === 1);
      this.value = value === false && this.argcount > 0 ? null : value;
      this.name = this.long || this.short;
    }

    Option.prototype.toString = function() {
      return "Option(" + this.short + ", " + this.long + ", " + this.argcount + ", " + this.value + ")";
    };

    Option.parse = function(option_description) {
      var _, argcount, description, j, len, long, matched, options, ref, ref1, ref2, s, short, value;
      ref = [null, null, 0, false], short = ref[0], long = ref[1], argcount = ref[2], value = ref[3];
      ref1 = option_description.trim().partition('  '), options = ref1[0], _ = ref1[1], description = ref1[2];
      options = options.replace(/,|=/g, ' ');
      ref2 = options._split();
      for (j = 0, len = ref2.length; j < len; j++) {
        s = ref2[j];
        if (s.startsWith('--')) {
          long = s;
        } else if (s.startsWith('-')) {
          short = s;
        } else {
          argcount = 1;
        }
      }
      if (argcount > 0) {
        matched = /\[default:\s+(.*)\]/ig.exec(description);
        value = matched ? matched[1] : null;
      }
      return new Option(short, long, argcount, value);
    };

    Option.prototype.singleMatch = function(left) {
      var j, len, n, pattern, ref, ref1;
      ref = enumerate(left);
      for (j = 0, len = ref.length; j < len; j++) {
        ref1 = ref[j], n = ref1[0], pattern = ref1[1];
        if (this.name === pattern.name) {
          return [n, pattern];
        }
      }
      return [null, null];
    };

    return Option;

  })(LeafPattern);

  Required = (function(superClass) {
    extend(Required, superClass);

    function Required() {
      return Required.__super__.constructor.apply(this, arguments);
    }

    Required.prototype.match = function(left, collected) {
      var c, j, l, len, matched, p, ref, ref1;
      if (collected == null) {
        collected = null;
      }
      if (collected === null) {
        collected = [];
      }
      l = left;
      c = collected;
      ref = this.children;
      for (j = 0, len = ref.length; j < len; j++) {
        p = ref[j];
        ref1 = p.match(l, c), matched = ref1[0], l = ref1[1], c = ref1[2];
        if (!matched) {
          return [false, left, collected];
        }
      }
      return [true, l, c];
    };

    return Required;

  })(BranchPattern);

  Optional = (function(superClass) {
    extend(Optional, superClass);

    function Optional() {
      return Optional.__super__.constructor.apply(this, arguments);
    }

    Optional.prototype.match = function(left, collected) {
      var j, len, m, p, ref, ref1;
      if (collected == null) {
        collected = null;
      }
      if (collected === null) {
        collected = [];
      }
      ref = this.children;
      for (j = 0, len = ref.length; j < len; j++) {
        p = ref[j];
        ref1 = p.match(left, collected), m = ref1[0], left = ref1[1], collected = ref1[2];
      }
      return [true, left, collected];
    };

    return Optional;

  })(BranchPattern);

  OptionsShortcut = (function(superClass) {
    "Marker/placeholder for [options] shortcut.";
    extend(OptionsShortcut, superClass);

    function OptionsShortcut() {
      return OptionsShortcut.__super__.constructor.apply(this, arguments);
    }

    return OptionsShortcut;

  })(Optional);

  OneOrMore = (function(superClass) {
    extend(OneOrMore, superClass);

    function OneOrMore() {
      return OneOrMore.__super__.constructor.apply(this, arguments);
    }

    OneOrMore.prototype.match = function(left, collected) {
      var c, l, l_, matched, ref, times;
      if (collected == null) {
        collected = null;
      }
      console.assert(this.children.length === 1);
      if (collected === null) {
        collected = [];
      }
      l = left;
      c = collected;
      l_ = [];
      matched = true;
      times = 0;
      while (matched) {
        ref = this.children[0].match(l, c), matched = ref[0], l = ref[1], c = ref[2];
        times += matched ? 1 : 0;
        if (l_.join(', ') === l.join(', ')) {
          break;
        }
        l_ = l;
      }
      if (times >= 1) {
        return [true, l, c];
      }
      return [false, left, collected];
    };

    return OneOrMore;

  })(BranchPattern);

  Either = (function(superClass) {
    extend(Either, superClass);

    function Either() {
      return Either.__super__.constructor.apply(this, arguments);
    }

    Either.prototype.match = function(left, collected) {
      var j, len, outcome, outcomes, p, ref;
      if (collected == null) {
        collected = null;
      }
      if (collected === null) {
        collected = [];
      }
      outcomes = [];
      ref = this.children;
      for (j = 0, len = ref.length; j < len; j++) {
        p = ref[j];
        outcome = p.match(left, collected);
        if (outcome[0]) {
          outcomes.push(outcome);
        }
      }
      if (outcomes.length > 0) {
        outcomes.sort(function(a, b) {
          if (a[1].length > b[1].length) {
            return 1;
          } else if (a[1].length < b[1].length) {
            return -1;
          } else {
            return 0;
          }
        });
        return outcomes[0];
      }
      return [false, left, collected];
    };

    return Either;

  })(BranchPattern);

  Tokens = (function(superClass) {
    extend(Tokens, superClass);

    function Tokens(source, error) {
      var stream;
      this.error = error != null ? error : DocoptExit;
      stream = source.constructor === String ? source._split() : source;
      this.push.apply(this, stream);
    }

    Tokens.prototype.move = function() {
      if (this.length) {
        return [].shift.apply(this);
      } else {
        return null;
      }
    };

    Tokens.prototype.current = function() {
      if (this.length) {
        return this[0];
      } else {
        return null;
      }
    };

    Tokens.from_pattern = function(source) {
      var s;
      source = source.replace(/([\[\]\(\)\|]|\.\.\.)/g, ' $1 ');
      source = (function() {
        var j, len, ref, results;
        ref = source.split(/\s+|(\S*<.*?>)/);
        results = [];
        for (j = 0, len = ref.length; j < len; j++) {
          s = ref[j];
          if (s) {
            results.push(s);
          }
        }
        return results;
      })();
      return new Tokens(source, DocoptLanguageError);
    };

    return Tokens;

  })(Array);

  parse_section = function(name, source) {
    var matches, s;
    matches = source.match(new RegExp('^([^\n]*' + name + '[^\n]*\n?(?:[ \t].*?(?:\n|$))*)', 'igm'));
    if (matches) {
      return (function() {
        var j, len, results;
        results = [];
        for (j = 0, len = matches.length; j < len; j++) {
          s = matches[j];
          results.push(s.trim());
        }
        return results;
      })();
    }
    return [];
  };

  parse_shorts = function(tokens, options) {
    "shorts ::= '-' ( chars )* [ [ ' ' ] chars ] ;";
    var left, o, parsed, ref, ref1, short, similar, token, value;
    token = tokens.move();
    console.assert(token.startsWith('-') && !token.startsWith('--'));
    left = token.replace(/^-+/g, '');
    parsed = [];
    while (left !== '') {
      ref = ['-' + left[0], left.slice(1)], short = ref[0], left = ref[1];
      similar = (function() {
        var j, len, results;
        results = [];
        for (j = 0, len = options.length; j < len; j++) {
          o = options[j];
          if (o.short === short) {
            results.push(o);
          }
        }
        return results;
      })();
      if (similar.length > 1) {
        throw new tokens.error(short + " is specified ambiguously " + similar.length + " times");
      } else if (similar.length < 1) {
        o = new Option(short, null, 0);
        options.push(o);
        if (tokens.error === DocoptExit) {
          o = new Option(short, null, 0, true);
        }
      } else {
        o = new Option(short, similar[0].long, similar[0].argcount, similar[0].value);
        value = null;
        if (o.argcount !== 0) {
          if (left === '') {
            if ((ref1 = tokens.current()) === null || ref1 === '--') {
              throw new tokens.error(short + " requires argument");
            }
            value = tokens.move();
          } else {
            value = left;
            left = '';
          }
        }
        if (tokens.error === DocoptExit) {
          o.value = value !== null ? value : true;
        }
      }
      parsed.push(o);
    }
    return parsed;
  };

  parse_long = function(tokens, options) {
    "long ::= '--' chars [ ( ' ' | '=' ) chars ] ;";
    var argcount, eq, long, longs, o, ref, ref1, similar, value;
    ref = tokens.move().partition('='), long = ref[0], eq = ref[1], value = ref[2];
    console.assert(long.startsWith('--'));
    if (eq === value && value === '') {
      value = null;
    }
    similar = (function() {
      var j, len, results;
      results = [];
      for (j = 0, len = options.length; j < len; j++) {
        o = options[j];
        if (o.long === long) {
          results.push(o);
        }
      }
      return results;
    })();
    if (tokens.error === DocoptExit && similar.length === 0) {
      similar = (function() {
        var j, len, results;
        results = [];
        for (j = 0, len = options.length; j < len; j++) {
          o = options[j];
          if (o.long && o.long.startsWith(long)) {
            results.push(o);
          }
        }
        return results;
      })();
    }
    if (similar.length > 1) {
      longs = ((function() {
        var j, len, results;
        results = [];
        for (j = 0, len = similar.length; j < len; j++) {
          o = similar[j];
          results.push(o.long);
        }
        return results;
      })()).join(', ');
      throw new tokens.error(long + " is not a unique prefix: " + longs + "?");
    } else if (similar.length < 1) {
      argcount = eq === '=' ? 1 : 0;
      o = new Option(null, long, argcount);
      options.push(o);
      if (tokens.error === DocoptExit) {
        o = new Option(null, long, argcount, argcount > 0 ? value : true);
      }
    } else {
      o = new Option(similar[0].short, similar[0].long, similar[0].argcount, similar[0].value);
      if (o.argcount === 0) {
        if (value !== null) {
          throw new tokens.error(o.long + " must not have an argument");
        }
      } else {
        if (value === null) {
          if ((ref1 = tokens.current()) === null || ref1 === '--') {
            throw new tokens.error(o.long + " requires argument");
          }
          value = tokens.move();
        }
      }
      if (tokens.error === DocoptExit) {
        o.value = value !== null ? value : true;
      }
    }
    return [o];
  };

  parse_pattern = function(source, options) {
    var result, tokens;
    tokens = Tokens.from_pattern(source);
    result = parse_expr(tokens, options);
    if (tokens.current() !== null) {
      throw new tokens.error('unexpected ending: ' + (tokens.join(' ')));
    }
    return new Required(result);
  };

  parse_expr = function(tokens, options) {
    "expr ::= seq ( '|' seq )* ;";
    var result, seq;
    seq = parse_seq(tokens, options);
    if (tokens.current() !== '|') {
      return seq;
    }
    result = seq.length > 1 ? [new Required(seq)] : seq;
    while (tokens.current() === '|') {
      tokens.move();
      seq = parse_seq(tokens, options);
      result = result.concat(seq.length > 1 ? [new Required(seq)] : seq);
    }
    if (result.length > 1) {
      return [new Either(result)];
    } else {
      return result;
    }
  };

  parse_seq = function(tokens, options) {
    "seq ::= ( atom [ '...' ] )* ;";
    var atom, ref, result;
    result = [];
    while ((ref = tokens.current()) !== null && ref !== ']' && ref !== ')' && ref !== '|') {
      atom = parse_atom(tokens, options);
      if (tokens.current() === '...') {
        atom = [new OneOrMore(atom)];
        tokens.move();
      }
      result = result.concat(atom);
    }
    return result;
  };

  parse_atom = function(tokens, options) {
    "atom ::= '(' expr ')' | '[' expr ']' | 'options'\n| long | shorts | argument | command ;";
    var matching, patternType, ref, result, token;
    token = tokens.current();
    result = [];
    if (indexOf.call('([', token) >= 0) {
      tokens.move();
      ref = {
        '(': [')', Required],
        '[': [']', Optional]
      }[token], matching = ref[0], patternType = ref[1];
      result = new patternType(parse_expr(tokens, options));
      if (tokens.move() !== matching) {
        throw new tokens.error("Unmatched '" + token + "'");
      }
      return [result];
    } else if (token === 'options') {
      tokens.move();
      return [new OptionsShortcut];
    } else if (token.startsWith('--') && token !== '--') {
      return parse_long(tokens, options);
    } else if (token.startsWith('-') && (token !== '-' && token !== '--')) {
      return parse_shorts(tokens, options);
    } else if (token.startsWith('<') && token.endsWith('>') || token.isUpper()) {
      return [new Argument(tokens.move())];
    } else {
      return [new Command(tokens.move())];
    }
  };

  parse_argv = function(tokens, options, options_first) {
    var parsed, v;
    if (options_first == null) {
      options_first = false;
    }
    "Parse command-line argument vector.\nIf options_first:\n    argv ::= [ long | shorts ]* [ argument ]* [ '--' [ argument ]* ] ;\nelse:\n    argv ::= [ long | shorts | argument ]* [ '--' [ argument ]* ] ;";
    parsed = [];
    while (tokens.current() !== null) {
      if (tokens.current() === '--') {
        return parsed.concat((function() {
          var j, len, results;
          results = [];
          for (j = 0, len = tokens.length; j < len; j++) {
            v = tokens[j];
            results.push(new Argument(null, v));
          }
          return results;
        })());
      } else if (tokens.current().startsWith('--')) {
        parsed = parsed.concat(parse_long(tokens, options));
      } else if (tokens.current().startsWith('-') && tokens.current() !== '-') {
        parsed = parsed.concat(parse_shorts(tokens, options));
      } else if (options_first) {
        return parsed.concat((function() {
          var j, len, results;
          results = [];
          for (j = 0, len = tokens.length; j < len; j++) {
            v = tokens[j];
            results.push(new Argument(null, v));
          }
          return results;
        })());
      } else {
        parsed.push(new Argument(null, tokens.move()));
      }
    }
    return parsed;
  };

  parse_defaults = function(doc) {
    var _, defaults, even, j, len, odd, options, ref, ref1, s, s1, s2, split, v;
    defaults = [];
    ref = parse_section('options:', doc);
    for (j = 0, len = ref.length; j < len; j++) {
      s = ref[j];
      ref1 = s.partition(':'), _ = ref1[0], _ = ref1[1], s = ref1[2];
      split = ('\n' + s).split(new RegExp('\\n[ \\t]*(-\\S+?)')).slice(1);
      odd = (function() {
        var len1, q, results;
        results = [];
        for (q = 0, len1 = split.length; q < len1; q += 2) {
          v = split[q];
          results.push(v);
        }
        return results;
      })();
      even = (function() {
        var len1, q, ref2, results;
        ref2 = split.slice(1);
        results = [];
        for (q = 0, len1 = ref2.length; q < len1; q += 2) {
          v = ref2[q];
          results.push(v);
        }
        return results;
      })();
      split = (function() {
        var len1, q, ref2, ref3, results;
        ref2 = zip(odd, even);
        results = [];
        for (q = 0, len1 = ref2.length; q < len1; q++) {
          ref3 = ref2[q], s1 = ref3[0], s2 = ref3[1];
          results.push(s1 + s2);
        }
        return results;
      })();
      options = (function() {
        var len1, q, results;
        results = [];
        for (q = 0, len1 = split.length; q < len1; q++) {
          s = split[q];
          if (s.startsWith('-')) {
            results.push(Option.parse(s));
          }
        }
        return results;
      })();
      defaults.push.apply(defaults, options);
    }
    return defaults;
  };

  formal_usage = function(section) {
    var _, pu, ref, s;
    ref = section.partition(':'), _ = ref[0], _ = ref[1], section = ref[2];
    pu = section._split();
    return '( ' + ((function() {
      var j, len, ref1, results;
      ref1 = pu.slice(1);
      results = [];
      for (j = 0, len = ref1.length; j < len; j++) {
        s = ref1[j];
        results.push(s === pu[0] ? ') | (' : s);
      }
      return results;
    })()).join(' ') + ' )';
  };

  extras = function(help, version, options, doc) {
    var o;
    if (help && any((function() {
      var j, len, ref, results;
      results = [];
      for (j = 0, len = options.length; j < len; j++) {
        o = options[j];
        results.push(((ref = o.name) === '--help' || ref === '-h') && o.value);
      }
      return results;
    })())) {
      return doc.replace(/^\s*|\s*$/, '');
    }
    if (version && any((function() {
      var j, len, results;
      results = [];
      for (j = 0, len = options.length; j < len; j++) {
        o = options[j];
        results.push((o.name === '--version') && o.value);
      }
      return results;
    })())) {
      return version;
    }
    return "";
  };

  Dict = (function(superClass) {
    extend(Dict, superClass);

    function Dict(pairs) {
      var j, key, len, ref, value;
      for (j = 0, len = pairs.length; j < len; j++) {
        ref = pairs[j], key = ref[0], value = ref[1];
        this[key] = value;
      }
    }

    Dict.prototype.toObject = function() {
      var dict, j, len, name, ref;
      dict = {};
      ref = Object.keys(this).sort();
      for (j = 0, len = ref.length; j < len; j++) {
        name = ref[j];
        dict[name] = this[name];
      }
      return dict;
    };

    return Dict;

  })(Object);

  docopt = function(doc, kwargs) {
    var a, allowedargs, arg, argv, collected, doc_options, e, exit, help, i, j, left, len, matched, name, options, options_first, options_shortcut, output, pattern, pattern_options, pattern_options_strings, ref, ref1, usage_sections, version;
    if (kwargs == null) {
      kwargs = {};
    }
    allowedargs = ['argv', 'name', 'help', 'version', 'options_first', 'exit'];
    for (arg in kwargs) {
      if (indexOf.call(allowedargs, arg) < 0) {
        throw new Error("unrecognized argument to docopt: ");
      }
    }
    argv = kwargs.argv === void 0 ? process.argv.slice(2) : kwargs.argv;
    name = kwargs.name === void 0 ? null : kwargs.name;
    help = kwargs.help === void 0 ? true : kwargs.help;
    version = kwargs.version === void 0 ? null : kwargs.version;
    options_first = kwargs.options_first === void 0 ? false : kwargs.options_first;
    exit = kwargs.exit === void 0 ? true : kwargs.exit;
    try {
      usage_sections = parse_section('usage:', doc);
      if (usage_sections.length === 0) {
        throw new DocoptLanguageError('"usage:" (case-insensitive) not found.');
      }
      if (usage_sections.length > 1) {
        throw new DocoptLanguageError('More than one "usage:" (case-insensitive).');
      }
      DocoptExit.usage = usage_sections[0];
      options = parse_defaults(doc);
      pattern = parse_pattern(formal_usage(DocoptExit.usage), options);
      argv = parse_argv(new Tokens(argv), options, options_first);
      pattern_options = pattern.flat(Option);
      ref = pattern.flat(OptionsShortcut);
      for (j = 0, len = ref.length; j < len; j++) {
        options_shortcut = ref[j];
        doc_options = parse_defaults(doc);
        pattern_options_strings = (function() {
          var len1, q, results;
          results = [];
          for (q = 0, len1 = pattern_options.length; q < len1; q++) {
            i = pattern_options[q];
            results.push(i.toString());
          }
          return results;
        })();
        options_shortcut.children = doc_options.filter(function(item) {
          var ref1;
          return ref1 = item.toString(), indexOf.call(pattern_options_strings, ref1) < 0;
        });
      }
      output = extras(help, version, argv, doc);
      if (output) {
        if (exit) {
          print(output);
          process.exit();
        } else {
          throw new Error(output);
        }
      }
      ref1 = pattern.fix().match(argv), matched = ref1[0], left = ref1[1], collected = ref1[2];
      if (matched && left.length === 0) {
        return new Dict((function() {
          var len1, q, ref2, results;
          ref2 = [].concat(pattern.flat(), collected);
          results = [];
          for (q = 0, len1 = ref2.length; q < len1; q++) {
            a = ref2[q];
            results.push([a.name, a.value]);
          }
          return results;
        })()).toObject();
      }
      throw new DocoptExit(DocoptExit.usage);
    } catch (_error) {
      e = _error;
      if (!exit) {
        throw e;
      } else {
        if (e.message) {
          print(e.message);
        }
        return process.exit(1);
      }
    }
  };

  module.exports = {
    docopt: docopt,
    DocoptLanguageError: DocoptLanguageError,
    DocoptExit: DocoptExit,
    Option: Option,
    Argument: Argument,
    Command: Command,
    Required: Required,
    OptionsShortcut: OptionsShortcut,
    Either: Either,
    Optional: Optional,
    Pattern: Pattern,
    OneOrMore: OneOrMore,
    Tokens: Tokens,
    Dict: Dict,
    transform: transform,
    formal_usage: formal_usage,
    parse_section: parse_section,
    parse_defaults: parse_defaults,
    parse_pattern: parse_pattern,
    parse_long: parse_long,
    parse_shorts: parse_shorts,
    parse_argv: parse_argv
  };

}).call(this);
