Codebase list cmdliner / fd3e355
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
25 changed file(s) with 127 addition(s) and 83 deletion(s). Raw diff Collapse all Expand all
00 open B0_kit.V000
1 open B00_std
21
32 (* OCaml library names *)
43
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
015 v1.1.1 2022-03-23 La Forclaz (VS)
116 ---------------------------------
217
101116
102117 * If you relied on `?term_err` defaulting to `1` in the various
103118 `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
105120 `1` instead if you use `Term.ret` with the `` `Error`` case
106121 or `Term.term_result`.
107122
257272 whenever unspecified in the man page.
258273 - Better automatic insertions of man page sections (#73). See the API
259274 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.
261276 - Fix repeated environment variable printing for flags (#64). Thanks to
262277 Thomas Gazagnaire for the report.
263278 - Fix rendering of env vars in man pages, bold is standard (#71).
309324 - Deprecate `Term.pure` in favor of `Term.const`.
310325 - Man page generation. Keep undefined variables untouched. Previously
311326 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
313328 `Invalid_arg`. These can be triggered by client programming errors
314329 (e.g. an unclosed variable in a documentation string).
315330 - Positional arguments. Invoke the printer on the default (absent)
362377 - Remove temporary files created for paged help. Thanks to Kaustuv Chaudhuri
363378 for the suggestion.
364379 - 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
366381 for the patch.
367382 - OPAM friendly workflow and drop OASIS support.
368383
3939 install: $(INSTALL-TARGETS)
4040
4141 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)"
4444 $(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"
4646
4747 clean:
4848 ocaml build.ml clean
5757 ocaml build.ml cmxs
5858
5959 create-libdir:
60 $(INSTALL) -d $(LIBDIR)
60 $(INSTALL) -d "$(LIBDIR)"
6161
6262 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"
6565
6666 install-byte: create-libdir
67 $(INSTALL) $(BASE).cma $(LIBDIR)
67 $(INSTALL) $(BASE).cma "$(LIBDIR)"
6868
6969 install-native: create-libdir
7070 $(INSTALL) $(BASE).cmxa $(BASE)$(EXT_LIB) $(wildcard $(B)/cmdliner*.cmx) \
71 $(LIBDIR)
71 "$(LIBDIR)"
7272
7373 install-native-dynlink: create-libdir
74 $(INSTALL) $(BASE).cmxs $(LIBDIR)
74 $(INSTALL) $(BASE).cmxs "$(LIBDIR)"
7575
7676 .PHONY: all install install-doc clean build-byte build-native \
7777 build-native-dynlink create-libdir install-common install-byte \
00 Cmdliner — Declarative definition of command line interfaces for OCaml
11 -------------------------------------------------------------------------------
2 v1.1.1
2 v1.2.0
33
44 Cmdliner allows the declarative definition of command line interfaces
55 for OCaml.
0 version: "1.1.1"
0 version: "1.2.0"
11 opam-version: "2.0"
22 name: "cmdliner"
33 synopsis: """Declarative definition of command line interfaces for OCaml"""
7878 `S Manpage.s_bugs; `P "Report bugs to <bugs@example.org>.";
7979 `S Manpage.s_see_also; `P "$(b,rmdir)(1), $(b,unlink)(2)" ]
8080 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
8282 Cmd.v info Term.(const rm $ prompt $ recursive $ files)
8383
8484 let main () = exit (Cmd.eval cmd)
148148 [ `S Manpage.s_bugs;
149149 `P "Email them to <bugs@example.org>."; ]
150150 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
152152 Cmd.v info Term.(ret (const cp $ verbose $ recurse $ force $ srcs $ dest))
153153
154154
257257 `S Manpage.s_see_also;
258258 `P "$(b,cat)(1), $(b,head)(1)" ]
259259 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
261261 Cmd.v info Term.(const tail $ lines $ follow $ verb $ pid $ files)
262262
263263
434434 let main_cmd =
435435 let doc = "a revision control system" in
436436 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
438438 let default = Term.(ret (const (fun _ -> `Help (`Pager, None)) $ copts_t)) in
439439 Cmd.group info ~default [initialize_cmd; record_cmd; help_cmd]
440440
0 {0 Cmdliner {%html: <span class="version">v1.1.1</span>%}}
0 {0 Cmdliner {%html: <span class="version">v1.2.0</span>%}}
11
22 [Cmdliner] provides a simple and compositional mechanism
33 to convert command line arguments to OCaml values and pass them to
33
44 Man page sections for a command are printed in the order specified by
55 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:
88
99 {ul
1010 {- {{!Cmdliner.Manpage.s_name}[NAME]} section.}
3434 is inserted at the right place in the order specified
3535 {{!Cmdliner.Manpage.standard_sections}here}, but after a
3636 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
3838 get the order number of the last previously specified standard section
3939 or the order of {!Cmdliner.Manpage.s_synopsis} if there is no such section.}
4040 {- non-standard, it is inserted before the {!Cmdliner.Manpage.s_commands}
6565 mandatory only in markup directives. Escaping ( is only here for
6666 your symmetric pleasure. Any other sequence of characters starting
6767 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
6969 errors on standard error during documentation generation.}}
44 With [Cmdliner] your tool's [main] function evaluates a command.
55
66 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.
1010
1111 One way to create terms is by lifting regular OCaml values with
1212 {!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"
11 description = "Declarative definition of command line interfaces"
22 requires = ""
33 archive(byte) = "cmdliner.cma"
346346 {- [$(mname)] the main term's name.}} *)
347347
348348 val name : info -> string
349 [@@ocaml.deprecated "Use Cmd.info_name instead."]
349 [@@ocaml.deprecated "Use Cmd.name instead."]
350350 (** [name ti] is the name of the term information. *)
351351
352352 (** {2:evaluation Evaluation} *)
603603 ?man:Manpage.block list -> ?envs:Env.info list -> ?exits:Exit.info list ->
604604 ?sdocs:string -> ?docs:string -> ?doc:string -> ?version:string ->
605605 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
607607 such that:
608608 {ul
609609 {- [name] is the name of the command.}
633633 markup language} in which the following variables are recognized:
634634 {ul
635635 {- [$(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 *)
637640
638641 (** {1:cmds Commands} *)
639642
717720 (** The type for successful evaluation results. *)
718721
719722 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. *) ]
723726 (** The type for erroring evaluation results. *)
724727
725728 val eval_value :
731734 {ul
732735 {- [argv] the command line arguments to parse (defaults to {!Sys.argv})}
733736 {- [env] the function used for environment variable lookup (defaults
734 to {!Sys.getenv}.}
737 to {!Sys.getenv}).}
735738 {- [catch] if [true] (default) uncaught exceptions
736739 are intercepted and their stack trace is written to the [err]
737740 formatter}
738741 {- [help] is the formatter used to print help or version messages
739742 (defaults to {!Format.std_formatter})}
740743 {- [err] is the formatter used to print error messages
741 (defaults to {!Format.err_formatter}.}} *)
744 (defaults to {!Format.err_formatter}).}} *)
742745
743746 val eval_peek_opts :
744747 ?version_opt:bool -> ?env:(string -> string option) ->
55 Cmdliner_msg
66 Cmdliner_cline
77 Cmdliner_arg
8 Cmdliner_term_deprecated
89 Cmdliner_term
910 Cmdliner_cmd
1011 Cmdliner_eval
7070 let cmd_info_subst ei = function
7171 | "tname" -> Some (strf "$(b,%s)" @@ cmd_name (Cmdliner_info.Eval.cmd ei))
7272 | "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)
7377 | _ -> None
7478
7579 (* Command docs *)
22 Distributed under the ISC license, see terms at the end of the file.
33 ---------------------------------------------------------------------------*)
44
5 (** Exit codes, environment variabes, arguments, commands and eval information.
5 (** Exit codes, environment variables, arguments, commands and eval information.
66
77 These information types gathers untyped data used to parse command
88 lines report errors and format man pages. *)
2525 let s_options = "OPTIONS"
2626 let s_common_options = "COMMON OPTIONS"
2727 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:"
3029
3130 let s_environment = "ENVIRONMENT"
3231 let s_environment_intro =
313312 let b = Buffer.create 1024 in
314313 let markup t = doc_to_plain ~errs b ~subst t in
315314 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
317319 | [] -> ()
318320 | 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
325331 | `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
328333 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)
337342 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
344344 in
345345 loop ts
346346
434434 Some file
435435 with Sys_error _ -> None
436436
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
437445 let find_cmd cmds =
438446 let test, null = match Sys.os_type with
439447 | "Win32" -> "where", " NUL"
444452
445453 let pp_to_pager print ppf v =
446454 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
449456 let cmds = try (Sys.getenv "PAGER", "") :: cmds with Not_found -> cmds in
450457 let cmds = try (Sys.getenv "MANPAGER", "") :: cmds with Not_found -> cmds in
451458 find_cmd cmds
453460 match pager with
454461 | None -> print `Plain ppf v
455462 | 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
457467 let groffer =
458468 let cmds =
459469 ["mandoc", " -m man -K utf-8 -T utf8";
472482 let groffer = groffer ^ opts in
473483 begin match pp_to_temp_file (print `Groff) v with
474484 | 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)
476496 end
477497 in
478498 match cmd with
7676 val doc_to_plain :
7777 errs:Format.formatter -> subst:(string -> string option) -> Buffer.t ->
7878 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
8080 their [subst] definition and renders cmdliner directives to plain
8181 text.
8282
00 (library
11 (public_name cmdliner)
2 (flags :standard -w -3-6-27-32-35)
32 (wrapped false))
2727 `S Manpage.s_bugs;
2828 `P "Email bug reports to <bugs@example.org>." ]
2929 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
3131 Cmd.v info chorus_t
3232
3333 let main () = exit (Cmd.eval cmd)
4444 [ `S Manpage.s_bugs;
4545 `P "Email them to <bugs@example.org>."; ]
4646 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
4848 Cmd.v info Term.(ret (const cp $ verbose $ recurse $ force $ srcs $ dest))
4949
5050
140140 let main_cmd =
141141 let doc = "a revision control system" in
142142 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
144144 let default = Term.(ret (const (fun _ -> `Help (`Pager, None)) $ copts_t)) in
145145 Cmd.group info ~default [initialize_cmd; record_cmd; help_cmd]
146146
5252 `S Manpage.s_bugs; `P "Report bugs to <bugs@example.org>.";
5353 `S Manpage.s_see_also; `P "$(b,rmdir)(1), $(b,unlink)(2)" ]
5454 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
5656 Cmd.v info Term.(const rm $ prompt $ recursive $ files)
5757
5858 let main () = exit (Cmd.eval cmd)
7676 `S Manpage.s_see_also;
7777 `P "$(b,cat)(1), $(b,head)(1)" ]
7878 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
8080 Cmd.v info Term.(const tail $ lines $ follow $ verb $ pid $ files)
8181
8282
8080 `P "() does not need to be escaped outside directives.";
8181 `Blocks [
8282 `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\\))";
8484 `P "This is another paragraph \\$(bla) $(i,\\$(bla\\)) $(b,\\$\\(bla\\))";
8585 ];
8686 `Noblank;
9595 `P "Email bug reports to <hehey at example.org>.";]
9696 in
9797 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
9999
100100 let () = exit (Cmd.eval (Cmd.v info man_test_t))
00
11 open Cmdliner
2
3 let man = [ `P "Use $(iname) to invoke." ]
24
35 let kind =
46 let doc = "Kind of entity" in
1416 Arg.(value & pos 0 string "pigeon" & info [] ~doc ~docv:"BIRD")
1517 in
1618 let fly =
17 let info = Cmd.info "fly" ~doc:"Fly birds." in
19 let info = Cmd.info "fly" ~doc:"Fly birds." ~man in
1820 Cmd.v info Term.(const (fun n v -> ()) $ bird $ speed)
1921 in
2022 let land' =
21 let info = Cmd.info "land" ~doc:"Land birds." in
23 let info = Cmd.info "land" ~doc:"Land birds." ~man in
2224 Cmd.v info Term.(const (fun n -> ()) $ bird)
2325 in
24 let info = Cmd.info "birds" ~doc:"Operate on birds." in
26 let info = Cmd.info "birds" ~doc:"Operate on birds." ~man in
2527 Cmd.group ~default:Term.(const (fun k -> ()) $ kind) info [fly; land']
2628
2729 let mammals =
2830 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
3032 Cmd.v info Term.(const (fun () -> ()) $ const ())
3133
3234 let fishs =
3436 let doc = "Use fish named $(docv)." in
3537 Arg.(value & pos 0 (some string) None & info [] ~doc ~docv:"NAME")
3638 in
37 let info = Cmd.info "fishs" ~doc:"Operate on fishs." in
39 let info = Cmd.info "fishs" ~doc:"Operate on fishs." ~man in
3840 Cmd.v info Term.(const (fun n -> ()) $ name')
3941
4042 let camels =
5153 in
5254 let deprecated = "deprecated, use 'mammals' instead."
5355 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
5557 Cmd.v info Term.(const (fun n h -> ()) $ bactrian $ herd)
5658
5759 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
5961 Cmd.group info [birds; mammals; fishs; camels]
6062
6163 let () = exit (Cmd.eval cmd)