@@ -38,18 +38,12 @@ object Settings:
38
38
this
39
39
end SettingsState
40
40
41
- case class ArgsSummary (
42
- sstate : SettingsState ,
43
- arguments : List [String ],
44
- errors : List [String ],
45
- warnings : List [String ]) {
41
+ case class ArgsSummary (sstate : SettingsState , arguments : List [String ], errors : List [String ], warnings : List [String ])
46
42
47
- def fail (msg : String ): Settings .ArgsSummary =
48
- ArgsSummary (sstate, arguments.tail, errors :+ msg, warnings)
49
-
50
- def warn (msg : String ): Settings .ArgsSummary =
51
- ArgsSummary (sstate, arguments.tail, errors, warnings :+ msg)
52
- }
43
+ extension (summary : ArgsSummary )
44
+ def fail (msg : String ): ArgsSummary = summary.copy(errors = summary.errors :+ msg)
45
+ def warn (msg : String ): ArgsSummary = summary.copy(warnings = summary.warnings :+ msg)
46
+ def skip (): ArgsSummary = summary.copy(arguments = if summary.arguments.isEmpty then Nil else summary.arguments.tail)
53
47
54
48
case class Setting [T : ClassTag ] private [Settings ] (
55
49
name : String ,
@@ -72,7 +66,7 @@ object Settings:
72
66
73
67
def isDefaultIn (state : SettingsState ): Boolean = valueIn(state) == default
74
68
75
- def isMultivalue : Boolean = implicitly [ClassTag [T ]] == ListTag
69
+ def isMultivalue : Boolean = summon [ClassTag [T ]] == ListTag
76
70
77
71
def legalChoices : String =
78
72
choices match {
@@ -85,91 +79,92 @@ object Settings:
85
79
def tryToSet (state : ArgsSummary ): ArgsSummary = {
86
80
val ArgsSummary (sstate, arg :: args, errors, warnings) = state
87
81
def update (value : Any , args : List [String ]): ArgsSummary =
88
- var dangers = warnings
89
82
val value1 =
90
- if changed && isMultivalue then
91
- val value0 = value.asInstanceOf [List [String ]]
92
- val current = valueIn(sstate).asInstanceOf [List [String ]]
93
- value0.filter(current.contains).foreach(s => dangers :+= s " Setting $name set to $s redundantly " )
94
- current ++ value0
95
- else
96
- if changed then dangers :+= s " Flag $name set repeatedly "
97
- value
83
+ if isMultivalue then valueIn(sstate).asInstanceOf [List [String ]] ++ value.asInstanceOf [List [String ]]
84
+ else value
98
85
changed = true
99
- ArgsSummary (updateIn(sstate, value1), args, errors, dangers)
100
- end update
86
+ ArgsSummary (updateIn(sstate, value1), args, errors, warnings)
87
+
88
+ def fail (msg : String , args : List [String ]) = ArgsSummary (sstate, args, errors :+ msg, warnings)
101
89
102
- def fail (msg : String , args : List [String ]) =
103
- ArgsSummary (sstate, args, errors :+ msg, warnings)
90
+ def missingArg = fail(s " missing argument for option $name" , args)
104
91
105
- def missingArg =
106
- fail(s " missing argument for option $name" , args)
92
+ def setBoolean (argValue : String ) =
93
+ def checkAndSet (v : Boolean ) =
94
+ val dubious = changed && v != valueIn(sstate).asInstanceOf [Boolean ]
95
+ val updated = update(v, args)
96
+ if dubious then updated.warn(s " Boolean flag $name flipped " ) else updated
97
+ if argValue.equalsIgnoreCase(" true" ) || argValue == " " then checkAndSet(true )
98
+ else if argValue.equalsIgnoreCase(" false" ) then checkAndSet(false )
99
+ else fail(s " invalid boolean value $argValue" , args)
107
100
108
101
def setString (argValue : String , args : List [String ]) =
109
102
choices match
110
- case Some (xs) if ! xs.contains(argValue) =>
111
- fail(s " $argValue is not a valid choice for $name" , args)
112
- case _ =>
113
- update(argValue, args)
103
+ case Some (xs) if ! xs.contains(argValue) => fail(s " $argValue is not a valid choice for $name" , args)
104
+ case _ if changed && argValue != valueIn(sstate).asInstanceOf [String ] => update(argValue, args).warn(s " Option $name was updated " )
105
+ case _ => update(argValue, args)
114
106
115
107
def setInt (argValue : String , args : List [String ]) =
116
108
try
117
109
val x = argValue.toInt
118
110
choices match
119
- case Some (r : Range ) if x < r.head || r.last < x =>
120
- fail(s " $argValue is out of legal range ${r.head} .. ${r.last} for $name" , args)
121
- case Some (xs) if ! xs.contains(x) =>
122
- fail(s " $argValue is not a valid choice for $name" , args)
123
- case _ =>
124
- update(x, args)
125
- catch case _ : NumberFormatException =>
126
- fail( s " $argValue is not an integer argument for $name " , args)
127
-
128
- def doSet ( argRest : String ) = ((implicitly[ ClassTag [ T ]], args) : @ unchecked) match {
129
- case ( BooleanTag , _) =>
130
- update( true , args)
131
- case ( OptionTag , _) =>
132
- update( Some (propertyClass.get.getConstructor().newInstance()), args)
133
- case ( ListTag , _) =>
134
- if (argRest.isEmpty) missingArg
135
- else
136
- val strings = argRest.split( " , " ).toList
137
- choices match
138
- case Some (valid) => strings .filterNot(valid.contains) match
139
- case Nil => update(strings, args)
111
+ case Some (r : Range ) if x < r.head || r.last < x => fail( s " $argValue is out of legal range ${r.head} .. ${r.last} for $name " , args)
112
+ case Some (xs) if ! xs.contains(x) => fail(s " $argValue is not a valid choice for $name" , args)
113
+ case _ => update(x, args)
114
+ catch case _ : NumberFormatException => fail(s " $argValue is not an integer argument for $name" , args)
115
+
116
+ def doSet ( argRest : String ) : ArgsSummary = (summon[ ClassTag [ T ]] : @ unchecked) match {
117
+ case BooleanTag => setBoolean(argRest)
118
+ case OptionTag => update( Some (propertyClass.get.getConstructor().newInstance()) , args)
119
+ case ListTag if argRest.isEmpty => missingArg
120
+ case ListTag =>
121
+ val split = argRest.split( " , " ).toList
122
+ def checkRepeated =
123
+ var dangers : List [ String ] = Nil
124
+ if changed then
125
+ val current = valueIn(sstate). asInstanceOf [ List [ String ]]
126
+ split.filter(current.contains).foreach(s => dangers :+= s " Setting $name set to $s redundantly " )
127
+ dangers.foldLeft(update(split, args))((sum, w) => sum.warn(w))
128
+ choices match
129
+ case Some (valid) =>
130
+ split .filterNot(valid.contains) match
131
+ case Nil => checkRepeated
140
132
case invalid => fail(s " invalid choice(s) for $name: ${invalid.mkString(" ," )}" , args)
141
- case _ => update(strings, args)
142
- case (StringTag , _) if argRest.nonEmpty || choices.exists(_.contains(" " )) =>
143
- setString(argRest, args)
144
- case (StringTag , arg2 :: args2) =>
145
- if (arg2 startsWith " -" ) missingArg
146
- else setString(arg2, args2)
147
- case (OutputTag , arg :: args) =>
148
- val path = Directory (arg)
149
- val isJar = path.extension == " jar"
150
- if (! isJar && ! path.isDirectory)
151
- fail(s " ' $arg' does not exist or is not a directory or .jar file " , args)
152
- else {
153
- val output = if (isJar) JarArchive .create(path) else new PlainDirectory (path)
154
- update(output, args)
155
- }
156
- case (IntTag , args) if argRest.nonEmpty =>
157
- setInt(argRest, args)
158
- case (IntTag , arg2 :: args2) =>
159
- setInt(arg2, args2)
160
- case (VersionTag , _) =>
133
+ case _ => checkRepeated
134
+ case StringTag if argRest.nonEmpty || choices.exists(_.contains(" " )) => setString(argRest, args)
135
+ case StringTag =>
136
+ args match
137
+ case arg2 :: _ if arg2.startsWith(" -" ) => missingArg
138
+ case arg2 :: args2 => setString(arg2, args2)
139
+ case _ => missingArg
140
+ case OutputTag =>
141
+ args match
142
+ case arg :: rest =>
143
+ val path = Directory (arg)
144
+ val isJar = path.extension == " jar"
145
+ if (! isJar && ! path.isDirectory) fail(s " ' $arg' does not exist or is not a directory or .jar file " , rest)
146
+ else
147
+ val output = if (isJar) JarArchive .create(path) else new PlainDirectory (path)
148
+ update(output, rest)
149
+ case _ => missingArg
150
+ case IntTag if argRest.nonEmpty => setInt(argRest, args)
151
+ case IntTag =>
152
+ args match
153
+ case arg :: rest => setInt(arg, rest)
154
+ case _ => missingArg
155
+ case VersionTag =>
161
156
ScalaVersion .parse(argRest) match {
162
157
case Success (v) => update(v, args)
163
- case Failure (ex ) => fail(ex .getMessage, args)
158
+ case Failure (x ) => fail(x .getMessage, args)
164
159
}
165
- case (_, Nil ) =>
166
- missingArg
160
+ case _ => missingArg
167
161
}
168
162
169
163
def matches (argName : String ) = (name :: aliases).exists(_ == argName)
170
164
165
+ // begin
171
166
if (prefix != " " && arg.startsWith(prefix))
172
- doSet(arg drop prefix.length)
167
+ doSet(arg. drop( prefix.length) )
173
168
else if (prefix == " " && matches(arg.takeWhile(_ != ':' )))
174
169
doSet(arg.dropWhile(_ != ':' ).drop(1 ))
175
170
else
@@ -236,7 +231,7 @@ object Settings:
236
231
if state1 ne state then state1
237
232
else loop(settings1)
238
233
case Nil =>
239
- state.warn(s " bad option ' $x' was ignored " )
234
+ state.warn(s " bad option ' $x' was ignored " ).skip()
240
235
processArguments(loop(allSettings.toList), processAll, skipped)
241
236
case arg :: args =>
242
237
if processAll then processArguments(stateWithArgs(args), processAll, skipped :+ arg)
0 commit comments