11import Lean.Data.RBTree
22
3+ namespace Cli
4+
35section Utils
46 /--
57 Matches the lengths of lists `a` and `b` by filling the shorter one with
@@ -20,7 +22,7 @@ section Utils
2022 return r
2123
2224 def flatMap (f : α → Array β) (xs : Array α) : Array β :=
23- xs.map f |>.join
25+ join ( xs.map f)
2426 end Array
2527
2628 namespace String
@@ -52,7 +54,7 @@ section Utils
5254 Panics if `maxWidth = 0`.
5355 -/
5456 def wrapAt! (s : String) (maxWidth : Nat) : String :=
55- s. wrapAt? maxWidth |>.get!
57+ wrapAt? s maxWidth |>.get!
5658
5759 /--
5860 Deletes all trailing spaces at the end of every line, as seperated by `\n`.
@@ -88,7 +90,7 @@ section Utils
8890 continue
8991 -- if `w` is the first proper word, this will insert a `\n` before the text, which we remove later.
9092 -- `w.wrapAt! maxWidth` ensures that our new line is not already too large.
91- let wordOnNewLine := "\n " ++ w. wrapAt! maxWidth
93+ let wordOnNewLine := "\n " ++ wrapAt! w maxWidth
9294 result := result.push wordOnNewLine
9395 let wrappedLines : Array String := wordOnNewLine.splitOn "\n " |>.toArray
9496 currentLineWidth := wrappedLines[wrappedLines.size - 1 ]!.length + 1
@@ -111,7 +113,7 @@ section Utils
111113 Panics if `maxWidth = 0`.
112114 -/
113115 def wrapWordsAt! (s : String) (maxWidth : Nat) : String :=
114- s. wrapWordsAt? maxWidth |>.get!
116+ wrapWordsAt? s maxWidth |>.get!
115117
116118 /--
117119 Inserts `n` spaces before each line as seperated by `\n` in `s`.
@@ -146,16 +148,16 @@ section Utils
146148 if maxWidth - margin - minRightColumnWidth < 1 then
147149 return none
148150 let rows : Array (List String × String) := rows.map fun (left, right) =>
149- (maxWidth - margin - minRightColumnWidth |> left .wrapWordsAt! |>.splitOn "\n " , right)
151+ (maxWidth - margin - minRightColumnWidth |> String .wrapWordsAt! left |>.splitOn "\n " , right)
150152 let leftColumnWidth :=
151- rows. flatMap (·.1 .map (·.length) |>.toArray)
153+ flatMap (·.1 .map (·.length) |>.toArray) rows
152154 |>.getMax? (· < ·)
153155 |>.get!
154156 let leftColumnWidth := leftColumnWidth + margin
155157 let rows : Array (List String × List String) := rows.map fun (left, right) =>
156- (left, maxWidth - leftColumnWidth |> right .wrapWordsAt! |>.splitOn "\n " )
157- let rows : Array (String × String) := rows. flatMap fun (left, right) =>
158- let (left, right) : List String × List String := left .matchLength right ""
158+ (left, maxWidth - leftColumnWidth |> String .wrapWordsAt! right |>.splitOn "\n " )
159+ let rows : Array (String × String) := flatMap (xs := rows) fun (left, right) =>
160+ let (left, right) : List String × List String := List .matchLength left right ""
159161 left.zip right |>.toArray
160162 let rows : Array String := rows.map fun (left, right) =>
161163 if right = "" then
@@ -174,7 +176,7 @@ section Utils
174176 -/
175177 def renderTable! (rows : Array (String × String)) (maxWidth : Nat) (margin : Nat := 2 )
176178 : String :=
177- rows. renderTable? maxWidth margin |>.get!
179+ renderTable? rows maxWidth margin |>.get!
178180 end Array
179181
180182 namespace Option
@@ -190,8 +192,6 @@ section Utils
190192 end Option
191193end Utils
192194
193- namespace Cli
194-
195195section Configuration
196196 /--
197197 Represents a type that can be parsed to a string and the corresponding name of the type.
@@ -457,9 +457,9 @@ section Configuration
457457 /-- Checks whether `m` has a flag with the corresponding `shortName`. -/
458458 def hasFlagByShortName (m : Meta) (name : String) : Bool := m.flagByShortName? name |>.isSome
459459
460- /--
460+ /--
461461 Adds help (`-h, --help`) and version (`--version`) flags to `m`. Does not add
462- a version flag if `m` does not designate a version.
462+ a version flag if `m` does not designate a version.
463463 -/
464464 def addHelpAndVersionFlags (m : Meta) : Meta := Id.run do
465465 let helpFlag := .paramless
@@ -475,7 +475,7 @@ section Configuration
475475 { m with flags := fixedFlags ++ m.flags }
476476 end Cmd.Meta
477477
478- /--
478+ /--
479479 Represents a recursive variant of `Cmd.Meta` that is used in `Parsed`
480480 to replicate the recursive subcommand structure of a command
481481 without referring to the command itself.
@@ -679,7 +679,7 @@ section Configuration
679679 (subCmds : Array ExtendableCmd := #[])
680680 : ExtendableCmd :=
681681 .mk'
682- ⟨name, parent.meta.parentNames.push parent.meta.name, version?, description, furtherInformation?,
682+ ⟨name, parent.meta.parentNames.push parent.meta.name, version?, description, furtherInformation?,
683683 flags, positionalArgs, variableArg?⟩
684684 run subCmds
685685
@@ -710,7 +710,7 @@ section Configuration
710710 (subCmds : Array ExtendableCmd := #[])
711711 : ExtendableCmd :=
712712 .mkWithHelpAndVersionFlags'
713- ⟨name, parent.meta.parentNames.push parent.meta.name, version?, description, furtherInformation?,
713+ ⟨name, parent.meta.parentNames.push parent.meta.name, version?, description, furtherInformation?,
714714 flags, positionalArgs, variableArg?⟩
715715 run subCmds
716716
@@ -783,18 +783,18 @@ section Configuration
783783 - The output of the parser can be postprocessed and validated.
784784 -/
785785 structure Extension where
786- /--
786+ /--
787787 Priority that dictates how early an extension is applied.
788788 The lower the priority, the later it is applied.
789789 -/
790790 priority : Nat := 1024
791- /--
791+ /--
792792 Extends a command to adjust the displayed help.
793793 The recursive subcommand structure may be mutated.
794794 -/
795795 extend : ExtendableCmd → ExtendableCmd := id
796- /--
797- Processes and validates the output of the parser for the given `ExtendableCmd`.
796+ /--
797+ Processes and validates the output of the parser for the given `ExtendableCmd`.
798798 Takes the `ExtendableCmd` that results from all extensions being applied.
799799 If postprocessing mutates the subcommand structure in `Parsed.cmd`, care must be taken to update
800800 `Parsed.parent?` accordingly as well.
@@ -852,7 +852,7 @@ section Configuration
852852 let subCmdParentNames := parentNames.push c.meta.name
853853 let subCmds := c.subCmds.map (loop · subCmdParentNames)
854854 .init { c.meta with parentNames := parentNames } c.run subCmds c.extension?
855-
855+
856856 /--
857857 Creates a new command. Adds a `-h, --help` and a `--version` flag if `meta` designates a version.
858858 Updates the `parentNames` of all subcommands.
@@ -947,7 +947,7 @@ section Configuration
947947 for ⟨fullName, extension?⟩ in extensions do
948948 extensionIndex := extensionIndex.insert fullName extension?
949949 let rec loop (c : ExtendableCmd) : Cli.Cmd :=
950- let extension? := do extensionIndex.find? (← c.originalFullName?) |>.join
950+ let extension? := do extensionIndex.find? (← c.originalFullName?) |> Option .join
951951 let subCmds := c.subCmds.map loop
952952 .init c.meta c.run subCmds extension?
953953 loop c |>.updateParentNames |> prependOriginalParentNames
@@ -1052,24 +1052,27 @@ section Macro
10521052 (description := $description)
10531053 (flags := $(quote (← flags.getD #[] |>.mapM expandFlag)))
10541054 (positionalArgs := $(quote (← positionalArgs.getD #[] |>.mapM expandPositionalArg)))
1055- (variableArg? := $(quote (← variableArg .join.mapM expandVariableArg)))
1055+ (variableArg? := $(quote (← (Option .join variableArg) .mapM expandVariableArg)))
10561056 (run := $(← expandRunFun run))
10571057 (subCmds := $(quote (subCommands.getD ⟨#[]⟩).getElems))
10581058 (extension? := some <| Array.foldl Extension.then { : Extension } <| Array.qsort
10591059 $(quote (extensions.getD ⟨#[]⟩).getElems) (·.priority > ·.priority)))
10601060end Macro
10611061
10621062section Info
1063+ open Cli.String
1064+ open Cli.Option
1065+
10631066 /-- Maximum width within which all formatted text should fit. -/
10641067 def maxWidth : Nat := 80
10651068 /-- Amount of spaces with which section content is indented. -/
10661069 def indentation : Nat := 4
10671070 /-- Maximum width within which all formatted text should fit, after indentation. -/
10681071 def maxIndentedWidth : Nat := maxWidth - indentation
10691072 /-- Formats `xs` by `String.optJoin`ing the components with a single space. -/
1070- def line (xs : Array String) : String := " " . optJoin xs
1073+ def line (xs : Array String) : String := optJoin xs " "
10711074 /-- Formats `xs` by `String.optJoin`ing the components with a newline `\n`. -/
1072- def lines (xs : Array String) : String := "\n " .optJoin xs
1075+ def lines (xs : Array String) : String := optJoin xs "\n "
10731076
10741077 /--
10751078 Renders a help section with the designated `title` and `content`.
@@ -1088,43 +1091,43 @@ section Info
10881091 else
10891092 return s! "{ title} :"
10901093 lines #[
1091- titleLine?.optStr ,
1092- content |>. wrapWordsAt! maxIndentedWidth |>. indent indentation
1094+ optStr titleLine?,
1095+ wrapWordsAt! content maxIndentedWidth |> indent (n := indentation)
10931096 ]
10941097
10951098 /--
1096- Renders a table using `Array.renderTable!` and then renders a section with
1099+ Renders a table using `Cli. Array.renderTable!` and then renders a section with
10971100 the designated `title` and the rendered table as content.
10981101 -/
10991102 def renderTable
11001103 (title : String)
11011104 (columns : Array (String × String))
11021105 (emptyTablePlaceholder? : Option String := none)
11031106 : String :=
1104- let table := columns .renderTable! (maxWidth := maxIndentedWidth)
1107+ let table := Array .renderTable! columns (maxWidth := maxIndentedWidth)
11051108 renderSection title table emptyTablePlaceholder?
11061109
11071110 namespace Cmd
11081111 private def metaDataInfo (c : Cmd) : String :=
11091112 let version? : Option String := do return s! "[{ ← c.meta.version?} ]"
11101113 lines #[
1111- line #[c.meta.fullName, version?.optStr ] |>. wrapWordsAt! maxWidth,
1112- c.meta.description.wrapWordsAt! maxWidth
1114+ line #[c.meta.fullName, optStr version?] |> wrapWordsAt! ( maxWidth := maxWidth) ,
1115+ wrapWordsAt! c.meta.description maxWidth
11131116 ]
11141117
11151118 private def usageInfo (c : Cmd) : String :=
11161119 let subCmdTitle? : Option String := if ¬c.subCmds.isEmpty then "[SUBCOMMAND]" else none
11171120 let posArgNames : String := line <| c.meta.positionalArgs.map (s! "<{ ·.name} >" )
11181121 let varArgName? : Option String := do return s! "<{ (← c.meta.variableArg?).name} >..."
1119- let info := line #[c.meta.fullName, subCmdTitle?.optStr , "[FLAGS]" , posArgNames, varArgName?.optStr ]
1122+ let info := line #[c.meta.fullName, optStr subCmdTitle?, "[FLAGS]" , posArgNames, optStr varArgName?]
11201123 renderSection "USAGE" info
11211124
11221125 private def flagInfo (c : Cmd) : String :=
11231126 let columns : Array (String × String) := c.meta.flags.map fun flag =>
11241127 let shortName? : Option String := do return s! "-{ ← flag.shortName?} "
1125- let names : String := ", " . optJoin #[shortName?.optStr , s! "--{ flag.longName} " ]
1128+ let names : String := optJoin #[optStr shortName?, s! "--{ flag.longName} " ] ", "
11261129 let type? : Option String := if ¬ flag.isParamless then s! ": { flag.type.name} " else none
1127- (line #[names, type?.optStr ], flag.description)
1130+ (line #[names, optStr type?], flag.description)
11281131 renderTable "FLAGS" columns (emptyTablePlaceholder? := "None" )
11291132
11301133 private def positionalArgInfo (c : Cmd) : String :=
@@ -1148,14 +1151,14 @@ section Info
11481151 "\n " ++ c.flagInfo,
11491152 (if ¬c.meta.positionalArgs.isEmpty ∨ c.meta.hasVariableArg then "\n " else "" ) ++ c.positionalArgInfo,
11501153 (if ¬c.subCmds.isEmpty then "\n " else "" ) ++ c.subCommandInfo,
1151- (if c.meta.hasFurtherInformation then "\n " else "" ) ++ c.meta.furtherInformation?.optStr
1154+ (if c.meta.hasFurtherInformation then "\n " else "" ) ++ optStr c.meta.furtherInformation?
11521155 ]
11531156
11541157 /-- Renders an error for `c` with the designated message `msg`. -/
11551158 def error (c : Cmd) (msg : String) : String :=
11561159 lines #[
1157- msg. wrapWordsAt! maxWidth,
1158- s! "Run `{ c.meta.fullName} -h` for further information.".wrapWordsAt! maxWidth
1160+ wrapWordsAt! msg maxWidth,
1161+ wrapWordsAt! s! "Run `{ c.meta.fullName} -h` for further information." maxWidth
11591162 ]
11601163
11611164 /-- Prints the help for `c`. -/
@@ -1216,7 +1219,7 @@ section Parsing
12161219 return s! " (`--{ flag.longName} `)"
12171220 else
12181221 return s! " (`-{ ← flag.shortName?} `)"
1219- s! "Duplicate flag `{ inputFlag} `{ complementaryName? .optStr} ." )
1222+ s! "Duplicate flag `{ inputFlag} `{ Option .optStr complementaryName? } ." )
12201223 | redundantFlagArg
12211224 (flag : Flag)
12221225 (inputFlag : InputFlag)
@@ -1538,12 +1541,12 @@ section Parsing
15381541 partial def applyExtensions (c : Cmd) : Cmd := Id.run do
15391542 let subCmds := c.subCmds.map applyExtensions
15401543 let c := c.update (subCmds := subCmds)
1541- let some extension := c.extension?
1544+ let some extension := c.extension?
15421545 | return c
15431546 extension.extend (.ofFullCmd c) |>.toFullCmd c
15441547
15451548 /--
1546- Processes `args` by applying all extensions in `c`, `Cmd.parse?`ing the input according to `c`
1549+ Processes `args` by applying all extensions in `c`, `Cmd.parse?`ing the input according to `c`
15471550 and then applying the postprocessing extension of the respective (sub)command that was called.
15481551 Note that `args` designates the list `<foo>` in `somebinary <foo>`.
15491552 Returns either the (sub)command that an error occured in and the corresponding error message or
0 commit comments