The unpac monorepo manager self-hosting as a monorepo using unpac

Tweak behaviour of --help again (close #201)

+62 -48
+7 -5
CHANGES.md
··· 31 31 indicate the `--help` option in the usage line. Having the error message 32 32 at the end makes it easier to spot. 33 33 34 - - Make `--help` request work in any context, except after `--`. Since 35 - the option has an optional argument value, one had to be carefull 36 - that it would not pickup the next argument and try to parse it 37 - according to `FMT`. This is no longer the case. If the argument 38 - fails to parse `--help=auto` is assumed. (#201). 34 + - Make `--help` request work in any context, except after `--` or on 35 + the arguments after an unknown command error in which case that 36 + error is reported (less confusing). Since the option has an optional 37 + argument value, one had to be carefull that it would not pickup the 38 + next argument and try to parse it according to `FMT`. This is no 39 + longer the case. If the argument fails to parse `--help=auto` is 40 + assumed. (#201). 39 41 40 42 - Deprecation messages are now prepended to the doc strings in the manpage. 41 43
-1
src/cmdliner_cline.ml
··· 254 254 `Error (errs, cl) 255 255 with Completion_requested c -> `Completion c 256 256 257 - 258 257 (* Deprecations *) 259 258 260 259 type deprecated = Cmdliner_info.Arg.t * arg
+13
src/cmdliner_cmd.ml
··· 34 34 Group (i, (parser, cmds)) 35 35 36 36 let name c = Cmdliner_info.Cmd.name (get_info c) 37 + 38 + let name_trie cmds = 39 + let add acc cmd = 40 + let i = get_info cmd in 41 + let name = Cmdliner_info.Cmd.name i in 42 + match Cmdliner_trie.add acc name cmd with 43 + | `New t -> t 44 + | `Replaced (cmd', _) -> 45 + let i' = get_info cmd' and kind = "command" in 46 + invalid_arg @@ 47 + Cmdliner_base.err_multi_def ~kind name Cmdliner_info.Cmd.doc i i' 48 + in 49 + List.fold_left add Cmdliner_trie.empty cmds
+2 -1
src/cmdliner_cmd.mli
··· 21 21 val make : info -> 'a Cmdliner_term.t -> 'a t 22 22 val v : info -> 'a Cmdliner_term.t -> 'a t 23 23 val group : ?default:'a Cmdliner_term.t -> info -> 'a t list -> 'a t 24 + val get_info : 'a t -> info 24 25 val name : 'a t -> string 25 - val get_info : 'a t -> info 26 + val name_trie : 'a t list -> 'a t Cmdliner_trie.t
+40 -41
src/cmdliner_eval.ml
··· 176 176 else Cmdliner_msg.pp_err err_ppf ei ~err); 177 177 Error `Term 178 178 179 - let cmd_name_trie cmds = 180 - let add acc cmd = 181 - let i = Cmdliner_cmd.get_info cmd in 182 - let name = Cmdliner_info.Cmd.name i in 183 - match Cmdliner_trie.add acc name cmd with 184 - | `New t -> t 185 - | `Replaced (cmd', _) -> 186 - let i' = Cmdliner_cmd.get_info cmd' and kind = "command" in 187 - invalid_arg @@ 188 - Cmdliner_base.err_multi_def ~kind name Cmdliner_info.Cmd.doc i i' 189 - in 190 - List.fold_left add Cmdliner_trie.empty cmds 179 + let do_deprecated_msgs ~env err_ppf cl ei = 180 + let cmd = Cmdliner_info.Eval.cmd ei in 181 + let deprecated = Cmdliner_cline.deprecated ~env cl in 182 + match Cmdliner_info.Cmd.deprecated cmd, deprecated with 183 + | None, [] -> () 184 + | depr_cmd, deprs -> 185 + let open Cmdliner_base in 186 + let pp_sep ppf () = 187 + if Option.is_some depr_cmd && deprs <> [] then Fmt.cut ppf (); 188 + in 189 + let subst = Cmdliner_info.Eval.doclang_subst ei in 190 + let pp_cmd_msg ppf cmd = 191 + match Cmdliner_info.Cmd.styled_deprecated ~subst ~errs:err_ppf cmd with 192 + | "" -> () 193 + | msg -> 194 + let name = Cmdliner_info.Cmd.name cmd in 195 + Fmt.pf ppf "@[%a command %a:@[ %a@]@]" 196 + Fmt.deprecated () Fmt.code_or_quote name Fmt.styled_text msg 197 + in 198 + let pp_deprs = Fmt.list (Cmdliner_cline.pp_deprecated ~subst) in 199 + Fmt.pf err_ppf "@[%a @[<v>%a%a%a@]@]@." 200 + Cmdliner_msg.pp_exec_msg ei pp_cmd_msg cmd pp_sep () pp_deprs deprs 191 201 192 202 let cmd_name_dom cmds = 193 203 let cmd_name c = Cmdliner_info.Cmd.name (Cmdliner_cmd.get_info c) in ··· 201 211 | Group (i, (None, children)) -> 202 212 let dom = cmd_name_dom children in 203 213 let err = Cmdliner_msg.err_cmd_missing ~dom in 204 - args, i, parents, Error (`Parse err) 214 + let try_stdopts = true in 215 + args, i, parents, Error (`Parse (try_stdopts, err)) 205 216 in 206 217 let rec loop parents cmd = function 207 218 | ("--" :: _ | [] as rest) -> stop rest parents cmd ··· 216 227 match cmd with 217 228 | Cmd (i, parser) -> rest, i, parents, Ok parser 218 229 | Group (i, (_, children)) -> 219 - let cmd_index = cmd_name_trie children in 230 + let cmd_index = Cmdliner_cmd.name_trie children in 220 231 match Cmdliner_trie.find ~legacy_prefixes cmd_index arg with 221 232 | Ok cmd -> loop (i :: parents) cmd args 222 233 | Error `Not_found -> ··· 225 236 let dom = cmd_name_dom children in 226 237 let kind = "command" in 227 238 let err = Cmdliner_base.err_unknown ~kind ~dom ~hints arg in 228 - rest, i, parents, Error (`Parse err) 239 + let try_stdopts = 240 + (* When we users writes cmd no_such_cmd --help it's 241 + better to show the unknown command error message 242 + rather than get into the help of the parent command. 243 + Otherwise one gets confused into thinking the 244 + command exists and/or annoyed not be reading the right 245 + man page. *) 246 + false 247 + in 248 + rest, i, parents, Error (`Parse (try_stdopts, err)) 229 249 | Error `Ambiguous (* Only on legacy prefixes *) -> 230 250 let ambs = Cmdliner_trie.ambiguities cmd_index arg in 231 251 let ambs = List.sort compare ambs in 232 252 let err = Cmdliner_base.err_ambiguous ~kind:"command" arg ~ambs in 233 - rest, i, parents, Error (`Parse err) 253 + let try_stdopts = true in 254 + rest, i, parents, Error (`Parse (try_stdopts, err)) 234 255 in 235 256 loop [] cmd args 236 257 ··· 239 260 | exec :: args -> false, args 240 261 | [] -> invalid_arg err_argv 241 262 242 - let do_deprecated_msgs ~env err_ppf cl ei = 243 - let cmd = Cmdliner_info.Eval.cmd ei in 244 - let deprecated = Cmdliner_cline.deprecated ~env cl in 245 - match Cmdliner_info.Cmd.deprecated cmd, deprecated with 246 - | None, [] -> () 247 - | depr_cmd, deprs -> 248 - let open Cmdliner_base in 249 - let pp_sep ppf () = 250 - if Option.is_some depr_cmd && deprs <> [] then Fmt.cut ppf (); 251 - in 252 - let subst = Cmdliner_info.Eval.doclang_subst ei in 253 - let pp_cmd_msg ppf cmd = 254 - match Cmdliner_info.Cmd.styled_deprecated ~subst ~errs:err_ppf cmd with 255 - | "" -> () 256 - | msg -> 257 - let name = Cmdliner_info.Cmd.name cmd in 258 - Fmt.pf ppf "@[%a command %a:@[ %a@]@]" 259 - Fmt.deprecated () Fmt.code_or_quote name Fmt.styled_text msg 260 - in 261 - let pp_deprs = Fmt.list (Cmdliner_cline.pp_deprecated ~subst) in 262 - Fmt.pf err_ppf "@[%a @[<v>%a%a%a@]@]@." 263 - Cmdliner_msg.pp_exec_msg ei pp_cmd_msg cmd pp_sep () pp_deprs deprs 264 - 265 263 let eval_value 266 264 ?help:(help_ppf = Format.std_formatter) 267 265 ?err:(err_ppf = Format.err_formatter) ··· 279 277 Cmdliner_cline.create ~legacy_prefixes ~for_completion term_args args 280 278 in 281 279 let res = match res with 282 - | Error (`Parse msg) -> 283 - (* Command lookup error, still prioritize stdargs *) 280 + | Error (`Parse (try_stdopts, msg)) -> 281 + (* Command lookup error, we may still prioritize stdargs *) 284 282 begin match cline with 285 283 | `Completion compl -> Error (`Complete (term_args, cmd, [], compl)) 286 284 | `Error (_, cl) | `Ok cl -> 285 + if not try_stdopts then Error (`Error (true, msg)) else 287 286 begin match try_eval_stdopts ~catch ei cl help version with 288 287 | Some e -> e 289 288 | None -> Error (`Error (true, msg))