1- {repeat , isCoffee } = require ' ./helpers'
1+ {repeat } = require ' ./helpers'
22
33# A simple **OptionParser** class to parse option flags from the command-line.
44# Use it like so:
@@ -25,45 +25,26 @@ exports.OptionParser = class OptionParser
2525 # parsers that allow you to attach callback actions for every flag. Instead,
2626 # you're responsible for interpreting the options object.
2727 parse : (args ) ->
28- # Pass all arguments to script unchanged if first argument is the script to
29- # be run; assume no options are for the coffeescript compiler. This allows
30- # the use of '#!/usr/bin/env coffee' to run executable scripts on Linux
31- # systems, which do not parse the '--' argument in the first line correctly.
32- if (args .indexOf ' --' is - 1 ) and
33- (args .length > 0 ) and
34- (isCoffee args[0 ])
35- return arguments : args
36- options = arguments : []
37- skippingArgument = no
38- originalArgs = args
39- args = normalizeArguments args
40- for arg, i in args
41- if skippingArgument
42- skippingArgument = no
43- continue
44- if arg is ' --'
45- pos = originalArgs .indexOf ' --'
46- options .arguments = options .arguments .concat originalArgs[(pos + 1 ).. ]
28+ state =
29+ argsLeft : args[.. ]
30+ options : {}
31+ while (arg = state .argsLeft .shift ())?
32+ if (arg .match (LONG_FLAG) ? arg .match (SHORT_FLAG))?
33+ tryMatchOptionalArgument (arg, state, @rules )
34+ else if (multiMatch = arg .match (MULTI_FLAG))?
35+ # Normalize arguments by expanding merged flags into multiple
36+ # flags. This allows you to have `-wl` be the same as `--watch --lint`.
37+ normalized = " -#{ multiArg} " for multiArg in multiMatch[1 ].split ' '
38+ state .argsLeft .unshift (normalized... )
39+ else
40+ # the CS option parser is a little odd; options after the first
41+ # non-option argument are treated as non-option arguments themselves.
42+ # executable scripts do not need to have a `--` at the end of the
43+ # shebang ("#!") line, and if they do, they won't work on Linux
44+ state .argsLeft .unshift (arg) unless arg is ' --'
4745 break
48- isOption = !! (arg .match (LONG_FLAG) or arg .match (SHORT_FLAG))
49- # the CS option parser is a little odd; options after the first
50- # non-option argument are treated as non-option arguments themselves
51- seenNonOptionArg = options .arguments .length > 0
52- unless seenNonOptionArg
53- matchedRule = no
54- for rule in @rules
55- if rule .shortFlag is arg or rule .longFlag is arg
56- value = true
57- if rule .hasArgument
58- skippingArgument = yes
59- value = args[i + 1 ]
60- options[rule .name ] = if rule .isList then (options[rule .name ] or []).concat value else value
61- matchedRule = yes
62- break
63- throw new Error " unrecognized option: #{ arg} " if isOption and not matchedRule
64- if seenNonOptionArg or not isOption
65- options .arguments .push arg
66- options
46+ state .options .arguments = state .argsLeft [.. ]
47+ state .options
6748
6849 # Return the help text for this **OptionParser**, listing and describing all
6950 # of the valid options, for `--help` and such.
@@ -107,14 +88,22 @@ buildRule = (shortFlag, longFlag, description, options = {}) ->
10788 isList : !! (match and match[2 ])
10889 }
10990
110- # Normalize arguments by expanding merged flags into multiple flags. This allows
111- # you to have `-wl` be the same as `--watch --lint`.
112- normalizeArguments = (args ) ->
113- args = args[.. ]
114- result = []
115- for arg in args
116- if match = arg .match MULTI_FLAG
117- result .push ' -' + l for l in match[1 ].split ' '
118- else
119- result .push arg
120- result
91+ addArgument = (rule , options , value ) ->
92+ options[rule .name ] = if rule .isList
93+ (options[rule .name ] ? []).concat value
94+ else value
95+
96+ tryMatchOptionalArgument = (arg , state , rules ) ->
97+ for rule in rules
98+ if arg in [rule .shortFlag , rule .longFlag ]
99+ if rule .hasArgument
100+ value = state .argsLeft .shift ()
101+ if not value?
102+ throw new Error " #{ arg} requires a value, but was the last argument"
103+ else
104+
105+ value = true
106+ addArgument (rule, state .options , value)
107+ return
108+
109+ throw new Error " unrecognized option: #{ arg} "
0 commit comments