Update upstream source from tag 'upstream/1.2.0'
Update to upstream version '1.2.0'
with Debian dir f9ea6d2f7593cb66feda736ebf5266ba16b45909
Stephane Glondu
9 months ago
0 | v1.2.0 2023-04-10 La Forclaz (VS) | |
1 | --------------------------------- | |
2 | ||
3 | - In manpage specification the new variable `$(iname)` substitutes the | |
4 | command invocation (from program name to subcommand) in bold (#168). | |
5 | This variable is now used in the default introduction of the `EXIT STATUS` | |
6 | section. Thanks to Ali Caglayan for suggesting. | |
7 | - Fix manpage rendering when `PAGER=less` is set (#167). | |
8 | - Plain text manpage rendering: fix broken handling of `` `Noblank ``. | |
9 | Thanks to Michael Richards and Reynir Björnsson for the report (#176). | |
10 | - Fix install to directory with spaces (#172). Thanks to | |
11 | @ZSFactory for reporting and suggesting the fix. | |
12 | - Fix manpage paging on Windows (#166). Thanks to Nicolás Ojeda Bär | |
13 | for the report and the solution. | |
14 | ||
0 | 15 | v1.1.1 2022-03-23 La Forclaz (VS) |
1 | 16 | --------------------------------- |
2 | 17 | |
101 | 116 | |
102 | 117 | * If you relied on `?term_err` defaulting to `1` in the various |
103 | 118 | `Term.exit*` function, note that the new `Cmd.eval*` function use |
104 | `Exit.cli_error` as a default. You may want to explicitely specify | |
119 | `Exit.cli_error` as a default. You may want to explicitly specify | |
105 | 120 | `1` instead if you use `Term.ret` with the `` `Error`` case |
106 | 121 | or `Term.term_result`. |
107 | 122 | |
257 | 272 | whenever unspecified in the man page. |
258 | 273 | - Better automatic insertions of man page sections (#73). See the API |
259 | 274 | docs about manual specification. As a side effect the `NAME` section |
260 | can now also be overriden manually. | |
275 | can now also be overridden manually. | |
261 | 276 | - Fix repeated environment variable printing for flags (#64). Thanks to |
262 | 277 | Thomas Gazagnaire for the report. |
263 | 278 | - Fix rendering of env vars in man pages, bold is standard (#71). |
309 | 324 | - Deprecate `Term.pure` in favor of `Term.const`. |
310 | 325 | - Man page generation. Keep undefined variables untouched. Previously |
311 | 326 | a `$(undef)` would be turned into `undef`. |
312 | - Turn a few misterious and spurious `Not_found` exceptions into | |
327 | - Turn a few mysterious and spurious `Not_found` exceptions into | |
313 | 328 | `Invalid_arg`. These can be triggered by client programming errors |
314 | 329 | (e.g. an unclosed variable in a documentation string). |
315 | 330 | - Positional arguments. Invoke the printer on the default (absent) |
362 | 377 | - Remove temporary files created for paged help. Thanks to Kaustuv Chaudhuri |
363 | 378 | for the suggestion. |
364 | 379 | - Avoid linking against `Oo` (was used to get program uuid). |
365 | - Check the environment for `$MANPAGER` aswell. Thanks to Raphaël Proust | |
380 | - Check the environment for `$MANPAGER` as well. Thanks to Raphaël Proust | |
366 | 381 | for the patch. |
367 | 382 | - OPAM friendly workflow and drop OASIS support. |
368 | 383 |
39 | 39 | install: $(INSTALL-TARGETS) |
40 | 40 | |
41 | 41 | install-doc: |
42 | $(INSTALL) -d $(DOCDIR)/odoc-pages | |
43 | $(INSTALL) CHANGES.md LICENSE.md README.md $(DOCDIR) | |
42 | $(INSTALL) -d "$(DOCDIR)/odoc-pages" | |
43 | $(INSTALL) CHANGES.md LICENSE.md README.md "$(DOCDIR)" | |
44 | 44 | $(INSTALL) doc/index.mld doc/cli.mld doc/examples.mld doc/tutorial.mld \ |
45 | doc/tool_man.mld $(DOCDIR)/odoc-pages | |
45 | doc/tool_man.mld "$(DOCDIR)/odoc-pages" | |
46 | 46 | |
47 | 47 | clean: |
48 | 48 | ocaml build.ml clean |
57 | 57 | ocaml build.ml cmxs |
58 | 58 | |
59 | 59 | create-libdir: |
60 | $(INSTALL) -d $(LIBDIR) | |
60 | $(INSTALL) -d "$(LIBDIR)" | |
61 | 61 | |
62 | 62 | install-common: create-libdir |
63 | $(INSTALL) pkg/META $(BASE).mli $(BASE).cmi $(BASE).cmti $(LIBDIR) | |
64 | $(INSTALL) cmdliner.opam $(LIBDIR)/opam | |
63 | $(INSTALL) pkg/META $(BASE).mli $(BASE).cmi $(BASE).cmti "$(LIBDIR)" | |
64 | $(INSTALL) cmdliner.opam "$(LIBDIR)/opam" | |
65 | 65 | |
66 | 66 | install-byte: create-libdir |
67 | $(INSTALL) $(BASE).cma $(LIBDIR) | |
67 | $(INSTALL) $(BASE).cma "$(LIBDIR)" | |
68 | 68 | |
69 | 69 | install-native: create-libdir |
70 | 70 | $(INSTALL) $(BASE).cmxa $(BASE)$(EXT_LIB) $(wildcard $(B)/cmdliner*.cmx) \ |
71 | $(LIBDIR) | |
71 | "$(LIBDIR)" | |
72 | 72 | |
73 | 73 | install-native-dynlink: create-libdir |
74 | $(INSTALL) $(BASE).cmxs $(LIBDIR) | |
74 | $(INSTALL) $(BASE).cmxs "$(LIBDIR)" | |
75 | 75 | |
76 | 76 | .PHONY: all install install-doc clean build-byte build-native \ |
77 | 77 | build-native-dynlink create-libdir install-common install-byte \ |
0 | 0 | Cmdliner — Declarative definition of command line interfaces for OCaml |
1 | 1 | ------------------------------------------------------------------------------- |
2 | v1.1.1 | |
2 | v1.2.0 | |
3 | 3 | |
4 | 4 | Cmdliner allows the declarative definition of command line interfaces |
5 | 5 | for OCaml. |
0 | version: "1.1.1" | |
0 | version: "1.2.0" | |
1 | 1 | opam-version: "2.0" |
2 | 2 | name: "cmdliner" |
3 | 3 | synopsis: """Declarative definition of command line interfaces for OCaml""" |
78 | 78 | `S Manpage.s_bugs; `P "Report bugs to <bugs@example.org>."; |
79 | 79 | `S Manpage.s_see_also; `P "$(b,rmdir)(1), $(b,unlink)(2)" ] |
80 | 80 | in |
81 | let info = Cmd.info "rm" ~version:"v1.1.1" ~doc ~man in | |
81 | let info = Cmd.info "rm" ~version:"v1.2.0" ~doc ~man in | |
82 | 82 | Cmd.v info Term.(const rm $ prompt $ recursive $ files) |
83 | 83 | |
84 | 84 | let main () = exit (Cmd.eval cmd) |
148 | 148 | [ `S Manpage.s_bugs; |
149 | 149 | `P "Email them to <bugs@example.org>."; ] |
150 | 150 | in |
151 | let info = Cmd.info "cp" ~version:"v1.1.1" ~doc ~man ~man_xrefs in | |
151 | let info = Cmd.info "cp" ~version:"v1.2.0" ~doc ~man ~man_xrefs in | |
152 | 152 | Cmd.v info Term.(ret (const cp $ verbose $ recurse $ force $ srcs $ dest)) |
153 | 153 | |
154 | 154 | |
257 | 257 | `S Manpage.s_see_also; |
258 | 258 | `P "$(b,cat)(1), $(b,head)(1)" ] |
259 | 259 | in |
260 | let info = Cmd.info "tail" ~version:"v1.1.1" ~doc ~man in | |
260 | let info = Cmd.info "tail" ~version:"v1.2.0" ~doc ~man in | |
261 | 261 | Cmd.v info Term.(const tail $ lines $ follow $ verb $ pid $ files) |
262 | 262 | |
263 | 263 | |
434 | 434 | let main_cmd = |
435 | 435 | let doc = "a revision control system" in |
436 | 436 | let man = help_secs in |
437 | let info = Cmd.info "darcs" ~version:"v1.1.1" ~doc ~sdocs ~man in | |
437 | let info = Cmd.info "darcs" ~version:"v1.2.0" ~doc ~sdocs ~man in | |
438 | 438 | let default = Term.(ret (const (fun _ -> `Help (`Pager, None)) $ copts_t)) in |
439 | 439 | Cmd.group info ~default [initialize_cmd; record_cmd; help_cmd] |
440 | 440 |
0 | {0 Cmdliner {%html: <span class="version">v1.1.1</span>%}} | |
0 | {0 Cmdliner {%html: <span class="version">v1.2.0</span>%}} | |
1 | 1 | |
2 | 2 | [Cmdliner] provides a simple and compositional mechanism |
3 | 3 | to convert command line arguments to OCaml values and pass them to |
3 | 3 | |
4 | 4 | Man page sections for a command are printed in the order specified by |
5 | 5 | manual as given to {!Cmdliner.Cmd.val-info}. Unless specified |
6 | explicitely in the command's manual the following sections are | |
7 | automaticaly created and populated for you: | |
6 | explicitly in the command's manual the following sections are | |
7 | automatically created and populated for you: | |
8 | 8 | |
9 | 9 | {ul |
10 | 10 | {- {{!Cmdliner.Manpage.s_name}[NAME]} section.} |
34 | 34 | is inserted at the right place in the order specified |
35 | 35 | {{!Cmdliner.Manpage.standard_sections}here}, but after a |
36 | 36 | possible non-standard |
37 | section explicitely specified by the command's manual since the latter | |
37 | section explicitly specified by the command's manual since the latter | |
38 | 38 | get the order number of the last previously specified standard section |
39 | 39 | or the order of {!Cmdliner.Manpage.s_synopsis} if there is no such section.} |
40 | 40 | {- non-standard, it is inserted before the {!Cmdliner.Manpage.s_commands} |
65 | 65 | mandatory only in markup directives. Escaping ( is only here for |
66 | 66 | your symmetric pleasure. Any other sequence of characters starting |
67 | 67 | with a \ is an illegal character sequence.} |
68 | {- Refering to unknown markup directives or variables will generate | |
68 | {- Referring to unknown markup directives or variables will generate | |
69 | 69 | errors on standard error during documentation generation.}} |
4 | 4 | With [Cmdliner] your tool's [main] function evaluates a command. |
5 | 5 | |
6 | 6 | A command is a value of type {!Cmdliner.Cmd.t} which gathers a command |
7 | name with a term of type {!Cmdliner.Term.t}. The type parameter of | |
8 | the term (and the command) indicates the type of the result of the | |
9 | evaluation. | |
7 | name and a term of type {!Cmdliner.Term.t}. A term is an expression to | |
8 | be evaluated. The type parameter of the term (and the command) | |
9 | indicates the type of the result of the evaluation. | |
10 | 10 | |
11 | 11 | One way to create terms is by lifting regular OCaml values with |
12 | 12 | {!Cmdliner.Term.const}. Terms can be applied to terms evaluating to |
0 | (env (_ (flags -g -bin-annot -safe-string))) ; Use the same flags as with ocamlbuild |
0 | version = "v1.1.1" | |
0 | version = "v1.2.0" | |
1 | 1 | description = "Declarative definition of command line interfaces" |
2 | 2 | requires = "" |
3 | 3 | archive(byte) = "cmdliner.cma" |
346 | 346 | {- [$(mname)] the main term's name.}} *) |
347 | 347 | |
348 | 348 | val name : info -> string |
349 | [@@ocaml.deprecated "Use Cmd.info_name instead."] | |
349 | [@@ocaml.deprecated "Use Cmd.name instead."] | |
350 | 350 | (** [name ti] is the name of the term information. *) |
351 | 351 | |
352 | 352 | (** {2:evaluation Evaluation} *) |
603 | 603 | ?man:Manpage.block list -> ?envs:Env.info list -> ?exits:Exit.info list -> |
604 | 604 | ?sdocs:string -> ?docs:string -> ?doc:string -> ?version:string -> |
605 | 605 | string -> info |
606 | (** [info name ?sdocs ?man ?docs ?doc ?version] is a term information | |
606 | (** [info ?sdocs ?man ?docs ?doc ?version name] is a term information | |
607 | 607 | such that: |
608 | 608 | {ul |
609 | 609 | {- [name] is the name of the command.} |
633 | 633 | markup language} in which the following variables are recognized: |
634 | 634 | {ul |
635 | 635 | {- [$(tname)] the (term's) command's name.} |
636 | {- [$(mname)] the main command name.}} *) | |
636 | {- [$(mname)] the main command name.} | |
637 | {- [$(iname)] the command invocation from main command to the | |
638 | command name.}} | |
639 | *) | |
637 | 640 | |
638 | 641 | (** {1:cmds Commands} *) |
639 | 642 | |
717 | 720 | (** The type for successful evaluation results. *) |
718 | 721 | |
719 | 722 | type eval_error = |
720 | [ `Parse (** A parse error occured. *) | |
721 | | `Term (** A term evaluation error occured. *) | |
722 | | `Exn (** An uncaught exception occured. *) ] | |
723 | [ `Parse (** A parse error occurred. *) | |
724 | | `Term (** A term evaluation error occurred. *) | |
725 | | `Exn (** An uncaught exception occurred. *) ] | |
723 | 726 | (** The type for erroring evaluation results. *) |
724 | 727 | |
725 | 728 | val eval_value : |
731 | 734 | {ul |
732 | 735 | {- [argv] the command line arguments to parse (defaults to {!Sys.argv})} |
733 | 736 | {- [env] the function used for environment variable lookup (defaults |
734 | to {!Sys.getenv}.} | |
737 | to {!Sys.getenv}).} | |
735 | 738 | {- [catch] if [true] (default) uncaught exceptions |
736 | 739 | are intercepted and their stack trace is written to the [err] |
737 | 740 | formatter} |
738 | 741 | {- [help] is the formatter used to print help or version messages |
739 | 742 | (defaults to {!Format.std_formatter})} |
740 | 743 | {- [err] is the formatter used to print error messages |
741 | (defaults to {!Format.err_formatter}.}} *) | |
744 | (defaults to {!Format.err_formatter}).}} *) | |
742 | 745 | |
743 | 746 | val eval_peek_opts : |
744 | 747 | ?version_opt:bool -> ?env:(string -> string option) -> |
5 | 5 | Cmdliner_msg |
6 | 6 | Cmdliner_cline |
7 | 7 | Cmdliner_arg |
8 | Cmdliner_term_deprecated | |
8 | 9 | Cmdliner_term |
9 | 10 | Cmdliner_cmd |
10 | 11 | Cmdliner_eval |
70 | 70 | let cmd_info_subst ei = function |
71 | 71 | | "tname" -> Some (strf "$(b,%s)" @@ cmd_name (Cmdliner_info.Eval.cmd ei)) |
72 | 72 | | "mname" -> Some (strf "$(b,%s)" @@ cmd_name (Cmdliner_info.Eval.main ei)) |
73 | | "iname" -> | |
74 | let cmd = Cmdliner_info.Eval.cmd ei :: Cmdliner_info.Eval.parents ei in | |
75 | let cmd = String.concat " " (List.rev_map Cmdliner_info.Cmd.name cmd) in | |
76 | Some (strf "$(b,%s)" cmd) | |
73 | 77 | | _ -> None |
74 | 78 | |
75 | 79 | (* Command docs *) |
2 | 2 | Distributed under the ISC license, see terms at the end of the file. |
3 | 3 | ---------------------------------------------------------------------------*) |
4 | 4 | |
5 | (** Exit codes, environment variabes, arguments, commands and eval information. | |
5 | (** Exit codes, environment variables, arguments, commands and eval information. | |
6 | 6 | |
7 | 7 | These information types gathers untyped data used to parse command |
8 | 8 | lines report errors and format man pages. *) |
25 | 25 | let s_options = "OPTIONS" |
26 | 26 | let s_common_options = "COMMON OPTIONS" |
27 | 27 | let s_exit_status = "EXIT STATUS" |
28 | let s_exit_status_intro = | |
29 | `P "$(tname) exits with the following status:" | |
28 | let s_exit_status_intro = `P "$(iname) exits with:" | |
30 | 29 | |
31 | 30 | let s_environment = "ENVIRONMENT" |
32 | 31 | let s_environment_intro = |
313 | 312 | let b = Buffer.create 1024 in |
314 | 313 | let markup t = doc_to_plain ~errs b ~subst t in |
315 | 314 | let pp_tokens ppf t = pp_tokens ~spaces:true ppf t in |
316 | let rec loop = function | |
315 | let rec blank_line = function | |
316 | | `Noblank :: ts -> loop ts | |
317 | | ts -> Format.pp_print_cut ppf (); loop ts | |
318 | and loop = function | |
317 | 319 | | [] -> () |
318 | 320 | | t :: ts -> |
319 | begin match t with | |
320 | | `Noblank -> () | |
321 | | `Blocks bs -> loop bs (* not T.R. *) | |
322 | | `P s -> pf ppf "%a@[%a@]@," pp_indent p_indent pp_tokens (markup s) | |
323 | | `S s -> pf ppf "@[%a@]" pp_tokens (markup s) | |
324 | | `Pre s -> pf ppf "%a@[%a@]@," pp_indent p_indent pp_lines (markup s) | |
321 | match t with | |
322 | | `Noblank -> loop ts | |
323 | | `Blocks bs -> loop (bs @ ts) | |
324 | | `P s -> | |
325 | pf ppf "%a@[%a@]@," pp_indent p_indent pp_tokens (markup s); | |
326 | blank_line ts | |
327 | | `S s -> pf ppf "@[%a@]@," pp_tokens (markup s); loop ts | |
328 | | `Pre s -> | |
329 | pf ppf "%a@[%a@]@," pp_indent p_indent pp_lines (markup s); | |
330 | blank_line ts | |
325 | 331 | | `I (label, s) -> |
326 | let label = markup label in | |
327 | let s = markup s in | |
332 | let label = markup label and s = markup s in | |
328 | 333 | pf ppf "@[%a@[%a@]" pp_indent p_indent pp_tokens label; |
329 | if s = "" then pf ppf "@]@," else | |
330 | let ll = String.length label in | |
331 | begin match ll < l_indent with | |
332 | | true -> | |
333 | pf ppf "%a@[%a@]@]" pp_indent (l_indent - ll) pp_tokens s | |
334 | | false -> | |
335 | pf ppf "@\n%a@[%a@]@]" | |
336 | pp_indent (p_indent + l_indent) pp_tokens s | |
334 | begin match s with | |
335 | | "" -> pf ppf "@]@," | |
336 | | s -> | |
337 | let ll = String.length label in | |
338 | if ll < l_indent | |
339 | then (pf ppf "%a@[%a@]@]@," pp_indent (l_indent - ll) pp_tokens s) | |
340 | else (pf ppf "@\n%a@[%a@]@]@," | |
341 | pp_indent (p_indent + l_indent) pp_tokens s) | |
337 | 342 | end; |
338 | match ts with `I _ :: _ -> pf ppf "@," | _ -> () | |
339 | end; | |
340 | begin match ts with | |
341 | | `Noblank :: ts -> loop ts | |
342 | | ts -> Format.pp_print_cut ppf (); loop ts | |
343 | end | |
343 | blank_line ts | |
344 | 344 | in |
345 | 345 | loop ts |
346 | 346 | |
434 | 434 | Some file |
435 | 435 | with Sys_error _ -> None |
436 | 436 | |
437 | let tmp_file_for_pager () = | |
438 | try | |
439 | let exec = Filename.basename Sys.argv.(0) in | |
440 | let file = Filename.temp_file exec "tty" in | |
441 | at_exit (fun () -> try Sys.remove file with Sys_error e -> ()); | |
442 | Some file | |
443 | with Sys_error _ -> None | |
444 | ||
437 | 445 | let find_cmd cmds = |
438 | 446 | let test, null = match Sys.os_type with |
439 | 447 | | "Win32" -> "where", " NUL" |
444 | 452 | |
445 | 453 | let pp_to_pager print ppf v = |
446 | 454 | let pager = |
447 | let cmds = ["less"," -R"; "more", ""] in | |
448 | (* Fundamentally env var lookups should try to cut the exec name. *) | |
455 | let cmds = ["less", ""; "more", ""] in | |
449 | 456 | let cmds = try (Sys.getenv "PAGER", "") :: cmds with Not_found -> cmds in |
450 | 457 | let cmds = try (Sys.getenv "MANPAGER", "") :: cmds with Not_found -> cmds in |
451 | 458 | find_cmd cmds |
453 | 460 | match pager with |
454 | 461 | | None -> print `Plain ppf v |
455 | 462 | | Some (pager, opts) -> |
456 | let pager = pager ^ opts in | |
463 | let pager = match Sys.win32 with | |
464 | | false -> "LESS=FRX " ^ pager ^ opts | |
465 | | true -> "set LESS=FRX && " ^ pager ^ opts | |
466 | in | |
457 | 467 | let groffer = |
458 | 468 | let cmds = |
459 | 469 | ["mandoc", " -m man -K utf-8 -T utf8"; |
472 | 482 | let groffer = groffer ^ opts in |
473 | 483 | begin match pp_to_temp_file (print `Groff) v with |
474 | 484 | | None -> None |
475 | | Some f -> Some (strf "%s < %s | %s" groffer f pager) | |
485 | | Some f when Sys.win32 -> | |
486 | (* For some obscure reason the pipe below does not | |
487 | work. We need to use a temporary file. | |
488 | https://github.com/dbuenzli/cmdliner/issues/166 *) | |
489 | begin match tmp_file_for_pager () with | |
490 | | None -> None | |
491 | | Some tmp -> | |
492 | Some (strf "%s <%s >%s && %s <%s" groffer f tmp pager tmp) | |
493 | end | |
494 | | Some f -> | |
495 | Some (strf "%s < %s | %s" groffer f pager) | |
476 | 496 | end |
477 | 497 | in |
478 | 498 | match cmd with |
76 | 76 | val doc_to_plain : |
77 | 77 | errs:Format.formatter -> subst:(string -> string option) -> Buffer.t -> |
78 | 78 | string -> string |
79 | (** [doc_to_plain b ~subst s] using [b], subsitutes in [s] variables by | |
79 | (** [doc_to_plain b ~subst s] using [b], substitutes in [s] variables by | |
80 | 80 | their [subst] definition and renders cmdliner directives to plain |
81 | 81 | text. |
82 | 82 |
27 | 27 | `S Manpage.s_bugs; |
28 | 28 | `P "Email bug reports to <bugs@example.org>." ] |
29 | 29 | in |
30 | let info = Cmd.info "chorus" ~version:"v1.1.1" ~doc ~man in | |
30 | let info = Cmd.info "chorus" ~version:"v1.2.0" ~doc ~man in | |
31 | 31 | Cmd.v info chorus_t |
32 | 32 | |
33 | 33 | let main () = exit (Cmd.eval cmd) |
44 | 44 | [ `S Manpage.s_bugs; |
45 | 45 | `P "Email them to <bugs@example.org>."; ] |
46 | 46 | in |
47 | let info = Cmd.info "cp" ~version:"v1.1.1" ~doc ~man ~man_xrefs in | |
47 | let info = Cmd.info "cp" ~version:"v1.2.0" ~doc ~man ~man_xrefs in | |
48 | 48 | Cmd.v info Term.(ret (const cp $ verbose $ recurse $ force $ srcs $ dest)) |
49 | 49 | |
50 | 50 |
140 | 140 | let main_cmd = |
141 | 141 | let doc = "a revision control system" in |
142 | 142 | let man = help_secs in |
143 | let info = Cmd.info "darcs" ~version:"v1.1.1" ~doc ~sdocs ~man in | |
143 | let info = Cmd.info "darcs" ~version:"v1.2.0" ~doc ~sdocs ~man in | |
144 | 144 | let default = Term.(ret (const (fun _ -> `Help (`Pager, None)) $ copts_t)) in |
145 | 145 | Cmd.group info ~default [initialize_cmd; record_cmd; help_cmd] |
146 | 146 |
52 | 52 | `S Manpage.s_bugs; `P "Report bugs to <bugs@example.org>."; |
53 | 53 | `S Manpage.s_see_also; `P "$(b,rmdir)(1), $(b,unlink)(2)" ] |
54 | 54 | in |
55 | let info = Cmd.info "rm" ~version:"v1.1.1" ~doc ~man in | |
55 | let info = Cmd.info "rm" ~version:"v1.2.0" ~doc ~man in | |
56 | 56 | Cmd.v info Term.(const rm $ prompt $ recursive $ files) |
57 | 57 | |
58 | 58 | let main () = exit (Cmd.eval cmd) |
76 | 76 | `S Manpage.s_see_also; |
77 | 77 | `P "$(b,cat)(1), $(b,head)(1)" ] |
78 | 78 | in |
79 | let info = Cmd.info "tail" ~version:"v1.1.1" ~doc ~man in | |
79 | let info = Cmd.info "tail" ~version:"v1.2.0" ~doc ~man in | |
80 | 80 | Cmd.v info Term.(const tail $ lines $ follow $ verb $ pid $ files) |
81 | 81 | |
82 | 82 |
80 | 80 | `P "() does not need to be escaped outside directives."; |
81 | 81 | `Blocks [ |
82 | 82 | `P "The following to paragraphs are spliced in."; |
83 | `P "This dollar needs escape \\$(var) this one aswell $(b,\\$(bla\\))"; | |
83 | `P "This dollar needs escape \\$(var) this one as well $(b,\\$(bla\\))"; | |
84 | 84 | `P "This is another paragraph \\$(bla) $(i,\\$(bla\\)) $(b,\\$\\(bla\\))"; |
85 | 85 | ]; |
86 | 86 | `Noblank; |
95 | 95 | `P "Email bug reports to <hehey at example.org>.";] |
96 | 96 | in |
97 | 97 | let man_xrefs = [`Page ("ascii", 7); `Main; `Tool "grep";] in |
98 | Cmd.info "man_test" ~version:"v1.1.1" ~doc ~envs ~exits ~man ~man_xrefs | |
98 | Cmd.info "man_test" ~version:"v1.2.0" ~doc ~envs ~exits ~man ~man_xrefs | |
99 | 99 | |
100 | 100 | let () = exit (Cmd.eval (Cmd.v info man_test_t)) |
0 | 0 | |
1 | 1 | open Cmdliner |
2 | ||
3 | let man = [ `P "Use $(iname) to invoke." ] | |
2 | 4 | |
3 | 5 | let kind = |
4 | 6 | let doc = "Kind of entity" in |
14 | 16 | Arg.(value & pos 0 string "pigeon" & info [] ~doc ~docv:"BIRD") |
15 | 17 | in |
16 | 18 | let fly = |
17 | let info = Cmd.info "fly" ~doc:"Fly birds." in | |
19 | let info = Cmd.info "fly" ~doc:"Fly birds." ~man in | |
18 | 20 | Cmd.v info Term.(const (fun n v -> ()) $ bird $ speed) |
19 | 21 | in |
20 | 22 | let land' = |
21 | let info = Cmd.info "land" ~doc:"Land birds." in | |
23 | let info = Cmd.info "land" ~doc:"Land birds." ~man in | |
22 | 24 | Cmd.v info Term.(const (fun n -> ()) $ bird) |
23 | 25 | in |
24 | let info = Cmd.info "birds" ~doc:"Operate on birds." in | |
26 | let info = Cmd.info "birds" ~doc:"Operate on birds." ~man in | |
25 | 27 | Cmd.group ~default:Term.(const (fun k -> ()) $ kind) info [fly; land'] |
26 | 28 | |
27 | 29 | let mammals = |
28 | 30 | let man_xrefs = [`Main; `Cmd "birds" ] in |
29 | let info = Cmd.info "mammals" ~doc:"Operate on mammals." ~man_xrefs in | |
31 | let info = Cmd.info "mammals" ~doc:"Operate on mammals." ~man_xrefs ~man in | |
30 | 32 | Cmd.v info Term.(const (fun () -> ()) $ const ()) |
31 | 33 | |
32 | 34 | let fishs = |
34 | 36 | let doc = "Use fish named $(docv)." in |
35 | 37 | Arg.(value & pos 0 (some string) None & info [] ~doc ~docv:"NAME") |
36 | 38 | in |
37 | let info = Cmd.info "fishs" ~doc:"Operate on fishs." in | |
39 | let info = Cmd.info "fishs" ~doc:"Operate on fishs." ~man in | |
38 | 40 | Cmd.v info Term.(const (fun n -> ()) $ name') |
39 | 41 | |
40 | 42 | let camels = |
51 | 53 | in |
52 | 54 | let deprecated = "deprecated, use 'mammals' instead." |
53 | 55 | in |
54 | let info = Cmd.info "camels" ~deprecated ~doc:"Operate on camels." in | |
56 | let info = Cmd.info "camels" ~deprecated ~doc:"Operate on camels." ~man in | |
55 | 57 | Cmd.v info Term.(const (fun n h -> ()) $ bactrian $ herd) |
56 | 58 | |
57 | 59 | let cmd = |
58 | let info = Cmd.info "test_nest" ~version:"X.Y.Z" in | |
60 | let info = Cmd.info "test_nest" ~version:"X.Y.Z" ~man in | |
59 | 61 | Cmd.group info [birds; mammals; fishs; camels] |
60 | 62 | |
61 | 63 | let () = exit (Cmd.eval cmd) |