1
- {repeat , isCoffee } = require ' ./helpers'
1
+ {repeat } = require ' ./helpers'
2
2
3
3
# A simple **OptionParser** class to parse option flags from the command-line.
4
4
# Use it like so:
@@ -25,45 +25,26 @@ exports.OptionParser = class OptionParser
25
25
# parsers that allow you to attach callback actions for every flag. Instead,
26
26
# you're responsible for interpreting the options object.
27
27
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 ' --'
47
45
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
67
48
68
49
# Return the help text for this **OptionParser**, listing and describing all
69
50
# of the valid options, for `--help` and such.
@@ -107,14 +88,22 @@ buildRule = (shortFlag, longFlag, description, options = {}) ->
107
88
isList : !! (match and match[2 ])
108
89
}
109
90
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
+ value = true
105
+
106
+ addArgument (rule, state .options , value)
107
+ return
108
+
109
+ throw new Error " unrecognized option: #{ arg} "
0 commit comments