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