···3131 indicate the `--help` option in the usage line. Having the error message
3232 at the end makes it easier to spot.
33333434-- Make `--help` request work in any context, except after `--`. Since
3535- the option has an optional argument value, one had to be carefull
3636- that it would not pickup the next argument and try to parse it
3737- according to `FMT`. This is no longer the case. If the argument
3838- fails to parse `--help=auto` is assumed. (#201).
3434+- Make `--help` request work in any context, except after `--` or on
3535+ the arguments after an unknown command error in which case that
3636+ error is reported (less confusing). Since the option has an optional
3737+ argument value, one had to be carefull that it would not pickup the
3838+ next argument and try to parse it according to `FMT`. This is no
3939+ longer the case. If the argument fails to parse `--help=auto` is
4040+ assumed. (#201).
39414042- Deprecation messages are now prepended to the doc strings in the manpage.
4143
-1
src/cmdliner_cline.ml
···254254 `Error (errs, cl)
255255 with Completion_requested c -> `Completion c
256256257257-258257(* Deprecations *)
259258260259type deprecated = Cmdliner_info.Arg.t * arg
+13
src/cmdliner_cmd.ml
···3434 Group (i, (parser, cmds))
35353636let name c = Cmdliner_info.Cmd.name (get_info c)
3737+3838+let name_trie cmds =
3939+ let add acc cmd =
4040+ let i = get_info cmd in
4141+ let name = Cmdliner_info.Cmd.name i in
4242+ match Cmdliner_trie.add acc name cmd with
4343+ | `New t -> t
4444+ | `Replaced (cmd', _) ->
4545+ let i' = get_info cmd' and kind = "command" in
4646+ invalid_arg @@
4747+ Cmdliner_base.err_multi_def ~kind name Cmdliner_info.Cmd.doc i i'
4848+ in
4949+ List.fold_left add Cmdliner_trie.empty cmds
+2-1
src/cmdliner_cmd.mli
···2121val make : info -> 'a Cmdliner_term.t -> 'a t
2222val v : info -> 'a Cmdliner_term.t -> 'a t
2323val group : ?default:'a Cmdliner_term.t -> info -> 'a t list -> 'a t
2424+val get_info : 'a t -> info
2425val name : 'a t -> string
2525-val get_info : 'a t -> info
2626+val name_trie : 'a t list -> 'a t Cmdliner_trie.t
+40-41
src/cmdliner_eval.ml
···176176 else Cmdliner_msg.pp_err err_ppf ei ~err);
177177 Error `Term
178178179179-let cmd_name_trie cmds =
180180- let add acc cmd =
181181- let i = Cmdliner_cmd.get_info cmd in
182182- let name = Cmdliner_info.Cmd.name i in
183183- match Cmdliner_trie.add acc name cmd with
184184- | `New t -> t
185185- | `Replaced (cmd', _) ->
186186- let i' = Cmdliner_cmd.get_info cmd' and kind = "command" in
187187- invalid_arg @@
188188- Cmdliner_base.err_multi_def ~kind name Cmdliner_info.Cmd.doc i i'
189189- in
190190- List.fold_left add Cmdliner_trie.empty cmds
179179+let do_deprecated_msgs ~env err_ppf cl ei =
180180+ let cmd = Cmdliner_info.Eval.cmd ei in
181181+ let deprecated = Cmdliner_cline.deprecated ~env cl in
182182+ match Cmdliner_info.Cmd.deprecated cmd, deprecated with
183183+ | None, [] -> ()
184184+ | depr_cmd, deprs ->
185185+ let open Cmdliner_base in
186186+ let pp_sep ppf () =
187187+ if Option.is_some depr_cmd && deprs <> [] then Fmt.cut ppf ();
188188+ in
189189+ let subst = Cmdliner_info.Eval.doclang_subst ei in
190190+ let pp_cmd_msg ppf cmd =
191191+ match Cmdliner_info.Cmd.styled_deprecated ~subst ~errs:err_ppf cmd with
192192+ | "" -> ()
193193+ | msg ->
194194+ let name = Cmdliner_info.Cmd.name cmd in
195195+ Fmt.pf ppf "@[%a command %a:@[ %a@]@]"
196196+ Fmt.deprecated () Fmt.code_or_quote name Fmt.styled_text msg
197197+ in
198198+ let pp_deprs = Fmt.list (Cmdliner_cline.pp_deprecated ~subst) in
199199+ Fmt.pf err_ppf "@[%a @[<v>%a%a%a@]@]@."
200200+ Cmdliner_msg.pp_exec_msg ei pp_cmd_msg cmd pp_sep () pp_deprs deprs
191201192202let cmd_name_dom cmds =
193203 let cmd_name c = Cmdliner_info.Cmd.name (Cmdliner_cmd.get_info c) in
···201211 | Group (i, (None, children)) ->
202212 let dom = cmd_name_dom children in
203213 let err = Cmdliner_msg.err_cmd_missing ~dom in
204204- args, i, parents, Error (`Parse err)
214214+ let try_stdopts = true in
215215+ args, i, parents, Error (`Parse (try_stdopts, err))
205216 in
206217 let rec loop parents cmd = function
207218 | ("--" :: _ | [] as rest) -> stop rest parents cmd
···216227 match cmd with
217228 | Cmd (i, parser) -> rest, i, parents, Ok parser
218229 | Group (i, (_, children)) ->
219219- let cmd_index = cmd_name_trie children in
230230+ let cmd_index = Cmdliner_cmd.name_trie children in
220231 match Cmdliner_trie.find ~legacy_prefixes cmd_index arg with
221232 | Ok cmd -> loop (i :: parents) cmd args
222233 | Error `Not_found ->
···225236 let dom = cmd_name_dom children in
226237 let kind = "command" in
227238 let err = Cmdliner_base.err_unknown ~kind ~dom ~hints arg in
228228- rest, i, parents, Error (`Parse err)
239239+ let try_stdopts =
240240+ (* When we users writes cmd no_such_cmd --help it's
241241+ better to show the unknown command error message
242242+ rather than get into the help of the parent command.
243243+ Otherwise one gets confused into thinking the
244244+ command exists and/or annoyed not be reading the right
245245+ man page. *)
246246+ false
247247+ in
248248+ rest, i, parents, Error (`Parse (try_stdopts, err))
229249 | Error `Ambiguous (* Only on legacy prefixes *) ->
230250 let ambs = Cmdliner_trie.ambiguities cmd_index arg in
231251 let ambs = List.sort compare ambs in
232252 let err = Cmdliner_base.err_ambiguous ~kind:"command" arg ~ambs in
233233- rest, i, parents, Error (`Parse err)
253253+ let try_stdopts = true in
254254+ rest, i, parents, Error (`Parse (try_stdopts, err))
234255 in
235256 loop [] cmd args
236257···239260| exec :: args -> false, args
240261| [] -> invalid_arg err_argv
241262242242-let do_deprecated_msgs ~env err_ppf cl ei =
243243- let cmd = Cmdliner_info.Eval.cmd ei in
244244- let deprecated = Cmdliner_cline.deprecated ~env cl in
245245- match Cmdliner_info.Cmd.deprecated cmd, deprecated with
246246- | None, [] -> ()
247247- | depr_cmd, deprs ->
248248- let open Cmdliner_base in
249249- let pp_sep ppf () =
250250- if Option.is_some depr_cmd && deprs <> [] then Fmt.cut ppf ();
251251- in
252252- let subst = Cmdliner_info.Eval.doclang_subst ei in
253253- let pp_cmd_msg ppf cmd =
254254- match Cmdliner_info.Cmd.styled_deprecated ~subst ~errs:err_ppf cmd with
255255- | "" -> ()
256256- | msg ->
257257- let name = Cmdliner_info.Cmd.name cmd in
258258- Fmt.pf ppf "@[%a command %a:@[ %a@]@]"
259259- Fmt.deprecated () Fmt.code_or_quote name Fmt.styled_text msg
260260- in
261261- let pp_deprs = Fmt.list (Cmdliner_cline.pp_deprecated ~subst) in
262262- Fmt.pf err_ppf "@[%a @[<v>%a%a%a@]@]@."
263263- Cmdliner_msg.pp_exec_msg ei pp_cmd_msg cmd pp_sep () pp_deprs deprs
264264-265263let eval_value
266264 ?help:(help_ppf = Format.std_formatter)
267265 ?err:(err_ppf = Format.err_formatter)
···279277 Cmdliner_cline.create ~legacy_prefixes ~for_completion term_args args
280278 in
281279 let res = match res with
282282- | Error (`Parse msg) ->
283283- (* Command lookup error, still prioritize stdargs *)
280280+ | Error (`Parse (try_stdopts, msg)) ->
281281+ (* Command lookup error, we may still prioritize stdargs *)
284282 begin match cline with
285283 | `Completion compl -> Error (`Complete (term_args, cmd, [], compl))
286284 | `Error (_, cl) | `Ok cl ->
285285+ if not try_stdopts then Error (`Error (true, msg)) else
287286 begin match try_eval_stdopts ~catch ei cl help version with
288287 | Some e -> e
289288 | None -> Error (`Error (true, msg))