@@ -54,59 +54,31 @@ trait CliCommand:
54
54
end distill
55
55
56
56
/** Creates a help message for a subset of options based on cond */
57
- protected def availableOptionsMsg (cond : Setting [? ] => Boolean )(using settings : ConcreteSettings )(using SettingsState ): String =
58
- val ss = (settings.allSettings filter cond).toList sortBy (_.name)
59
- val maxNameWidth = 30
60
- val nameWidths = ss.map(_.name.length).filter(_ < maxNameWidth)
61
- val width = if nameWidths.nonEmpty then nameWidths.max else maxNameWidth
62
- val terminalWidth = settings.pageWidth.value
63
- val (nameWidth, descriptionWidth) = {
64
- val w1 =
65
- if width < maxNameWidth then width
66
- else maxNameWidth
67
- val w2 =
68
- if terminalWidth < w1 + maxNameWidth then 0
69
- else terminalWidth - w1 - 1
70
- (w1, w2)
71
- }
72
- def formatName (name : String ) =
73
- if name.length <= nameWidth then (" %-" + nameWidth + " s" ) format name
74
- else (name + " \n %-" + nameWidth + " s" ) format " "
75
- def formatDescription (text : String ): String =
76
- if descriptionWidth == 0 then text
77
- else if text.length < descriptionWidth then text
78
- else {
79
- val inx = text.substring(0 , descriptionWidth).lastIndexOf(" " )
80
- if inx < 0 then text
81
- else
82
- val str = text.substring(0 , inx)
83
- s " ${str}\n ${formatName(" " )} ${formatDescription(text.substring(inx + 1 ))}"
84
- }
85
- def formatSetting (name : String , value : String ) =
86
- if (value.nonEmpty)
87
- // the format here is helping to make empty padding and put the additional information exactly under the description.
88
- s " \n ${formatName(" " )} $name: $value. "
89
- else
90
- " "
91
- def helpStr (s : Setting [? ]) =
57
+ protected def availableOptionsMsg (p : Setting [? ] => Boolean )(using settings : ConcreteSettings )(using SettingsState ): String =
58
+ // result is (Option Name, descrption\ndefault: value\nchoices: x, y, z
59
+ def help (s : Setting [? ]): (String , String ) =
60
+ // For now, skip the default values that do not make sense for the end user, such as 'false' for the version command.
92
61
def defaultValue = s.default match
93
62
case _ : Int | _ : String => s.default.toString
94
- case _ =>
95
- // For now, skip the default values that do not make sense for the end user.
96
- // For example 'false' for the version command.
97
- " "
98
- s " ${formatName(s.name)} ${formatDescription(shortHelp(s))}${formatSetting(" Default" , defaultValue)}${formatSetting(" Choices" , s.legalChoices)}"
99
- ss.map(helpStr).mkString(" " , " \n " , s " \n ${formatName(" @<file>" )} ${formatDescription(" A text file containing compiler arguments (options and source files)." )}\n " )
63
+ case _ => " "
64
+ val info = List (shortHelp(s), if defaultValue.nonEmpty then s " Default $defaultValue" else " " , if s.legalChoices.nonEmpty then s " Choices ${s.legalChoices}" else " " )
65
+ (s.name, info.filter(_.nonEmpty).mkString(" \n " ))
66
+ end help
67
+
68
+ val ss = settings.allSettings.filter(p).toList.sortBy(_.name)
69
+ val formatter = Columnator (" " , " " , maxField = 30 )
70
+ val fresh = ContextBase ().initialCtx.fresh.setSettings(summon[SettingsState ])
71
+ formatter(List (ss.map(help) :+ (" @<file>" , " A text file containing compiler arguments (options and source files)." )))(using fresh)
100
72
end availableOptionsMsg
101
73
102
74
protected def shortUsage : String = s " Usage: $cmdName <options> <source files> "
103
75
104
76
protected def createUsageMsg (label : String , shouldExplain : Boolean , cond : Setting [? ] => Boolean )(using settings : ConcreteSettings )(using SettingsState ): String =
105
77
val prefix = List (
106
78
Some (shortUsage),
107
- Some (explainAdvanced) filter (_ => shouldExplain),
79
+ Some (explainAdvanced). filter(_ => shouldExplain),
108
80
Some (label + " options include:" )
109
- ).flatten mkString " \n "
81
+ ).flatten. mkString( " \n " )
110
82
111
83
prefix + " \n " + availableOptionsMsg(cond)
112
84
@@ -143,7 +115,7 @@ trait CliCommand:
143
115
/** Used for the formatted output of -Xshow-phases */
144
116
protected def phasesMessage (using Context ): String =
145
117
val phases = new Compiler ().phases
146
- val formatter = Columnator (" phase name" , " description" , maxField = 25 , separation = 2 )
118
+ val formatter = Columnator (" phase name" , " description" , maxField = 25 )
147
119
formatter(phases.map(mega => mega.map(p => (p.phaseName, p.description))))
148
120
149
121
/** Provide usage feedback on argument summary, assuming that all settings
@@ -177,7 +149,7 @@ trait CliCommand:
177
149
def padLeft (width : Int ): String = StringBuilder ().tap(_.append(" " * (width - s.length)).append(s)).toString
178
150
179
151
// Formatting for -help and -Vphases in two columns, handling long field1 and wrapping long field2
180
- class Columnator (heading1 : String , heading2 : String , maxField : Int , separation : Int = 1 ):
152
+ class Columnator (heading1 : String , heading2 : String , maxField : Int , separation : Int = 2 ):
181
153
def apply (texts : List [List [(String , String )]])(using Context ): String = StringBuilder ().tap(columnate(_, texts)).toString
182
154
183
155
private def columnate (sb : StringBuilder , texts : List [List [(String , String )]])(using Context ): Unit =
@@ -190,21 +162,15 @@ trait CliCommand:
190
162
val field1 = maxField.min(texts.flatten.map(_._1.length).filter(_ < maxField).max) // widest field under maxField
191
163
val field2 = if field1 + separation + maxField < maxCol then maxCol - field1 - separation else 0 // skinny window -> terminal wrap
192
164
val separator = " " * separation
193
- def formatField1 (text : String ): String = if text.length <= field1 then text.padLeft(field1) else EOL + " " .padLeft(field1)
165
+ def formatField1 (text : String ): String = if text.length <= field1 then text.padLeft(field1) else text + EOL + " " .padLeft(field1)
194
166
def formatField2 (text : String ): String =
195
- def loopOverField2 (fld : String ): String =
196
- if field2 == 0 || fld.length <= field2 then fld
167
+ def loopOverField2 (fld : String ): List [ String ] =
168
+ if field2 == 0 || fld.length <= field2 then List ( fld)
197
169
else
198
170
fld.lastIndexOf(" " , field2) match
199
- case - 1 => fld
200
- case i =>
201
- val (prefix, rest) = fld.splitAt(i)
202
- s " ${prefix}${EOL }${formatField1(" " )}${separator}${loopOverField2(rest.trim)}"
203
- def loopOverFields2 (rest : List [String ]): String =
204
- rest match
205
- case h :: t => loopOverField2(h.trim) + loopOverFields2(t)
206
- case Nil => " "
207
- loopOverFields2(text.split(" \n " ).toList)
171
+ case - 1 => List (fld)
172
+ case i => val (prefix, rest) = fld.splitAt(i) ; prefix :: loopOverField2(rest.trim)
173
+ text.split(" \n " ).toList.flatMap(loopOverField2).filter(_.nonEmpty).mkString(EOL + " " .padLeft(field1) + separator)
208
174
end formatField2
209
175
def format (first : String , second : String , index : Int , colorPicker : Int => String => Highlight ) =
210
176
sb.append(colorPicker(index)(formatField1(first)).show)
0 commit comments