···9595 |> ~~ B0_opam.build {|[[ make "all" "PREFIX=%{prefix}%" ]]|}
9696 |> ~~ B0_opam.install
9797{|[[make "install" "BINDIR=%{_:bin}%" "LIBDIR=%{_:lib}%" "DOCDIR=%{_:doc}%"
9898- "SHAREDIR=%{share}%"]
9999- [make "install-doc" "LIBDIR=%{_:lib}%" "DOCDIR=%{_:doc}%"]]|}
9898+ "SHAREDIR=%{share}%" "MANDIR=%{man}%"]
9999+ [make "install-doc" "LIBDIR=%{_:lib}%" "DOCDIR=%{_:doc}%"
100100+ "SHAREDIR=%{share}%" "MANDIR=%{man}%"]]|}
100101 |> B0_meta.tag B0_opam.tag
101102 in
102103 let locked = false (* So that it looks up b0.std *) in
+6-6
CHANGES.md
···205205functions and `Term.info` information values in favor of the new
206206`Cmdliner.Cmd` module.
207207208208-The `Cmd` module generalizes the existing sub command support to allow
209209-arbitrarily nested sub commands each with its own man page and command
208208+The `Cmd` module generalizes the existing subcommand support to allow
209209+arbitrarily nested subcommands each with its own man page and command
210210line syntax represented by a `Term.t` value.
211211212212The mapping between the old interface and the new one should be rather
···221221 * The `?exits` argument which defaults to `Cmd.Exit.defaults`
222222 rather than the empty list.
223223 * The `?man_xrefs` which defaults to the list ``[`Main]`` rather
224224- than the empty list (this means that by default sub commands
224224+ than the empty list (this means that by default subcommands
225225 at any level automatically cross-reference the main command).
226226 * The `?sdocs` argument which defaults to `Manpage.s_common_options`
227227 rather than `Manpage.s_options`.
···241241 or `Term.term_result`.
242242243243Finally be aware that if you replace, in an existing tool, an encoding
244244-of sub commands as positional arguments you will effectively break the
244244+of subcommands as positional arguments you will effectively break the
245245command line compatibility of your tool since options can no longer be
246246-specified before the sub commands, i.e. your tool synopsis moves from:
246246+specified before the subcommands, i.e. your tool synopsis moves from:
247247248248```
249249tool cmd [OPTION]… SUBCMD [ARG]…
···472472 the sense that only more command lines are parsed. Thanks to Hugo
473473 Heuzard for the patch.
474474- End user error message improvements using heuristics and edit
475475- distance search in the optional argument and sub command name
475475+ distance search in the optional argument and subcommand name
476476 spaces. Thanks to Hugo Heuzard for the patch.
477477- Adds `Arg.doc_{quote,alts,alts_enum}`, documentation string
478478 helpers.
···5566{1:invocation Tool invocation}
7788-For tools evaluating a command without sub commands the most general
88+For tools evaluating a command without subcommands the most general
99form of invocation is:
10101111{v
···2525resolve them: anything that follows it is treated as a positional
2626argument.
27272828-Tools evaluating commands with sub commands have this form of invocation
2828+Tools evaluating commands with subcommands have this form of invocation
29293030{v
3131tool [COMMAND]… [OPTION]… [ARG]…
···3434Commands automatically respond to the [--help] option by printing
3535{{!help}their help}. The sequence of [COMMAND] strings must be the first
3636strings following the tool name – as soon as an optional argument is
3737-seen the search for a sub command stops.
3737+seen the search for a subcommand stops.
38383939{1:args Arguments}
4040···130130131131{1:help Help and man pages}
132132133133-Help and man pages are are generated when you call your tool or a sub
134134-command with [--help]. By default, if the [TERM] environment variable
133133+Help and man pages are are generated when you call your tool or a subcommand
134134+with [--help]. By default, if the [TERM] environment variable
135135is not [dumb] or unset, the tool tries to {{!paging}page} the manual
136136so that you can directly search it. Otherwise it outputs the manual
137137as plain text.
···159159environment unless, the [LESS] environment variable is set in your
160160environment.
161161162162+{2:install_tool_manpages Install}
163163+164164+The manpages of a tool and its subcommands can be installed to a root
165165+[man] directory [$MANDIR] by invoking:
166166+167167+{@shell[
168168+cmdliner install tool-manpages thetool $MANDIR
169169+]}
170170+171171+This looks up [thetool] in the [PATH]. Use an explicit file path like
172172+[./thetool] to directly specify an executable.
173173+174174+If your are installing your package for [thetool] with [opam]
175175+and have [cmdliner] as a direct dependency and your tool is located
176176+in the build at the path [$BUILD/thetool] you can add the following
177177+[install:] instruction (also works if your build system is using
178178+a [.install] file).
179179+{@sh[
180180+install: ["cmdliner" "install" "tool-manpages" "$BUILD/thetool" "%{man}%"]
181181+]}
182182+Note that you need to specify the path to the built executable, trying
183183+to lookup the tool in the [PATH] does not work as the install does not
184184+see it yet. If [cmdliner] is only an optional dependency use the
185185+[{cmdliner:installed}] opam filter on the command invocation.
186186+187187+If you are also {{!install_tool_completion}installing completions} rather
188188+use the [install tool-support] command, see this
189189+{{!page-cookbook.tip_tool_support}cookbook tip}.
190190+162191{1:cli_completion Command line completion}
163192164193Cmdliner programs automatically get support for shell command line
···169198installed by the library. For now the [zsh] and [bash] shells are
170199supported.
171200172172-Tool developers can easily {{!install_completion_tool}install}
201201+Tool developers can easily {{!install_tool_completion}install}
173202completion definitions that invoke these completion scripts. Tool
174203end-users need to {{!user_configuration}make sure} these definitions are
175204looked up by their shell.
···212241213242If the function cannnot be found make sure the [cmdliner] library is
214243installed, that the generic scripts were
215215-{{!install_completion_generic}installed} and that the
244244+{{!install_generic_completion}installed} and that the
216245[_cmdliner_generic] file can be found in one of the directories
217246mentioned in the [FPATH] variable.
218247219248With this setup, if you are using a cmdliner based tool named
220220-[thetool] that did not {{!install_completion_tool}install} a completion
249249+[thetool] that did not {{!install_tool_completion}install} a completion
221250definition. You can always do it yourself by invoking:
222251223252{@sh[
···253282254283If the function cannot be found make sure the [cmdliner] library is
255284installed, that the generic scripts were
256256-{{!install_completion_generic}installed} and that the
285285+{{!install_generic_completion}installed} and that the
257286[_cmdliner_generic] file can be looked up by [_completion_loader].
258287259288With this setup, if you are using a cmdliner based tool named
260260-[thetool] that did not {{!install_completion_tool}install} a completion
289289+[thetool] that did not {{!install_tool_completion}install} a completion
261290definition. You can always do it yourself by invoking:
262291263292{@sh[
···291320where you want with the [cmdliner generic-completion] and
292321[cmdliner tool-completion] commands.
293322294294-{3:install_completion_generic Generic completion scripts}
323323+{3:install_generic_completion Generic completion scripts}
295324296325The generic completion scripts must be installed by the
297326[cmdliner] library. They should not be part of your tool install. If
···307336Directories are created as needed. Use option [--dry-run] to see which
308337paths would be written by an [install] invocation.
309338310310-{3:install_completion_tool Tool completion scripts}
339339+{3:install_tool_completion Tool completion scripts}
311340312341If your tool named [thetool] uses Cmdliner you should install completion
313313-definitions for them. They rely on the {{!install_completion_generic}generic
342342+definitions for them. They rely on the {{!install_generic_completion}generic
314343scripts} to be installed. These tool specific scripts can be inspected
315344and installed via these invocations:
316345···333362install: [ "cmdliner" "install" "tool-completion" "thetool" "%{share}%"]
334363]}
335364336336-If [cmdliner] is only an optional dependency use:
365365+If [cmdliner] is only an optional dependency use the [{cmdliner:installed}]
366366+filter on the command invocation.
337367338338-{@sh[
339339-install: [ "cmdliner" "install" "tool-completion" "thetool" "%{share}%"
340340- {cmdliner:installed} ]
341341-]}
368368+If you are also {{!install_tool_manpages}installing manpages} rather
369369+use the [install tool-support] command, see this
370370+{{!page-cookbook.tip_tool_support}cookbook tip}.
342371343372{2:completion_protocol Completion protocol}
344373
+38-22
doc/cookbook.mld
···76767777Unless your tool is very simple, avoid making manpages the main
7878documentation medium of your tool. The medium is rather limited and
7979-even though you can convert them to HTML, their cross references
7979+even though you can convert them to HTML, its cross references
8080capabilities are rather limited which makes discussing your tool
8181online more difficult.
8282···170170let main () = Cmd.value' tool
171171let () = if !Sys.interactive then () else exit (main ())
172172]}
173173+174174+{2:tip_tool_support Installing completions and manpages}
175175+176176+The [cmdliner] tool can be used to install completion scripts and
177177+manpages for you tool and its subcommands by using the dedicated
178178+{{!page-cli.install_tool_completion}[install tool-completion]} and
179179+{{!page-cli.install_tool_manpages}[install tool-manpages]} subcommands.
180180+181181+To install both directly (and possibly other support files in the future)
182182+it is more concise to use the [install
183183+tool-support] command. Invoke with [--help] for more information.
184184+185185+If you are installing your package for [thetool] with [opam] and have
186186+[cmdliner] as a direct dependency and the tool is located in the
187187+build at the path [$BUILD/thetool], you can add the following
188188+[install:] instruction (also works if your build system is using a
189189+[.install] file).
190190+191191+{@sh[
192192+install: ["cmdliner" "install" "tool-support"
193193+ "--sharedir=%{share}%" "--mandir=%{man}%"
194194+ "$BUILD/thetool" "%{prefix}%"]
195195+]}
196196+197197+Note that you need to specify the path to the built executable, trying
198198+to lookup the tool in the [PATH] does not work as the install does not
199199+see it yet. Also more than one tool can be specified and there is a
200200+syntax for specifying the actual tool name if it is renamed when
201201+installed; see [--help] for more details. If [cmdliner] is only an
202202+optional dependency use the opam filter [{cmdliner:installed}] on the
203203+command invocation.
173204174205{1:conventions Conventions}
175206···453484454485The command line interface manual has all
455486{{!page-cli.cli_completion}the details} and
456456-{{!page-cli.install_completion_tool} specific instructions} for
457457-complementing your tool install.
487487+{{!page-cli.install_tool_completion} specific instructions} for
488488+complementing your tool install, see also {!tip_tool_support}.
458489459490{2:cmds_listing How can I list all the commands of my tool?}
460491···485516{{:https://erratique.ch/software/b0/doc/B0_std/Fmt/index.html#val-strip_styles}
486517this one} has been applied that automatically strips the styling.
487518488488-489519{1:manpage Manpages}
490520491521{3:manpage_hide How do I prevent an item from being automatically listed?}
···513543 `P "Without a command $(cmd) invokes $(i,TOOL)"; ]
514544]}
515545516516-{2:manpage_gen How can I generate all the command manpages of my tool?}
546546+{2:manpage_install How can I install all the manpages of my tool?}
517547518518-The [tool-commands] command of the [cmdliner] tool allows to list
519519-all the commands of a cmdliner based tool. The following shell snippet
520520-generates all the manpages in the current working directory (note it
521521-assumes that the manual section of each command is [1]):
522522-{@shell[
523523-TOOL=mytool
524524-$TOOL --help=groff > $TOOL.1
525525-while IFS= read -r SUB; do
526526- $TOOL $SUB --help=groff > $TOOL-$(echo $SUB | tr ' ' '-').1
527527-done < <(cmdliner tool-commands $TOOL)
528528-]}
529529-530530-See also {!manpage_install}.
531531-532532-{2:manpage_install How can I install all the command manpages of my tool?}
533533-534534-TODO
548548+The command line interface manual
549549+{{!page-cli.install_tool_manpages}the details} on how to install the manpages
550550+of your tool and its subcommands. See also {!tip_tool_support}.
535551536552{1:blueprints Blueprints}
537553
+6-6
src/cmdliner.mli
···270270 {- [`Help (format, name)], the evaluation fails and [Cmdliner] prints
271271 a manpage in format [format]. If [name] is [None] this is the
272272 the main command's manpage. If [name] is [Some c] this is
273273- the man page of the sub command [c] of the main command.}} *)
273273+ the man page of the subcommand [c] of the main command.}} *)
274274end
275275276276(** Commands.
···279279 values. A command value binds a term and its documentation to a
280280 command name.
281281282282- A command can group a list of sub commands (and recursively). In this
282282+ A command can group a list of subcommands (and recursively). In this
283283 case your tool defines a tree of commands, each with its own command
284284 line syntax. The root of that tree is called the {e main command};
285285 it represents your tool and its name. *)
···456456457457 val group : ?default:'a Term.t -> info -> 'a t list -> 'a t
458458 (** [group i ?default cmds] is a command with information [i] that
459459- groups sub commands [cmds]. [default] is the command line syntax
460460- to parse if no sub command is specified on the command line. If
461461- [default] is [None] (default), the tool errors when no sub
462462- command is specified. *)
459459+ groups subcommands [cmds]. [default] is the command line syntax
460460+ to parse if no subcommand is specified on the command line. If
461461+ [default] is [None] (default), the tool errors when no subcommand
462462+ is specified. *)
463463464464 val name : 'a t -> string
465465 (** [name c] is the name of [c]. *)
+223-45
src/tool/cmdliner_main.ml
···5656 with
5757 | Sys_error e -> Error e
58585959-(* Tool command list *)
5959+(* Cmdliner based tool introspection.
6060+6161+ Note this is a bit hackish but does the job. At some point we could
6262+ investigate cleaner protocols with the `--cmdliner` reserved option. *)
6363+6464+let split_toolname toolexec =
6565+ let tool, name = Scanf.sscanf toolexec "%s@:%s" (fun n e -> n, e) in
6666+ let name =
6767+ if name <> "" then name else
6868+ let name = Filename.basename tool in
6969+ match Filename.chop_suffix_opt ~suffix:".exe" tool with
7070+ | None -> name | Some name -> name
7171+ in
7272+ tool, name
60736161-let tool_commands tool =
7474+let get_tool_commands tool =
7575+ (* We get that by using the completion protocol, see doc/cli.mld *)
6276 try
6377 let subcommands cmd =
6478 let rec find_subs = function
···6680 let rec subs acc = function
6781 | "group" :: _ | [] -> acc
6882 | "item" :: sub :: lines ->
6969- let sub =
7070- if cmd = "" then sub else String.concat " " [cmd; sub]
7171- in
8383+ let sub = if cmd = "" then sub else String.concat " " [cmd; sub]in
7284 subs (sub :: acc) lines
7385 | _ :: lines -> subs acc lines
7486 in
···8698 loop (if cmd <> "" then cmd :: acc else acc) (List.rev_append subs cmds)
8799 | [] -> List.sort String.compare acc
88100 in
8989- List.iter print_endline (loop [] [""]);
9090- Cmdliner.Cmd.Exit.ok
9191- with
9292- | Failure e ->
9393- prerr_endline e;
9494- prerr_endline "Are you sure this a cmdliner based tool?";
9595- Cmdliner.Cmd.Exit.some_error
101101+ Ok (loop [] [""])
102102+ with Failure e -> Error e
103103+104104+let get_tool_command_man tool ~name cmd =
105105+ let exec = if cmd = "" then tool else String.concat " " [tool; cmd] in
106106+ let man_basename =
107107+ let exec = if cmd = "" then name else String.concat " " [name; cmd] in
108108+ (String.map (function ' ' -> '-' | c -> c) exec)
109109+ in
110110+ let add_section man =
111111+ let rec extract_section = function
112112+ | line :: lines ->
113113+ begin match Scanf.sscanf line ".TH %s %d" (fun _ n -> n) with
114114+ | n -> Ok (n, man_basename, man)
115115+ | exception Scanf.Scan_failure _ -> extract_section lines
116116+ end
117117+ | [] ->
118118+ Error (strf "%s command: Could not extract section from manual" exec)
119119+ in
120120+ extract_section (String.split_on_char '\n' man)
121121+ in
122122+ let get_groff = exec ^ " --help=groff" in
123123+ match exec_stdout get_groff with
124124+ | Error _ as e -> e
125125+ | Ok man -> add_section man
126126+127127+let get_tool_manpages tool ~name = match get_tool_commands tool with
128128+| Error _ as e -> e
129129+| Ok cmds ->
130130+ try
131131+ let man cmd = match get_tool_command_man tool ~name cmd with
132132+ | Error e -> failwith e
133133+ | Ok man -> man
134134+ in
135135+ Ok (List.sort compare (List.map man ("" :: cmds)))
136136+ with
137137+ | Failure e -> Error e
9613897139(* File path actions *)
98140···111153 | Error e -> failwith e
112154 end
113155114114-(* Shells *)
156156+(* Shells completion *)
115157116158module type SHELL = sig
117159 val name : string
···163205 print_string (Shell.tool_completion ~toolname);
164206 Cmdliner.Cmd.Exit.ok
165207208208+(* Install commands *)
209209+166210let install_generic_completion ~dry_run shells sharedir =
167211 with_binary_stdout @@ fun () ->
168212 let install ~dry_run sharedir (module Shell : SHELL) =
···174218 List.iter (install ~dry_run sharedir) shells;
175219 Cmdliner.Cmd.Exit.ok
176220177177-let install_tool_completion ~dry_run shells ~toolnames sharedir =
221221+let install_tool_completion ~dry_run ~shells ~toolnames ~sharedir =
178222 with_binary_stdout @@ fun () ->
179223 let install ~dry_run ~toolnames sharedir (module Shell : SHELL) =
180224 let dest = Filename.concat sharedir Shell.sharedir in
···188232 List.iter (install ~dry_run ~toolnames sharedir) shells;
189233 Cmdliner.Cmd.Exit.ok
190234235235+let install_tool_manpages ~dry_run ~tools ~mandir =
236236+ (* Note this correctly handles manpages sections but at the moment
237237+ all manpages for tool and commands are in section 1. *)
238238+ let rec get_mans tool =
239239+ let tool, name = split_toolname tool in
240240+ match get_tool_manpages tool ~name with
241241+ | Ok mans -> mans
242242+ | Error e -> failwith e
243243+ in
244244+ try
245245+ let mans = List.sort compare (List.concat (List.map get_mans tools)) in
246246+ let rec install ~dry_run ~last_sec = function
247247+ | (sec, basename, man) :: mans ->
248248+ let mandir = Filename.concat mandir (strf "man%d" sec) in
249249+ let manfile = Filename.concat mandir (strf "%s.%d" basename sec) in
250250+ if last_sec <> sec then mkdir ~dry_run mandir;
251251+ write_file ~dry_run manfile man;
252252+ install ~dry_run ~last_sec:sec mans
253253+ | [] -> ()
254254+ in
255255+ install ~dry_run ~last_sec:(-1) mans;
256256+ Cmdliner.Cmd.Exit.ok
257257+ with Failure e -> prerr_endline e; Cmdliner.Cmd.Exit.some_error
258258+259259+let install_tool_support ~dry_run tools shells ~prefix ~sharedir ~mandir =
260260+ let sharedir = match sharedir with
261261+ | None -> Filename.concat prefix "share" | Some sharedir -> sharedir
262262+ in
263263+ let mandir = match mandir with
264264+ | None -> Filename.concat sharedir "man" | Some mandir -> mandir
265265+ in
266266+ let rc = install_tool_manpages ~dry_run ~tools ~mandir in
267267+ if rc <> Cmdliner.Cmd.Exit.ok then rc else
268268+ let toolnames = List.map snd (List.map split_toolname tools) in
269269+ install_tool_completion ~dry_run ~shells ~toolnames ~sharedir
270270+271271+(* Tool command listing command *)
272272+273273+let tool_commands tool = match get_tool_commands tool with
274274+| Ok subs -> List.iter print_endline subs; Cmdliner.Cmd.Exit.ok
275275+| Error e -> prerr_endline e; Cmdliner.Cmd.Exit.some_error
276276+191277(* Command line interface *)
192278193279open Cmdliner
···197283 let doc = "Do not install, output paths that would be written." in
198284 Arg.(value & flag & info ["dry-run"] ~doc)
199285286286+let prefix =
287287+ let doc = "$(docv) is the install prefix. For example $(b,/usr/local)." in
288288+ Arg.(required & pos ~rev:true 0 (some dirpath) None &
289289+ info [] ~doc ~docv:"PREFIX")
290290+291291+let sharedir_doc = "$(docv) is the $(b,share) directory to install to."
292292+let sharedir_docv = "SHAREDIR"
200293let sharedir_posn ~rev n =
201201- let doc = "$(docv) is the $(b,share) directory to install to." in
202294 Arg.(required & pos ~rev n (some dirpath) None &
203203- info [] ~doc ~docv:"SHAREDIR")
295295+ info [] ~doc:sharedir_doc ~docv:sharedir_docv)
204296205297let sharedir_pos0 = sharedir_posn ~rev:false 0
206298let sharedir_poslast = sharedir_posn ~rev:true 0
299299+let sharedir_opt =
300300+ let absent = "$(i,PREFIX)$(b,/share)" in
301301+ Arg.(value & opt (some dirpath) None &
302302+ info ["sharedir"] ~doc:sharedir_doc ~docv:sharedir_docv ~absent)
303303+304304+let mandir_doc = "$(docv) is the root $(b,man) directory to install to."
305305+let mandir_docv = "MANDIR"
306306+let mandir_poslast =
307307+ Arg.(required & pos ~rev:true 0 (some dirpath) None &
308308+ info [] ~doc:mandir_doc ~docv:mandir_docv)
309309+310310+let mandir_opt =
311311+ let absent = "$(i,SHAREDIR)$(b,/man)" in
312312+ Arg.(value & opt (some dirpath) None &
313313+ info ["mandir"] ~doc:mandir_doc ~docv:mandir_docv ~absent)
207314208315let shell_assoc = List.map (fun ((module S : SHELL) as s) -> S.name, s) shells
209316let shells_doc = Arg.doc_alts_enum shell_assoc
···221328let shell_pos1 = shell_posn 1
222329223330let toolname_posn n =
224224- let doc = "$(docv) is the name of the tool to complete" in
225225- Arg.(required & pos n (some string) None & info [] ~doc ~docv:"TOOLNAME")
331331+ let doc = "$(docv) is the name of the tool to complete." in
332332+ Arg.(required & pos n (some filepath) None & info [] ~doc ~docv:"TOOLNAME")
226333227334let toolname_pos0 = toolname_posn 0
228335let toolname_pos1 = toolname_posn 1
···231338 Arg.(non_empty & pos_left ~rev:true 0 string [] &
232339 info [] ~doc ~docv:"TOOLNAME")
233340341341+let tools_posleft =
342342+ let doc =
343343+ "$(i,TOOLEXEC) is the tool executable. Searched in the $(b,PATH) unless \
344344+ an explicit file path is specified. $(i,NAME) is the tool name, if \
345345+ unspecified derived from $(i,TOOLEXEC) by taking the basename and \
346346+ stripping any $(b,.exe) extension. Repeatable."
347347+ in
348348+ let docv = "TOOLEXEC[:NAME]" in
349349+ Arg.(non_empty & pos_left ~rev:true 0 filepath [] & info [] ~doc ~docv)
350350+234351let generic_completion_cmd =
235352 let doc = "Output generic completion scripts" in
236353 let man =
237354 [ `S Manpage.s_description;
238238- `P "$(cmd) outputs the generic completion script of a given shell. \
239239- For example:";
355355+ `P "$(cmd) outputs the generic cmdliner completion script for a given \
356356+ shell. Examples:";
240357 `Pre "$(cmd) $(b,zsh)"; `Noblank;
241241- `Pre "$(b,eval) \\$($(cmd) $(b,zsh))"; ]
358358+ `Pre "$(b,eval) $(b,\\$\\()$(cmd) $(b,zsh\\))";
359359+ `P "The script needs to be loaded in a shell for tool specific \
360360+ scripts output by the command $(b,tool-completion) to work. See \
361361+ command $(b,install generic-completion) to install them.";
362362+ ]
242363 in
243364 Cmd.make (Cmd.info "generic-completion" ~doc ~man) @@
244365 let+ shell = shell_pos0 in
245366 generic_completion shell
246367247368let tool_commands_cmd =
248248- let doc = "Output all commands of a cmdliner tool" in
369369+ let doc = "Output all subcommands of a cmdliner tool" in
249370 let man =
250371 [ `S Manpage.s_description;
251251- `P "$(cmd) $(i,TOOL) outputs all the commands of the cmdliner based \
252252- tool, one per line.";
372372+ `P "$(cmd) outputs all the subcommands of a given cmdliner based \
373373+ tool, one per line. Examples:";
374374+ `Pre "$(cmd) $(b,./mytool)"; `Noblank;
375375+ `Pre "$(cmd) $(b,cmdliner)";
253376 ]
254377 in
255378 Cmd.make (Cmd.info "tool-commands" ~doc ~man) @@
256379 let+ tool =
257257- Arg.(required & pos 0 (some filepath) None & info [] ~docv:"TOOL")
380380+ let doc =
381381+ "$(docv) is the tool executable. Searched in the $(b,PATH) unless \
382382+ an explicit file path is specified."
383383+ in
384384+ Arg.(required & pos 0 (some string) None & info [] ~doc ~docv:"TOOLEXEC")
258385 in
259386 tool_commands tool
260387261261-262388let tool_completion_cmd =
263389 let doc = "Output tool completion scripts" in
264390 let man =
265391 [ `S Manpage.s_description;
266266- `P "$(cmd) outputs the tool completion script of a given shell. \
267267- For example:";
268268- `Pre "$(cmd) $(b,zsh mytool)"; ]
392392+ `P "$(cmd) outputs the tool specific completion script of a given shell. \
393393+ Example:";
394394+ `Pre "$(cmd) $(b,zsh mytool)";
395395+ `P "Note that tool specific completion script need the corresponding \
396396+ generic completion script output by $(b,generic-completion) to be \
397397+ loaded in the shell. To install these scripts see command \
398398+ $(b,install tool-completion).";
399399+ ]
269400 in
270401 Cmd.make (Cmd.info "tool-completion" ~doc ~man) @@
271402 let+ shell = shell_pos0 and+ toolname = toolname_pos1 in
···277408 `S Manpage.s_description;
278409 `P "$(cmd) installs the generic completion script of given shells in \
279410 a $(b,share) directory according to specific shell conventions. \
280280- Directories are not created. \
411411+ Directories are created if needed. \
281412 Use option $(b,--dry-run) to see which paths would be written. \
282282- For example:";
413413+ Examples:";
283414 `Pre "$(cmd) $(b,/usr/local/share) # All supported shells"; `Noblank;
284284- `Pre "$(cmd) $(b,--shell zsh /usr/local/share)"; ]
415415+ `Pre "$(cmd) $(b,--shell zsh /usr/local/share)";
416416+ `P "To inspect the actual scripts use the command \
417417+ $(b,generic-completion).";
418418+ ]
285419 in
286420 Cmd.make (Cmd.info "generic-completion" ~doc ~man) @@
287421 (* No let punning in < 4.13 *)
···293427 let doc = "Install tool completion scripts" in
294428 let man = [
295429 `S Manpage.s_description;
296296- `P "$(cmd) installs the tool completion script of given shells in \
430430+ `P "$(cmd) installs tool completion script of given tools and shells in \
297431 a $(b,share) directory according to specific shell conventions. \
298298- Directories are not created. \
432432+ Directories are created if needed. \
299433 Use option $(b,--dry-run) to see which paths would be written. \
300300- For example:";
434434+ Example:";
301435 `Pre "$(cmd) $(b,mytool) $(b,/usr/local/share) # All supported shells";
302436 `Noblank;
303303- `Pre "$(cmd) $(b,--shell zsh mytool /usr/local/share)"; ]
437437+ `Pre "$(cmd) $(b,--shell zsh mytool /usr/local/share)";
438438+ `P "Note that the command $(b,install tool-support) also installs \
439439+ completions like this command does. To inspect the actual scripts \
440440+ use the command $(b,tool-completion).";
441441+ ]
304442 in
305443 Cmd.make (Cmd.info "tool-completion" ~doc ~man) @@
306444 (* No let punning in < 4.13 *)
307445 let+ dry_run = dry_run and+ shells = shells_opt
308308- and+ toolnames = toolnames_posleft and+ sharedir_poslast = sharedir_poslast in
309309- install_tool_completion ~dry_run shells ~toolnames sharedir_poslast
446446+ and+ toolnames = toolnames_posleft and+ sharedir = sharedir_poslast in
447447+ install_tool_completion ~dry_run ~shells ~toolnames ~sharedir
448448+449449+let install_tool_manpages_cmd =
450450+ let doc = "Install tool and subcommand manpages" in
451451+ let man = [
452452+ `S Manpage.s_description;
453453+ `P "$(cmd) installs the manpages of the tool and its commands \
454454+ according in directories of a $(b,man) directory. Directories are \
455455+ created if needed. \
456456+ Use option $(b,--dry-run) to see which paths would be written. \
457457+ Example:";
458458+ `Pre "$(cmd) $(b,./mytool) $(b,/usr/local/share/man)";
459459+ `P "Note that the command $(b,install tool-support) also installs manpages \
460460+ like this command does."
461461+ ]
462462+ in
463463+ Cmd.make (Cmd.info "tool-manpages" ~doc ~man) @@
464464+ let+ dry_run = dry_run
465465+ and+ tools = tools_posleft and+ mandir = mandir_poslast in
466466+ install_tool_manpages ~dry_run ~tools ~mandir
467467+468468+let install_tool_support_cmd =
469469+ let doc = "Install both tool completion and manpages" in
470470+ let man = [
471471+ `S Manpage.s_description;
472472+ `P "$(cmd) combines commands $(b,install tool-completion) and \
473473+ $(b,install tool-manpages) to install all tool support files \
474474+ in a given $(i,PREFIX) which is assumed to follow the Filesystem \
475475+ Hierarchy Standard.
476476+ Use options $(b,--sharedir) and/or $(b,--mandir) if that is
477477+ not the case (e.g. in $(b,opam) as of writing).
478478+ Use option $(b,--dry-run) to see which paths would be written. \
479479+ Example:";
480480+ `Pre "$(cmd) $(b,./mytool) $(b,/usr/local)"; ]
481481+ in
482482+ Cmd.make (Cmd.info "tool-support" ~doc ~man) @@
483483+ let+ dry_run = dry_run and+ shells = shells_opt
484484+ and+ tools = tools_posleft and+ sharedir = sharedir_opt
485485+ and+ mandir = mandir_opt and+ prefix = prefix in
486486+ install_tool_support ~dry_run tools shells ~prefix ~sharedir ~mandir
310487311488let install_cmd =
312312- let doc = "Install cmdliner support files" in
489489+ let doc = "Install support files for cmdliner tools" in
313490 let man =
314491 [ `S Manpage.s_description;
315492 `P "$(cmd) subcommands install cmdliner support files. \
···317494 subcommands with $(b,--help) for more details."; ]
318495 in
319496 Cmd.group (Cmd.info "install" ~doc ~man) @@
320320- [install_generic_completion_cmd; install_tool_completion_cmd]
497497+ [install_generic_completion_cmd; install_tool_completion_cmd;
498498+ install_tool_manpages_cmd; install_tool_support_cmd]
321499322500let main_cmd =
323323- let doc = "Helper tool for cmdliner based programs" in
501501+ let doc = "Helper tool for cmdliner based tools" in
324502 let default = Term.(ret (const (`Help (`Pager, None)))) in
325503 let man =
326504 [ `S Manpage.s_description;
327327- `P "$(tool) is a helper tool for Cmdliner based programs. It \
328328- helps with installing command line completion scripts. \
329329- See the library documentation or invoke \
330330- subcommands with $(b,--help) for more details."; ]
505505+ `P "$(tool) is a helper for tools using the cmdliner command line \
506506+ interface library. It helps with installing command line \
507507+ completion scripts and manpages. See the library documentation or \
508508+ invoke subcommands with $(b,--help) for more details."; ]
331509 in
332510 Cmd.group (Cmd.info "cmdliner" ~version:"%%VERSION%%" ~doc ~man) ~default @@
333511 [generic_completion_cmd; tool_commands_cmd; tool_completion_cmd; install_cmd]