diff --git a/B0.ml b/B0.ml index 7a65936..40d2aac 100644 --- a/B0.ml +++ b/B0.ml @@ -1,5 +1,4 @@ open B0_kit.V000 -open B00_std (* OCaml library names *) diff --git a/CHANGES.md b/CHANGES.md index 496860f..67d7f8e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,18 @@ +v1.2.0 2023-04-10 La Forclaz (VS) +--------------------------------- + +- In manpage specification the new variable `$(iname)` substitutes the + command invocation (from program name to subcommand) in bold (#168). + This variable is now used in the default introduction of the `EXIT STATUS` + section. Thanks to Ali Caglayan for suggesting. +- Fix manpage rendering when `PAGER=less` is set (#167). +- Plain text manpage rendering: fix broken handling of `` `Noblank ``. + Thanks to Michael Richards and Reynir Björnsson for the report (#176). +- Fix install to directory with spaces (#172). Thanks to + @ZSFactory for reporting and suggesting the fix. +- Fix manpage paging on Windows (#166). Thanks to Nicolás Ojeda Bär + for the report and the solution. + v1.1.1 2022-03-23 La Forclaz (VS) --------------------------------- @@ -102,7 +117,7 @@ * If you relied on `?term_err` defaulting to `1` in the various `Term.exit*` function, note that the new `Cmd.eval*` function use - `Exit.cli_error` as a default. You may want to explicitely specify + `Exit.cli_error` as a default. You may want to explicitly specify `1` instead if you use `Term.ret` with the `` `Error`` case or `Term.term_result`. @@ -258,7 +273,7 @@ whenever unspecified in the man page. - Better automatic insertions of man page sections (#73). See the API docs about manual specification. As a side effect the `NAME` section - can now also be overriden manually. + can now also be overridden manually. - Fix repeated environment variable printing for flags (#64). Thanks to Thomas Gazagnaire for the report. - Fix rendering of env vars in man pages, bold is standard (#71). @@ -310,7 +325,7 @@ - Deprecate `Term.pure` in favor of `Term.const`. - Man page generation. Keep undefined variables untouched. Previously a `$(undef)` would be turned into `undef`. -- Turn a few misterious and spurious `Not_found` exceptions into +- Turn a few mysterious and spurious `Not_found` exceptions into `Invalid_arg`. These can be triggered by client programming errors (e.g. an unclosed variable in a documentation string). - Positional arguments. Invoke the printer on the default (absent) @@ -363,7 +378,7 @@ - Remove temporary files created for paged help. Thanks to Kaustuv Chaudhuri for the suggestion. - Avoid linking against `Oo` (was used to get program uuid). -- Check the environment for `$MANPAGER` aswell. Thanks to Raphaël Proust +- Check the environment for `$MANPAGER` as well. Thanks to Raphaël Proust for the patch. - OPAM friendly workflow and drop OASIS support. diff --git a/Makefile b/Makefile index aa0a104..a3921d7 100644 --- a/Makefile +++ b/Makefile @@ -40,10 +40,10 @@ install: $(INSTALL-TARGETS) install-doc: - $(INSTALL) -d $(DOCDIR)/odoc-pages - $(INSTALL) CHANGES.md LICENSE.md README.md $(DOCDIR) + $(INSTALL) -d "$(DOCDIR)/odoc-pages" + $(INSTALL) CHANGES.md LICENSE.md README.md "$(DOCDIR)" $(INSTALL) doc/index.mld doc/cli.mld doc/examples.mld doc/tutorial.mld \ - doc/tool_man.mld $(DOCDIR)/odoc-pages + doc/tool_man.mld "$(DOCDIR)/odoc-pages" clean: ocaml build.ml clean @@ -58,21 +58,21 @@ ocaml build.ml cmxs create-libdir: - $(INSTALL) -d $(LIBDIR) + $(INSTALL) -d "$(LIBDIR)" install-common: create-libdir - $(INSTALL) pkg/META $(BASE).mli $(BASE).cmi $(BASE).cmti $(LIBDIR) - $(INSTALL) cmdliner.opam $(LIBDIR)/opam + $(INSTALL) pkg/META $(BASE).mli $(BASE).cmi $(BASE).cmti "$(LIBDIR)" + $(INSTALL) cmdliner.opam "$(LIBDIR)/opam" install-byte: create-libdir - $(INSTALL) $(BASE).cma $(LIBDIR) + $(INSTALL) $(BASE).cma "$(LIBDIR)" install-native: create-libdir $(INSTALL) $(BASE).cmxa $(BASE)$(EXT_LIB) $(wildcard $(B)/cmdliner*.cmx) \ - $(LIBDIR) + "$(LIBDIR)" install-native-dynlink: create-libdir - $(INSTALL) $(BASE).cmxs $(LIBDIR) + $(INSTALL) $(BASE).cmxs "$(LIBDIR)" .PHONY: all install install-doc clean build-byte build-native \ build-native-dynlink create-libdir install-common install-byte \ diff --git a/README.md b/README.md index 5a348eb..6e5ff4c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ Cmdliner — Declarative definition of command line interfaces for OCaml ------------------------------------------------------------------------------- -v1.1.1 +v1.2.0 Cmdliner allows the declarative definition of command line interfaces for OCaml. diff --git a/cmdliner.opam b/cmdliner.opam index 7c2dd08..f8e67f8 100644 --- a/cmdliner.opam +++ b/cmdliner.opam @@ -1,4 +1,4 @@ -version: "1.1.1" +version: "1.2.0" opam-version: "2.0" name: "cmdliner" synopsis: """Declarative definition of command line interfaces for OCaml""" diff --git a/doc/examples.mld b/doc/examples.mld index e8543ca..8ac8821 100644 --- a/doc/examples.mld +++ b/doc/examples.mld @@ -79,7 +79,7 @@ `S Manpage.s_bugs; `P "Report bugs to ."; `S Manpage.s_see_also; `P "$(b,rmdir)(1), $(b,unlink)(2)" ] in - let info = Cmd.info "rm" ~version:"v1.1.1" ~doc ~man in + let info = Cmd.info "rm" ~version:"v1.2.0" ~doc ~man in Cmd.v info Term.(const rm $ prompt $ recursive $ files) let main () = exit (Cmd.eval cmd) @@ -149,7 +149,7 @@ [ `S Manpage.s_bugs; `P "Email them to ."; ] in - let info = Cmd.info "cp" ~version:"v1.1.1" ~doc ~man ~man_xrefs in + let info = Cmd.info "cp" ~version:"v1.2.0" ~doc ~man ~man_xrefs in Cmd.v info Term.(ret (const cp $ verbose $ recurse $ force $ srcs $ dest)) @@ -258,7 +258,7 @@ `S Manpage.s_see_also; `P "$(b,cat)(1), $(b,head)(1)" ] in - let info = Cmd.info "tail" ~version:"v1.1.1" ~doc ~man in + let info = Cmd.info "tail" ~version:"v1.2.0" ~doc ~man in Cmd.v info Term.(const tail $ lines $ follow $ verb $ pid $ files) @@ -435,7 +435,7 @@ let main_cmd = let doc = "a revision control system" in let man = help_secs in - let info = Cmd.info "darcs" ~version:"v1.1.1" ~doc ~sdocs ~man in + let info = Cmd.info "darcs" ~version:"v1.2.0" ~doc ~sdocs ~man in let default = Term.(ret (const (fun _ -> `Help (`Pager, None)) $ copts_t)) in Cmd.group info ~default [initialize_cmd; record_cmd; help_cmd] diff --git a/doc/index.mld b/doc/index.mld index b543c04..962dd49 100644 --- a/doc/index.mld +++ b/doc/index.mld @@ -1,4 +1,4 @@ -{0 Cmdliner {%html: v1.1.1%}} +{0 Cmdliner {%html: v1.2.0%}} [Cmdliner] provides a simple and compositional mechanism to convert command line arguments to OCaml values and pass them to diff --git a/doc/tool_man.mld b/doc/tool_man.mld index 0abf475..7029d34 100644 --- a/doc/tool_man.mld +++ b/doc/tool_man.mld @@ -4,8 +4,8 @@ Man page sections for a command are printed in the order specified by manual as given to {!Cmdliner.Cmd.val-info}. Unless specified -explicitely in the command's manual the following sections are -automaticaly created and populated for you: +explicitly in the command's manual the following sections are +automatically created and populated for you: {ul {- {{!Cmdliner.Manpage.s_name}[NAME]} section.} @@ -35,7 +35,7 @@ is inserted at the right place in the order specified {{!Cmdliner.Manpage.standard_sections}here}, but after a possible non-standard - section explicitely specified by the command's manual since the latter + section explicitly specified by the command's manual since the latter get the order number of the last previously specified standard section or the order of {!Cmdliner.Manpage.s_synopsis} if there is no such section.} {- non-standard, it is inserted before the {!Cmdliner.Manpage.s_commands} @@ -66,5 +66,5 @@ mandatory only in markup directives. Escaping ( is only here for your symmetric pleasure. Any other sequence of characters starting with a \ is an illegal character sequence.} -{- Refering to unknown markup directives or variables will generate +{- Referring to unknown markup directives or variables will generate errors on standard error during documentation generation.}} diff --git a/doc/tutorial.mld b/doc/tutorial.mld index 528f9c4..a950e66 100644 --- a/doc/tutorial.mld +++ b/doc/tutorial.mld @@ -5,9 +5,9 @@ With [Cmdliner] your tool's [main] function evaluates a command. A command is a value of type {!Cmdliner.Cmd.t} which gathers a command -name with a term of type {!Cmdliner.Term.t}. The type parameter of -the term (and the command) indicates the type of the result of the -evaluation. +name and a term of type {!Cmdliner.Term.t}. A term is an expression to +be evaluated. The type parameter of the term (and the command) +indicates the type of the result of the evaluation. One way to create terms is by lifting regular OCaml values with {!Cmdliner.Term.const}. Terms can be applied to terms evaluating to diff --git a/dune b/dune new file mode 100644 index 0000000..d117085 --- /dev/null +++ b/dune @@ -0,0 +1 @@ +(env (_ (flags -g -bin-annot -safe-string))) ; Use the same flags as with ocamlbuild diff --git a/pkg/META b/pkg/META index 0eba8e8..34d8083 100644 --- a/pkg/META +++ b/pkg/META @@ -1,4 +1,4 @@ -version = "v1.1.1" +version = "v1.2.0" description = "Declarative definition of command line interfaces" requires = "" archive(byte) = "cmdliner.cma" diff --git a/src/cmdliner.mli b/src/cmdliner.mli index 43622e2..1932d9c 100644 --- a/src/cmdliner.mli +++ b/src/cmdliner.mli @@ -347,7 +347,7 @@ {- [$(mname)] the main term's name.}} *) val name : info -> string - [@@ocaml.deprecated "Use Cmd.info_name instead."] + [@@ocaml.deprecated "Use Cmd.name instead."] (** [name ti] is the name of the term information. *) (** {2:evaluation Evaluation} *) @@ -604,7 +604,7 @@ ?man:Manpage.block list -> ?envs:Env.info list -> ?exits:Exit.info list -> ?sdocs:string -> ?docs:string -> ?doc:string -> ?version:string -> string -> info - (** [info name ?sdocs ?man ?docs ?doc ?version] is a term information + (** [info ?sdocs ?man ?docs ?doc ?version name] is a term information such that: {ul {- [name] is the name of the command.} @@ -634,7 +634,10 @@ markup language} in which the following variables are recognized: {ul {- [$(tname)] the (term's) command's name.} - {- [$(mname)] the main command name.}} *) + {- [$(mname)] the main command name.} + {- [$(iname)] the command invocation from main command to the + command name.}} + *) (** {1:cmds Commands} *) @@ -718,9 +721,9 @@ (** The type for successful evaluation results. *) type eval_error = - [ `Parse (** A parse error occured. *) - | `Term (** A term evaluation error occured. *) - | `Exn (** An uncaught exception occured. *) ] + [ `Parse (** A parse error occurred. *) + | `Term (** A term evaluation error occurred. *) + | `Exn (** An uncaught exception occurred. *) ] (** The type for erroring evaluation results. *) val eval_value : @@ -732,14 +735,14 @@ {ul {- [argv] the command line arguments to parse (defaults to {!Sys.argv})} {- [env] the function used for environment variable lookup (defaults - to {!Sys.getenv}.} + to {!Sys.getenv}).} {- [catch] if [true] (default) uncaught exceptions are intercepted and their stack trace is written to the [err] formatter} {- [help] is the formatter used to print help or version messages (defaults to {!Format.std_formatter})} {- [err] is the formatter used to print error messages - (defaults to {!Format.err_formatter}.}} *) + (defaults to {!Format.err_formatter}).}} *) val eval_peek_opts : ?version_opt:bool -> ?env:(string -> string option) -> diff --git a/src/cmdliner.mllib b/src/cmdliner.mllib index fd479c0..f426ed6 100644 --- a/src/cmdliner.mllib +++ b/src/cmdliner.mllib @@ -6,6 +6,7 @@ Cmdliner_msg Cmdliner_cline Cmdliner_arg +Cmdliner_term_deprecated Cmdliner_term Cmdliner_cmd Cmdliner_eval diff --git a/src/cmdliner_docgen.ml b/src/cmdliner_docgen.ml index d452ae8..8e40497 100644 --- a/src/cmdliner_docgen.ml +++ b/src/cmdliner_docgen.ml @@ -71,6 +71,10 @@ let cmd_info_subst ei = function | "tname" -> Some (strf "$(b,%s)" @@ cmd_name (Cmdliner_info.Eval.cmd ei)) | "mname" -> Some (strf "$(b,%s)" @@ cmd_name (Cmdliner_info.Eval.main ei)) +| "iname" -> + let cmd = Cmdliner_info.Eval.cmd ei :: Cmdliner_info.Eval.parents ei in + let cmd = String.concat " " (List.rev_map Cmdliner_info.Cmd.name cmd) in + Some (strf "$(b,%s)" cmd) | _ -> None (* Command docs *) diff --git a/src/cmdliner_info.mli b/src/cmdliner_info.mli index d82b03c..2ded9dc 100644 --- a/src/cmdliner_info.mli +++ b/src/cmdliner_info.mli @@ -3,7 +3,7 @@ Distributed under the ISC license, see terms at the end of the file. ---------------------------------------------------------------------------*) -(** Exit codes, environment variabes, arguments, commands and eval information. +(** Exit codes, environment variables, arguments, commands and eval information. These information types gathers untyped data used to parse command lines report errors and format man pages. *) diff --git a/src/cmdliner_manpage.ml b/src/cmdliner_manpage.ml index 46353d5..941220a 100644 --- a/src/cmdliner_manpage.ml +++ b/src/cmdliner_manpage.ml @@ -26,8 +26,7 @@ let s_options = "OPTIONS" let s_common_options = "COMMON OPTIONS" let s_exit_status = "EXIT STATUS" -let s_exit_status_intro = - `P "$(tname) exits with the following status:" +let s_exit_status_intro = `P "$(iname) exits with:" let s_environment = "ENVIRONMENT" let s_environment_intro = @@ -314,34 +313,35 @@ let b = Buffer.create 1024 in let markup t = doc_to_plain ~errs b ~subst t in let pp_tokens ppf t = pp_tokens ~spaces:true ppf t in - let rec loop = function + let rec blank_line = function + | `Noblank :: ts -> loop ts + | ts -> Format.pp_print_cut ppf (); loop ts + and loop = function | [] -> () | t :: ts -> - begin match t with - | `Noblank -> () - | `Blocks bs -> loop bs (* not T.R. *) - | `P s -> pf ppf "%a@[%a@]@," pp_indent p_indent pp_tokens (markup s) - | `S s -> pf ppf "@[%a@]" pp_tokens (markup s) - | `Pre s -> pf ppf "%a@[%a@]@," pp_indent p_indent pp_lines (markup s) + match t with + | `Noblank -> loop ts + | `Blocks bs -> loop (bs @ ts) + | `P s -> + pf ppf "%a@[%a@]@," pp_indent p_indent pp_tokens (markup s); + blank_line ts + | `S s -> pf ppf "@[%a@]@," pp_tokens (markup s); loop ts + | `Pre s -> + pf ppf "%a@[%a@]@," pp_indent p_indent pp_lines (markup s); + blank_line ts | `I (label, s) -> - let label = markup label in - let s = markup s in + let label = markup label and s = markup s in pf ppf "@[%a@[%a@]" pp_indent p_indent pp_tokens label; - if s = "" then pf ppf "@]@," else - let ll = String.length label in - begin match ll < l_indent with - | true -> - pf ppf "%a@[%a@]@]" pp_indent (l_indent - ll) pp_tokens s - | false -> - pf ppf "@\n%a@[%a@]@]" - pp_indent (p_indent + l_indent) pp_tokens s + begin match s with + | "" -> pf ppf "@]@," + | s -> + let ll = String.length label in + if ll < l_indent + then (pf ppf "%a@[%a@]@]@," pp_indent (l_indent - ll) pp_tokens s) + else (pf ppf "@\n%a@[%a@]@]@," + pp_indent (p_indent + l_indent) pp_tokens s) end; - match ts with `I _ :: _ -> pf ppf "@," | _ -> () - end; - begin match ts with - | `Noblank :: ts -> loop ts - | ts -> Format.pp_print_cut ppf (); loop ts - end + blank_line ts in loop ts @@ -435,6 +435,14 @@ Some file with Sys_error _ -> None +let tmp_file_for_pager () = + try + let exec = Filename.basename Sys.argv.(0) in + let file = Filename.temp_file exec "tty" in + at_exit (fun () -> try Sys.remove file with Sys_error e -> ()); + Some file + with Sys_error _ -> None + let find_cmd cmds = let test, null = match Sys.os_type with | "Win32" -> "where", " NUL" @@ -445,8 +453,7 @@ let pp_to_pager print ppf v = let pager = - let cmds = ["less"," -R"; "more", ""] in - (* Fundamentally env var lookups should try to cut the exec name. *) + let cmds = ["less", ""; "more", ""] in let cmds = try (Sys.getenv "PAGER", "") :: cmds with Not_found -> cmds in let cmds = try (Sys.getenv "MANPAGER", "") :: cmds with Not_found -> cmds in find_cmd cmds @@ -454,7 +461,10 @@ match pager with | None -> print `Plain ppf v | Some (pager, opts) -> - let pager = pager ^ opts in + let pager = match Sys.win32 with + | false -> "LESS=FRX " ^ pager ^ opts + | true -> "set LESS=FRX && " ^ pager ^ opts + in let groffer = let cmds = ["mandoc", " -m man -K utf-8 -T utf8"; @@ -473,7 +483,17 @@ let groffer = groffer ^ opts in begin match pp_to_temp_file (print `Groff) v with | None -> None - | Some f -> Some (strf "%s < %s | %s" groffer f pager) + | Some f when Sys.win32 -> + (* For some obscure reason the pipe below does not + work. We need to use a temporary file. + https://github.com/dbuenzli/cmdliner/issues/166 *) + begin match tmp_file_for_pager () with + | None -> None + | Some tmp -> + Some (strf "%s <%s >%s && %s <%s" groffer f tmp pager tmp) + end + | Some f -> + Some (strf "%s < %s | %s" groffer f pager) end in match cmd with diff --git a/src/cmdliner_manpage.mli b/src/cmdliner_manpage.mli index 5d43a5b..d4d0849 100644 --- a/src/cmdliner_manpage.mli +++ b/src/cmdliner_manpage.mli @@ -77,7 +77,7 @@ val doc_to_plain : errs:Format.formatter -> subst:(string -> string option) -> Buffer.t -> string -> string -(** [doc_to_plain b ~subst s] using [b], subsitutes in [s] variables by +(** [doc_to_plain b ~subst s] using [b], substitutes in [s] variables by their [subst] definition and renders cmdliner directives to plain text. diff --git a/src/dune b/src/dune index b9ef5c9..7001301 100644 --- a/src/dune +++ b/src/dune @@ -1,4 +1,3 @@ (library (public_name cmdliner) - (flags :standard -w -3-6-27-32-35) (wrapped false)) diff --git a/test/chorus.ml b/test/chorus.ml index ee113cf..cbefc30 100644 --- a/test/chorus.ml +++ b/test/chorus.ml @@ -28,7 +28,7 @@ `S Manpage.s_bugs; `P "Email bug reports to ." ] in - let info = Cmd.info "chorus" ~version:"v1.1.1" ~doc ~man in + let info = Cmd.info "chorus" ~version:"v1.2.0" ~doc ~man in Cmd.v info chorus_t let main () = exit (Cmd.eval cmd) diff --git a/test/cp_ex.ml b/test/cp_ex.ml index 944037d..6a83069 100644 --- a/test/cp_ex.ml +++ b/test/cp_ex.ml @@ -45,7 +45,7 @@ [ `S Manpage.s_bugs; `P "Email them to ."; ] in - let info = Cmd.info "cp" ~version:"v1.1.1" ~doc ~man ~man_xrefs in + let info = Cmd.info "cp" ~version:"v1.2.0" ~doc ~man ~man_xrefs in Cmd.v info Term.(ret (const cp $ verbose $ recurse $ force $ srcs $ dest)) diff --git a/test/darcs_ex.ml b/test/darcs_ex.ml index 8ebd2f6..2534044 100644 --- a/test/darcs_ex.ml +++ b/test/darcs_ex.ml @@ -141,7 +141,7 @@ let main_cmd = let doc = "a revision control system" in let man = help_secs in - let info = Cmd.info "darcs" ~version:"v1.1.1" ~doc ~sdocs ~man in + let info = Cmd.info "darcs" ~version:"v1.2.0" ~doc ~sdocs ~man in let default = Term.(ret (const (fun _ -> `Help (`Pager, None)) $ copts_t)) in Cmd.group info ~default [initialize_cmd; record_cmd; help_cmd] diff --git a/test/rm_ex.ml b/test/rm_ex.ml index 967d28f..566869e 100644 --- a/test/rm_ex.ml +++ b/test/rm_ex.ml @@ -53,7 +53,7 @@ `S Manpage.s_bugs; `P "Report bugs to ."; `S Manpage.s_see_also; `P "$(b,rmdir)(1), $(b,unlink)(2)" ] in - let info = Cmd.info "rm" ~version:"v1.1.1" ~doc ~man in + let info = Cmd.info "rm" ~version:"v1.2.0" ~doc ~man in Cmd.v info Term.(const rm $ prompt $ recursive $ files) let main () = exit (Cmd.eval cmd) diff --git a/test/tail_ex.ml b/test/tail_ex.ml index 4a9a782..1010280 100644 --- a/test/tail_ex.ml +++ b/test/tail_ex.ml @@ -77,7 +77,7 @@ `S Manpage.s_see_also; `P "$(b,cat)(1), $(b,head)(1)" ] in - let info = Cmd.info "tail" ~version:"v1.1.1" ~doc ~man in + let info = Cmd.info "tail" ~version:"v1.2.0" ~doc ~man in Cmd.v info Term.(const tail $ lines $ follow $ verb $ pid $ files) diff --git a/test/test_man.ml b/test/test_man.ml index 5d41b70..e0bcc2c 100644 --- a/test/test_man.ml +++ b/test/test_man.ml @@ -81,7 +81,7 @@ `P "() does not need to be escaped outside directives."; `Blocks [ `P "The following to paragraphs are spliced in."; - `P "This dollar needs escape \\$(var) this one aswell $(b,\\$(bla\\))"; + `P "This dollar needs escape \\$(var) this one as well $(b,\\$(bla\\))"; `P "This is another paragraph \\$(bla) $(i,\\$(bla\\)) $(b,\\$\\(bla\\))"; ]; `Noblank; @@ -96,6 +96,6 @@ `P "Email bug reports to .";] in let man_xrefs = [`Page ("ascii", 7); `Main; `Tool "grep";] in - Cmd.info "man_test" ~version:"v1.1.1" ~doc ~envs ~exits ~man ~man_xrefs + Cmd.info "man_test" ~version:"v1.2.0" ~doc ~envs ~exits ~man ~man_xrefs let () = exit (Cmd.eval (Cmd.v info man_test_t)) diff --git a/test/test_nest.ml b/test/test_nest.ml index f741b2e..1b6badc 100644 --- a/test/test_nest.ml +++ b/test/test_nest.ml @@ -1,5 +1,7 @@ open Cmdliner + +let man = [ `P "Use $(iname) to invoke." ] let kind = let doc = "Kind of entity" in @@ -15,19 +17,19 @@ Arg.(value & pos 0 string "pigeon" & info [] ~doc ~docv:"BIRD") in let fly = - let info = Cmd.info "fly" ~doc:"Fly birds." in + let info = Cmd.info "fly" ~doc:"Fly birds." ~man in Cmd.v info Term.(const (fun n v -> ()) $ bird $ speed) in let land' = - let info = Cmd.info "land" ~doc:"Land birds." in + let info = Cmd.info "land" ~doc:"Land birds." ~man in Cmd.v info Term.(const (fun n -> ()) $ bird) in - let info = Cmd.info "birds" ~doc:"Operate on birds." in + let info = Cmd.info "birds" ~doc:"Operate on birds." ~man in Cmd.group ~default:Term.(const (fun k -> ()) $ kind) info [fly; land'] let mammals = let man_xrefs = [`Main; `Cmd "birds" ] in - let info = Cmd.info "mammals" ~doc:"Operate on mammals." ~man_xrefs in + let info = Cmd.info "mammals" ~doc:"Operate on mammals." ~man_xrefs ~man in Cmd.v info Term.(const (fun () -> ()) $ const ()) let fishs = @@ -35,7 +37,7 @@ let doc = "Use fish named $(docv)." in Arg.(value & pos 0 (some string) None & info [] ~doc ~docv:"NAME") in - let info = Cmd.info "fishs" ~doc:"Operate on fishs." in + let info = Cmd.info "fishs" ~doc:"Operate on fishs." ~man in Cmd.v info Term.(const (fun n -> ()) $ name') let camels = @@ -52,11 +54,11 @@ in let deprecated = "deprecated, use 'mammals' instead." in - let info = Cmd.info "camels" ~deprecated ~doc:"Operate on camels." in + let info = Cmd.info "camels" ~deprecated ~doc:"Operate on camels." ~man in Cmd.v info Term.(const (fun n h -> ()) $ bactrian $ herd) let cmd = - let info = Cmd.info "test_nest" ~version:"X.Y.Z" in + let info = Cmd.info "test_nest" ~version:"X.Y.Z" ~man in Cmd.group info [birds; mammals; fishs; camels] let () = exit (Cmd.eval cmd)