@@ -51,59 +51,31 @@ trait CliCommand:
5151 end distill
5252
5353 /** Creates a help message for a subset of options based on cond */
54- protected def availableOptionsMsg (cond : Setting [? ] => Boolean )(using settings : ConcreteSettings )(using SettingsState ): String =
55- val ss = (settings.allSettings filter cond).toList sortBy (_.name)
56- val maxNameWidth = 30
57- val nameWidths = ss.map(_.name.length).filter(_ < maxNameWidth)
58- val width = if nameWidths.nonEmpty then nameWidths.max else maxNameWidth
59- val terminalWidth = settings.pageWidth.value
60- val (nameWidth, descriptionWidth) = {
61- val w1 =
62- if width < maxNameWidth then width
63- else maxNameWidth
64- val w2 =
65- if terminalWidth < w1 + maxNameWidth then 0
66- else terminalWidth - w1 - 1
67- (w1, w2)
68- }
69- def formatName (name : String ) =
70- if name.length <= nameWidth then (" %-" + nameWidth + " s" ) format name
71- else (name + " \n %-" + nameWidth + " s" ) format " "
72- def formatDescription (text : String ): String =
73- if descriptionWidth == 0 then text
74- else if text.length < descriptionWidth then text
75- else {
76- val inx = text.substring(0 , descriptionWidth).lastIndexOf(" " )
77- if inx < 0 then text
78- else
79- val str = text.substring(0 , inx)
80- s " ${str}\n ${formatName(" " )} ${formatDescription(text.substring(inx + 1 ))}"
81- }
82- def formatSetting (name : String , value : String ) =
83- if (value.nonEmpty)
84- // the format here is helping to make empty padding and put the additional information exactly under the description.
85- s " \n ${formatName(" " )} $name: $value. "
86- else
87- " "
88- def helpStr (s : Setting [? ]) =
54+ protected def availableOptionsMsg (p : Setting [? ] => Boolean )(using settings : ConcreteSettings )(using SettingsState ): String =
55+ // result is (Option Name, descrption\ndefault: value\nchoices: x, y, z
56+ def help (s : Setting [? ]): (String , String ) =
57+ // For now, skip the default values that do not make sense for the end user, such as 'false' for the version command.
8958 def defaultValue = s.default match
9059 case _ : Int | _ : String => s.default.toString
91- case _ =>
92- // For now, skip the default values that do not make sense for the end user.
93- // For example 'false' for the version command.
94- " "
95- s " ${formatName(s.name)} ${formatDescription(shortHelp(s))}${formatSetting(" Default" , defaultValue)}${formatSetting(" Choices" , s.legalChoices)}"
96- ss.map(helpStr).mkString(" " , " \n " , s " \n ${formatName(" @<file>" )} ${formatDescription(" A text file containing compiler arguments (options and source files)." )}\n " )
60+ case _ => " "
61+ val info = List (shortHelp(s), if defaultValue.nonEmpty then s " Default $defaultValue" else " " , if s.legalChoices.nonEmpty then s " Choices ${s.legalChoices}" else " " )
62+ (s.name, info.filter(_.nonEmpty).mkString(" \n " ))
63+ end help
64+
65+ val ss = settings.allSettings.filter(p).toList.sortBy(_.name)
66+ val formatter = Columnator (" " , " " , maxField = 30 )
67+ val fresh = ContextBase ().initialCtx.fresh.setSettings(summon[SettingsState ])
68+ formatter(List (ss.map(help) :+ (" @<file>" , " A text file containing compiler arguments (options and source files)." )))(using fresh)
9769 end availableOptionsMsg
9870
9971 protected def shortUsage : String = s " Usage: $cmdName <options> <source files> "
10072
10173 protected def createUsageMsg (label : String , shouldExplain : Boolean , cond : Setting [? ] => Boolean )(using settings : ConcreteSettings )(using SettingsState ): String =
10274 val prefix = List (
10375 Some (shortUsage),
104- Some (explainAdvanced) filter (_ => shouldExplain),
76+ Some (explainAdvanced). filter(_ => shouldExplain),
10577 Some (label + " options include:" )
106- ).flatten mkString " \n "
78+ ).flatten. mkString( " \n " )
10779
10880 prefix + " \n " + availableOptionsMsg(cond)
10981
@@ -140,7 +112,7 @@ trait CliCommand:
140112 /** Used for the formatted output of -Xshow-phases */
141113 protected def phasesMessage (using Context ): String =
142114 val phases = new Compiler ().phases
143- val formatter = Columnator (" phase name" , " description" , maxField = 25 , separation = 2 )
115+ val formatter = Columnator (" phase name" , " description" , maxField = 25 )
144116 formatter(phases.map(mega => mega.map(p => (p.phaseName, p.description))))
145117
146118 /** Provide usage feedback on argument summary, assuming that all settings
@@ -174,7 +146,7 @@ trait CliCommand:
174146 def padLeft (width : Int ): String = StringBuilder ().tap(_.append(" " * (width - s.length)).append(s)).toString
175147
176148 // Formatting for -help and -Vphases in two columns, handling long field1 and wrapping long field2
177- class Columnator (heading1 : String , heading2 : String , maxField : Int , separation : Int = 1 ):
149+ class Columnator (heading1 : String , heading2 : String , maxField : Int , separation : Int = 2 ):
178150 def apply (texts : List [List [(String , String )]])(using Context ): String = StringBuilder ().tap(columnate(_, texts)).toString
179151
180152 private def columnate (sb : StringBuilder , texts : List [List [(String , String )]])(using Context ): Unit =
@@ -187,21 +159,15 @@ trait CliCommand:
187159 val field1 = maxField.min(texts.flatten.map(_._1.length).filter(_ < maxField).max) // widest field under maxField
188160 val field2 = if field1 + separation + maxField < maxCol then maxCol - field1 - separation else 0 // skinny window -> terminal wrap
189161 val separator = " " * separation
190- def formatField1 (text : String ): String = if text.length <= field1 then text.padLeft(field1) else EOL + " " .padLeft(field1)
162+ def formatField1 (text : String ): String = if text.length <= field1 then text.padLeft(field1) else text + EOL + " " .padLeft(field1)
191163 def formatField2 (text : String ): String =
192- def loopOverField2 (fld : String ): String =
193- if field2 == 0 || fld.length <= field2 then fld
164+ def loopOverField2 (fld : String ): List [ String ] =
165+ if field2 == 0 || fld.length <= field2 then List ( fld)
194166 else
195167 fld.lastIndexOf(" " , field2) match
196- case - 1 => fld
197- case i =>
198- val (prefix, rest) = fld.splitAt(i)
199- s " ${prefix}${EOL }${formatField1(" " )}${separator}${loopOverField2(rest.trim)}"
200- def loopOverFields2 (rest : List [String ]): String =
201- rest match
202- case h :: t => loopOverField2(h.trim) + loopOverFields2(t)
203- case Nil => " "
204- loopOverFields2(text.split(" \n " ).toList)
168+ case - 1 => List (fld)
169+ case i => val (prefix, rest) = fld.splitAt(i) ; prefix :: loopOverField2(rest.trim)
170+ text.split(" \n " ).toList.flatMap(loopOverField2).filter(_.nonEmpty).mkString(EOL + " " .padLeft(field1) + separator)
205171 end formatField2
206172 def format (first : String , second : String , index : Int , colorPicker : Int => String => Highlight ) =
207173 sb.append(colorPicker(index)(formatField1(first)).show)
0 commit comments