mirror of
https://github.com/c-cube/linol.git
synced 2026-01-21 08:56:40 -05:00
deploy: fb49472f34
This commit is contained in:
parent
09bb1db5c8
commit
247371f990
47 changed files with 1921 additions and 379 deletions
|
|
@ -3,8 +3,8 @@
|
|||
@import url("theme.css");
|
||||
|
||||
/* Copyright (c) 2019 The odig programmers. All rights reserved.
|
||||
Distributed under the ISC license, see terms at the end of the file.
|
||||
odig v0.0.9 */
|
||||
SPDX-License-Identifier: ISC
|
||||
odig v0.1.0 */
|
||||
|
||||
:root { --font-headings: "PT-Sans-Caption";
|
||||
--font-body: "PT-Sans";
|
||||
|
|
@ -373,4 +373,4 @@ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
*/
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
@import url("theme.css");
|
||||
|
||||
/* Copyright (c) 2019 The odig programmers. All rights reserved.
|
||||
Distributed under the ISC license, see terms at the end of the file. */
|
||||
SPDX-License-Identifier: ISC */
|
||||
|
||||
/* Reset a few things. */
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ table { border-collapse: collapse; border-spacing: 0; }
|
|||
.odoc-nav { grid-area: nav; }
|
||||
.odoc-preamble { grid-area: header; }
|
||||
.odoc-content { grid-area: content; margin: 0 }
|
||||
.odoc-toc
|
||||
.odoc-tocs
|
||||
{ grid-area: toc;
|
||||
margin-top: var(--size-line);
|
||||
border-top: solid thin var(--color-rule); }
|
||||
|
|
@ -331,4 +331,4 @@ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
*/
|
||||
5
cmdliner/Cmdliner/Arg/Completion/index.html
Normal file
5
cmdliner/Cmdliner/Arg/Completion/index.html
Normal file
File diff suppressed because one or more lines are too long
14
cmdliner/Cmdliner/Arg/Conv/index.html
Normal file
14
cmdliner/Cmdliner/Arg/Conv/index.html
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Conv (cmdliner.Cmdliner.Arg.Conv)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../../../index.html">Index</a> » <a href="../../../index.html">cmdliner</a> » <a href="../../index.html">Cmdliner</a> » <a href="../index.html">Arg</a> » Conv</nav><header class="odoc-preamble"><h1>Module <code><span>Arg.Conv</span></code></h1><p>Argument converters.</p><p>An argument converter transforms a string argument of the command line to an OCaml value. <a href="../index.html#converters" title="converters">Predefined converters</a> are provided for many types of the standard library.</p></header><div class="odoc-tocs"><nav class="odoc-toc odoc-local-toc"><ul><li><a href="#converters">Converters</a></li><li><a href="#properties">Properties</a></li></ul></nav></div><div class="odoc-content"><h2 id="converters"><a href="#converters" class="anchor"></a>Converters</h2><div class="odoc-spec"><div class="spec type anchored" id="type-parser"><a href="#type-parser" class="anchor"></a><code><span><span class="keyword">type</span> <span>'a parser</span></span><span> = <span>string <span class="arrow">-></span></span> <span><span>(<span class="type-var">'a</span>, string)</span> <a href="../../../../ocaml/Stdlib/index.html#type-result">result</a></span></span></code></div><div class="spec-doc"><p>The type for parsing arguments to values of type <code>'a</code>.</p></div></div><div class="odoc-spec"><div class="spec type anchored" id="type-fmt"><a href="#type-fmt" class="anchor"></a><code><span><span class="keyword">type</span> <span>'a fmt</span></span><span> = <span><a href="../../../../ocaml/Stdlib/Format/index.html#type-formatter">Stdlib.Format.formatter</a> <span class="arrow">-></span></span> <span><span class="type-var">'a</span> <span class="arrow">-></span></span> unit</span></code></div><div class="spec-doc"><p>The type for formatting values of type <code>'a</code>.</p></div></div><div class="odoc-spec"><div class="spec type anchored" id="type-t"><a href="#type-t" class="anchor"></a><code><span><span class="keyword">type</span> <span>'a t</span></span></code></div><div class="spec-doc"><p>The type for converting arguments to values of type <code>'a</code>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-make"><a href="#val-make" class="anchor"></a><code><span><span class="keyword">val</span> make :
|
||||
<span><span class="optlabel">?completion</span>:<span><span class="type-var">'a</span> <a href="../Completion/index.html#type-t">Completion.t</a></span> <span class="arrow">-></span></span>
|
||||
<span><span class="label">docv</span>:string <span class="arrow">-></span></span>
|
||||
<span><span class="label">parser</span>:<span><span class="type-var">'a</span> <a href="#type-parser">parser</a></span> <span class="arrow">-></span></span>
|
||||
<span><span class="label">pp</span>:<span><span class="type-var">'a</span> <a href="#type-fmt">fmt</a></span> <span class="arrow">-></span></span>
|
||||
<span>unit <span class="arrow">-></span></span>
|
||||
<span><span class="type-var">'a</span> <a href="#type-t">t</a></span></span></code></div><div class="spec-doc"><p><code>make ~docv ~parser ~pp ()</code> is an argument converter with given properties. See corresponding accessors for semantics.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-of_conv"><a href="#val-of_conv" class="anchor"></a><code><span><span class="keyword">val</span> of_conv :
|
||||
<span><span class="optlabel">?completion</span>:<span><span class="type-var">'a</span> <a href="../Completion/index.html#type-t">Completion.t</a></span> <span class="arrow">-></span></span>
|
||||
<span><span class="optlabel">?docv</span>:string <span class="arrow">-></span></span>
|
||||
<span><span class="optlabel">?parser</span>:<span><span class="type-var">'a</span> <a href="#type-parser">parser</a></span> <span class="arrow">-></span></span>
|
||||
<span><span class="optlabel">?pp</span>:<span><span class="type-var">'a</span> <a href="#type-fmt">fmt</a></span> <span class="arrow">-></span></span>
|
||||
<span><span><span class="type-var">'a</span> <a href="#type-t">t</a></span> <span class="arrow">-></span></span>
|
||||
<span><span class="type-var">'a</span> <a href="#type-t">t</a></span></span></code></div><div class="spec-doc"><p><code>of_conv conv ()</code> is a new converter with given unspecified properties defaulting to those of <code>conv</code>.</p></div></div><h2 id="properties"><a href="#properties" class="anchor"></a>Properties</h2><div class="odoc-spec"><div class="spec value anchored" id="val-docv"><a href="#val-docv" class="anchor"></a><code><span><span class="keyword">val</span> docv : <span><span><span class="type-var">'a</span> <a href="#type-t">t</a></span> <span class="arrow">-></span></span> string</span></code></div><div class="spec-doc"><p><code>docv c</code> is <code>c</code>'s documentation meta-variable. This value can be refered to as <code>$(docv)</code> in the documentation strings of arguments. It can be overriden by the <a href="../index.html#val-info"><code>info</code></a> value of an argument.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-parser"><a href="#val-parser" class="anchor"></a><code><span><span class="keyword">val</span> parser : <span><span><span class="type-var">'a</span> <a href="#type-t">t</a></span> <span class="arrow">-></span></span> <span><span class="type-var">'a</span> <a href="#type-parser">parser</a></span></span></code></div><div class="spec-doc"><p><code>parser c</code> is <code>c</code>'s argument parser.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-pp"><a href="#val-pp" class="anchor"></a><code><span><span class="keyword">val</span> pp : <span><span><span class="type-var">'a</span> <a href="#type-t">t</a></span> <span class="arrow">-></span></span> <span><span class="type-var">'a</span> <a href="#type-fmt">fmt</a></span></span></code></div><div class="spec-doc"><p><code>pp c</code> is <code>c</code>'s argument formatter.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-completion"><a href="#val-completion" class="anchor"></a><code><span><span class="keyword">val</span> completion : <span><span><span class="type-var">'a</span> <a href="#type-t">t</a></span> <span class="arrow">-></span></span> <span><span class="type-var">'a</span> <a href="../Completion/index.html#type-t">Completion.t</a></span></span></code></div><div class="spec-doc"><p><code>completion c</code> is <code>c</code>'s completion.</p></div></div></div></body></html>
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,2 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Env (cmdliner.Cmdliner.Cmd.Env)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../../../index.html">Index</a> » <a href="../../../index.html">cmdliner</a> » <a href="../../index.html">Cmdliner</a> » <a href="../index.html">Cmd</a> » Env</nav><header class="odoc-preamble"><h1>Module <code><span>Cmd.Env</span></code></h1><p>Environment variable and their information.</p></header><div class="odoc-tocs"><nav class="odoc-toc odoc-local-toc"><ul><li><a href="#envvars">Environment variables</a></li><li><a href="#info">Environment variable information</a></li></ul></nav></div><div class="odoc-content"><h2 id="envvars"><a href="#envvars" class="anchor"></a>Environment variables</h2><div class="odoc-spec"><div class="spec type anchored" id="type-var"><a href="#type-var" class="anchor"></a><code><span><span class="keyword">type</span> var</span><span> = string</span></code></div><div class="spec-doc"><p>The type for environment names.</p></div></div><h2 id="info"><a href="#info" class="anchor"></a>Environment variable information</h2><div class="odoc-spec"><div class="spec type anchored" id="type-info"><a href="#type-info" class="anchor"></a><code><span><span class="keyword">type</span> info</span><span> = <a href="../../Term/index.html#type-env_info">Term.env_info</a></span></code></div><div class="spec-doc"><p>The type for environment variable information.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-info"><a href="#val-info" class="anchor"></a><code><span><span class="keyword">val</span> info : <span><span class="optlabel">?deprecated</span>:string <span class="arrow">-></span></span> <span><span class="optlabel">?docs</span>:string <span class="arrow">-></span></span> <span><span class="optlabel">?doc</span>:string <span class="arrow">-></span></span> <span><a href="#type-var">var</a> <span class="arrow">-></span></span> <a href="#type-info">info</a></span></code></div><div class="spec-doc"><p><code>info ~docs ~doc var</code> describes an environment variable <code>var</code> such that:</p><ul><li><code>doc</code> is the man page information of the environment variable, defaults to <code>"undocumented"</code>.</li><li><code>docs</code> is the title of the man page section in which the environment variable will be listed, it defaults to <a href="../../Manpage/index.html#val-s_environment"><code>Cmdliner.Manpage.s_environment</code></a>.</li><li><code>deprecated</code>, if specified the environment is deprecated and the string is a message output on standard error when the environment variable gets used to lookup the default value of an argument.</li></ul><p>In <code>doc</code> the <a href="../../../tool_man.html#doclang" title="doclang">documentation markup language</a> can be used with following variables:</p><ul><li><code>$(env)</code>, the value of <code>var</code>.</li><li>The variables mentioned in <a href="#val-info"><code>info</code></a>.</li></ul></div></div></div></body></html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Env (cmdliner.Cmdliner.Cmd.Env)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../../../index.html">Index</a> » <a href="../../../index.html">cmdliner</a> » <a href="../../index.html">Cmdliner</a> » <a href="../index.html">Cmd</a> » Env</nav><header class="odoc-preamble"><h1>Module <code><span>Cmd.Env</span></code></h1><p>Environment variable and their information.</p></header><div class="odoc-tocs"><nav class="odoc-toc odoc-local-toc"><ul><li><a href="#envvars">Environment variables</a></li><li><a href="#info">Environment variable information</a></li></ul></nav></div><div class="odoc-content"><h2 id="envvars"><a href="#envvars" class="anchor"></a>Environment variables</h2><div class="odoc-spec"><div class="spec type anchored" id="type-var"><a href="#type-var" class="anchor"></a><code><span><span class="keyword">type</span> var</span><span> = string</span></code></div><div class="spec-doc"><p>The type for environment variable names.</p></div></div><h2 id="info"><a href="#info" class="anchor"></a>Environment variable information</h2><div class="odoc-spec"><div class="spec type anchored" id="type-info"><a href="#type-info" class="anchor"></a><code><span><span class="keyword">type</span> info</span></code></div><div class="spec-doc"><p>The type for environment variable information.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-info"><a href="#val-info" class="anchor"></a><code><span><span class="keyword">val</span> info :
|
||||
<span><span class="optlabel">?deprecated</span>:string <span class="arrow">-></span></span>
|
||||
<span><span class="optlabel">?docs</span>:<a href="../../Manpage/index.html#type-section_name">Manpage.section_name</a> <span class="arrow">-></span></span>
|
||||
<span><span class="optlabel">?doc</span>:string <span class="arrow">-></span></span>
|
||||
<span><a href="#type-var">var</a> <span class="arrow">-></span></span>
|
||||
<a href="#type-info">info</a></span></code></div><div class="spec-doc"><p><code>info ~docs ~doc var</code> describes an environment variable <code>var</code> such that:</p><ul><li><code>doc</code> is the man page information of the environment variable, defaults to <code>"See option $(opt)."</code>.</li><li><code>docs</code> is the title of the man page section in which the environment variable will be listed, it defaults to <a href="../../Manpage/index.html#val-s_environment"><code>Cmdliner.Manpage.s_environment</code></a>.</li><li><code>deprecated</code>, if specified the environment variable is deprecated. Use of the variable warns on dep<code>stderr</code> This message which should be a capitalized sentence is preprended to <code>doc</code> and output on standard error when the environment variable ends up being used.</li></ul><p>In <code>doc</code> and <code>deprecated</code> the <a href="../../../tool_man.html#doclang" title="doclang">documentation markup language</a> can be used with following variables:</p><ul><li><code>$(opt)</code>, if any the option name of the argument the variable is looked up for.</li><li><code>$(env)</code>, the value of <code>var</code>.</li><li>The variables mentioned in the doc string of <a href="../index.html#val-info"><code>Cmd.info</code></a>.</li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-info_var"><a href="#val-info_var" class="anchor"></a><code><span><span class="keyword">val</span> info_var : <span><a href="#type-info">info</a> <span class="arrow">-></span></span> <a href="#type-var">var</a></span></code></div><div class="spec-doc"><p><code>info_var info</code> is the variable described by <code>info</code>.</p></div></div></div></body></html>
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,2 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Syntax (cmdliner.Cmdliner.Term.Syntax)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../../../index.html">Index</a> » <a href="../../../index.html">cmdliner</a> » <a href="../../index.html">Cmdliner</a> » <a href="../index.html">Term</a> » Syntax</nav><header class="odoc-preamble"><h1>Module <code><span>Term.Syntax</span></code></h1><p><code>let</code> operators.</p></header><div class="odoc-content"><div class="odoc-spec"><div class="spec value anchored" id="val-(let+)"><a href="#val-(let+)" class="anchor"></a><code><span><span class="keyword">val</span> (let+) : <span><span><span class="type-var">'a</span> <a href="../index.html#type-t">t</a></span> <span class="arrow">-></span></span> <span><span>(<span><span class="type-var">'a</span> <span class="arrow">-></span></span> <span class="type-var">'b</span>)</span> <span class="arrow">-></span></span> <span><span class="type-var">'b</span> <a href="../index.html#type-t">t</a></span></span></code></div><div class="spec-doc"><p><code>( let+ )</code> is <a href="../index.html#val-map"><code>map</code></a>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-(and+)"><a href="#val-(and+)" class="anchor"></a><code><span><span class="keyword">val</span> (and+) : <span><span><span class="type-var">'a</span> <a href="../index.html#type-t">t</a></span> <span class="arrow">-></span></span> <span><span><span class="type-var">'b</span> <a href="../index.html#type-t">t</a></span> <span class="arrow">-></span></span> <span><span>(<span class="type-var">'a</span> * <span class="type-var">'b</span>)</span> <a href="../index.html#type-t">t</a></span></span></code></div><div class="spec-doc"><p><code>( and* )</code> is <a href="../index.html#val-product"><code>product</code></a>.</p></div></div></div></body></html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Syntax (cmdliner.Cmdliner.Term.Syntax)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../../../index.html">Index</a> » <a href="../../../index.html">cmdliner</a> » <a href="../../index.html">Cmdliner</a> » <a href="../index.html">Term</a> » Syntax</nav><header class="odoc-preamble"><h1>Module <code><span>Term.Syntax</span></code></h1><p><code>let</code> operators.</p><p>See how to use them in the <a href="../../../cookbook.html#blueprints" title="blueprints">blueprints</a>.</p></header><div class="odoc-content"><div class="odoc-spec"><div class="spec value anchored" id="val-(let+)"><a href="#val-(let+)" class="anchor"></a><code><span><span class="keyword">val</span> (let+) : <span><span><span class="type-var">'a</span> <a href="../index.html#type-t">t</a></span> <span class="arrow">-></span></span> <span><span>(<span><span class="type-var">'a</span> <span class="arrow">-></span></span> <span class="type-var">'b</span>)</span> <span class="arrow">-></span></span> <span><span class="type-var">'b</span> <a href="../index.html#type-t">t</a></span></span></code></div><div class="spec-doc"><p><code>( let+ )</code> is <a href="../index.html#val-map"><code>map</code></a>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-(and+)"><a href="#val-(and+)" class="anchor"></a><code><span><span class="keyword">val</span> (and+) : <span><span><span class="type-var">'a</span> <a href="../index.html#type-t">t</a></span> <span class="arrow">-></span></span> <span><span><span class="type-var">'b</span> <a href="../index.html#type-t">t</a></span> <span class="arrow">-></span></span> <span><span>(<span class="type-var">'a</span> * <span class="type-var">'b</span>)</span> <a href="../index.html#type-t">t</a></span></span></code></div><div class="spec-doc"><p><code>( and+ )</code> is <a href="../index.html#val-product"><code>product</code></a>.</p></div></div></div></body></html>
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,2 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Cmdliner (cmdliner.Cmdliner)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../index.html">Index</a> » <a href="../index.html">cmdliner</a> » Cmdliner</nav><header class="odoc-preamble"><h1>Module <code><span>Cmdliner</span></code></h1><p>Declarative definition of command line interfaces.</p><p>Consult the <a href="../tutorial.html" title="tutorial">tutorial</a>, details about the supported <a href="../cli.html" title="cli">command line syntax</a> and <a href="../examples.html" title="examples">examples</a> of use.</p><p>Open the module to use it, it defines only three modules in your scope.</p></header><div class="odoc-content"><div class="odoc-spec"><div class="spec module anchored" id="module-Manpage"><a href="#module-Manpage" class="anchor"></a><code><span><span class="keyword">module</span> <a href="Manpage/index.html">Manpage</a></span><span> : <span class="keyword">sig</span> ... <span class="keyword">end</span></span></code></div><div class="spec-doc"><p>Man page specification.</p></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-Term"><a href="#module-Term" class="anchor"></a><code><span><span class="keyword">module</span> <a href="Term/index.html">Term</a></span><span> : <span class="keyword">sig</span> ... <span class="keyword">end</span></span></code></div><div class="spec-doc"><p>Terms.</p></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-Cmd"><a href="#module-Cmd" class="anchor"></a><code><span><span class="keyword">module</span> <a href="Cmd/index.html">Cmd</a></span><span> : <span class="keyword">sig</span> ... <span class="keyword">end</span></span></code></div><div class="spec-doc"><p>Commands.</p></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-Arg"><a href="#module-Arg" class="anchor"></a><code><span><span class="keyword">module</span> <a href="Arg/index.html">Arg</a></span><span> : <span class="keyword">sig</span> ... <span class="keyword">end</span></span></code></div><div class="spec-doc"><p>Terms for command line arguments.</p></div></div></div></body></html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Cmdliner (cmdliner.Cmdliner)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../index.html">Index</a> » <a href="../index.html">cmdliner</a> » Cmdliner</nav><header class="odoc-preamble"><h1>Module <code><span>Cmdliner</span></code></h1><p>Declarative definition of command line interfaces.</p><p>Consult the <a href="../tutorial.html" title="tutorial">tutorial</a>, the <a href="../cookbook.html" title="cookbook">cookbook</a>, program <a href="../cookbook.html#blueprints" title="blueprints">blueprints</a> and <a href="../cookbook.html#tip_src_structure" title="tip_src_structure">source structure</a>, details about the supported <a href="../cli.html" title="cli">command line syntax</a> and <a href="../examples.html" title="examples">examples</a> of use.</p><p>Open the module to use it, it defines only these modules in your scope.</p></header><div class="odoc-content"><div class="odoc-spec"><div class="spec module anchored" id="module-Manpage"><a href="#module-Manpage" class="anchor"></a><code><span><span class="keyword">module</span> <a href="Manpage/index.html">Manpage</a></span><span> : <span class="keyword">sig</span> ... <span class="keyword">end</span></span></code></div><div class="spec-doc"><p>Man pages.</p></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-Term"><a href="#module-Term" class="anchor"></a><code><span><span class="keyword">module</span> <a href="Term/index.html">Term</a></span><span> : <span class="keyword">sig</span> ... <span class="keyword">end</span></span></code></div><div class="spec-doc"><p>Terms.</p></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-Cmd"><a href="#module-Cmd" class="anchor"></a><code><span><span class="keyword">module</span> <a href="Cmd/index.html">Cmd</a></span><span> : <span class="keyword">sig</span> ... <span class="keyword">end</span></span></code></div><div class="spec-doc"><p>Commands.</p></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-Arg"><a href="#module-Arg" class="anchor"></a><code><span><span class="keyword">module</span> <a href="Arg/index.html">Arg</a></span><span> : <span class="keyword">sig</span> ... <span class="keyword">end</span></span></code></div><div class="spec-doc"><p>Terms for command line arguments.</p></div></div></div></body></html>
|
||||
|
|
|
|||
2
cmdliner/Cmdliner_arg/index.html
Normal file
2
cmdliner/Cmdliner_arg/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Cmdliner_arg (cmdliner.Cmdliner_arg)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../index.html">Index</a> » <a href="../index.html">cmdliner</a> » Cmdliner_arg</nav><header class="odoc-preamble"><h1>Module <code><span>Cmdliner_arg</span></code></h1></header><div class="odoc-content"><p>This module is hidden.</p></div></body></html>
|
||||
2
cmdliner/Cmdliner_base/index.html
Normal file
2
cmdliner/Cmdliner_base/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Cmdliner_base (cmdliner.Cmdliner_base)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../index.html">Index</a> » <a href="../index.html">cmdliner</a> » Cmdliner_base</nav><header class="odoc-preamble"><h1>Module <code><span>Cmdliner_base</span></code></h1></header><div class="odoc-content"><p>This module is hidden.</p></div></body></html>
|
||||
2
cmdliner/Cmdliner_cline/index.html
Normal file
2
cmdliner/Cmdliner_cline/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Cmdliner_cline (cmdliner.Cmdliner_cline)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../index.html">Index</a> » <a href="../index.html">cmdliner</a> » Cmdliner_cline</nav><header class="odoc-preamble"><h1>Module <code><span>Cmdliner_cline</span></code></h1></header><div class="odoc-content"><p>This module is hidden.</p></div></body></html>
|
||||
2
cmdliner/Cmdliner_cmd/index.html
Normal file
2
cmdliner/Cmdliner_cmd/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Cmdliner_cmd (cmdliner.Cmdliner_cmd)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../index.html">Index</a> » <a href="../index.html">cmdliner</a> » Cmdliner_cmd</nav><header class="odoc-preamble"><h1>Module <code><span>Cmdliner_cmd</span></code></h1></header><div class="odoc-content"><p>This module is hidden.</p></div></body></html>
|
||||
2
cmdliner/Cmdliner_completion/index.html
Normal file
2
cmdliner/Cmdliner_completion/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Cmdliner_completion (cmdliner.Cmdliner_completion)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../index.html">Index</a> » <a href="../index.html">cmdliner</a> » Cmdliner_completion</nav><header class="odoc-preamble"><h1>Module <code><span>Cmdliner_completion</span></code></h1></header><div class="odoc-content"><p>This module is hidden.</p></div></body></html>
|
||||
2
cmdliner/Cmdliner_def/index.html
Normal file
2
cmdliner/Cmdliner_def/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Cmdliner_def (cmdliner.Cmdliner_def)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../index.html">Index</a> » <a href="../index.html">cmdliner</a> » Cmdliner_def</nav><header class="odoc-preamble"><h1>Module <code><span>Cmdliner_def</span></code></h1></header><div class="odoc-content"><p>This module is hidden.</p></div></body></html>
|
||||
2
cmdliner/Cmdliner_docgen/index.html
Normal file
2
cmdliner/Cmdliner_docgen/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Cmdliner_docgen (cmdliner.Cmdliner_docgen)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../index.html">Index</a> » <a href="../index.html">cmdliner</a> » Cmdliner_docgen</nav><header class="odoc-preamble"><h1>Module <code><span>Cmdliner_docgen</span></code></h1></header><div class="odoc-content"><p>This module is hidden.</p></div></body></html>
|
||||
2
cmdliner/Cmdliner_eval/index.html
Normal file
2
cmdliner/Cmdliner_eval/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Cmdliner_eval (cmdliner.Cmdliner_eval)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../index.html">Index</a> » <a href="../index.html">cmdliner</a> » Cmdliner_eval</nav><header class="odoc-preamble"><h1>Module <code><span>Cmdliner_eval</span></code></h1></header><div class="odoc-content"><p>This module is hidden.</p></div></body></html>
|
||||
2
cmdliner/Cmdliner_manpage/index.html
Normal file
2
cmdliner/Cmdliner_manpage/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Cmdliner_manpage (cmdliner.Cmdliner_manpage)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../index.html">Index</a> » <a href="../index.html">cmdliner</a> » Cmdliner_manpage</nav><header class="odoc-preamble"><h1>Module <code><span>Cmdliner_manpage</span></code></h1></header><div class="odoc-content"><p>This module is hidden.</p></div></body></html>
|
||||
2
cmdliner/Cmdliner_msg/index.html
Normal file
2
cmdliner/Cmdliner_msg/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Cmdliner_msg (cmdliner.Cmdliner_msg)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../index.html">Index</a> » <a href="../index.html">cmdliner</a> » Cmdliner_msg</nav><header class="odoc-preamble"><h1>Module <code><span>Cmdliner_msg</span></code></h1></header><div class="odoc-content"><p>This module is hidden.</p></div></body></html>
|
||||
2
cmdliner/Cmdliner_term/index.html
Normal file
2
cmdliner/Cmdliner_term/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Cmdliner_term (cmdliner.Cmdliner_term)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../index.html">Index</a> » <a href="../index.html">cmdliner</a> » Cmdliner_term</nav><header class="odoc-preamble"><h1>Module <code><span>Cmdliner_term</span></code></h1></header><div class="odoc-content"><p>This module is hidden.</p></div></body></html>
|
||||
2
cmdliner/Cmdliner_trie/index.html
Normal file
2
cmdliner/Cmdliner_trie/index.html
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Cmdliner_trie (cmdliner.Cmdliner_trie)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../../index.html">Index</a> » <a href="../index.html">cmdliner</a> » Cmdliner_trie</nav><header class="odoc-preamble"><h1>Module <code><span>Cmdliner_trie</span></code></h1></header><div class="odoc-content"><p>This module is hidden.</p></div></body></html>
|
||||
142
cmdliner/_doc-dir/CHANGES.md
Executable file → Normal file
142
cmdliner/_doc-dir/CHANGES.md
Executable file → Normal file
|
|
@ -1,3 +1,133 @@
|
|||
v2.0.0 2025-09-26 Zagreb
|
||||
------------------------
|
||||
|
||||
### End-user visible changes
|
||||
|
||||
- **IMPORTANT** Cmdliner no longer allows command names, option names,
|
||||
and `Arg.enum` values to be specified by a prefix if the prefix is
|
||||
unambiguous. See #200 for the rationale. To quickly salvage scripts
|
||||
that may be relying on the old behaviour, it can be restored by
|
||||
setting the environment variable `CMDLINER_LEGACY_PREFIXES=true`.
|
||||
However the scripts should be fixed: this escape hatch will be
|
||||
removed in the future.
|
||||
|
||||
- Pager. If set, respect the user's `LESS` environment variable
|
||||
(otherwise the default `LESS=FRX` is left unchanged). Note however
|
||||
that you likely need at least `R` specified if you define it
|
||||
yourself, otherwise the manpage may look garbled (#191). Thanks to
|
||||
Yukai Chou for suggesting.
|
||||
|
||||
- Fix lack of output whenever `PAGER` or `MANPAGER` is set but empty;
|
||||
fallback to pager discovery (#194). For example this prevented to
|
||||
see manpages in `emacs`'s compilation mode which unhelpfully
|
||||
hardcodes `PAGER=""`.
|
||||
|
||||
- Fix synopsis rendering of required optional arguments (#203).
|
||||
|
||||
- Output error messages on `stderr` with styled text (#144). Quoted
|
||||
and typewriter text is in bold. Variables are written as
|
||||
underlines. Key words of error messages are in red.
|
||||
|
||||
- Output error messages after the usage line and remove the `Try with
|
||||
$(tool) --help for more information` message. Instead we explicitly
|
||||
indicate the `--help` option in the usage line. Having the error message
|
||||
at the end makes it easier to spot.
|
||||
|
||||
- Make `--help` request work in any context, except after `--` or on
|
||||
the arguments after an unknown command error in which case that
|
||||
error is reported (less confusing). Since the option has an optional
|
||||
argument value, one had to be carefull that it would not pickup the
|
||||
next argument and try to parse it according to `FMT`. This is no
|
||||
longer the case. If the argument fails to parse `--help=auto` is
|
||||
assumed. (#201).
|
||||
|
||||
- Deprecation messages are now prepended to the doc strings in the manpage.
|
||||
|
||||
### API changes
|
||||
|
||||
- Reserve the `--__complete` option for library use.
|
||||
|
||||
- Documentation language, `$(cmd)`, `$(cmd.name)` and `$(tool)` can be
|
||||
used and should be prefered over of `$(iname)`, `$(tname)` and
|
||||
`$(mname)`. `$(cmd.parent)` is added to refer to a command's parent
|
||||
or itself at the root.
|
||||
|
||||
- Make `Cmdliner.Arg.conv` abstract. Thanks to Andrey Popp for
|
||||
the patch (#206).
|
||||
|
||||
- Thanks to the previous point, use the `docv` parameter of argument
|
||||
converters can now be used to define the default value used by `docv` in
|
||||
`Arg.info`. See `Arg.Conv.docv`.
|
||||
|
||||
- Add `Manpage.section_name` type alias (#202).
|
||||
|
||||
- Add `Cmd.make` which should be preferred to `Cmd.v` (The `M.v` notation is
|
||||
nice for simulating literals, not for heavy constructor).
|
||||
|
||||
- Add `Cmd.Env.info_var`. To get back the environment variable name
|
||||
from a variable info.
|
||||
|
||||
- Add optional `doc_envs` argument to `Arg.info` for adding the given
|
||||
environment variables info to the command in which the argument is used.
|
||||
Sometimes more than one variable make sense and the `env` argument is
|
||||
not directly used.
|
||||
|
||||
- Add `Arg.Completion` a module to define argument completion
|
||||
strategies (#1, #187).
|
||||
|
||||
- Add `Arg.Conv` module to define converters. This should be used in
|
||||
new code.
|
||||
|
||||
- Add `Arg.{file,dir,}path` string converters equiped with appropriate
|
||||
file system completions.
|
||||
|
||||
- Add `docv` optional parameter to `Arg.enum`.
|
||||
|
||||
- Add `Term.env` which provides access to the environment access
|
||||
function provided to evaluation functions.
|
||||
|
||||
- Clarify the semantics of the `deprecated` argument of
|
||||
`Cmdliner.Cmd.info`, `Cmdliner.Arg.info` and
|
||||
`Cmdliner.Cmd.Env.info`. First, the language markup is now supported
|
||||
therein. Second the message is no longer only used to warn about
|
||||
usage it is now also prepended to the doc string of the entity.
|
||||
|
||||
- Use `Arg.conv`'s `docv` property in the documentation of arguments
|
||||
whenever `Arg.info`'s `docv` is unspecified (#207).
|
||||
|
||||
- Do not check file existence for `-` in `Arg.file` or
|
||||
`Arg.non_dir_file` values. This is supposed to mean `stdin` or
|
||||
`stdout` (#208).
|
||||
|
||||
- Fix manpage rendering performing direct calls to `Sys.getenv` in
|
||||
`Cmd.eval*` functions instead of calling the `env` argument as
|
||||
advertised in the docs. Incidentally add an `env` optional argument
|
||||
to `Manpage.print` (#209).
|
||||
|
||||
- Deprecate. `Arg.{printer,conv_docv,conv_parser,
|
||||
conv_printer,parser_of_kind_of_string,conv,conv'}`. These will
|
||||
likely never be removed but they should no longer be used for
|
||||
new code. Use `Arg.Conv`.
|
||||
|
||||
- Remove deprecated `Arg.{converter,parser,pconv}` (#206).
|
||||
- Remove deprecated `Arg.{env,env_var}` (#206).
|
||||
- Remove deprecated `Term.{pure,man_format}` (#206).
|
||||
- Remove deprecated `Term` evaluation interface (#206).
|
||||
|
||||
### Other
|
||||
|
||||
- Install a `cmdliner` tool to help with manpage and completion script
|
||||
installation. See the command line interface manual of the library
|
||||
for more information (#187, #227, #228).
|
||||
|
||||
- Install all source files for `odoc` and goto definition editor
|
||||
functionality. Thanks to Emile Trotignon and Paul-Elliot Anglès
|
||||
d'Auriac for noticing and suggesting (#225).
|
||||
|
||||
- Added a proper test suite to the library to check for regressions.
|
||||
Replaces most of the test executables that had to be run and inspected
|
||||
manually (#205).
|
||||
|
||||
v1.3.0 2024-05-23 La Forclaz (VS)
|
||||
---------------------------------
|
||||
|
||||
|
|
@ -100,8 +230,8 @@ This version of cmdliner deprecates the `Term.eval*` evaluation
|
|||
functions and `Term.info` information values in favor of the new
|
||||
`Cmdliner.Cmd` module.
|
||||
|
||||
The `Cmd` module generalizes the existing sub command support to allow
|
||||
arbitrarily nested sub commands each with its own man page and command
|
||||
The `Cmd` module generalizes the existing subcommand support to allow
|
||||
arbitrarily nested subcommands each with its own man page and command
|
||||
line syntax represented by a `Term.t` value.
|
||||
|
||||
The mapping between the old interface and the new one should be rather
|
||||
|
|
@ -116,7 +246,7 @@ However in this transition the following things are changed or added:
|
|||
* The `?exits` argument which defaults to `Cmd.Exit.defaults`
|
||||
rather than the empty list.
|
||||
* The `?man_xrefs` which defaults to the list ``[`Main]`` rather
|
||||
than the empty list (this means that by default sub commands
|
||||
than the empty list (this means that by default subcommands
|
||||
at any level automatically cross-reference the main command).
|
||||
* The `?sdocs` argument which defaults to `Manpage.s_common_options`
|
||||
rather than `Manpage.s_options`.
|
||||
|
|
@ -136,9 +266,9 @@ However in this transition the following things are changed or added:
|
|||
or `Term.term_result`.
|
||||
|
||||
Finally be aware that if you replace, in an existing tool, an encoding
|
||||
of sub commands as positional arguments you will effectively break the
|
||||
of subcommands as positional arguments you will effectively break the
|
||||
command line compatibility of your tool since options can no longer be
|
||||
specified before the sub commands, i.e. your tool synopsis moves from:
|
||||
specified before the subcommands, i.e. your tool synopsis moves from:
|
||||
|
||||
```
|
||||
tool cmd [OPTION]… SUBCMD [ARG]…
|
||||
|
|
@ -367,7 +497,7 @@ v0.9.6 2014-11-18 La Forclaz (VS)
|
|||
the sense that only more command lines are parsed. Thanks to Hugo
|
||||
Heuzard for the patch.
|
||||
- End user error message improvements using heuristics and edit
|
||||
distance search in the optional argument and sub command name
|
||||
distance search in the optional argument and subcommand name
|
||||
spaces. Thanks to Hugo Heuzard for the patch.
|
||||
- Adds `Arg.doc_{quote,alts,alts_enum}`, documentation string
|
||||
helpers.
|
||||
|
|
|
|||
0
cmdliner/_doc-dir/LICENSE.md
Executable file → Normal file
0
cmdliner/_doc-dir/LICENSE.md
Executable file → Normal file
36
cmdliner/_doc-dir/README.md
Executable file → Normal file
36
cmdliner/_doc-dir/README.md
Executable file → Normal file
|
|
@ -1,22 +1,22 @@
|
|||
Cmdliner — Declarative definition of command line interfaces for OCaml
|
||||
-------------------------------------------------------------------------------
|
||||
v1.3.0
|
||||
======================================================================
|
||||
|
||||
Cmdliner allows the declarative definition of command line interfaces
|
||||
for OCaml.
|
||||
|
||||
It provides a simple and compositional mechanism to convert command
|
||||
line arguments to OCaml values and pass them to your functions. The
|
||||
module automatically handles syntax errors, help messages and UNIX man
|
||||
page generation. It supports programs with single or multiple commands
|
||||
and respects most of the [POSIX][1] and [GNU][2] conventions.
|
||||
module automatically handles command line completion, syntax errors,
|
||||
help messages and UNIX man page generation. It supports programs with
|
||||
single or multiple commands and respects most of the [POSIX] and [GNU]
|
||||
conventions.
|
||||
|
||||
Cmdliner has no dependencies and is distributed under the ISC license.
|
||||
|
||||
[1]: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html
|
||||
[2]: http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
|
||||
Homepage: <http://erratique.ch/software/cmdliner>
|
||||
|
||||
Home page: http://erratique.ch/software/cmdliner
|
||||
[POSIX]: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html
|
||||
[GNU]: http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
@ -27,23 +27,17 @@ Cmdliner can be installed with `opam`:
|
|||
If you don't use `opam` consult the [`opam`](opam) file for build
|
||||
instructions.
|
||||
|
||||
|
||||
## Documentation
|
||||
|
||||
The documentation and API reference is automatically generated by from
|
||||
the source interfaces. It can be consulted [online][doc] or via
|
||||
`odig doc cmdliner`.
|
||||
The documentation can be consulted [online] or via `odig doc cmdliner`.
|
||||
|
||||
[doc]: http://erratique.ch/software/cmdliner/doc/Cmdliner
|
||||
Questions are welcome but better asked on the [OCaml forum] than on the
|
||||
issue tracker.
|
||||
|
||||
[online]: http://erratique.ch/software/cmdliner/doc/
|
||||
[OCaml forum]: https://discuss.ocaml.org/
|
||||
|
||||
## Sample programs
|
||||
|
||||
If you installed Cmdliner with `opam` sample programs are located in
|
||||
the directory `opam config var cmdliner:doc`. These programs define
|
||||
the command line of some classic programs.
|
||||
|
||||
In the distribution sample programs are located in the `test`
|
||||
directory of the distribution. They can be built and run with:
|
||||
|
||||
topkg build --tests true && topkg test
|
||||
A few examples and blueprints can be found in the
|
||||
[documentation][online] and in the [test](test/) directory.
|
||||
|
|
|
|||
421
cmdliner/_doc-dir/odoc-pages/cli.mld
Executable file → Normal file
421
cmdliner/_doc-dir/odoc-pages/cli.mld
Executable file → Normal file
|
|
@ -1,14 +1,19 @@
|
|||
{0:cmdline Command line interface}
|
||||
|
||||
For tools evaluating a command without sub commands the most general
|
||||
This manual describes how your tool ends up interacting
|
||||
with shells when you use Cmdliner.
|
||||
|
||||
{1:invocation Tool invocation}
|
||||
|
||||
For tools evaluating a command without subcommands the most general
|
||||
form of invocation is:
|
||||
|
||||
{[
|
||||
{v
|
||||
tool [OPTION]… [ARG]…
|
||||
]}
|
||||
v}
|
||||
|
||||
The tool automatically reponds to the [--help] option by printing the
|
||||
help. If a version string is provided in the
|
||||
The tool automatically reponds to the [--help] option by printing
|
||||
{{!help}the help}. If a version string is provided in the
|
||||
{{!Cmdliner.Cmd.val-info}command information}, it also automatically
|
||||
responds to the [--version] option by printing this string on standard
|
||||
output.
|
||||
|
|
@ -17,22 +22,23 @@ Command line arguments are either {{!optargs}{e optional}} or
|
|||
{{!posargs}{e positional}}. Both can be freely interleaved but since
|
||||
[Cmdliner] accepts many optional forms this may result in
|
||||
ambiguities. The special {{!posargs} token [--]} can be used to
|
||||
resolve them; anything that follows it is treated as a positional
|
||||
resolve them: anything that follows it is treated as a positional
|
||||
argument.
|
||||
|
||||
Tools evaluating commands with sub commands have this form of invocation
|
||||
Tools evaluating commands with subcommands have this form of invocation
|
||||
|
||||
{[
|
||||
{v
|
||||
tool [COMMAND]… [OPTION]… [ARG]…
|
||||
]}
|
||||
v}
|
||||
|
||||
Commands automatically respond to the [--help] option by printing
|
||||
their help. The sequence of [COMMAND] strings must be the first
|
||||
{{!help}their help}. The sequence of [COMMAND] strings must be the first
|
||||
strings following the tool name – as soon as an optional argument is
|
||||
seen the search for a sub command stops. Command names may be specified by
|
||||
a prefixe as long as they are not ambiguous.
|
||||
seen the search for a subcommand stops.
|
||||
|
||||
{1:optargs Optional arguments}
|
||||
{1:args Arguments}
|
||||
|
||||
{2:optargs Optional arguments}
|
||||
|
||||
An optional argument is specified on the command line by a {e name}
|
||||
possibly followed by a {e value}.
|
||||
|
|
@ -48,7 +54,7 @@ The name of an option can be short or long.
|
|||
More than one name may refer to the same optional argument. For
|
||||
example in a given program the names [-q], [--quiet] and [--silent]
|
||||
may all stand for the same boolean argument indicating the program to
|
||||
be quiet. Long names can be specified by any non ambiguous prefix.
|
||||
be quiet.
|
||||
|
||||
The value of an option can be specified in three different ways.
|
||||
|
||||
|
|
@ -74,7 +80,7 @@ group can end with a short option. For example assuming [-v] and
|
|||
{- [-vxf opt] will be parsed as [-v -x -fopt].}
|
||||
{- [-fvx] will be parsed as [-f=vx].}}
|
||||
|
||||
{1:posargs Positional arguments}
|
||||
{2:posargs Positional arguments}
|
||||
|
||||
Positional arguments are tokens on the command line that are not
|
||||
option names and are not the value of an optional argument. They are
|
||||
|
|
@ -85,14 +91,28 @@ optional argument or they may need to look like option names, anything
|
|||
that follows the special token ["--"] on the command line is
|
||||
considered to be a positional argument:
|
||||
|
||||
{[
|
||||
tool --option -- we -are --all positional --argu=ments
|
||||
]}
|
||||
{v
|
||||
tool --option -- but --now we -are --all positional --argu=ments
|
||||
v}
|
||||
|
||||
{2:constraints Constraints on option names}
|
||||
|
||||
Using the cmdliner library puts the following constraints on your
|
||||
command line interface:
|
||||
|
||||
{ul
|
||||
{- The option names [--cmdliner] and [--__complete] are reserved by the
|
||||
library.}
|
||||
{- The option name [--help], (and [--version] if you specify a version
|
||||
string) is reserved by the library. Using it as a term or option
|
||||
name may result in undefined behaviour.}
|
||||
{- Defining the same option or command name via two different
|
||||
arguments or terms is illegal and raises [Invalid_argument].}}
|
||||
|
||||
{1:envlookup Environment variables}
|
||||
|
||||
Non-required command line arguments can be backed up by an environment
|
||||
variable. If the argument is absent from the command line and that
|
||||
variable. If the argument is absent from the command line and
|
||||
the environment variable is defined, its value is parsed using the
|
||||
argument converter and defines the value of the argument.
|
||||
|
||||
|
|
@ -105,17 +125,360 @@ as follows:
|
|||
{- ["true"], ["yes"], ["y"] or ["1"] is [true].}
|
||||
{- Any other string is an error.}}
|
||||
|
||||
Note that environment variables are not supported for {!Cmdliner.Arg.vflag} and
|
||||
{!Cmdliner.Arg.vflag_all}.
|
||||
Note that environment variables are not supported for
|
||||
{!Cmdliner.Arg.vflag} and {!Cmdliner.Arg.vflag_all}.
|
||||
|
||||
{1:reserved Reserved option names}
|
||||
{1:help Help and man pages}
|
||||
|
||||
Using the cmdliner library puts the following constraints o
|
||||
Help and man pages are are generated when you call your tool or a subcommand
|
||||
with [--help]. By default, if the [TERM] environment variable
|
||||
is not [dumb] or unset, the tool tries to {{!paging}page} the manual
|
||||
so that you can directly search it. Otherwise it outputs the manual
|
||||
as plain text.
|
||||
|
||||
Alternative help formats can be specified with the optional argument
|
||||
of [--help], see your own [tool --help] for more information.
|
||||
|
||||
{@sh[
|
||||
tool --help
|
||||
tool cmd --help
|
||||
tool --help=groff > tool.1
|
||||
]}
|
||||
|
||||
{2:paging Paging}
|
||||
|
||||
The pager is selected by looking up, in order:
|
||||
|
||||
{ol
|
||||
{- The [MANPAGER] variable.}
|
||||
{- The [PAGER] variable.}
|
||||
{- The tool [less].}
|
||||
{- The tool [more].}}
|
||||
|
||||
Regardless of the pager, it is invoked with [LESS=FRX] set in the
|
||||
environment unless, the [LESS] environment variable is set in your
|
||||
environment.
|
||||
|
||||
{2:install_tool_manpages Install}
|
||||
|
||||
The manpages of a tool and its subcommands can be installed to a root
|
||||
[man] directory [$MANDIR] by invoking:
|
||||
|
||||
{@shell[
|
||||
cmdliner install tool-manpages thetool $MANDIR
|
||||
]}
|
||||
|
||||
This looks up [thetool] in the [PATH]. Use an explicit file path like
|
||||
[./thetool] to directly specify an executable.
|
||||
|
||||
If you are also {{!install_tool_completion}installing completions}
|
||||
rather use the [install tool-support] command, see this
|
||||
{{!page-cookbook.tip_tool_support}cookbook tip} which also has
|
||||
instructions on how to install if you are using [opam].
|
||||
|
||||
{1:cli_completion Command line completion}
|
||||
|
||||
Cmdliner programs automatically get support for shell command line
|
||||
completion.
|
||||
|
||||
The completion process happens via a {{!completion_protocol}protocol}
|
||||
which is interpreted by generic shell completion scripts that are
|
||||
installed by the library. For now the [zsh] and [bash] shells are
|
||||
supported.
|
||||
|
||||
Tool developers can easily {{!install_tool_completion}install}
|
||||
completion definitions that invoke these completion scripts. Tool
|
||||
end-users need to {{!user_configuration}make sure} these definitions are
|
||||
looked up by their shell.
|
||||
|
||||
{2:user_configuration End-user configuration}
|
||||
|
||||
If you are the user of a cmdliner based tool, the following
|
||||
shell-dependent steps need to be performed in order to benefit from
|
||||
command line completion.
|
||||
|
||||
{3:user_zsh For [zsh]}
|
||||
|
||||
The [FPATH] environment variable must be setup to include the
|
||||
directory where the generic cmdliner completion function is
|
||||
{{!install_completion} installed} {b before} properly initializing the
|
||||
completion system.
|
||||
|
||||
For example, {{:https://github.com/ocaml/opam/issues/6427}for now}, if
|
||||
you are using [opam]. You should add something like this to your
|
||||
[.zshrc]:
|
||||
|
||||
{@sh[
|
||||
FPATH="$(opam var share)/zsh/site-functions:${FPATH}"
|
||||
autoload -Uz compinit
|
||||
compinit -u
|
||||
]}
|
||||
|
||||
Also make sure this {b happens before} [opam]'s [zsh] init script
|
||||
inclusion, see {{:https://github.com/ocaml/opam/issues/6428}this
|
||||
issue}. Note that these instruction do not react dynamically
|
||||
to [opam] switches changes so you may see odd completion behaviours
|
||||
when you do so, see this {{:https://github.com/ocaml/opam/issues/6427}this
|
||||
opam issue}.
|
||||
|
||||
After this, to test everything is right, check that the [_cmdliner_generic]
|
||||
function can be looked by invoking it (this will result in an error).
|
||||
|
||||
{@sh[
|
||||
> autoload _cmdliner_generic
|
||||
> _cmdliner_generic
|
||||
_cmdliner_generic:1: words: assignment to invalid subscript range
|
||||
]}
|
||||
|
||||
If the function cannnot be found make sure the [cmdliner] library is
|
||||
installed, that the generic scripts were
|
||||
{{!install_generic_completion}installed} and that the
|
||||
[_cmdliner_generic] file can be found in one of the directories
|
||||
mentioned in the [FPATH] variable.
|
||||
|
||||
With this setup, if you are using a cmdliner based tool named
|
||||
[thetool] that did not {{!install_tool_completion}install} a completion
|
||||
definition. You can always do it yourself by invoking:
|
||||
|
||||
{@sh[
|
||||
autoload _cmdliner_generic
|
||||
compdef _cmdliner_generic thetool
|
||||
]}
|
||||
|
||||
{3:user_bash For [bash]}
|
||||
|
||||
These instructions assume that you have
|
||||
{{:https://repology.org/project/bash-completion/versions}[bash-completion]}
|
||||
installed and setup in some way in your [.bashrc].
|
||||
|
||||
The [XDG_DATA_DIRS] environment variable must be setup to include the
|
||||
[share] directory where the generic cmdliner completion function is
|
||||
{{!install_completion}installed}.
|
||||
|
||||
For example, {{:https://github.com/ocaml/opam/issues/6427}for now}, if
|
||||
you are using [opam]. You should add something like this to your
|
||||
[.bashrc]:
|
||||
{@sh[
|
||||
XDG_DATA_DIRS="$(opam var share):${XDG_DATA_DIRS}"
|
||||
]}
|
||||
|
||||
Note that these instruction do not react dynamically to [opam]
|
||||
switches changes so you may see odd completion behaviours when you do
|
||||
so, see this {{:https://github.com/ocaml/opam/issues/6427}this opam
|
||||
issue}.
|
||||
|
||||
After this, to test everything is right, check that the [_cmdliner_generic]
|
||||
function can be looked up:
|
||||
|
||||
{@sh[
|
||||
> _completion_loader _cmdliner_generic
|
||||
> declare -F _cmdliner_generic &>/dev/null && echo "Found" || echo "Not found"
|
||||
Found!
|
||||
]}
|
||||
|
||||
If the function cannot be found make sure the [cmdliner] library is
|
||||
installed, that the generic scripts were
|
||||
{{!install_generic_completion}installed} and that the
|
||||
[_cmdliner_generic] file can be looked up by [_completion_loader].
|
||||
|
||||
With this setup, if you are using a cmdliner based tool named
|
||||
[thetool] that did not {{!install_tool_completion}install} a completion
|
||||
definition. You can always do it yourself by invoking:
|
||||
|
||||
{@sh[
|
||||
_completion_loader _cmdliner_generic
|
||||
complete -F _cmdliner_generic thetool
|
||||
]}
|
||||
|
||||
{b Note.} {{:https://github.com/scop/bash-completion/commit/9efc596735c4509001178f0cf28e02f66d1f7703}It seems} [_completion_loader] was deprecated in
|
||||
bash-completion [2.12] in favour of [_comp_load] but many distributions
|
||||
are on [< 2.12] and in [2.12] [_completion_loader] simply calls
|
||||
[_comp_load].
|
||||
|
||||
{2:install_completion Install}
|
||||
|
||||
Completion scripts need to be installed in subdirectories of a
|
||||
{{:https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch04s11.html}[share]}
|
||||
directory which we denote by the [$SHAREDIR] variable below. In a
|
||||
package installation script this variable is typically defined by:
|
||||
|
||||
{@sh[
|
||||
SHAREDIR="$DESTDIR/$PREFIX/share"
|
||||
]}
|
||||
|
||||
The final destination directory in [share] depends on the shell:
|
||||
|
||||
{ul
|
||||
{- The option name [--cmdliner] is reserved by the library.}
|
||||
{- The option name [--help], (and [--version] if you specify a version
|
||||
string) is reserved by the library. Using it as a term or option
|
||||
name may result in undefined behaviour.}
|
||||
{- Defining the same option or command name via two different
|
||||
arguments or terms is illegal and raises [Invalid_argument].}}
|
||||
{- For [zsh] it is [$SHAREDIR/zsh/site-functions]}
|
||||
{- For [bash] it is [$SHAREDIR/bash-completion/completions]}}
|
||||
|
||||
If that is unsatisfying you can output the completion scripts directly
|
||||
where you want with the [cmdliner generic-completion] and
|
||||
[cmdliner tool-completion] commands.
|
||||
|
||||
{3:install_generic_completion Generic completion scripts}
|
||||
|
||||
The generic completion scripts must be installed by the
|
||||
[cmdliner] library. They should not be part of your tool install. If
|
||||
they are not installed you can inspect and install them with the
|
||||
following invocations, invoke with [--help] for more information.
|
||||
|
||||
{@sh[
|
||||
cmdliner generic-completion zsh # Output generic zsh script on stdout
|
||||
cmdliner install generic-completion $SHAREDIR # All shells
|
||||
cmdliner install generic-completion --shell zsh $SHAREDIR # Only zsh
|
||||
]}
|
||||
|
||||
Directories are created as needed. Use option [--dry-run] to see which
|
||||
paths would be written by an [install] invocation.
|
||||
|
||||
{3:install_tool_completion Tool completion scripts}
|
||||
|
||||
If your tool named [thetool] uses Cmdliner you should install completion
|
||||
definitions for them. They rely on the {{!install_generic_completion}generic
|
||||
scripts} to be installed. These tool specific scripts can be inspected
|
||||
and installed via these invocations:
|
||||
|
||||
{@sh[
|
||||
cmdliner tool-completion zsh thetool # Output tool zsh script on stdout.
|
||||
cmdliner install tool-completion thetool $SHAREDIR # All shells
|
||||
cmdliner install tool-completion --shell zsh thetool $SHAREDIR # Only zsh
|
||||
]}
|
||||
|
||||
Directories are created as needed. Use option [--dry-run] to see which
|
||||
paths would be written by an [install] invocation.
|
||||
|
||||
If you are also {{!install_tool_manpages}installing manpages} rather
|
||||
use the [install tool-support] command, see this
|
||||
{{!page-cookbook.tip_tool_support}cookbook tip} which also has
|
||||
instructions on how to install if you are using [opam].
|
||||
|
||||
{2:completion_protocol Completion protocol}
|
||||
|
||||
There is no standard that allows tools and shells to interact to
|
||||
perform shell command line completion. Completion is supposed to
|
||||
happen through idiosyncratic, ad-hoc, obscure and brain damaging
|
||||
shell-specific completion scripts.
|
||||
|
||||
To alleviate this, Cmdliner defines one generic script per shell and
|
||||
interacts with it using the protocol described below. The protocol can
|
||||
be used to implement generic completion scripts for other shells. The
|
||||
protocol is versioned but can change even between minor versions of
|
||||
Cmdliner. Generic scripts for popular shells can be inspected via
|
||||
the [cmdliner generic-completion] command.
|
||||
|
||||
The protocol betwen the shell completion {e script} and a
|
||||
cmdliner based {e tool} is as follows:
|
||||
|
||||
{ol
|
||||
{- When completion is requested the script invokes the tool with a
|
||||
modified command line:
|
||||
{ul
|
||||
{- The first argument to the tool ([Sys.argv.(1)]) must be the
|
||||
option [--__complete].}
|
||||
{- The (possibly empty) argument [ARG] on which the completion is
|
||||
requested must be replaced by {e exactly} [--__complete=ARG]. Note
|
||||
that this can happen after the [--] token, this is the reason
|
||||
why we have an explicit [--__complete] argument in [Sys.argv.(1)]:
|
||||
it indicates the command line parser must operate in a special mode.}}}
|
||||
{- The tool responds by writing on standard output a list of
|
||||
completion directives which match the [completions] rule of the grammar
|
||||
given below.}
|
||||
{- The script interprets the completion directives according
|
||||
to the given semantics below so that the shell can display the
|
||||
completions. The script is free to ignore directives
|
||||
or data that it is unable to present.}}
|
||||
|
||||
The following ABNF grammar is described using the notations of
|
||||
{{:https://www.rfc-editor.org/rfc/rfc5234}RFC 5234} and
|
||||
{{:https://www.rfc-editor.org/rfc/rfc7405}RFC 7405}. A few constraints
|
||||
are not expressed by the grammar:
|
||||
|
||||
{ul
|
||||
{- Except in the [completion] rule, the byte stream may contain ANSI escape
|
||||
sequences introduced by the byte [0x1B].}
|
||||
{- After stripping the ANSI escape sequences, the resulting byte stream must
|
||||
be valid UTF-8 text.}}
|
||||
|
||||
{@abnf[
|
||||
completions = version nl directives
|
||||
version = "1"
|
||||
directives = *(directive nl)
|
||||
directive = message / group / %s"files" / %s"dirs" / %"restart"
|
||||
message = %s"message" nl text nl %s"message-end"
|
||||
group = %s"group" nl group_name nl *item
|
||||
group_name = *pchar
|
||||
item = %s"item" nl completion nl item_doc nl %s"item-end"
|
||||
completion = *pchar
|
||||
item_doc = text
|
||||
text = *(pchar / nl)
|
||||
nl = %0A
|
||||
pchar = %20-%7E / %8A-%FF
|
||||
]}
|
||||
|
||||
The semantics of directives is as follows:
|
||||
|
||||
{ul
|
||||
{- A [message] directive defines a message to be reported to the user.
|
||||
It is multi-line ANSI styled text which cannot have a line that is
|
||||
exactly made of the text [message-end] as it is used to signal the
|
||||
end of the message. Messages should be reported in the order they
|
||||
are received.}
|
||||
{- A [group] directive defines an informational [group_name] followed
|
||||
by a possibly empty list of completion items that are part of the
|
||||
group. An item provides a [completion] value, this is a string that
|
||||
defines what the requested [ARG] value can be replaced with. It is
|
||||
followed by an [item_doc], multi-line ANSI styled text which cannot
|
||||
have a line that is exactly made of the text [item-end] as it is
|
||||
used to signal the end of the item.}
|
||||
{- A [file] directive indicates that the script should add existing
|
||||
files staring with [ARG] to completion values.}
|
||||
{- A [dir] directive indicates that the script should add existing
|
||||
directories starting with [ARG] to completion values.}
|
||||
{- A [restart] directive indicates that the script should restart
|
||||
shell completion as if the command line was starting after the leftmost
|
||||
[--] disambiguation token. The directive never gets emited if
|
||||
there is no [--] on the command line.}}
|
||||
|
||||
You can easily inspect the completions of any cmdliner based tool by
|
||||
invoking it like the protocol suggests. For example for the [cmdliner]
|
||||
tool itself:
|
||||
|
||||
{@shell[
|
||||
cmdliner --__complete --__complete=
|
||||
]}
|
||||
|
||||
{1:error_message_styling Error message ANSI styling}
|
||||
|
||||
Since Cmdliner 2.0 error messages printed on [stderr] use styled text
|
||||
with ANSI escapes unless one of the following conditions is met:
|
||||
|
||||
{ul
|
||||
{- The [NO_COLOR] environment variable is set and different
|
||||
from the empty string. Yes, even if you have [NO_COLOR=false], that's
|
||||
what the particularly dumb {:https://no-color.org} standard says.}
|
||||
{- The [TERM] environment variable is [dumb].}
|
||||
{- The [TERM] environment variable is unset and {!Sys.backend_type} is
|
||||
not [Other "js_of_ocaml"]. Yes, browser consoles support
|
||||
ANSI escapes. Yes, you can run Cmdliner in your browser.}}
|
||||
|
||||
{1:legacy_prefix_specification Legacy prefix specification}
|
||||
|
||||
Before Cmdliner 2.0, command names, long option names and
|
||||
{!Cmdliner.Arg.enum} values could be specified by a prefix as long as
|
||||
the prefix was not ambiguous.
|
||||
|
||||
This turned out to be a mistake. It makes the user experience of the
|
||||
tool unstable as it evolves: former user established shortcuts or
|
||||
invocations in scripts may be broken by new command, option and
|
||||
enumerant additions.
|
||||
|
||||
Therefore this behaviour was unconditionally removed in Cmdliner
|
||||
2.0. If you happen to have scripts that rely on it, you can invoke
|
||||
them with [CMDLINER_LEGACY_PREFIXES=true] set in the environment to
|
||||
recover the old behaviour. {b However the scripts should be fixed: this
|
||||
escape hatch will be removed in the future.}
|
||||
|
||||
The [CMDLINER_LEGACY_PREFIX=true] escape hatch should not be used for
|
||||
interactive tool interaction. In particular the behaviour of Cmdliner
|
||||
completion support under this setting is undefined.
|
||||
|
|
|
|||
720
cmdliner/_doc-dir/odoc-pages/cookbook.mld
Normal file
720
cmdliner/_doc-dir/odoc-pages/cookbook.mld
Normal file
|
|
@ -0,0 +1,720 @@
|
|||
{0 [Cmdliner] cookbook}
|
||||
|
||||
A few recipes and starting {{!blueprints}blueprints} to describe your
|
||||
command lines with {!Cmdliner}.
|
||||
|
||||
{b Note.} Some of the code snippets here assume they are done after:
|
||||
{[
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
]}
|
||||
|
||||
{1:tips Tips and pitfalls}
|
||||
|
||||
Command line interfaces are a rather crude and inexpressive user
|
||||
interaction medium. It is tempting to try to be nice to users in
|
||||
various ways but this often backfires in confusing context sensitive
|
||||
behaviours. Here are a few tips and Cmdliner features you {b should
|
||||
rather not use}.
|
||||
|
||||
{2:tip_avoid_default_command Avoid default commands in groups}
|
||||
|
||||
Command {{!Cmdliner.Cmd.group}groups} can have a default command, that
|
||||
is be of the form [tool [CMD]]. Except perhaps at the top level of
|
||||
your tool, it's better to avoid them. They increase command line
|
||||
parsing ambiguities.
|
||||
|
||||
In particular if the default command has positional arguments, users
|
||||
are forced to use the {{!cli.posargs}disambiguation token [--]} to
|
||||
specify them so that they can be distinguished from command
|
||||
names. For example:
|
||||
|
||||
{@sh[
|
||||
tool -- file …
|
||||
]}
|
||||
|
||||
One thing that is acceptable is to have a default command that simply
|
||||
{{!cmds_show_docs}shows documentation} for the group of subcommands as
|
||||
this not interfere with tool operation.
|
||||
|
||||
{2:tip_avoid_default_option_values Avoid default option values}
|
||||
|
||||
Optional arguments {{!Cmdliner.Arg.opt}with values} can have a default
|
||||
value, that is be of the form [--opt[=VALUE]]. In general it is better
|
||||
to avoid them as they lead to context sensitive command lines
|
||||
specifications and surprises when users refine invocations. For examples
|
||||
suppose you have the synopsis
|
||||
|
||||
{@sh[
|
||||
tool --opt[=VALUE] [FILE]
|
||||
]}
|
||||
|
||||
Trying to refine the following invocation to add a [FILE] parameter is
|
||||
error prone and painful:
|
||||
|
||||
{@sh[
|
||||
tool --opt
|
||||
]}
|
||||
|
||||
There is more than one way but the easiest way is to specify:
|
||||
{@sh[
|
||||
tool --opt -- FILE
|
||||
]}
|
||||
which is not obvious unless you have [tool]'s cli hard wired in your
|
||||
brain. This would have been a careless refinement if [--opt] did not
|
||||
have a default option value.
|
||||
|
||||
{2:tip_avoid_required_opt Avoid required optional arguments}
|
||||
|
||||
Cmdliner allows to define required optional arguments. Avoid doing
|
||||
this, it's a contradiction in the terms. In command line interfaces
|
||||
optional arguments are defined to be… optional, not doing so is
|
||||
surprising for your users. Use required positional arguments if
|
||||
arguments are required by your command invocation.
|
||||
|
||||
Required optional arguments can be useful though if your tool is not
|
||||
meant to be invoked manually but rather through scripts and has many
|
||||
required arguments. In this case they become a form of labelled
|
||||
arguments which can make invocations easier to understand.
|
||||
|
||||
{2:tip_avoid_manpages Avoid making manpages your main documentation}
|
||||
|
||||
Unless your tool is very simple, avoid making manpages the main
|
||||
documentation medium of your tool. The medium is rather limited and
|
||||
even though you can convert them to HTML, its cross references
|
||||
capabilities are rather limited which makes discussing your tool
|
||||
online more difficult.
|
||||
|
||||
Keep information in manpages to the minimum needed to operate your
|
||||
tool without having to leave the terminal too much and defer reference
|
||||
manuals, conceptual information and tutorials to a more evolved medium
|
||||
like HTML.
|
||||
|
||||
{2:tip_migrating Migrating from other conventions}
|
||||
|
||||
If you are porting your command line parsing to [Cmdliner] and that
|
||||
you have conventions that clash with [Cmdliner]'s ones but you need to
|
||||
preserve backward compatibility, one way of proceeding is to
|
||||
pre-process {!Sys.argv} into a new array of the right shape before
|
||||
giving it to command {{!Cmdliner.Cmd.section-eval}evaluation
|
||||
functions} via the [?argv] optional argument.
|
||||
|
||||
These are two common cases:
|
||||
|
||||
{ul
|
||||
{- Long option names with a single dash like [-warn-error]. In this
|
||||
case simply prefix an additional [-] to these arguments when they
|
||||
occur in {!Sys.argv} before the [--] argument; after it, all arguments are
|
||||
positional and to be treated literally.}
|
||||
{- Long option names with a single letter like [--X]. In this
|
||||
case simply chop the first [-] to make it a short option when they
|
||||
occur in {!Sys.argv} before the [--] argument; after it all arguments are
|
||||
positional and to be treated literally.}}
|
||||
|
||||
{2:tip_src_structure Source code structure}
|
||||
|
||||
In general Cmdliner wants you to see your tools as regular OCaml functions
|
||||
that you make available to the shell. This means adopting the following
|
||||
source structure:
|
||||
|
||||
{[
|
||||
(* Implementation of your command. Except for exit codes does not deal with
|
||||
command line interface related matters and is independent from
|
||||
Cmdliner. *)
|
||||
|
||||
let exit_ok = 0
|
||||
let tool … = …; exit_ok
|
||||
|
||||
(* Command line interface. Adds metadata to your [tool] function arguments
|
||||
so that they can be parsed from the command line and documented. *)
|
||||
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
let cmd = … (* Has a term that invokes [tool] *)
|
||||
let main () = Cmd.eval' cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())
|
||||
]}
|
||||
|
||||
In particular it is good for your readers' understanding that your
|
||||
program has a single point where it {!Stdlib.exit}s. This structure is
|
||||
also useful for playing with your program in the OCaml toplevel
|
||||
(REPL), you can invoke its [main] function without having the risk of it
|
||||
[exit]ing the toplevel.
|
||||
|
||||
If your tool named [tool] is growing into multiple commands which
|
||||
have a lot of definitions it is advised to:
|
||||
{ul
|
||||
{- Gather command line definition commonalities such as argument
|
||||
converters or common options in a module called [Tool_cli].}
|
||||
{- Define each command named [name] in a separate module [Cmd_name] which
|
||||
exports its command as a [val cmd : int Cmd.t] value.}
|
||||
{- Gather the commands with {!Cmdliner.Cmd.group} in a source file
|
||||
called [tool_main.ml].}}
|
||||
|
||||
For an hypothetic tool named [tool] with commands [import], [serve]
|
||||
and [user], this leads to the following set of files:
|
||||
|
||||
{[
|
||||
cmd_import.ml cmd_serve.ml cmd_user.ml tool_cli.ml tool_main.ml
|
||||
cmd_import.mli cmd_serve.mli cmd_user.mli tool_cli.mli
|
||||
]}
|
||||
|
||||
The [.mli] files simply export commands:
|
||||
{[
|
||||
val cmd : int Cmdliner.Cmd.t
|
||||
]}
|
||||
|
||||
And the [tool_main.ml] gathers them with a {!Cmdliner.Cmd.group}:
|
||||
{[
|
||||
let cmd =
|
||||
let default = Term.(ret (const (`Help (`Auto, None)))) (* show help *) in
|
||||
Cmd.group (Cmd.info "tool") ~default @@
|
||||
[Cmd_import.cmd; Cmd_serve.cmd; Cmd_user.cmd]
|
||||
|
||||
let main () = Cmd.value' cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())
|
||||
]}
|
||||
|
||||
{2:tip_tool_support Installing completions and manpages}
|
||||
|
||||
The [cmdliner] tool can be used to install completion scripts and
|
||||
manpages for you tool and its subcommands by using the dedicated
|
||||
{{!page-cli.install_tool_completion}[install tool-completion]} and
|
||||
{{!page-cli.install_tool_manpages}[install tool-manpages]} subcommands.
|
||||
|
||||
To install both directly (and possibly other support files in the future)
|
||||
it is more concise to use the [install
|
||||
tool-support] command. Invoke with [--help] for more information.
|
||||
|
||||
{3:tip_tool_support_with_opam With [opam]}
|
||||
|
||||
If you are installing your package with [opam] for a tool named [tool]
|
||||
located in the build at the path [$BUILD/tool], you can add the following
|
||||
instruction after your build instructions in the [build:] field of
|
||||
your [opam] file (also works if your build system is not using a
|
||||
[.install] file).
|
||||
|
||||
{@sh[
|
||||
build: [
|
||||
[ … ] # Your regular build instructions
|
||||
["cmdliner" "install" "tool-support"
|
||||
"--update-opam-install=%{_:name}%.install"
|
||||
"$BUILD/tool" "_build/cmdliner-install"]]
|
||||
]}
|
||||
|
||||
You need to specify the path to the built executable, as it cannot be
|
||||
looked up in the [PATH] yet. Also more than one tool can be specified
|
||||
in a single invocation and there is a syntax for specifying the actual
|
||||
tool name if it is renamed on install; see [--help] for more
|
||||
details.
|
||||
|
||||
If [cmdliner] is only an optional dependency of your package use the
|
||||
opam filter [{cmdliner:installed}] after the closing bracket of the command
|
||||
invocation.
|
||||
|
||||
{3:tip_tool_support_with_opam_dune With [opam] and [dune]}
|
||||
|
||||
First make sure your understand the
|
||||
{{!tip_tool_support_with_opam}above basic instructions} for [opam].
|
||||
You then
|
||||
{{:https://dune.readthedocs.io/en/stable/reference/packages.html#generating-opam-files}need to figure out} how to add the [cmdliner install] instruction to the [build:]
|
||||
field of the opam file after your [dune] build instructions. For a tool named
|
||||
[tool] the result should eventually look this:
|
||||
|
||||
{@sh[
|
||||
build: [
|
||||
[ … ] # Your regular dune build instructions
|
||||
["cmdliner" "install" "tool-support"
|
||||
"--update-opam-install=%{_:name}%.install"
|
||||
"_build/default/install/bin/tool" {os != "win32"}
|
||||
"_build/default/install/bin/tool.exe" {os = "win32"}
|
||||
"_build/cmdliner-install"]]
|
||||
]}
|
||||
|
||||
{1:conventions Conventions}
|
||||
|
||||
By simply using Cmdliner you are already abiding to a great deal
|
||||
of command line interface conventions. Here are a few other ones that
|
||||
are not necessarily enforced by the library but that are good to
|
||||
adopt for your users.
|
||||
|
||||
{2:conv_use_dash Use ["-"] to specify [stdio] in file path arguments}
|
||||
|
||||
Whenever a command line argument specifies a file path to read or
|
||||
write you should let the user specify [-] to denote standard in or
|
||||
standard out, if possible. If you worry about a file sporting this
|
||||
name, note that the user can always specify it using [./-] for
|
||||
the argument.
|
||||
|
||||
Very often tools default to [stdin] or [stdout] when a file
|
||||
input or output is unspecified, here is typical argument definitions
|
||||
to support these conventions:
|
||||
|
||||
{[
|
||||
let infile =
|
||||
let doc = "$(docv) is the file to read from. Use $(b,-) for $(b,stdin)" in
|
||||
Arg.(value & opt string "-" & info ["i", "input-file"] ~doc ~docv:"FILE")
|
||||
|
||||
let outfile =
|
||||
let doc = "$(docv) is the file to write to. Use $(b,-) for $(b,stdout)" in
|
||||
Arg.(value & opt string "-" & info ["o", "output-file"] ~doc ~docv:"FILE")
|
||||
]}
|
||||
|
||||
Here is {!Stdlib} based code to read to a string a file or standard
|
||||
input if [-] is specified:
|
||||
|
||||
{[
|
||||
let read_file file =
|
||||
let read file ic = try Ok (In_channel.input_all ic) with
|
||||
| Sys_error e -> Error (Printf.sprintf "%s: %s" file e)
|
||||
in
|
||||
let binary_stdin () = In_channel.set_binary_mode In_channel.stdin true in
|
||||
try match file with
|
||||
| "-" -> binary_stdin (); read file In_channel.stdin
|
||||
| file -> In_channel.with_open_bin file (read file)
|
||||
with Sys_error e -> Error e
|
||||
]}
|
||||
|
||||
Here is {!Stdlib} based code to write a string to a file or standard output
|
||||
if [-] is specified:
|
||||
|
||||
{[
|
||||
let write_file file s =
|
||||
let write file s oc = try Ok (Out_channel.output_string oc s) with
|
||||
| Sys_error e -> Error (Printf.sprintf "%s: %s" file e)
|
||||
in
|
||||
let binary_stdout () = Out_channel.(set_binary_mode stdout true) in
|
||||
try match file with
|
||||
| "-" -> binary_stdout (); write file s Out_channel.stdout
|
||||
| file -> Out_channel.with_open_bin file (write file s)
|
||||
with Sys_error e -> Error e
|
||||
]}
|
||||
|
||||
{2:conv_env_defaults Environment variables as default modifiers}
|
||||
|
||||
Cmdliner has support to back values defined by arguments with
|
||||
environment variables. The value specified via an environment variable
|
||||
should never take over an argument specified explicitely on the
|
||||
command line. The environment variable should be seen as providing
|
||||
the default value when the argument is absent.
|
||||
|
||||
This is exactly what Cmdliner's support for environment variables does,
|
||||
see {!env_args}
|
||||
|
||||
{1:args Arguments}
|
||||
|
||||
{2:args_positional How do I define a positional argument?}
|
||||
|
||||
Positional arguments are extracted from the command line using
|
||||
{{!Cmdliner.Arg.posargs}these combinators} which use zero-based
|
||||
indexing. The following example extracts the first argument and if
|
||||
the argument is absent from the command line it evaluates
|
||||
to ["Revolt!"].
|
||||
{[
|
||||
let msg =
|
||||
let doc = "$(docv) is the message to utter." and docv = "MSG" in
|
||||
Arg.(value & pos 0 string "Revolt!" & info [] ~doc ~docv)
|
||||
]}
|
||||
|
||||
{2:args_optional How do I define an optional argument?}
|
||||
|
||||
Optional arguments are extracted from the command line using
|
||||
{{!Cmdliner.Arg.optargs}these combinators}. The actual option
|
||||
name is defined in the {!Cmdliner.Arg.val-info} structure without
|
||||
dashes. One character strings define short options, others long
|
||||
options (see the {{!page-cli.optargs}parsed syntax}).
|
||||
|
||||
The following defines the [-l] and [--loud] options. This is a simple
|
||||
command line argument without a value also known as a command line {e
|
||||
flag}. The term [loud] evaluates to [false] when the argument is
|
||||
absent on the command line and [true] otherwise.
|
||||
|
||||
{[
|
||||
let loud =
|
||||
let doc = "Say the message loudly." in
|
||||
Arg.(value & flag & info ["l"; "loud"] ~doc)
|
||||
]}
|
||||
|
||||
The following defines the [-m] and [--message] options. The term [msg] evalutes
|
||||
to ["Revolt!"] when the option is absent on the command line.
|
||||
{[
|
||||
let msg =
|
||||
let doc = "$(docv) is the message to utter." and docv = "MSG" in
|
||||
Arg.(value & opt string "Revolt!" & info ["m"; "message"] ~doc ~docv)
|
||||
]}
|
||||
|
||||
{2:args_required How do I define a required argument?}
|
||||
|
||||
Some of the constraints on the presence of arguments occur when the
|
||||
specification of arguments is {{!Cmdliner.Arg.argterms}converted} to
|
||||
terms. The following says that the first positional argument is required:
|
||||
|
||||
{[
|
||||
let msg =
|
||||
let msg = "$(docv) is the message to utter." and docv = "MSG" in
|
||||
Arg.(required & pos 0 (some string) None & info [] ~absent ~doc ~docv)
|
||||
]}
|
||||
|
||||
The value [msg] ends up being a term of type [string]. If the argument
|
||||
is not provided, Cmdliner will automatically bail out during evaluation
|
||||
with an error message.
|
||||
|
||||
Note that while it is possible to define required positional argument
|
||||
it is {{!tip_avoid_required_opt}discouraged}.
|
||||
|
||||
{2:args_detect_absent How can I know if an argument was absent?}
|
||||
|
||||
Most {{!Cmdliner.Arg.posargs}positional} and
|
||||
{{!Cmdliner.Arg.optargs}optional} arguments have a default value. You
|
||||
can use a [None] for the default argument and the {!Cmdliner.Arg.some} or
|
||||
{!Cmdliner.Arg.some'} combinators on your argument converter which simply
|
||||
wrap its result in a [Some].
|
||||
|
||||
{[
|
||||
let msg =
|
||||
let msg = "$(docv) is the message to utter." in
|
||||
let absent = "Random quote." in
|
||||
Arg.(value & pos 0 (some string) None & info [] ~absent ~doc ~docv:"MSG")
|
||||
]}
|
||||
|
||||
There is more than one way to document the value when it is
|
||||
absent. See {!args_absent_doc}
|
||||
|
||||
{2:args_absent_doc How do I document absent argument behaviours?}
|
||||
|
||||
There are three ways to document the behaviour when an argument is
|
||||
unspecified on the command line.
|
||||
|
||||
{ul
|
||||
{- If you specify a default value in the argument combinator, this value
|
||||
gets printed in bold using the {{!Cmdliner.Arg.conv_printer}printer}
|
||||
of the converter.}
|
||||
{- If you are using the {!Cmdliner.Arg.some'} and {!Cmdliner.Arg.some}
|
||||
there is an optional [none] argument that allows you to specify
|
||||
the default value. If you can exhibit this value at definition
|
||||
point use {!Cmdliner.Arg.some'}, the underlying converter's
|
||||
{{!Cmdliner.Arg.conv_printer}printer} will be used. If not
|
||||
you can specify it as a string rendered in bold via {!Cmdliner.Arg.some}.}
|
||||
{- If you want to describe a more complex, but short, behaviour use
|
||||
the [~absent] parameter of {!Cmdliner.Arg.val-info}. Using this
|
||||
parameter overrides the two previous ways. See
|
||||
{{!args_detect_absent}this} example. }}
|
||||
|
||||
{2:args_completion How can I customize positional and option value completion?}
|
||||
|
||||
Positional argument values and option values are completed according
|
||||
to the {{!Cmdliner.Arg.argconv}argument converter} you use for defining
|
||||
the optional or positional argument.
|
||||
|
||||
A couple of predefined argument converter like {!Cmdliner.Arg.path},
|
||||
{!Cmdliner.Arg.filepath} and {!Cmdliner.Arg.dirpath} or
|
||||
{!Cmdliner.Arg.enum} automatically handle this for you.
|
||||
|
||||
If you would like to perform custom or more elaborate context
|
||||
sensitive completions you can define your own argument converter with
|
||||
a completion defined with {!Cmdliner.Arg.Completion.make}.
|
||||
|
||||
Here is an example where the first positional argument is completed
|
||||
with the filenames found in a directory specified via the [--dir]
|
||||
option (which defaults to the current working directory if unspecified).
|
||||
{[
|
||||
let dir = Arg.(value & opt dirpath "." & info ["d"; "dir"])
|
||||
let dir_filenames_conv =
|
||||
let complete dir ~token = match dir with
|
||||
| None -> Error "Could not determine directory to lookup"
|
||||
| Some dir ->
|
||||
match Array.to_list (Sys.readdir dir) with
|
||||
| exception Sys_error e -> Error (String.concat ": " [dir; e])
|
||||
| fnames ->
|
||||
let fnames = List.filter (String.starts_with ~prefix:token) fnames in
|
||||
Ok (List.map Arg.Completion.string fnames)
|
||||
in
|
||||
let completion = Arg.Completion.make ~context:dir complete in
|
||||
Arg.Conv.of_conv ~completion Arg.string
|
||||
|
||||
let pos0 = Arg.(required & pos 0 (some dir_filenames_conv) None & info [])
|
||||
]}
|
||||
|
||||
Note that when you use [pos0] in a command line definition you also
|
||||
need to make sure [dir] is part of the term otherwise the context will
|
||||
always be [None]:
|
||||
|
||||
{[
|
||||
let+ pos0 and+ dir and+ … in …
|
||||
]}
|
||||
|
||||
{1:envs Environment variables}
|
||||
|
||||
{2:env_args How can environment variables define defaults?}
|
||||
|
||||
As mentioned in {!conv_env_defaults}, any non-required argument can be
|
||||
defined by an environment variable when absent. This works by
|
||||
specifying the [env] argument in the argument's {!Cmdliner.Arg.val-info}
|
||||
information. For example:
|
||||
|
||||
{[
|
||||
let msg =
|
||||
let doc = "$(docv) is the message to utter." and docv = "MSG" in
|
||||
let env = Cmd.Env.info "MESSAGE" in
|
||||
Arg.(value & pos 0 string "Revolt!" & info [] ~env ~doc ~docv)
|
||||
]}
|
||||
|
||||
When the first positional argument is absent it takes the default
|
||||
value ["Revolt!"], unless the [MESSAGE] variable is defined in
|
||||
the environment in which case it takes its value.
|
||||
|
||||
Cmdliner handles the environment variable lookup for you. By using the
|
||||
[msg] term in your command definition all this gets automatically
|
||||
documented in the tool help.
|
||||
|
||||
{2:env_cmd How do I document environment variables influencing a command?}
|
||||
|
||||
Environment variable that are used to change {{!env_args}argument
|
||||
defaults} automatically get documented in a command's man page when
|
||||
you use the argument's term in the command's term.
|
||||
|
||||
However if your command implementation looks up other variables and you
|
||||
wish to document them in the command's man page, use the [envs]
|
||||
argument of {!Cmdliner.Cmd.val-info} or the [docs_env] argument
|
||||
of {!Cmdliner.Arg.val-info}.
|
||||
|
||||
This documents in the {!Cmdliner.Manpage.s_environment} manual section
|
||||
of [tool] that [EDITOR] is looked up to find the tool to invoke to
|
||||
edit the files:
|
||||
|
||||
{[
|
||||
let editor_env = "EDITOR"
|
||||
let tool … = … Sys.getenv_opt editor_env
|
||||
let cmd =
|
||||
let env = Cmd.Env.info editor_env ~doc:"The editor used to edit files." in
|
||||
Cmd.make (Cmd.info "tool" ~envs:[env]) @@
|
||||
…
|
||||
]}
|
||||
|
||||
{1:cmds Commands}
|
||||
|
||||
{2:cmds_exit_code_docs How do I document command exit codes?}
|
||||
|
||||
Exit codes are documentd by {!Cmdliner.Cmd.Exit.type-info} values and
|
||||
must be given to the command's {!Cmdliner.Cmd.type-info} value via the
|
||||
[exits] optional arguments. For example:
|
||||
|
||||
{[
|
||||
let conf_not_found = 1
|
||||
let tool … =
|
||||
let tool_cmd =
|
||||
let exits =
|
||||
Cmd.Exit.info conf_not_found "if no configuration could be found." ::
|
||||
Cmd.Exit.defaults
|
||||
in
|
||||
Cmd.make (Cmd.info "mycmd" ~exits) @@
|
||||
…
|
||||
]}
|
||||
|
||||
{2:cmds_show_docs How do I show help in a command group's default?}
|
||||
|
||||
While it is usually {{!tip_avoid_default_command}not advised} to have a default
|
||||
command in a group, just showing docs is acceptable. A term can request
|
||||
Cmdliner's generated help by using {!Cmdliner.Term.val-ret}:
|
||||
{[
|
||||
let group_cmd =
|
||||
let default = Term.(ret (const (`Help (`Auto, None)))) (* show help *) in
|
||||
Cmd.group (Cmd.info "group") ~default @@
|
||||
[first_cmd; second_cmd]
|
||||
]}
|
||||
|
||||
{2:cmds_which_eval Which [Cmd] evaluation function should I use?}
|
||||
|
||||
There are (too) many {{!Cmdliner.Cmd.section-eval}command evaluation}
|
||||
functions. They have grown organically in a rather ad-hoc manner. Some
|
||||
of these are there for backwards compatibility reasons and advanced
|
||||
usage for complex tools.
|
||||
|
||||
Here are the main ones to use and why you may want to use them which
|
||||
essentially depends on how you want to handle errors and exit codes
|
||||
in your tool function.
|
||||
|
||||
{ul
|
||||
{- {!Cmdliner.Cmd.val-eval}. This forces your tool function to return [()].
|
||||
The evaluation function always returns an exit code of [0] unless a
|
||||
command line parsing error occurs.}
|
||||
{- {!Cmdliner.Cmd.eval'}. {b Recommended}. This forces your tool function to
|
||||
return an exit code [exit] which is returned by the evaluation function
|
||||
unless a command line parsing error occurs. This is the recommended
|
||||
function to use as it forces you to think about how to report errors and
|
||||
design useful exit codes for users.}
|
||||
{- {!Cmdliner.Cmd.eval_result} is akin to {!Cmdliner.Cmd.val-eval} except
|
||||
it forces your function to return either [Ok ()] or [Error msg].
|
||||
The evaluation function returns with exit code [0] unless [Error msg] is
|
||||
computed in which case [msg] is printed on the error stream prefixed by the
|
||||
executable name and the evaluation function returns with
|
||||
exit code {!Cmdliner.Cmd.Exit.some_error}.}
|
||||
{- {!Cmdliner.Cmd.eval_result'} is akin to {!Cmdliner.Cmd.eval_result}, except
|
||||
the [Ok] case carries an exit code which is returned by the evaluation
|
||||
function.}}
|
||||
|
||||
{2:cmds_howto_complete How can my tool support command line completion?}
|
||||
|
||||
The command line interface manual has all
|
||||
{{!page-cli.cli_completion}the details} and
|
||||
{{!page-cli.install_tool_completion} specific instructions} for
|
||||
complementing your tool install. See also {!tip_tool_support}.
|
||||
|
||||
{2:cmds_listing How can I list all the commands of my tool?}
|
||||
|
||||
In a shell the invocation [cmdliner tool-commands $TOOL] lists every
|
||||
command of the tool $TOOL.
|
||||
|
||||
{2:cmds_errmsg_styling How can I suppress error message styling?}
|
||||
|
||||
Since Cmdliner 2.0, error message printed on [stderr] use styled text
|
||||
with ANSI escapes. Styled text is disabled if one of the conditions
|
||||
mentioned {{!page-cli.error_message_styling}here} is met.
|
||||
|
||||
If you want to be more aggressive in suppressing them you can use the
|
||||
[err] formatter argument of {{!Cmdliner.Cmd.section-eval}command
|
||||
evaluation} functions with a suitable formatter on which a function
|
||||
like
|
||||
{{:https://erratique.ch/software/more/doc/More/Fmt/index.html#val-strip_styles}
|
||||
this one} has been applied that automatically strips the styling.
|
||||
|
||||
{1:manpage Manpages}
|
||||
|
||||
{2:manpage_hide How do I prevent an item from being automatically listed?}
|
||||
|
||||
In general it's not a good idea to hide stuff from your users but in
|
||||
case an item needs to be hidden you can use the special
|
||||
{!Cmdliner.Manpage.s_none} section name. This ensures the item does
|
||||
not get listed in any section.
|
||||
|
||||
{[
|
||||
let secret = Arg.(value & flag & info ["super-secret"] ~docs:Manpage.s_none)
|
||||
]}
|
||||
|
||||
{2:manpage_synopsis How can I write a better command synopsis section?}
|
||||
|
||||
Define the {!Cmdliner.Manpage.s_synopsis} section in the manpage of
|
||||
your command. It takes over the one generated by Cmdliner. For example:
|
||||
|
||||
{[
|
||||
let man = [
|
||||
`S Manpage.s_synopsis;
|
||||
`P "$(cmd) $(b,--) $(i,TOOL) [$(i,ARG)]…"; `Noblank;
|
||||
`P "$(cmd) $(i,COMMAND) …";
|
||||
`S Manpage.s_description;
|
||||
`P "Without a command $(cmd) invokes $(i,TOOL)"; ]
|
||||
]}
|
||||
|
||||
{2:manpage_install How can I install all the manpages of my tool?}
|
||||
|
||||
The command line interface manual
|
||||
{{!page-cli.install_tool_manpages}the details} on how to install the manpages
|
||||
of your tool and its subcommands. See also {!tip_tool_support}.
|
||||
|
||||
{1:blueprints Blueprints}
|
||||
|
||||
These blueprints when copied to a [src.ml] file can be compiled and run with:
|
||||
|
||||
{@sh[
|
||||
ocamlfind ocamlopt -package cmdliner -linkgpkg src.ml
|
||||
./a.out --help
|
||||
]}
|
||||
|
||||
More concrete examples can be found on the {{!page-examples}examples page}
|
||||
and the {{!page-tutorial}tutorial} may help too.
|
||||
|
||||
These examples follow a conventional {!tip_src_structure}.
|
||||
|
||||
{2:blueprint_min Minimal}
|
||||
|
||||
A minimal example.
|
||||
|
||||
{@ocaml name=blueprint_min.ml[
|
||||
let tool () = Cmdliner.Cmd.Exit.ok
|
||||
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
let cmd =
|
||||
Cmd.make (Cmd.info "TODO" ~version:"v2.0.0") @@
|
||||
let+ unit = Term.const () in
|
||||
tool unit
|
||||
|
||||
let main () = Cmd.eval' cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())
|
||||
]}
|
||||
|
||||
{2:blueprint_tool A simple tool}
|
||||
|
||||
This is a tool that has a flag, an optional positional argument for
|
||||
specifying an input file. It also responds to the [--version] option.
|
||||
|
||||
{@ocaml name=blueprint_tool.ml[
|
||||
let exit_todo = 1
|
||||
let tool ~flag ~infile = exit_todo
|
||||
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
let flag = Arg.(value & flag & info ["flag"] ~doc:"The flag")
|
||||
let infile =
|
||||
let doc = "$(docv) is the input file. Use $(b,-) for $(b,stdin)." in
|
||||
Arg.(value & pos 0 string "-" & info [] ~doc ~docv:"FILE")
|
||||
|
||||
let cmd =
|
||||
let doc = "The tool synopsis is TODO" in
|
||||
let man = [
|
||||
`S Manpage.s_description;
|
||||
`P "$(cmd) does TODO" ]
|
||||
in
|
||||
let exits =
|
||||
Cmd.Exit.info exit_todo ~doc:"When there is stuff todo" ::
|
||||
Cmd.Exit.defaults
|
||||
in
|
||||
Cmd.make (Cmd.info "TODO" ~version:"v2.0.0" ~doc ~man ~exits) @@
|
||||
let+ flag and+ infile in
|
||||
tool ~flag ~infile
|
||||
|
||||
let main () = Cmd.eval' cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())
|
||||
]}
|
||||
|
||||
{2:blueprint_cmds A tool with subcommands}
|
||||
|
||||
This is a tool with two subcommands [hey] and [ho]. If your tools
|
||||
grows many subcommands you may want to follow these
|
||||
{{!tip_src_structure}source code conventions}.
|
||||
|
||||
{@ocaml name=blueprint_cmds.ml[
|
||||
let hey () = Cmdliner.Cmd.Exit.ok
|
||||
let ho () = Cmdliner.Cmd.Exit.ok
|
||||
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
let flag = Arg.(value & flag & info ["flag"] ~doc:"The flag")
|
||||
let infile =
|
||||
let doc = "$(docv) is the input file. Use $(b,-) for $(b,stdin)." in
|
||||
Arg.(value & pos 0 file "-" & info [] ~doc ~docv:"FILE")
|
||||
|
||||
let hey_cmd =
|
||||
let doc = "The hey command synopsis is TODO" in
|
||||
Cmd.make (Cmd.info "hey" ~doc) @@
|
||||
let+ unit = Term.const () in
|
||||
ho ()
|
||||
|
||||
let ho_cmd =
|
||||
let doc = "The ho command synopsis is TODO" in
|
||||
Cmd.make (Cmd.info "ho" ~doc) @@
|
||||
let+ unit = Term.const () in
|
||||
ho unit
|
||||
|
||||
let cmd =
|
||||
let doc = "The tool synopsis is TODO" in
|
||||
Cmd.group (Cmd.info "TODO" ~version:"v2.0.0" ~doc) @@
|
||||
[hey_cmd; ho_cmd]
|
||||
|
||||
let main () = Cmd.eval' cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())
|
||||
]}
|
||||
158
cmdliner/_doc-dir/odoc-pages/examples.mld
Executable file → Normal file
158
cmdliner/_doc-dir/odoc-pages/examples.mld
Executable file → Normal file
|
|
@ -1,9 +1,10 @@
|
|||
{0 Examples}
|
||||
|
||||
The examples are self-contained, cut and paste them in a file to play
|
||||
with them.
|
||||
with them. See also the suggested {{!page-cookbook.tip_src_structure}source
|
||||
code structure} and program {{!page-cookbook.blueprints}blueprints}.
|
||||
|
||||
{1:exrm A [rm] command}
|
||||
{1:example_rm A [rm] command}
|
||||
|
||||
We define the command line interface of an [rm] command with the
|
||||
synopsis:
|
||||
|
|
@ -25,20 +26,21 @@ line and we just take the {!Cmdliner.Arg.last} one to define our term
|
|||
value. If there is no occurrence the last value of the default list
|
||||
[[Always]] is taken. This means the default prompt behaviour is [Always].
|
||||
|
||||
{[
|
||||
{@ocaml name=example_rm.ml[
|
||||
(* Implementation of the command, we just print the args. *)
|
||||
|
||||
type prompt = Always | Once | Never
|
||||
let prompt_str = function
|
||||
| Always -> "always" | Once -> "once" | Never -> "never"
|
||||
|
||||
let rm prompt recurse files =
|
||||
let rm ~prompt ~recurse files =
|
||||
Printf.printf "prompt = %s\nrecurse = %B\nfiles = %s\n"
|
||||
(prompt_str prompt) recurse (String.concat ", " files)
|
||||
|
||||
(* Command line interface *)
|
||||
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
let files = Arg.(non_empty & pos_all file [] & info [] ~docv:"FILE")
|
||||
let prompt =
|
||||
|
|
@ -63,32 +65,34 @@ let recursive =
|
|||
let doc = "Remove directories and their contents recursively." in
|
||||
Arg.(value & flag & info ["r"; "R"; "recursive"] ~doc)
|
||||
|
||||
let cmd =
|
||||
let rm_cmd =
|
||||
let doc = "Remove files or directories" in
|
||||
let man = [
|
||||
`S Manpage.s_description;
|
||||
`P "$(tname) removes each specified $(i,FILE). By default it does not
|
||||
`P "$(cmd) removes each specified $(i,FILE). By default it does not
|
||||
remove directories, to also remove them and their contents, use the
|
||||
option $(b,--recursive) ($(b,-r) or $(b,-R)).";
|
||||
`P "To remove a file whose name starts with a $(b,-), for example
|
||||
$(b,-foo), use one of these commands:";
|
||||
`Pre "$(mname) $(b,-- -foo)"; `Noblank;
|
||||
`Pre "$(mname) $(b,./-foo)";
|
||||
`P "$(tname) removes symbolic links, not the files referenced by the
|
||||
`Pre "$(cmd) $(b,-- -foo)"; `Noblank;
|
||||
`Pre "$(cmd) $(b,./-foo)";
|
||||
`P "$(cmd.name) removes symbolic links, not the files referenced by the
|
||||
links.";
|
||||
`S Manpage.s_bugs; `P "Report bugs to <bugs@example.org>.";
|
||||
`S Manpage.s_see_also; `P "$(b,rmdir)(1), $(b,unlink)(2)" ]
|
||||
in
|
||||
let info = Cmd.info "rm" ~version:"v1.3.0" ~doc ~man in
|
||||
Cmd.v info Term.(const rm $ prompt $ recursive $ files)
|
||||
Cmd.make (Cmd.info "rm" ~version:"v2.0.0" ~doc ~man) @@
|
||||
let+ prompt and+ recursive and+ files in
|
||||
rm ~prompt ~recurse:recursive files
|
||||
|
||||
let main () = exit (Cmd.eval cmd)
|
||||
let () = main ()
|
||||
let main () = Cmd.eval rm_cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())
|
||||
]}
|
||||
|
||||
{1:excp A [cp] command}
|
||||
{1:example_cp A [cp] command}
|
||||
|
||||
We define the command line interface of a [cp] command with the synopsis:
|
||||
|
||||
{v
|
||||
cp [OPTION]… SOURCE… DEST
|
||||
v}
|
||||
|
|
@ -97,16 +101,16 @@ The [DEST] argument must be a directory if there is more than one
|
|||
[SOURCE]. This constraint is too complex to be expressed by the
|
||||
combinators of {!Cmdliner.Arg}.
|
||||
|
||||
Hence we just give [DEST] the {!Cmdliner.Arg.string} type and verify the
|
||||
constraint at the beginning of the implementation of [cp]. If the
|
||||
Hence we just give [DEST] the {!Cmdliner.Arg.string} type and verify
|
||||
the constraint at the beginning of the implementation of [cp]. If the
|
||||
constraint is unsatisfied we return an [`Error] result. By using
|
||||
{!Cmdliner.Term.val-ret} on the lifted result [cp_t] of [cp],
|
||||
[Cmdliner] handles the error reporting.
|
||||
{!Cmdliner.Term.val-ret} on the command's term for [cp], [Cmdliner]
|
||||
handles the error reporting.
|
||||
|
||||
{[
|
||||
{@ocaml name=example_cp.ml[
|
||||
(* Implementation, we check the dest argument and print the args *)
|
||||
|
||||
let cp verbose recurse force srcs dest =
|
||||
let cp ~verbose ~recurse ~force srcs dest =
|
||||
let many = List.length srcs > 1 in
|
||||
if many && (not (Sys.file_exists dest) || not (Sys.is_directory dest))
|
||||
then `Error (false, dest ^ ": not a directory") else
|
||||
|
|
@ -117,6 +121,7 @@ let cp verbose recurse force srcs dest =
|
|||
(* Command line interface *)
|
||||
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
let verbose =
|
||||
let doc = "Print file names as they are copied." in
|
||||
|
|
@ -140,24 +145,25 @@ let dest =
|
|||
let docv = "DEST" in
|
||||
Arg.(required & pos ~rev:true 0 (some string) None & info [] ~docv ~doc)
|
||||
|
||||
let cmd =
|
||||
let cp_cmd =
|
||||
let doc = "Copy files" in
|
||||
let man_xrefs =
|
||||
[ `Tool "mv"; `Tool "scp"; `Page ("umask", 2); `Page ("symlink", 7) ]
|
||||
[`Tool "mv"; `Tool "scp"; `Page ("umask", 2); `Page ("symlink", 7)]
|
||||
in
|
||||
let man =
|
||||
[ `S Manpage.s_bugs;
|
||||
`P "Email them to <bugs@example.org>."; ]
|
||||
let man = [
|
||||
`S Manpage.s_bugs;
|
||||
`P "Email them to <bugs@example.org>."; ]
|
||||
in
|
||||
let info = Cmd.info "cp" ~version:"v1.3.0" ~doc ~man ~man_xrefs in
|
||||
Cmd.v info Term.(ret (const cp $ verbose $ recurse $ force $ srcs $ dest))
|
||||
Cmd.make (Cmd.info "cp" ~version:"v2.0.0" ~doc ~man ~man_xrefs) @@
|
||||
Term.ret @@
|
||||
let+ verbose and+ recurse and+ force and+ srcs and+ dest in
|
||||
cp ~verbose ~recurse ~force srcs dest
|
||||
|
||||
|
||||
let main () = exit (Cmd.eval cmd)
|
||||
let () = main ()
|
||||
let main () = Cmd.eval cp_cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())
|
||||
]}
|
||||
|
||||
{1:extail A [tail] command}
|
||||
{1:example_tail A [tail] command}
|
||||
|
||||
We define the command line interface of a [tail] command with the
|
||||
synopsis:
|
||||
|
|
@ -180,7 +186,7 @@ the option [--follow] evaluates to [None] if [--follow] is absent from
|
|||
the command line, to [Some Descriptor] if present but without a value
|
||||
and to [Some v] if present with a value [v] specified.
|
||||
|
||||
{[
|
||||
{@ocaml name=example_tail.ml[
|
||||
(* Implementation of the command, we just print the args. *)
|
||||
|
||||
type loc = bool * int
|
||||
|
|
@ -193,7 +199,7 @@ let loc_str (rev, k) = if rev then str "%d" k else str "+%d" k
|
|||
let follow_str = function Name -> "name" | Descriptor -> "descriptor"
|
||||
let verb_str = function Verbose -> "verbose" | Quiet -> "quiet"
|
||||
|
||||
let tail lines follow verb pid files =
|
||||
let tail ~lines ~follow ~verb ~pid files =
|
||||
Printf.printf
|
||||
"lines = %s\nfollow = %s\nverb = %s\npid = %s\nfiles = %s\n"
|
||||
(loc_str lines) (opt_str follow_str follow) (verb_str verb)
|
||||
|
|
@ -202,17 +208,18 @@ let tail lines follow verb pid files =
|
|||
(* Command line interface *)
|
||||
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
let loc_arg =
|
||||
let parse s =
|
||||
let parser s =
|
||||
try
|
||||
if s <> "" && s.[0] <> '+'
|
||||
then Ok (true, int_of_string s)
|
||||
else Ok (false, int_of_string (String.sub s 1 (String.length s - 1)))
|
||||
with Failure _ -> Error (`Msg "unable to parse integer")
|
||||
with Failure _ -> Error "unable to parse integer"
|
||||
in
|
||||
let print ppf p = Format.fprintf ppf "%s" (loc_str p) in
|
||||
Arg.conv ~docv:"N" (parse, print)
|
||||
let pp ppf p = Format.fprintf ppf "%s" (loc_str p) in
|
||||
Arg.Conv.make ~docv:"N" ~parser ~pp ()
|
||||
|
||||
let lines =
|
||||
let doc = "Output the last $(docv) lines or use $(i,+)$(docv) to start \
|
||||
|
|
@ -246,27 +253,27 @@ let pid =
|
|||
|
||||
let files = Arg.(value & (pos_all non_dir_file []) & info [] ~docv:"FILE")
|
||||
|
||||
let cmd =
|
||||
let tail_cmd =
|
||||
let doc = "Display the last part of a file" in
|
||||
let man = [
|
||||
`S Manpage.s_description;
|
||||
`P "$(tname) prints the last lines of each $(i,FILE) to standard output. If
|
||||
no file is specified reads standard input. The number of printed
|
||||
`P "$(cmd) prints the last lines of each $(i,FILE) to standard output.
|
||||
If no file is specified reads standard input. The number of printed
|
||||
lines can be specified with the $(b,-n) option.";
|
||||
`S Manpage.s_bugs;
|
||||
`P "Report them to <bugs@example.org>.";
|
||||
`S Manpage.s_see_also;
|
||||
`P "$(b,cat)(1), $(b,head)(1)" ]
|
||||
in
|
||||
let info = Cmd.info "tail" ~version:"v1.3.0" ~doc ~man in
|
||||
Cmd.v info Term.(const tail $ lines $ follow $ verb $ pid $ files)
|
||||
Cmd.make (Cmd.info "tail" ~version:"v2.0.0" ~doc ~man) @@
|
||||
let+ lines and+ follow and+ verb and+ pid and+ files in
|
||||
tail ~lines ~follow ~verb ~pid files
|
||||
|
||||
|
||||
let main () = exit (Cmd.eval cmd)
|
||||
let () = main ()
|
||||
let main () = Cmd.eval tail_cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())
|
||||
]}
|
||||
|
||||
{1:exdarcs A [darcs] command}
|
||||
{1:example_darcs A [darcs] command}
|
||||
|
||||
We define the command line interface of a [darcs] command with the
|
||||
synopsis:
|
||||
|
|
@ -280,10 +287,8 @@ each command. To avoid having to pass them individually to each
|
|||
command we gather them in a record of type [copts]. By lifting the
|
||||
record constructor [copts] into the term [copts_t] we now have a term
|
||||
that we can pass to the commands to stand for an argument of type
|
||||
[copts]. These options are documented in a section called [COMMON
|
||||
OPTIONS], since we also want to put [--help] and [--version] in this
|
||||
section, the term information of commands makes a judicious use of the
|
||||
[sdocs] parameter of {!Cmdliner.Term.val-info}.
|
||||
[copts]. These options are documented in the section
|
||||
{!Cmdliner.Manpage.s_common_options}.
|
||||
|
||||
The [help] command shows help about commands or other topics. The help
|
||||
shown for commands is generated by [Cmdliner] by making an appropriate
|
||||
|
|
@ -291,9 +296,9 @@ use of {!Cmdliner.Term.val-ret} on the lifted [help] function.
|
|||
|
||||
If the program is invoked without a command we just want to show the
|
||||
help of the program as printed by [Cmdliner] with [--help]. This is
|
||||
done by the [default_cmd] term.
|
||||
done by the [default] term.
|
||||
|
||||
{[
|
||||
{@ocaml name=example_darcs.ml[
|
||||
(* Implementations, just print the args. *)
|
||||
|
||||
type verb = Normal | Quiet | Verbose
|
||||
|
|
@ -321,16 +326,18 @@ let help copts man_format cmds topic = match topic with
|
|||
| None -> `Help (`Pager, None) (* help about the program. *)
|
||||
| Some topic ->
|
||||
let topics = "topics" :: "patterns" :: "environment" :: cmds in
|
||||
let conv, _ = Cmdliner.Arg.enum (List.rev_map (fun s -> (s, s)) topics) in
|
||||
match conv topic with
|
||||
| `Error e -> `Error (false, e)
|
||||
| `Ok t when t = "topics" -> List.iter print_endline topics; `Ok ()
|
||||
| `Ok t when List.mem t cmds -> `Help (man_format, Some t)
|
||||
| `Ok t ->
|
||||
let conv = Cmdliner.Arg.enum (List.rev_map (fun s -> (s, s)) topics) in
|
||||
let parse = Cmdliner.Arg.Conv.parser conv in
|
||||
match parse topic with
|
||||
| Error e -> `Error (false, e)
|
||||
| Ok t when t = "topics" -> List.iter print_endline topics; `Ok ()
|
||||
| Ok t when List.mem t cmds -> `Help (man_format, Some t)
|
||||
| Ok t ->
|
||||
let page = (topic, 7, "", "", ""), [`S topic; `P "Say something";] in
|
||||
`Ok (Cmdliner.Manpage.print man_format Format.std_formatter page)
|
||||
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
(* Help sections common to all commands *)
|
||||
|
||||
|
|
@ -338,9 +345,9 @@ let help_secs = [
|
|||
`S Manpage.s_common_options;
|
||||
`P "These options are common to all commands.";
|
||||
`S "MORE HELP";
|
||||
`P "Use $(mname) $(i,COMMAND) --help for help on a single command.";`Noblank;
|
||||
`P "Use $(mname) $(b,help patterns) for help on patch matching."; `Noblank;
|
||||
`P "Use $(mname) $(b,help environment) for help on environment variables.";
|
||||
`P "Use $(tool) $(i,COMMAND) --help for help on a single command.";`Noblank;
|
||||
`P "Use $(tool) $(b,help patterns) for help on patch matching."; `Noblank;
|
||||
`P "Use $(tool) $(b,help environment) for help on environment variables.";
|
||||
`S Manpage.s_bugs; `P "Check bug reports at http://bugs.example.org.";]
|
||||
|
||||
(* Options common to all commands *)
|
||||
|
|
@ -360,7 +367,7 @@ let copts_t =
|
|||
Arg.(last & vflag_all [Normal] [quiet; verbose])
|
||||
in
|
||||
let prehook =
|
||||
let doc = "Specify command to run before this $(mname) command." in
|
||||
let doc = "Specify command to run before this $(tool) command." in
|
||||
Arg.(value & opt (some string) None & info ["prehook"] ~docs ~doc)
|
||||
in
|
||||
Term.(const copts $ debug $ verb $ prehook)
|
||||
|
|
@ -382,8 +389,9 @@ let initialize_cmd =
|
|||
existing files and subdirectories become …";
|
||||
`Blocks help_secs; ]
|
||||
in
|
||||
let info = Cmd.info "initialize" ~doc ~sdocs ~man in
|
||||
Cmd.v info Term.(const initialize $ copts_t $ repodir)
|
||||
Cmd.make (Cmd.info "initialize" ~doc ~sdocs ~man) @@
|
||||
let+ copts_t and+ repodir in
|
||||
initialize copts_t repodir
|
||||
|
||||
let record_cmd =
|
||||
let pname =
|
||||
|
|
@ -409,12 +417,12 @@ let record_cmd =
|
|||
let man =
|
||||
[`S Manpage.s_description;
|
||||
`P "Creates a patch from changes in the working tree. If you specify
|
||||
a set of files …";
|
||||
a set of files…";
|
||||
`Blocks help_secs; ]
|
||||
in
|
||||
let info = Cmd.info "record" ~doc ~sdocs ~man in
|
||||
Cmd.v info
|
||||
Term.(const record $ copts_t $ pname $ author $ all $ ask_deps $ files)
|
||||
Cmd.make (Cmd.info "record" ~doc ~sdocs ~man) @@
|
||||
let+ copts_t and+ pname and+ author and+ all and+ ask_deps and+ files in
|
||||
record copts_t pname author all ask_deps files
|
||||
|
||||
let help_cmd =
|
||||
let topic =
|
||||
|
|
@ -427,17 +435,19 @@ let help_cmd =
|
|||
`P "Prints help about darcs commands and other subjects…";
|
||||
`Blocks help_secs; ]
|
||||
in
|
||||
let info = Cmd.info "help" ~doc ~man in
|
||||
Cmd.v info
|
||||
Term.(ret (const help $ copts_t $ Arg.man_format $ Term.choice_names $
|
||||
topic))
|
||||
Cmd.make (Cmd.info "help" ~doc ~man) @@
|
||||
Term.ret @@
|
||||
let+ copts_t and+ man_format = Arg.man_format
|
||||
and+ choice_names = Term.choice_names and+ topic in
|
||||
help copts_t man_format choice_names topic
|
||||
|
||||
let main_cmd =
|
||||
let doc = "a revision control system" in
|
||||
let man = help_secs in
|
||||
let info = Cmd.info "darcs" ~version:"v1.3.0" ~doc ~sdocs ~man in
|
||||
let info = Cmd.info "darcs" ~version:"v2.0.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]
|
||||
|
||||
let () = exit (Cmd.eval main_cmd)
|
||||
let main () = Cmd.eval main_cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())
|
||||
]}
|
||||
|
|
|
|||
44
cmdliner/_doc-dir/odoc-pages/index.mld
Executable file → Normal file
44
cmdliner/_doc-dir/odoc-pages/index.mld
Executable file → Normal file
|
|
@ -1,12 +1,13 @@
|
|||
{0 Cmdliner {%html: <span class="version">v1.3.0</span>%}}
|
||||
{0 Cmdliner {%html: <span class="version">v2.0.0</span>%}}
|
||||
|
||||
[Cmdliner] provides a simple and compositional mechanism
|
||||
Cmdliner provides a simple and compositional mechanism
|
||||
to convert command line arguments to OCaml values and pass them to
|
||||
your functions.
|
||||
|
||||
The library automatically handles syntax errors, help messages and
|
||||
UNIX man page generation. It supports programs with single or multiple
|
||||
commands (like [git]) and respect most of the
|
||||
The library automatically handles command line completion, syntax
|
||||
errors, help messages and UNIX man page generation. It supports
|
||||
programs with single or multiple commands (like [git]) and respect
|
||||
most of the
|
||||
{{:http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html}
|
||||
POSIX} and
|
||||
{{:http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html}
|
||||
|
|
@ -17,18 +18,29 @@ GNU} conventions.
|
|||
The following manuals are available.
|
||||
|
||||
{ul
|
||||
{- The {{!page-tutorial}tutorial} gets you through the steps to write
|
||||
your first command line interface with Cmdliner.}
|
||||
{- The {{!page-cli}Command line interface manual} describes how command
|
||||
lines and environment variables are parsed by Cmdliner.}
|
||||
{- {{!page-tool_man}Tool man pages} describes how Cmdliner generates
|
||||
man pages for your tools and how you can format them.}
|
||||
{- The {{!page-examples}examples page} has a few annoted examples that
|
||||
show to express the command line interface of a few classic tools with
|
||||
Cmdliner}}
|
||||
{- The {{!page-tutorial}tutorial} makes you write your first command line
|
||||
interface with Cmdliner.}
|
||||
{- The {{!page-cookbook}cookbook} has a few off-the-shelf recipes,
|
||||
tips about {{!page-cookbook.tip_src_structure}source code structure},
|
||||
and {{!page-cookbook.blueprints}blueprints} to define your command lines
|
||||
with Cmdliner.}
|
||||
{- The {{!page-cli}command line interface manual} describes how command
|
||||
lines and environment variables are parsed by Cmdliner and how command line
|
||||
completion is performed. This can be communicated to the users of your
|
||||
tools.}
|
||||
{- The {{!page-tool_man}tool man page} manual describes how
|
||||
Cmdliner generates man pages for your tools and their commands and how
|
||||
you can format them.}
|
||||
{- The {{!page-examples}examples page} has examples of a some
|
||||
classic UNIX tools with their command line interface implemented by
|
||||
Cmdliner.}}
|
||||
|
||||
{1:api API}
|
||||
{1:library Library [cmdliner]}
|
||||
|
||||
{!modules: Cmdliner}
|
||||
{!modules:
|
||||
Cmdliner
|
||||
Cmdliner.Arg
|
||||
Cmdliner.Cmd
|
||||
Cmdliner.Manpage
|
||||
Cmdliner.Term
|
||||
}
|
||||
|
|
|
|||
37
cmdliner/_doc-dir/odoc-pages/tool_man.mld
Executable file → Normal file
37
cmdliner/_doc-dir/odoc-pages/tool_man.mld
Executable file → Normal file
|
|
@ -1,11 +1,14 @@
|
|||
{0:tool_man Tool man pages}
|
||||
|
||||
{1:manual Manual}
|
||||
See also the {{!page-cli.help}section} about man pages in the command
|
||||
line interface manual.
|
||||
|
||||
{1:manual Man page generation}
|
||||
|
||||
Man page sections for a command are printed in the order specified by
|
||||
manual as given to {!Cmdliner.Cmd.val-info}. Unless specified
|
||||
explicitly in the command's manual the following sections are
|
||||
automatically created and populated for you:
|
||||
the [man] value given to {!Cmdliner.Cmd.val-info}. Unless
|
||||
specified explicitly in the [man] value the following sections
|
||||
are automatically created and populated for you:
|
||||
|
||||
{ul
|
||||
{- {{!Cmdliner.Manpage.s_name}[NAME]} section.}
|
||||
|
|
@ -21,11 +24,10 @@ they respectively mention in their [docs] argument:
|
|||
both the [docv] and [doc] string is specified by {!Cmdliner.Arg.val-info}.}
|
||||
{- For optional arguments, see {!Cmdliner.Arg.val-info}.}
|
||||
{- For exit statuses, see {!Cmdliner.Cmd.Exit.val-info}.}
|
||||
{- For environment variables, see
|
||||
{!Cmdliner.Arg.val-env_var} and {!Cmdliner.Cmd.Env.val-info}.}}
|
||||
{- For environment variables, see {!Cmdliner.Cmd.Env.val-info}.}}
|
||||
|
||||
If a [docs] section name is mentioned and does not exist in the command's
|
||||
manual, an empty section is created for it, after which the [doc] strings
|
||||
[man] value, an empty section is created for it, after which the [doc] strings
|
||||
are inserted, possibly prefixed by boilerplate text (e.g. for
|
||||
{!Cmdliner.Manpage.s_environment} and {!Cmdliner.Manpage.s_exit_status}).
|
||||
|
||||
|
|
@ -35,7 +37,7 @@ If the created section is:
|
|||
is inserted at the right place in the order specified
|
||||
{{!Cmdliner.Manpage.standard_sections}here}, but after a
|
||||
possible non-standard
|
||||
section explicitly specified by the command's manual since the latter
|
||||
section explicitly specified by the command's [man] value 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}
|
||||
|
|
@ -51,20 +53,21 @@ it.
|
|||
|
||||
{1:doclang Documentation markup language}
|
||||
|
||||
Manpage {{!Cmdliner.Manpage.block}blocks} and doc strings support the
|
||||
following markup language.
|
||||
Manpage {{!Cmdliner.Manpage.block}blocks} and the doc strings of the
|
||||
various [info] values support the following markup language.
|
||||
|
||||
{ul
|
||||
{- Markup directives [$(i,text)] and [$(b,text)], where [text] is raw
|
||||
text respectively rendered in italics and bold.}
|
||||
{- Outside markup directives, context dependent variables of the form
|
||||
[$(var)] are substituted by marked up data. For example in a term's
|
||||
man page [$(tname)] is substituted by the term name in bold.}
|
||||
{- Characters $, (, ) and \ can respectively be escaped by \$, \(, \)
|
||||
and \\ (in OCaml strings this will be ["\\$"], ["\\("], ["\\)"],
|
||||
["\\\\"]). Escaping $ and \ is mandatory everywhere. Escaping ) is
|
||||
mandatory only in markup directives. Escaping ( is only here for
|
||||
[$(var)] are substituted by marked up data. For example in a command
|
||||
man page [$(cmd)] is substituted by the command's invocation in
|
||||
bold.}
|
||||
{- Characters '$', '(', ')' and '\' can respectively be escaped by \$, \(, \)
|
||||
and \\ . In OCaml strings this will be ["\\$"], ["\\("], ["\\)"],
|
||||
["\\\\"]. Escaping '$' and '\' is mandatory everywhere. Escaping ')' is
|
||||
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.}
|
||||
with a '\' is an illegal character sequence.}
|
||||
{- Referring to unknown markup directives or variables will generate
|
||||
errors on standard error during documentation generation.}}
|
||||
|
|
|
|||
147
cmdliner/_doc-dir/odoc-pages/tutorial.mld
Executable file → Normal file
147
cmdliner/_doc-dir/odoc-pages/tutorial.mld
Executable file → Normal file
|
|
@ -1,82 +1,117 @@
|
|||
{0:tutorial Tutorial}
|
||||
|
||||
{1:started Getting started}
|
||||
See also the {{!page-cookbook}cookbook},
|
||||
{{!page-cookbook.blueprints}blueprints} and
|
||||
{{!page-examples}examples}.
|
||||
|
||||
{1:terms Commands and terms}
|
||||
|
||||
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 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)
|
||||
name and a term of type {!Cmdliner.Term.t}. A term represents both a
|
||||
command line syntax fragment and an expression to be evaluated that
|
||||
implements your tool. 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
|
||||
functional values with {!Cmdliner.Term.($)}.
|
||||
functional values with {!Cmdliner.Term.app}.
|
||||
|
||||
For example, in a [revolt.ml] file, for the function:
|
||||
|
||||
{[
|
||||
{@ocaml name=example_revolt1.ml[
|
||||
let revolt () = print_endline "Revolt!"
|
||||
]}
|
||||
|
||||
the term :
|
||||
|
||||
{[
|
||||
{@ocaml name=example_revolt1.ml[
|
||||
open Cmdliner
|
||||
|
||||
let revolt_t = Term.(const revolt $ const ())
|
||||
let revolt_term = Term.app (Term.const revolt) (Term.const ())
|
||||
]}
|
||||
|
||||
is a term that evaluates to the result (and effect) of the [revolt]
|
||||
function. This term can be attached to a command:
|
||||
function. This term can be associated to a command:
|
||||
|
||||
{[
|
||||
let cmd = Cmd.v (Cmd.info "revolt") revolt_t
|
||||
{@ocaml name=example_revolt1.ml[
|
||||
let cmd_revolt = Cmd.make (Cmd.info "revolt") revolt_term
|
||||
]}
|
||||
|
||||
and evaluated with {!Cmdliner.Cmd.val-eval}:
|
||||
{[
|
||||
let () = exit (Cmd.eval cmd)
|
||||
{@ocaml name=example_revolt1.ml[
|
||||
let main () = Cmd.eval cmd_revolt
|
||||
let () = if !Sys.interactive then () else exit (main ())
|
||||
]}
|
||||
|
||||
This defines a command line tool named ["revolt"] (this name will be
|
||||
used in error reporting and documentation generation), without command
|
||||
line arguments, that just prints ["Revolt!"] on [stdout].
|
||||
|
||||
{[
|
||||
{@sh[
|
||||
> ocamlfind ocamlopt -linkpkg -package cmdliner -o revolt revolt.ml
|
||||
> ./revolt
|
||||
Revolt!
|
||||
]}
|
||||
|
||||
{1:term_syntax Term syntax}
|
||||
|
||||
There is a special syntax that uses OCaml's
|
||||
{{:https://ocaml.org/manual/5.3/bindingops.html}binding operators} for
|
||||
writing terms which is less error prone when the number of arguments
|
||||
you want to give to your function grows. In particular it allows you to
|
||||
easily lift functions which have labels.
|
||||
|
||||
So in fact the program we have just shown above is usually rather
|
||||
written this way:
|
||||
|
||||
{@ocaml name=example_revolt2.ml[
|
||||
let revolt () = print_endline "Revolt!"
|
||||
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
let cmd_revolt =
|
||||
Cmd.make (Cmd.info "revolt") @@
|
||||
let+ () = Term.const () in
|
||||
revolt ()
|
||||
|
||||
let main () = Cmd.eval cmd_revolt
|
||||
let () = if !Sys.interactive then () else exit (main ())
|
||||
]}
|
||||
|
||||
{1:args_as_terms Command line arguments as terms}
|
||||
|
||||
The combinators in the {!Cmdliner.Arg} module allow to extract command
|
||||
line arguments as terms. These terms can then be applied to lifted
|
||||
OCaml functions to be evaluated.
|
||||
|
||||
Terms corresponding to command line argument data that are part of a
|
||||
term evaluation implicitly define a command line syntax. We show this
|
||||
on an concrete example.
|
||||
OCaml functions to be evaluated. A term that uses terms that correspond
|
||||
to command line argument implicitely defines a command line syntax
|
||||
fragment. We show this on an concrete example.
|
||||
|
||||
In a [chorus.ml] file, consider the [chorus] function that prints
|
||||
repeatedly a given message :
|
||||
|
||||
{[
|
||||
let chorus count msg = for i = 1 to count do print_endline msg done
|
||||
{@ocaml name=example_chorus.ml[
|
||||
let chorus ~count msg = for i = 1 to count do print_endline msg done
|
||||
]}
|
||||
|
||||
we want to make it available from the command line with the synopsis:
|
||||
|
||||
{[
|
||||
{@sh[
|
||||
chorus [-c COUNT | --count=COUNT] [MSG]
|
||||
]}
|
||||
|
||||
where [COUNT] defaults to [10] and [MSG] defaults to ["Revolt!"]. We
|
||||
first define a term corresponding to the [--count] option:
|
||||
|
||||
{[
|
||||
{@ocaml name=example_chorus.ml[
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
let count =
|
||||
let doc = "Repeat the message $(docv) times." in
|
||||
Arg.(value & opt int 10 & info ["c"; "count"] ~docv:"COUNT" ~doc)
|
||||
Arg.(value & opt int 10 & info ["c"; "count"] ~doc ~docv:"COUNT")
|
||||
]}
|
||||
|
||||
This says that [count] is a term that evaluates to the value of an
|
||||
|
|
@ -86,14 +121,14 @@ and [docv] are used to generate the option's man page information.
|
|||
|
||||
The term for the positional argument [MSG] is:
|
||||
|
||||
{[
|
||||
{@ocaml name=example_chorus.ml[
|
||||
let msg =
|
||||
let env =
|
||||
let doc = "Overrides the default message to print." in
|
||||
Cmd.Env.info "CHORUS_MSG" ~doc
|
||||
in
|
||||
let doc = "The message to print." in
|
||||
Arg.(value & pos 0 string "Revolt!" & info [] ~env ~docv:"MSG" ~doc)
|
||||
Arg.(value & pos 0 string "Revolt!" & info [] ~env ~doc ~docv:"MSG")
|
||||
]}
|
||||
|
||||
which says that [msg] is a term whose value is the positional argument
|
||||
|
|
@ -102,39 +137,37 @@ value of the environment variable [CHORUS_MSG] if the argument is
|
|||
unspecified on the command line. Here again [doc] and [docv] are used
|
||||
for the man page information.
|
||||
|
||||
The term for executing [chorus] with these command line arguments is :
|
||||
We can now define a term and command for invoking the [chorus] function
|
||||
using the {{!term_syntax}term syntax} and the obscure but handy
|
||||
{{:https://ocaml.org/manual/5.2/bindingops.html#ss%3Aletops-punning}
|
||||
let-punning} OCaml notation. This also shows that the
|
||||
value {!Cmdliner.Cmd.val-info} can be given more
|
||||
information about the term we execute which is notably used to
|
||||
to generate the tool's man page.
|
||||
|
||||
{[
|
||||
let chorus_t = Term.(const chorus $ count $ msg)
|
||||
]}
|
||||
|
||||
We are now ready to define the [main] function of our tool:
|
||||
|
||||
{[
|
||||
let cmd =
|
||||
let doc = "print a customizable message repeatedly" in
|
||||
{@ocaml name=example_chorus.ml[
|
||||
let chorus_cmd =
|
||||
let doc = "Print a customizable message repeatedly" in
|
||||
let man = [
|
||||
`S Manpage.s_bugs;
|
||||
`P "Email bug reports to <bugs@example.org>." ]
|
||||
in
|
||||
let info = Cmd.info "chorus" ~version:"%%VERSION%%" ~doc ~man in
|
||||
Cmd.v info chorus_t
|
||||
Cmd.make (Cmd.info "chorus" ~version:"v2.0.0" ~doc ~man) @@
|
||||
let+ count and+ msg in
|
||||
chorus ~count msg
|
||||
|
||||
let main () = exit (Cmd.eval cmd)
|
||||
let () = main ()
|
||||
let main () = Cmd.eval chorus_cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())
|
||||
]}
|
||||
|
||||
The [info] value created with {!Cmdliner.Cmd.val-info} gives more
|
||||
information about the term we execute and is used to generate the
|
||||
tool's man page. Since we provided a [~version] string, the tool
|
||||
will automatically respond to the [--version] option by printing this
|
||||
string.
|
||||
Since we provided a [~version] string, the tool will automatically
|
||||
respond to the [--version] option by printing this string.
|
||||
|
||||
A tool using {!Cmdliner.Cmd.val-eval} always responds to the [--help]
|
||||
option by showing the tool's man page generated using the information
|
||||
you provided with {!Cmdliner.Cmd.val-info} and
|
||||
{!Cmdliner.Arg.val-info}. Here is the output generated by our
|
||||
example:
|
||||
Besides a tool using {!Cmdliner.Cmd.val-eval} always responds to the
|
||||
[--help] option by showing the tool's man page
|
||||
{{!page-tool_man.manual}generated} using the information you provided
|
||||
with {!Cmdliner.Cmd.val-info} and {!Cmdliner.Arg.val-info}. Here is
|
||||
the manual generated by our example:
|
||||
|
||||
{v
|
||||
> ocamlfind ocamlopt -linkpkg -package cmdliner -o chorus chorus.ml
|
||||
|
|
@ -189,15 +222,7 @@ is also available in plain text or in the
|
|||
by invoking the program with the option [--help=plain] or
|
||||
[--help=groff].
|
||||
|
||||
For examples of more complex command line definitions look and run
|
||||
the {{!page-examples}examples}.
|
||||
|
||||
{1:subcommands Sub commands}
|
||||
|
||||
[Cmdliner] also provides support for programs like [git] that have sub
|
||||
commands each with their own command line syntax and manual:
|
||||
|
||||
{[tool [COMMAND]… [OPTION]… ARG…]}
|
||||
|
||||
These sub commands are defined by grouping them under a parent command
|
||||
via the {!Cmdliner.Cmd.group} function.
|
||||
And with this you should master the basics of Cmdliner, for examples
|
||||
of more complex command line definitions consult the
|
||||
{{!page-examples}examples}. For more tips, off-the-shelf recipes and
|
||||
conventions have look at the {{!page-cookbook}cookbook}.
|
||||
File diff suppressed because one or more lines are too long
173
cmdliner/cookbook.html
Normal file
173
cmdliner/cookbook.html
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -1,17 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>examples (cmdliner.examples)</title><meta charset="utf-8"/><link rel="stylesheet" href="../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="index.html">Up</a> – <a href="../index.html">Index</a> » <a href="index.html">cmdliner</a> » examples</nav><header class="odoc-preamble"><h1 id="examples"><a href="#examples" class="anchor"></a>Examples</h1><p>The examples are self-contained, cut and paste them in a file to play with them.</p></header><div class="odoc-tocs"><nav class="odoc-toc odoc-local-toc"><ul><li><a href="#exrm">A <code>rm</code> command</a></li><li><a href="#excp">A <code>cp</code> command</a></li><li><a href="#extail">A <code>tail</code> command</a></li><li><a href="#exdarcs">A <code>darcs</code> command</a></li></ul></nav></div><div class="odoc-content"><h2 id="exrm"><a href="#exrm" class="anchor"></a>A <code>rm</code> command</h2><p>We define the command line interface of an <code>rm</code> command with the synopsis:</p><pre>rm [OPTION]… FILE…</pre><p>The <code>-f</code>, <code>-i</code> and <code>-I</code> flags define the prompt behaviour of <code>rm</code>. It is represented in our program by the <code>prompt</code> type. If more than one of these flags is present on the command line the last one takes precedence.</p><p>To implement this behaviour we map the presence of these flags to values of the <code>prompt</code> type by using <a href="Cmdliner/Arg/index.html#val-vflag_all"><code>Cmdliner.Arg.vflag_all</code></a>.</p><p>This argument will contain all occurrences of the flag on the command line and we just take the <a href="Cmdliner/Arg/index.html#val-last"><code>Cmdliner.Arg.last</code></a> one to define our term value. If there is no occurrence the last value of the default list <code>[Always]</code> is taken. This means the default prompt behaviour is <code>Always</code>.</p><pre class="language-ocaml"><code>(* Implementation of the command, we just print the args. *)
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>examples (cmdliner.examples)</title><meta charset="utf-8"/><link rel="stylesheet" href="../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="index.html">Up</a> – <a href="../index.html">Index</a> » <a href="index.html">cmdliner</a> » examples</nav><header class="odoc-preamble"><h1 id="examples"><a href="#examples" class="anchor"></a>Examples</h1><p>The examples are self-contained, cut and paste them in a file to play with them. See also the suggested <a href="cookbook.html#tip_src_structure" title="tip_src_structure">source code structure</a> and program <a href="cookbook.html#blueprints" title="blueprints">blueprints</a>.</p></header><div class="odoc-tocs"><nav class="odoc-toc odoc-local-toc"><ul><li><a href="#example_rm">A <code>rm</code> command</a></li><li><a href="#example_cp">A <code>cp</code> command</a></li><li><a href="#example_tail">A <code>tail</code> command</a></li><li><a href="#example_darcs">A <code>darcs</code> command</a></li></ul></nav></div><div class="odoc-content"><h2 id="example_rm"><a href="#example_rm" class="anchor"></a>A <code>rm</code> command</h2><p>We define the command line interface of an <code>rm</code> command with the synopsis:</p><pre>rm [OPTION]… FILE…</pre><p>The <code>-f</code>, <code>-i</code> and <code>-I</code> flags define the prompt behaviour of <code>rm</code>. It is represented in our program by the <code>prompt</code> type. If more than one of these flags is present on the command line the last one takes precedence.</p><p>To implement this behaviour we map the presence of these flags to values of the <code>prompt</code> type by using <a href="Cmdliner/Arg/index.html#val-vflag_all"><code>Cmdliner.Arg.vflag_all</code></a>.</p><p>This argument will contain all occurrences of the flag on the command line and we just take the <a href="Cmdliner/Arg/index.html#val-last"><code>Cmdliner.Arg.last</code></a> one to define our term value. If there is no occurrence the last value of the default list <code>[Always]</code> is taken. This means the default prompt behaviour is <code>Always</code>.</p><pre class="language-ocaml"><code>(* Implementation of the command, we just print the args. *)
|
||||
|
||||
type prompt = Always | Once | Never
|
||||
let prompt_str = function
|
||||
| Always -> "always" | Once -> "once" | Never -> "never"
|
||||
|
||||
let rm prompt recurse files =
|
||||
let rm ~prompt ~recurse files =
|
||||
Printf.printf "prompt = %s\nrecurse = %B\nfiles = %s\n"
|
||||
(prompt_str prompt) recurse (String.concat ", " files)
|
||||
|
||||
(* Command line interface *)
|
||||
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
let files = Arg.(non_empty & pos_all file [] & info [] ~docv:"FILE")
|
||||
let prompt =
|
||||
|
|
@ -36,29 +37,30 @@ let recursive =
|
|||
let doc = "Remove directories and their contents recursively." in
|
||||
Arg.(value & flag & info ["r"; "R"; "recursive"] ~doc)
|
||||
|
||||
let cmd =
|
||||
let rm_cmd =
|
||||
let doc = "Remove files or directories" in
|
||||
let man = [
|
||||
`S Manpage.s_description;
|
||||
`P "$(tname) removes each specified $(i,FILE). By default it does not
|
||||
`P "$(cmd) removes each specified $(i,FILE). By default it does not
|
||||
remove directories, to also remove them and their contents, use the
|
||||
option $(b,--recursive) ($(b,-r) or $(b,-R)).";
|
||||
`P "To remove a file whose name starts with a $(b,-), for example
|
||||
$(b,-foo), use one of these commands:";
|
||||
`Pre "$(mname) $(b,-- -foo)"; `Noblank;
|
||||
`Pre "$(mname) $(b,./-foo)";
|
||||
`P "$(tname) removes symbolic links, not the files referenced by the
|
||||
`Pre "$(cmd) $(b,-- -foo)"; `Noblank;
|
||||
`Pre "$(cmd) $(b,./-foo)";
|
||||
`P "$(cmd.name) removes symbolic links, not the files referenced by the
|
||||
links.";
|
||||
`S Manpage.s_bugs; `P "Report bugs to <bugs@example.org>.";
|
||||
`S Manpage.s_see_also; `P "$(b,rmdir)(1), $(b,unlink)(2)" ]
|
||||
in
|
||||
let info = Cmd.info "rm" ~version:"v1.3.0" ~doc ~man in
|
||||
Cmd.v info Term.(const rm $ prompt $ recursive $ files)
|
||||
Cmd.make (Cmd.info "rm" ~version:"v2.0.0" ~doc ~man) @@
|
||||
let+ prompt and+ recursive and+ files in
|
||||
rm ~prompt ~recurse:recursive files
|
||||
|
||||
let main () = exit (Cmd.eval cmd)
|
||||
let () = main ()</code></pre><h2 id="excp"><a href="#excp" class="anchor"></a>A <code>cp</code> command</h2><p>We define the command line interface of a <code>cp</code> command with the synopsis:</p><pre>cp [OPTION]… SOURCE… DEST</pre><p>The <code>DEST</code> argument must be a directory if there is more than one <code>SOURCE</code>. This constraint is too complex to be expressed by the combinators of <a href="Cmdliner/Arg/index.html"><code>Cmdliner.Arg</code></a>.</p><p>Hence we just give <code>DEST</code> the <a href="Cmdliner/Arg/index.html#val-string"><code>Cmdliner.Arg.string</code></a> type and verify the constraint at the beginning of the implementation of <code>cp</code>. If the constraint is unsatisfied we return an <code>`Error</code> result. By using <a href="Cmdliner/Term/index.html#val-ret"><code>Cmdliner.Term.ret</code></a> on the lifted result <code>cp_t</code> of <code>cp</code>, <code>Cmdliner</code> handles the error reporting.</p><pre class="language-ocaml"><code>(* Implementation, we check the dest argument and print the args *)
|
||||
let main () = Cmd.eval rm_cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())</code></pre><h2 id="example_cp"><a href="#example_cp" class="anchor"></a>A <code>cp</code> command</h2><p>We define the command line interface of a <code>cp</code> command with the synopsis:</p><pre>cp [OPTION]… SOURCE… DEST</pre><p>The <code>DEST</code> argument must be a directory if there is more than one <code>SOURCE</code>. This constraint is too complex to be expressed by the combinators of <a href="Cmdliner/Arg/index.html"><code>Cmdliner.Arg</code></a>.</p><p>Hence we just give <code>DEST</code> the <a href="Cmdliner/Arg/index.html#val-string"><code>Cmdliner.Arg.string</code></a> type and verify the constraint at the beginning of the implementation of <code>cp</code>. If the constraint is unsatisfied we return an <code>`Error</code> result. By using <a href="Cmdliner/Term/index.html#val-ret"><code>Cmdliner.Term.ret</code></a> on the command's term for <code>cp</code>, <code>Cmdliner</code> handles the error reporting.</p><pre class="language-ocaml"><code>(* Implementation, we check the dest argument and print the args *)
|
||||
|
||||
let cp verbose recurse force srcs dest =
|
||||
let cp ~verbose ~recurse ~force srcs dest =
|
||||
let many = List.length srcs > 1 in
|
||||
if many && (not (Sys.file_exists dest) || not (Sys.is_directory dest))
|
||||
then `Error (false, dest ^ ": not a directory") else
|
||||
|
|
@ -69,6 +71,7 @@ let cp verbose recurse force srcs dest =
|
|||
(* Command line interface *)
|
||||
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
let verbose =
|
||||
let doc = "Print file names as they are copied." in
|
||||
|
|
@ -92,21 +95,22 @@ let dest =
|
|||
let docv = "DEST" in
|
||||
Arg.(required & pos ~rev:true 0 (some string) None & info [] ~docv ~doc)
|
||||
|
||||
let cmd =
|
||||
let cp_cmd =
|
||||
let doc = "Copy files" in
|
||||
let man_xrefs =
|
||||
[ `Tool "mv"; `Tool "scp"; `Page ("umask", 2); `Page ("symlink", 7) ]
|
||||
[`Tool "mv"; `Tool "scp"; `Page ("umask", 2); `Page ("symlink", 7)]
|
||||
in
|
||||
let man =
|
||||
[ `S Manpage.s_bugs;
|
||||
`P "Email them to <bugs@example.org>."; ]
|
||||
let man = [
|
||||
`S Manpage.s_bugs;
|
||||
`P "Email them to <bugs@example.org>."; ]
|
||||
in
|
||||
let info = Cmd.info "cp" ~version:"v1.3.0" ~doc ~man ~man_xrefs in
|
||||
Cmd.v info Term.(ret (const cp $ verbose $ recurse $ force $ srcs $ dest))
|
||||
Cmd.make (Cmd.info "cp" ~version:"v2.0.0" ~doc ~man ~man_xrefs) @@
|
||||
Term.ret @@
|
||||
let+ verbose and+ recurse and+ force and+ srcs and+ dest in
|
||||
cp ~verbose ~recurse ~force srcs dest
|
||||
|
||||
|
||||
let main () = exit (Cmd.eval cmd)
|
||||
let () = main ()</code></pre><h2 id="extail"><a href="#extail" class="anchor"></a>A <code>tail</code> command</h2><p>We define the command line interface of a <code>tail</code> command with the synopsis:</p><pre>tail [OPTION]… [FILE]…</pre><p>The <code>--lines</code> option whose value specifies the number of last lines to print has a special syntax where a <code>+</code> prefix indicates to start printing from that line number. In the program this is represented by the <code>loc</code> type. We define a custom <code>loc_arg</code> <a href="Cmdliner/Arg/index.html#type-conv" title="Cmdliner.Arg.conv">argument converter</a> for this option.</p><p>The <code>--follow</code> option has an optional enumerated value. The argument converter <code>follow</code>, created with <a href="Cmdliner/Arg/index.html#val-enum"><code>Cmdliner.Arg.enum</code></a> parses the option value into the enumeration. By using <a href="Cmdliner/Arg/index.html#val-some"><code>Cmdliner.Arg.some</code></a> and the <code>~vopt</code> argument of <a href="Cmdliner/Arg/index.html#val-opt"><code>Cmdliner.Arg.opt</code></a>, the term corresponding to the option <code>--follow</code> evaluates to <code>None</code> if <code>--follow</code> is absent from the command line, to <code>Some Descriptor</code> if present but without a value and to <code>Some v</code> if present with a value <code>v</code> specified.</p><pre class="language-ocaml"><code>(* Implementation of the command, we just print the args. *)
|
||||
let main () = Cmd.eval cp_cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())</code></pre><h2 id="example_tail"><a href="#example_tail" class="anchor"></a>A <code>tail</code> command</h2><p>We define the command line interface of a <code>tail</code> command with the synopsis:</p><pre>tail [OPTION]… [FILE]…</pre><p>The <code>--lines</code> option whose value specifies the number of last lines to print has a special syntax where a <code>+</code> prefix indicates to start printing from that line number. In the program this is represented by the <code>loc</code> type. We define a custom <code>loc_arg</code> <a href="Cmdliner/Arg/index.html#type-conv" title="Cmdliner.Arg.conv">argument converter</a> for this option.</p><p>The <code>--follow</code> option has an optional enumerated value. The argument converter <code>follow</code>, created with <a href="Cmdliner/Arg/index.html#val-enum"><code>Cmdliner.Arg.enum</code></a> parses the option value into the enumeration. By using <a href="Cmdliner/Arg/index.html#val-some"><code>Cmdliner.Arg.some</code></a> and the <code>~vopt</code> argument of <a href="Cmdliner/Arg/index.html#val-opt"><code>Cmdliner.Arg.opt</code></a>, the term corresponding to the option <code>--follow</code> evaluates to <code>None</code> if <code>--follow</code> is absent from the command line, to <code>Some Descriptor</code> if present but without a value and to <code>Some v</code> if present with a value <code>v</code> specified.</p><pre class="language-ocaml"><code>(* Implementation of the command, we just print the args. *)
|
||||
|
||||
type loc = bool * int
|
||||
type verb = Verbose | Quiet
|
||||
|
|
@ -118,7 +122,7 @@ let loc_str (rev, k) = if rev then str "%d" k else str "+%d"
|
|||
let follow_str = function Name -> "name" | Descriptor -> "descriptor"
|
||||
let verb_str = function Verbose -> "verbose" | Quiet -> "quiet"
|
||||
|
||||
let tail lines follow verb pid files =
|
||||
let tail ~lines ~follow ~verb ~pid files =
|
||||
Printf.printf
|
||||
"lines = %s\nfollow = %s\nverb = %s\npid = %s\nfiles = %s\n"
|
||||
(loc_str lines) (opt_str follow_str follow) (verb_str verb)
|
||||
|
|
@ -127,17 +131,18 @@ let tail lines follow verb pid files =
|
|||
(* Command line interface *)
|
||||
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
let loc_arg =
|
||||
let parse s =
|
||||
let parser s =
|
||||
try
|
||||
if s <> "" && s.[0] <> '+'
|
||||
then Ok (true, int_of_string s)
|
||||
else Ok (false, int_of_string (String.sub s 1 (String.length s - 1)))
|
||||
with Failure _ -> Error (`Msg "unable to parse integer")
|
||||
with Failure _ -> Error "unable to parse integer"
|
||||
in
|
||||
let print ppf p = Format.fprintf ppf "%s" (loc_str p) in
|
||||
Arg.conv ~docv:"N" (parse, print)
|
||||
let pp ppf p = Format.fprintf ppf "%s" (loc_str p) in
|
||||
Arg.Conv.make ~docv:"N" ~parser ~pp ()
|
||||
|
||||
let lines =
|
||||
let doc = "Output the last $(docv) lines or use $(i,+)$(docv) to start \
|
||||
|
|
@ -171,24 +176,24 @@ let pid =
|
|||
|
||||
let files = Arg.(value & (pos_all non_dir_file []) & info [] ~docv:"FILE")
|
||||
|
||||
let cmd =
|
||||
let tail_cmd =
|
||||
let doc = "Display the last part of a file" in
|
||||
let man = [
|
||||
`S Manpage.s_description;
|
||||
`P "$(tname) prints the last lines of each $(i,FILE) to standard output. If
|
||||
no file is specified reads standard input. The number of printed
|
||||
`P "$(cmd) prints the last lines of each $(i,FILE) to standard output.
|
||||
If no file is specified reads standard input. The number of printed
|
||||
lines can be specified with the $(b,-n) option.";
|
||||
`S Manpage.s_bugs;
|
||||
`P "Report them to <bugs@example.org>.";
|
||||
`S Manpage.s_see_also;
|
||||
`P "$(b,cat)(1), $(b,head)(1)" ]
|
||||
in
|
||||
let info = Cmd.info "tail" ~version:"v1.3.0" ~doc ~man in
|
||||
Cmd.v info Term.(const tail $ lines $ follow $ verb $ pid $ files)
|
||||
Cmd.make (Cmd.info "tail" ~version:"v2.0.0" ~doc ~man) @@
|
||||
let+ lines and+ follow and+ verb and+ pid and+ files in
|
||||
tail ~lines ~follow ~verb ~pid files
|
||||
|
||||
|
||||
let main () = exit (Cmd.eval cmd)
|
||||
let () = main ()</code></pre><h2 id="exdarcs"><a href="#exdarcs" class="anchor"></a>A <code>darcs</code> command</h2><p>We define the command line interface of a <code>darcs</code> command with the synopsis:</p><pre>darcs [COMMAND] …</pre><p>The <code>--debug</code>, <code>-q</code>, <code>-v</code> and <code>--prehook</code> options are available in each command. To avoid having to pass them individually to each command we gather them in a record of type <code>copts</code>. By lifting the record constructor <code>copts</code> into the term <code>copts_t</code> we now have a term that we can pass to the commands to stand for an argument of type <code>copts</code>. These options are documented in a section called <code>COMMON OPTIONS</code>, since we also want to put <code>--help</code> and <code>--version</code> in this section, the term information of commands makes a judicious use of the <code>sdocs</code> parameter of <a href="Cmdliner/Term/index.html#val-info"><code>Cmdliner.Term.info</code></a>.</p><p>The <code>help</code> command shows help about commands or other topics. The help shown for commands is generated by <code>Cmdliner</code> by making an appropriate use of <a href="Cmdliner/Term/index.html#val-ret"><code>Cmdliner.Term.ret</code></a> on the lifted <code>help</code> function.</p><p>If the program is invoked without a command we just want to show the help of the program as printed by <code>Cmdliner</code> with <code>--help</code>. This is done by the <code>default_cmd</code> term.</p><pre class="language-ocaml"><code>(* Implementations, just print the args. *)
|
||||
let main () = Cmd.eval tail_cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())</code></pre><h2 id="example_darcs"><a href="#example_darcs" class="anchor"></a>A <code>darcs</code> command</h2><p>We define the command line interface of a <code>darcs</code> command with the synopsis:</p><pre>darcs [COMMAND] …</pre><p>The <code>--debug</code>, <code>-q</code>, <code>-v</code> and <code>--prehook</code> options are available in each command. To avoid having to pass them individually to each command we gather them in a record of type <code>copts</code>. By lifting the record constructor <code>copts</code> into the term <code>copts_t</code> we now have a term that we can pass to the commands to stand for an argument of type <code>copts</code>. These options are documented in the section <a href="Cmdliner/Manpage/index.html#val-s_common_options"><code>Cmdliner.Manpage.s_common_options</code></a>.</p><p>The <code>help</code> command shows help about commands or other topics. The help shown for commands is generated by <code>Cmdliner</code> by making an appropriate use of <a href="Cmdliner/Term/index.html#val-ret"><code>Cmdliner.Term.ret</code></a> on the lifted <code>help</code> function.</p><p>If the program is invoked without a command we just want to show the help of the program as printed by <code>Cmdliner</code> with <code>--help</code>. This is done by the <code>default</code> term.</p><pre class="language-ocaml"><code>(* Implementations, just print the args. *)
|
||||
|
||||
type verb = Normal | Quiet | Verbose
|
||||
type copts = { debug : bool; verb : verb; prehook : string option }
|
||||
|
|
@ -215,16 +220,18 @@ let help copts man_format cmds topic = match topic with
|
|||
| None -> `Help (`Pager, None) (* help about the program. *)
|
||||
| Some topic ->
|
||||
let topics = "topics" :: "patterns" :: "environment" :: cmds in
|
||||
let conv, _ = Cmdliner.Arg.enum (List.rev_map (fun s -> (s, s)) topics) in
|
||||
match conv topic with
|
||||
| `Error e -> `Error (false, e)
|
||||
| `Ok t when t = "topics" -> List.iter print_endline topics; `Ok ()
|
||||
| `Ok t when List.mem t cmds -> `Help (man_format, Some t)
|
||||
| `Ok t ->
|
||||
let conv = Cmdliner.Arg.enum (List.rev_map (fun s -> (s, s)) topics) in
|
||||
let parse = Cmdliner.Arg.Conv.parser conv in
|
||||
match parse topic with
|
||||
| Error e -> `Error (false, e)
|
||||
| Ok t when t = "topics" -> List.iter print_endline topics; `Ok ()
|
||||
| Ok t when List.mem t cmds -> `Help (man_format, Some t)
|
||||
| Ok t ->
|
||||
let page = (topic, 7, "", "", ""), [`S topic; `P "Say something";] in
|
||||
`Ok (Cmdliner.Manpage.print man_format Format.std_formatter page)
|
||||
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
(* Help sections common to all commands *)
|
||||
|
||||
|
|
@ -232,9 +239,9 @@ let help_secs = [
|
|||
`S Manpage.s_common_options;
|
||||
`P "These options are common to all commands.";
|
||||
`S "MORE HELP";
|
||||
`P "Use $(mname) $(i,COMMAND) --help for help on a single command.";`Noblank;
|
||||
`P "Use $(mname) $(b,help patterns) for help on patch matching."; `Noblank;
|
||||
`P "Use $(mname) $(b,help environment) for help on environment variables.";
|
||||
`P "Use $(tool) $(i,COMMAND) --help for help on a single command.";`Noblank;
|
||||
`P "Use $(tool) $(b,help patterns) for help on patch matching."; `Noblank;
|
||||
`P "Use $(tool) $(b,help environment) for help on environment variables.";
|
||||
`S Manpage.s_bugs; `P "Check bug reports at http://bugs.example.org.";]
|
||||
|
||||
(* Options common to all commands *)
|
||||
|
|
@ -254,7 +261,7 @@ let copts_t =
|
|||
Arg.(last & vflag_all [Normal] [quiet; verbose])
|
||||
in
|
||||
let prehook =
|
||||
let doc = "Specify command to run before this $(mname) command." in
|
||||
let doc = "Specify command to run before this $(tool) command." in
|
||||
Arg.(value & opt (some string) None & info ["prehook"] ~docs ~doc)
|
||||
in
|
||||
Term.(const copts $ debug $ verb $ prehook)
|
||||
|
|
@ -276,8 +283,9 @@ let initialize_cmd =
|
|||
existing files and subdirectories become …";
|
||||
`Blocks help_secs; ]
|
||||
in
|
||||
let info = Cmd.info "initialize" ~doc ~sdocs ~man in
|
||||
Cmd.v info Term.(const initialize $ copts_t $ repodir)
|
||||
Cmd.make (Cmd.info "initialize" ~doc ~sdocs ~man) @@
|
||||
let+ copts_t and+ repodir in
|
||||
initialize copts_t repodir
|
||||
|
||||
let record_cmd =
|
||||
let pname =
|
||||
|
|
@ -303,12 +311,12 @@ let record_cmd =
|
|||
let man =
|
||||
[`S Manpage.s_description;
|
||||
`P "Creates a patch from changes in the working tree. If you specify
|
||||
a set of files …";
|
||||
a set of files…";
|
||||
`Blocks help_secs; ]
|
||||
in
|
||||
let info = Cmd.info "record" ~doc ~sdocs ~man in
|
||||
Cmd.v info
|
||||
Term.(const record $ copts_t $ pname $ author $ all $ ask_deps $ files)
|
||||
Cmd.make (Cmd.info "record" ~doc ~sdocs ~man) @@
|
||||
let+ copts_t and+ pname and+ author and+ all and+ ask_deps and+ files in
|
||||
record copts_t pname author all ask_deps files
|
||||
|
||||
let help_cmd =
|
||||
let topic =
|
||||
|
|
@ -321,16 +329,18 @@ let help_cmd =
|
|||
`P "Prints help about darcs commands and other subjects…";
|
||||
`Blocks help_secs; ]
|
||||
in
|
||||
let info = Cmd.info "help" ~doc ~man in
|
||||
Cmd.v info
|
||||
Term.(ret (const help $ copts_t $ Arg.man_format $ Term.choice_names $
|
||||
topic))
|
||||
Cmd.make (Cmd.info "help" ~doc ~man) @@
|
||||
Term.ret @@
|
||||
let+ copts_t and+ man_format = Arg.man_format
|
||||
and+ choice_names = Term.choice_names and+ topic in
|
||||
help copts_t man_format choice_names topic
|
||||
|
||||
let main_cmd =
|
||||
let doc = "a revision control system" in
|
||||
let man = help_secs in
|
||||
let info = Cmd.info "darcs" ~version:"v1.3.0" ~doc ~sdocs ~man in
|
||||
let info = Cmd.info "darcs" ~version:"v2.0.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]
|
||||
|
||||
let () = exit (Cmd.eval main_cmd)</code></pre></div></body></html>
|
||||
let main () = Cmd.eval main_cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())</code></pre></div></body></html>
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>index (cmdliner.index)</title><meta charset="utf-8"/><link rel="stylesheet" href="../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../index.html">Index</a> » cmdliner</nav><header class="odoc-preamble"><h1 id="package-cmdliner"><a href="#package-cmdliner" class="anchor"></a>Package cmdliner <nav><a type="text/plain; charset=UTF-8" href="_doc-dir/CHANGES.md">changes</a> <a href="#package_info">more…</a></nav></h1><p><code>Cmdliner</code> provides a simple and compositional mechanism to convert command line arguments to OCaml values and pass them to your functions.</p><p>The library automatically handles syntax errors, help messages and UNIX man page generation. It supports programs with single or multiple commands (like <code>git</code>) and respect most of the <a href="http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html">POSIX</a> and <a href="http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html">GNU</a> conventions.</p></header><div class="odoc-tocs"><nav class="odoc-toc odoc-local-toc"><ul><li><a href="#manuals">Manuals</a></li><li><a href="#api">API</a></li><li><a href="#package_info">Package info</a></li></ul></nav></div><div class="odoc-content"><h2 id="manuals"><a href="#manuals" class="anchor"></a>Manuals</h2><p>The following manuals are available.</p><ul><li>The <a href="tutorial.html" title="tutorial">tutorial</a> gets you through the steps to write your first command line interface with Cmdliner.</li><li>The <a href="cli.html" title="cli">Command line interface manual</a> describes how command lines and environment variables are parsed by Cmdliner.</li><li><a href="tool_man.html" title="tool_man">Tool man pages</a> describes how Cmdliner generates man pages for your tools and how you can format them.</li><li>The <a href="examples.html" title="examples">examples page</a> has a few annoted examples that show to express the command line interface of a few classic tools with Cmdliner</li></ul><h2 id="api"><a href="#api" class="anchor"></a>API</h2><ul class="modules"><li><a href="Cmdliner/index.html"><code>Cmdliner</code></a> <span class="synopsis">Declarative definition of command line interfaces.</span></li></ul><h2 id="package_info"><a href="#package_info" class="anchor"></a>Package info</h2><table class="package info"><tr id="info-changes-files"><td><a href="#info-changes-files" aria-hidden="true" class="anchor"></a>changes-files</td><td><ul><li><a type="text/plain; charset=UTF-8" href="_doc-dir/CHANGES.md">CHANGES.md</a></li></ul></td></tr><tr id="info-license-files"><td><a href="#info-license-files" aria-hidden="true" class="anchor"></a>license-files</td><td><ul><li><a type="text/plain; charset=UTF-8" href="_doc-dir/LICENSE.md">LICENSE.md</a></li></ul></td></tr><tr id="info-readme-files"><td><a href="#info-readme-files" aria-hidden="true" class="anchor"></a>readme-files</td><td><ul><li><a type="text/plain; charset=UTF-8" href="_doc-dir/README.md">README.md</a></li></ul></td></tr></table></div></body></html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>index (cmdliner.index)</title><meta charset="utf-8"/><link rel="stylesheet" href="../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> – <a href="../index.html">Index</a> » cmdliner</nav><header class="odoc-preamble"><h1 id="package-cmdliner"><a href="#package-cmdliner" class="anchor"></a>Package cmdliner <nav><a type="text/plain; charset=UTF-8" href="_doc-dir/CHANGES.md">changes</a> <a href="#package_info">more…</a></nav></h1><p>Cmdliner provides a simple and compositional mechanism to convert command line arguments to OCaml values and pass them to your functions.</p><p>The library automatically handles command line completion, syntax errors, help messages and UNIX man page generation. It supports programs with single or multiple commands (like <code>git</code>) and respect most of the <a href="http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html">POSIX</a> and <a href="http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html">GNU</a> conventions.</p></header><div class="odoc-tocs"><nav class="odoc-toc odoc-local-toc"><ul><li><a href="#manuals">Manuals</a></li><li><a href="#library">Library <code>cmdliner</code></a></li><li><a href="#package_info">Package info</a></li></ul></nav></div><div class="odoc-content"><h2 id="manuals"><a href="#manuals" class="anchor"></a>Manuals</h2><p>The following manuals are available.</p><ul><li>The <a href="tutorial.html" title="tutorial">tutorial</a> makes you write your first command line interface with Cmdliner.</li><li>The <a href="cookbook.html" title="cookbook">cookbook</a> has a few off-the-shelf recipes, tips about <a href="cookbook.html#tip_src_structure" title="tip_src_structure">source code structure</a>, and <a href="cookbook.html#blueprints" title="blueprints">blueprints</a> to define your command lines with Cmdliner.</li><li>The <a href="cli.html" title="cli">command line interface manual</a> describes how command lines and environment variables are parsed by Cmdliner and how command line completion is performed. This can be communicated to the users of your tools.</li><li>The <a href="tool_man.html" title="tool_man">tool man page</a> manual describes how Cmdliner generates man pages for your tools and their commands and how you can format them.</li><li>The <a href="examples.html" title="examples">examples page</a> has examples of a some classic UNIX tools with their command line interface implemented by Cmdliner.</li></ul><h2 id="library"><a href="#library" class="anchor"></a>Library <code>cmdliner</code></h2><ul class="modules"><li><a href="Cmdliner/index.html"><code>Cmdliner</code></a> <span class="synopsis">Declarative definition of command line interfaces.</span></li></ul><ul class="modules"><li><a href="Cmdliner/Arg/index.html"><code>Cmdliner.Arg</code></a> <span class="synopsis">Terms for command line arguments.</span></li><li><a href="Cmdliner/Cmd/index.html"><code>Cmdliner.Cmd</code></a> <span class="synopsis">Commands.</span></li><li><a href="Cmdliner/Manpage/index.html"><code>Cmdliner.Manpage</code></a> <span class="synopsis">Man pages.</span></li><li><a href="Cmdliner/Term/index.html"><code>Cmdliner.Term</code></a> <span class="synopsis">Terms.</span></li></ul><h2 id="package_info"><a href="#package_info" class="anchor"></a>Package info</h2><table class="package info"><tr id="info-changes-files"><td><a href="#info-changes-files" aria-hidden="true" class="anchor"></a>changes-files</td><td><ul><li><a type="text/plain; charset=UTF-8" href="_doc-dir/CHANGES.md">CHANGES.md</a></li></ul></td></tr><tr id="info-license-files"><td><a href="#info-license-files" aria-hidden="true" class="anchor"></a>license-files</td><td><ul><li><a type="text/plain; charset=UTF-8" href="_doc-dir/LICENSE.md">LICENSE.md</a></li></ul></td></tr><tr id="info-readme-files"><td><a href="#info-readme-files" aria-hidden="true" class="anchor"></a>readme-files</td><td><ul><li><a type="text/plain; charset=UTF-8" href="_doc-dir/README.md">README.md</a></li></ul></td></tr></table></div></body></html>
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,27 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>tutorial (cmdliner.tutorial)</title><meta charset="utf-8"/><link rel="stylesheet" href="../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="index.html">Up</a> – <a href="../index.html">Index</a> » <a href="index.html">cmdliner</a> » tutorial</nav><header class="odoc-preamble"><h1 id="tutorial"><a href="#tutorial" class="anchor"></a>Tutorial</h1></header><div class="odoc-tocs"><nav class="odoc-toc odoc-local-toc"><ul><li><a href="#started">Getting started</a></li><li><a href="#subcommands">Sub commands</a></li></ul></nav></div><div class="odoc-content"><h2 id="started"><a href="#started" class="anchor"></a>Getting started</h2><p>With <code>Cmdliner</code> your tool's <code>main</code> function evaluates a command.</p><p>A command is a value of type <a href="Cmdliner/Cmd/index.html#type-t"><code>Cmdliner.Cmd.t</code></a> which gathers a command name and a term of type <a href="Cmdliner/Term/index.html#type-t"><code>Cmdliner.Term.t</code></a>. 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.</p><p>One way to create terms is by lifting regular OCaml values with <a href="Cmdliner/Term/index.html#val-const"><code>Cmdliner.Term.const</code></a>. Terms can be applied to terms evaluating to functional values with <a href="Cmdliner/Term/index.html#val-($)"><code>Cmdliner.Term.($)</code></a>.</p><p>For example, in a <code>revolt.ml</code> file, for the function:</p><pre class="language-ocaml"><code>let revolt () = print_endline "Revolt!"</code></pre><p>the term :</p><pre class="language-ocaml"><code>open Cmdliner
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>tutorial (cmdliner.tutorial)</title><meta charset="utf-8"/><link rel="stylesheet" href="../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="index.html">Up</a> – <a href="../index.html">Index</a> » <a href="index.html">cmdliner</a> » tutorial</nav><header class="odoc-preamble"><h1 id="tutorial"><a href="#tutorial" class="anchor"></a>Tutorial</h1><p>See also the <a href="cookbook.html" title="cookbook">cookbook</a>, <a href="cookbook.html#blueprints" title="blueprints">blueprints</a> and <a href="examples.html" title="examples">examples</a>.</p></header><div class="odoc-tocs"><nav class="odoc-toc odoc-local-toc"><ul><li><a href="#terms">Commands and terms</a></li><li><a href="#term_syntax">Term syntax</a></li><li><a href="#args_as_terms">Command line arguments as terms</a></li></ul></nav></div><div class="odoc-content"><h2 id="terms"><a href="#terms" class="anchor"></a>Commands and terms</h2><p>With <code>Cmdliner</code> your tool's <code>main</code> function evaluates a command.</p><p>A command is a value of type <a href="Cmdliner/Cmd/index.html#type-t"><code>Cmdliner.Cmd.t</code></a> which gathers a command name and a term of type <a href="Cmdliner/Term/index.html#type-t"><code>Cmdliner.Term.t</code></a>. A term represents both a command line syntax fragment and an expression to be evaluated that implements your tool. The type parameter of the term (and the command) indicates the type of the result of the evaluation.</p><p>One way to create terms is by lifting regular OCaml values with <a href="Cmdliner/Term/index.html#val-const"><code>Cmdliner.Term.const</code></a>. Terms can be applied to terms evaluating to functional values with <a href="Cmdliner/Term/index.html#val-app"><code>Cmdliner.Term.app</code></a>.</p><p>For example, in a <code>revolt.ml</code> file, for the function:</p><pre class="language-ocaml"><code>let revolt () = print_endline "Revolt!"</code></pre><p>the term :</p><pre class="language-ocaml"><code>open Cmdliner
|
||||
|
||||
let revolt_t = Term.(const revolt $ const ())</code></pre><p>is a term that evaluates to the result (and effect) of the <code>revolt</code> function. This term can be attached to a command:</p><pre class="language-ocaml"><code>let cmd = Cmd.v (Cmd.info "revolt") revolt_t</code></pre><p>and evaluated with <a href="Cmdliner/Cmd/index.html#val-eval"><code>Cmdliner.Cmd.eval</code></a>:</p><pre class="language-ocaml"><code>let () = exit (Cmd.eval cmd)</code></pre><p>This defines a command line tool named <code>"revolt"</code> (this name will be used in error reporting and documentation generation), without command line arguments, that just prints <code>"Revolt!"</code> on <code>stdout</code>.</p><pre class="language-ocaml"><code>> ocamlfind ocamlopt -linkpkg -package cmdliner -o revolt revolt.ml
|
||||
let revolt_term = Term.app (Term.const revolt) (Term.const ())</code></pre><p>is a term that evaluates to the result (and effect) of the <code>revolt</code> function. This term can be associated to a command:</p><pre class="language-ocaml"><code>let cmd_revolt = Cmd.make (Cmd.info "revolt") revolt_term</code></pre><p>and evaluated with <a href="Cmdliner/Cmd/index.html#val-eval"><code>Cmdliner.Cmd.eval</code></a>:</p><pre class="language-ocaml"><code>let main () = Cmd.eval cmd_revolt
|
||||
let () = if !Sys.interactive then () else exit (main ())</code></pre><p>This defines a command line tool named <code>"revolt"</code> (this name will be used in error reporting and documentation generation), without command line arguments, that just prints <code>"Revolt!"</code> on <code>stdout</code>.</p><pre class="language-sh"><code>> ocamlfind ocamlopt -linkpkg -package cmdliner -o revolt revolt.ml
|
||||
> ./revolt
|
||||
Revolt!</code></pre><p>The combinators in the <a href="Cmdliner/Arg/index.html"><code>Cmdliner.Arg</code></a> module allow to extract command line arguments as terms. These terms can then be applied to lifted OCaml functions to be evaluated.</p><p>Terms corresponding to command line argument data that are part of a term evaluation implicitly define a command line syntax. We show this on an concrete example.</p><p>In a <code>chorus.ml</code> file, consider the <code>chorus</code> function that prints repeatedly a given message :</p><pre class="language-ocaml"><code>let chorus count msg = for i = 1 to count do print_endline msg done</code></pre><p>we want to make it available from the command line with the synopsis:</p><pre class="language-ocaml"><code>chorus [-c COUNT | --count=COUNT] [MSG]</code></pre><p>where <code>COUNT</code> defaults to <code>10</code> and <code>MSG</code> defaults to <code>"Revolt!"</code>. We first define a term corresponding to the <code>--count</code> option:</p><pre class="language-ocaml"><code>let count =
|
||||
Revolt!</code></pre><h2 id="term_syntax"><a href="#term_syntax" class="anchor"></a>Term syntax</h2><p>There is a special syntax that uses OCaml's <a href="https://ocaml.org/manual/5.3/bindingops.html">binding operators</a> for writing terms which is less error prone when the number of arguments you want to give to your function grows. In particular it allows you to easily lift functions which have labels.</p><p>So in fact the program we have just shown above is usually rather written this way:</p><pre class="language-ocaml"><code>let revolt () = print_endline "Revolt!"
|
||||
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
let cmd_revolt =
|
||||
Cmd.make (Cmd.info "revolt") @@
|
||||
let+ () = Term.const () in
|
||||
revolt ()
|
||||
|
||||
let main () = Cmd.eval cmd_revolt
|
||||
let () = if !Sys.interactive then () else exit (main ())</code></pre><h2 id="args_as_terms"><a href="#args_as_terms" class="anchor"></a>Command line arguments as terms</h2><p>The combinators in the <a href="Cmdliner/Arg/index.html"><code>Cmdliner.Arg</code></a> module allow to extract command line arguments as terms. These terms can then be applied to lifted OCaml functions to be evaluated. A term that uses terms that correspond to command line argument implicitely defines a command line syntax fragment. We show this on an concrete example.</p><p>In a <code>chorus.ml</code> file, consider the <code>chorus</code> function that prints repeatedly a given message :</p><pre class="language-ocaml"><code>let chorus ~count msg = for i = 1 to count do print_endline msg done</code></pre><p>we want to make it available from the command line with the synopsis:</p><pre class="language-sh"><code>chorus [-c COUNT | --count=COUNT] [MSG]</code></pre><p>where <code>COUNT</code> defaults to <code>10</code> and <code>MSG</code> defaults to <code>"Revolt!"</code>. We first define a term corresponding to the <code>--count</code> option:</p><pre class="language-ocaml"><code>open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
let count =
|
||||
let doc = "Repeat the message $(docv) times." in
|
||||
Arg.(value & opt int 10 & info ["c"; "count"] ~docv:"COUNT" ~doc)</code></pre><p>This says that <code>count</code> is a term that evaluates to the value of an optional argument of type <code>int</code> that defaults to <code>10</code> if unspecified and whose option name is either <code>-c</code> or <code>--count</code>. The arguments <code>doc</code> and <code>docv</code> are used to generate the option's man page information.</p><p>The term for the positional argument <code>MSG</code> is:</p><pre class="language-ocaml"><code>let msg =
|
||||
Arg.(value & opt int 10 & info ["c"; "count"] ~doc ~docv:"COUNT")</code></pre><p>This says that <code>count</code> is a term that evaluates to the value of an optional argument of type <code>int</code> that defaults to <code>10</code> if unspecified and whose option name is either <code>-c</code> or <code>--count</code>. The arguments <code>doc</code> and <code>docv</code> are used to generate the option's man page information.</p><p>The term for the positional argument <code>MSG</code> is:</p><pre class="language-ocaml"><code>let msg =
|
||||
let env =
|
||||
let doc = "Overrides the default message to print." in
|
||||
Cmd.Env.info "CHORUS_MSG" ~doc
|
||||
in
|
||||
let doc = "The message to print." in
|
||||
Arg.(value & pos 0 string "Revolt!" & info [] ~env ~docv:"MSG" ~doc)</code></pre><p>which says that <code>msg</code> is a term whose value is the positional argument at index <code>0</code> of type <code>string</code> and defaults to <code>"Revolt!"</code> or the value of the environment variable <code>CHORUS_MSG</code> if the argument is unspecified on the command line. Here again <code>doc</code> and <code>docv</code> are used for the man page information.</p><p>The term for executing <code>chorus</code> with these command line arguments is :</p><pre class="language-ocaml"><code>let chorus_t = Term.(const chorus $ count $ msg)</code></pre><p>We are now ready to define the <code>main</code> function of our tool:</p><pre class="language-ocaml"><code>let cmd =
|
||||
let doc = "print a customizable message repeatedly" in
|
||||
Arg.(value & pos 0 string "Revolt!" & info [] ~env ~doc ~docv:"MSG")</code></pre><p>which says that <code>msg</code> is a term whose value is the positional argument at index <code>0</code> of type <code>string</code> and defaults to <code>"Revolt!"</code> or the value of the environment variable <code>CHORUS_MSG</code> if the argument is unspecified on the command line. Here again <code>doc</code> and <code>docv</code> are used for the man page information.</p><p>We can now define a term and command for invoking the <code>chorus</code> function using the <a href="#term_syntax" title="term_syntax">term syntax</a> and the obscure but handy <a href="https://ocaml.org/manual/5.2/bindingops.html#ss%3Aletops-punning">let-punning</a> OCaml notation. This also shows that the value <a href="Cmdliner/Cmd/index.html#val-info"><code>Cmdliner.Cmd.info</code></a> can be given more information about the term we execute which is notably used to to generate the tool's man page.</p><pre class="language-ocaml"><code>let chorus_cmd =
|
||||
let doc = "Print a customizable message repeatedly" in
|
||||
let man = [
|
||||
`S Manpage.s_bugs;
|
||||
`P "Email bug reports to <bugs@example.org>." ]
|
||||
in
|
||||
let info = Cmd.info "chorus" ~version:"%%VERSION%%" ~doc ~man in
|
||||
Cmd.v info chorus_t
|
||||
Cmd.make (Cmd.info "chorus" ~version:"v2.0.0" ~doc ~man) @@
|
||||
let+ count and+ msg in
|
||||
chorus ~count msg
|
||||
|
||||
let main () = exit (Cmd.eval cmd)
|
||||
let () = main ()</code></pre><p>The <code>info</code> value created with <a href="Cmdliner/Cmd/index.html#val-info"><code>Cmdliner.Cmd.info</code></a> gives more information about the term we execute and is used to generate the tool's man page. Since we provided a <code>~version</code> string, the tool will automatically respond to the <code>--version</code> option by printing this string.</p><p>A tool using <a href="Cmdliner/Cmd/index.html#val-eval"><code>Cmdliner.Cmd.eval</code></a> always responds to the <code>--help</code> option by showing the tool's man page generated using the information you provided with <a href="Cmdliner/Cmd/index.html#val-info"><code>Cmdliner.Cmd.info</code></a> and <a href="Cmdliner/Arg/index.html#val-info"><code>Cmdliner.Arg.info</code></a>. Here is the output generated by our example:</p><pre>> ocamlfind ocamlopt -linkpkg -package cmdliner -o chorus chorus.ml
|
||||
let main () = Cmd.eval chorus_cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())</code></pre><p>Since we provided a <code>~version</code> string, the tool will automatically respond to the <code>--version</code> option by printing this string.</p><p>Besides a tool using <a href="Cmdliner/Cmd/index.html#val-eval"><code>Cmdliner.Cmd.eval</code></a> always responds to the <code>--help</code> option by showing the tool's man page <a href="tool_man.html#manual" title="manual">generated</a> using the information you provided with <a href="Cmdliner/Cmd/index.html#val-info"><code>Cmdliner.Cmd.info</code></a> and <a href="Cmdliner/Arg/index.html#val-info"><code>Cmdliner.Arg.info</code></a>. Here is the manual generated by our example:</p><pre>> ocamlfind ocamlopt -linkpkg -package cmdliner -o chorus chorus.ml
|
||||
> ./chorus --help
|
||||
NAME
|
||||
chorus - Print a customizable message repeatedly
|
||||
|
|
@ -64,4 +80,4 @@ ENVIRONMENT
|
|||
Overrides the default message to print.
|
||||
|
||||
BUGS
|
||||
Email bug reports to <bugs@example.org>.</pre><p>If a pager is available, this output is written to a pager. This help is also available in plain text or in the <a href="http://www.gnu.org/software/groff/groff.html">groff</a> man page format by invoking the program with the option <code>--help=plain</code> or <code>--help=groff</code>.</p><p>For examples of more complex command line definitions look and run the <a href="examples.html" title="examples">examples</a>.</p><h2 id="subcommands"><a href="#subcommands" class="anchor"></a>Sub commands</h2><p><code>Cmdliner</code> also provides support for programs like <code>git</code> that have sub commands each with their own command line syntax and manual:</p><pre class="language-ocaml"><code>tool [COMMAND]… [OPTION]… ARG…</code></pre><p>These sub commands are defined by grouping them under a parent command via the <a href="Cmdliner/Cmd/index.html#val-group"><code>Cmdliner.Cmd.group</code></a> function.</p></div></body></html>
|
||||
Email bug reports to <bugs@example.org>.</pre><p>If a pager is available, this output is written to a pager. This help is also available in plain text or in the <a href="http://www.gnu.org/software/groff/groff.html">groff</a> man page format by invoking the program with the option <code>--help=plain</code> or <code>--help=groff</code>.</p><p>And with this you should master the basics of Cmdliner, for examples of more complex command line definitions consult the <a href="examples.html" title="examples">examples</a>. For more tips, off-the-shelf recipes and conventions have look at the <a href="cookbook.html" title="cookbook">cookbook</a>.</p></div></body></html>
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
<!DOCTYPE html>
|
||||
<html><head><meta charset="utf-8"><meta name="generator" content="odig v0.0.9"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" type="text/css" media="screen, print" href="_odoc-theme/odoc.css"><title>_opam</title></head><body class="odoc"><nav class="odoc-nav">🐫</nav><header class="odoc-preamble"><h1>OCaml package documentation</h1><p>Browse <a href="#by-name">by name</a>, <a href="#by-tag">by tag</a>, the <a href="ocaml/Stdlib/index.html#modules">standard library</a> and the <a href="https://ocaml.org/manual/">OCaml manual</a> (online, latest version).</p><p><small>Generated for <code>/home/runner/work/linol/linol/_opam/lib</code></small></p></header><nav class="odoc-toc"><ul><li><a href="ocaml/Stdlib/index.html#modules">OCaml standard library</a></li><li><a href="https://ocaml.org/manual/">OCaml manual</a></li><li><a href="#by-name">Packages by name</a></li><li><a href="#by-tag">Packages by tag</a></li></ul></nav><div class="odoc-content"><h2 id="by-name"><a href="#by-name" aria-hidden="true" class="anchor"></a>Packages by name</h2><div class="by-name"><nav><a href="#name-c">c</a><a href="#name-f">f</a><a href="#name-l">l</a><a href="#name-o">o</a><a href="#name-p">p</a><a href="#name-t">t</a><a href="#name-u">u</a><a href="#name-y">y</a></nav><h3 id="name-c"><a href="#name-c" aria-hidden="true" class="anchor"></a>c</h3><ol class="packages"><li id="package-cmdliner"><a href="#package-cmdliner" aria-hidden="true" class="anchor"></a><a href="cmdliner/index.html">cmdliner</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-f"><a href="#name-f" aria-hidden="true" class="anchor"></a>f</h3><ol class="packages"><li id="package-fmt"><a href="#package-fmt" aria-hidden="true" class="anchor"></a><a href="fmt/index.html">fmt</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-l"><a href="#name-l" aria-hidden="true" class="anchor"></a>l</h3><ol class="packages"><li id="package-linol"><a href="#package-linol" aria-hidden="true" class="anchor"></a><a href="linol/index.html">linol</a> <span class="version"></span> <span class="synopsis"></span></li><li id="package-linol-lwt"><a href="#package-linol-lwt" aria-hidden="true" class="anchor"></a><a href="linol-lwt/index.html">linol-lwt</a> <span class="version"></span> <span class="synopsis"></span></li><li id="package-logs"><a href="#package-logs" aria-hidden="true" class="anchor"></a><a href="logs/index.html">logs</a> <span class="version"></span> <span class="synopsis"></span></li><li id="package-lwt"><a href="#package-lwt" aria-hidden="true" class="anchor"></a><a href="lwt/index.html">lwt</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-o"><a href="#name-o" aria-hidden="true" class="anchor"></a>o</h3><ol class="packages"><li id="package-ocaml"><a href="#package-ocaml" aria-hidden="true" class="anchor"></a><a href="ocaml/index.html">ocaml</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-p"><a href="#name-p" aria-hidden="true" class="anchor"></a>p</h3><ol class="packages"><li id="package-ppx_yojson_conv_lib"><a href="#package-ppx_yojson_conv_lib" aria-hidden="true" class="anchor"></a><a href="ppx_yojson_conv_lib/index.html">ppx_yojson_conv_lib</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-t"><a href="#name-t" aria-hidden="true" class="anchor"></a>t</h3><ol class="packages"><li id="package-trace"><a href="#package-trace" aria-hidden="true" class="anchor"></a><a href="trace/index.html">trace</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-u"><a href="#name-u" aria-hidden="true" class="anchor"></a>u</h3><ol class="packages"><li id="package-uutf"><a href="#package-uutf" aria-hidden="true" class="anchor"></a><a href="uutf/index.html">uutf</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-y"><a href="#name-y" aria-hidden="true" class="anchor"></a>y</h3><ol class="packages"><li id="package-yojson"><a href="#package-yojson" aria-hidden="true" class="anchor"></a><a href="yojson/index.html">yojson</a> <span class="version"></span> <span class="synopsis"></span></li></ol></div><h2 id="by-tag"><a href="#by-tag" aria-hidden="true" class="anchor"></a>Packages by tag</h2><div class="by-tag"><nav><table></table></nav></div></div></body></html>
|
||||
<html><head><meta charset="utf-8"><meta name="generator" content="odig v0.1.0"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" type="text/css" media="screen, print" href="_odoc-theme/odoc.css"><title>_opam</title></head><body class="odoc"><nav class="odoc-nav">🐫</nav><header class="odoc-preamble"><h1>OCaml package documentation</h1><p>Browse <a href="#by-name">by name</a>, <a href="#by-tag">by tag</a>, the <a href="ocaml/index.html#library_stdlib">standard library</a> and the <a href="https://ocaml.org/manual/">OCaml manual</a> (online, latest version).</p><p><small>Generated for <code>/home/runner/work/linol/linol/_opam/lib</code></small></p></header><div class="odoc-tocs"><nav class="odoc-toc"><ul><li><a href="ocaml/index.html#library_stdlib">OCaml standard library</a></li><li><a href="https://ocaml.org/manual/">OCaml manual</a></li><li><a href="#by-name">Packages by name</a></li><li><a href="#by-tag">Packages by tag</a></li></ul></nav></div><div class="odoc-content"><h2 id="by-name"><a href="#by-name" aria-hidden="true" class="anchor"></a>Packages by name</h2><div class="by-name"><nav><a href="#name-c">c</a><a href="#name-f">f</a><a href="#name-l">l</a><a href="#name-o">o</a><a href="#name-p">p</a><a href="#name-t">t</a><a href="#name-u">u</a><a href="#name-y">y</a></nav><h3 id="name-c"><a href="#name-c" aria-hidden="true" class="anchor"></a>c</h3><ol class="packages"><li id="package-cmdliner"><a href="#package-cmdliner" aria-hidden="true" class="anchor"></a><a href="cmdliner/index.html">cmdliner</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-f"><a href="#name-f" aria-hidden="true" class="anchor"></a>f</h3><ol class="packages"><li id="package-fmt"><a href="#package-fmt" aria-hidden="true" class="anchor"></a><a href="fmt/index.html">fmt</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-l"><a href="#name-l" aria-hidden="true" class="anchor"></a>l</h3><ol class="packages"><li id="package-linol"><a href="#package-linol" aria-hidden="true" class="anchor"></a><a href="linol/index.html">linol</a> <span class="version"></span> <span class="synopsis"></span></li><li id="package-linol-lwt"><a href="#package-linol-lwt" aria-hidden="true" class="anchor"></a><a href="linol-lwt/index.html">linol-lwt</a> <span class="version"></span> <span class="synopsis"></span></li><li id="package-logs"><a href="#package-logs" aria-hidden="true" class="anchor"></a><a href="logs/index.html">logs</a> <span class="version"></span> <span class="synopsis"></span></li><li id="package-lwt"><a href="#package-lwt" aria-hidden="true" class="anchor"></a><a href="lwt/index.html">lwt</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-o"><a href="#name-o" aria-hidden="true" class="anchor"></a>o</h3><ol class="packages"><li id="package-ocaml"><a href="#package-ocaml" aria-hidden="true" class="anchor"></a><a href="ocaml/index.html">ocaml</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-p"><a href="#name-p" aria-hidden="true" class="anchor"></a>p</h3><ol class="packages"><li id="package-ppx_yojson_conv_lib"><a href="#package-ppx_yojson_conv_lib" aria-hidden="true" class="anchor"></a><a href="ppx_yojson_conv_lib/index.html">ppx_yojson_conv_lib</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-t"><a href="#name-t" aria-hidden="true" class="anchor"></a>t</h3><ol class="packages"><li id="package-trace"><a href="#package-trace" aria-hidden="true" class="anchor"></a><a href="trace/index.html">trace</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-u"><a href="#name-u" aria-hidden="true" class="anchor"></a>u</h3><ol class="packages"><li id="package-uutf"><a href="#package-uutf" aria-hidden="true" class="anchor"></a><a href="uutf/index.html">uutf</a> <span class="version"></span> <span class="synopsis"></span></li></ol><h3 id="name-y"><a href="#name-y" aria-hidden="true" class="anchor"></a>y</h3><ol class="packages"><li id="package-yojson"><a href="#package-yojson" aria-hidden="true" class="anchor"></a><a href="yojson/index.html">yojson</a> <span class="version"></span> <span class="synopsis"></span></li></ol></div><h2 id="by-tag"><a href="#by-tag" aria-hidden="true" class="anchor"></a>Packages by tag</h2><div class="by-tag"><nav><table></table></nav></div></div></body></html>
|
||||
|
|
@ -1,4 +1,9 @@
|
|||
|
||||
# 0.11
|
||||
|
||||
- breaking: the Eio library now needs the output channel to be paired with
|
||||
an `Eio.Mutex.t` to prevent race conditions (#58)
|
||||
|
||||
# 0.10
|
||||
|
||||
- use `git subtree` to vendor lsp+jsonrpc, so that they
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
|
||||
# 0.11
|
||||
|
||||
- breaking: the Eio library now needs the output channel to be paired with
|
||||
an `Eio.Mutex.t` to prevent race conditions (#58)
|
||||
|
||||
# 0.10
|
||||
|
||||
- use `git subtree` to vendor lsp+jsonrpc, so that they
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
Logs.warn (fun m -> m "Something bad may happen in the future.");
|
||||
if Logs.err_count () > 0 then 1 else 0
|
||||
|
||||
let setup_log style_renderer level =
|
||||
let setup_log ~style_renderer ~level =
|
||||
Fmt_tty.setup_std_outputs ?style_renderer ();
|
||||
Logs.set_level level;
|
||||
Logs.set_reporter (Logs_fmt.reporter ())
|
||||
|
|
@ -19,17 +19,20 @@ let setup_log style_renderer level =
|
|||
(* Command line interface *)
|
||||
|
||||
open Cmdliner
|
||||
open Cmdliner.Term.Syntax
|
||||
|
||||
let setup_log =
|
||||
let cmd =
|
||||
Cmd.make (Cmd.info "tool") @@
|
||||
let env = Cmd.Env.info "TOOL_VERBOSITY" in
|
||||
Term.(const setup_log $ Fmt_cli.style_renderer () $ Logs_cli.level ~env ())
|
||||
let+ style_renderer = Fmt_cli.style_renderer ()
|
||||
and+ level = Logs_cli.level ~env ()
|
||||
and+ msg =
|
||||
let doc = "The message to output." in
|
||||
Arg.(value & pos 0 string "Hello horrible world!" & info [] ~doc)
|
||||
in
|
||||
setup_log ~style_renderer ~level;
|
||||
hello msg
|
||||
|
||||
let msg =
|
||||
let doc = "The message to output." in
|
||||
Arg.(value & pos 0 string "Hello horrible world!" & info [] ~doc)
|
||||
|
||||
let main () =
|
||||
let cmd = Cmd.make (Cmd.info "tool") Term.(const hello $ setup_log $ msg) in
|
||||
Cmd.eval' cmd
|
||||
|
||||
let main () = Cmd.eval' cmd
|
||||
let () = if !Sys.interactive then () else exit (main ())</code></pre></div></body></html>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
v0.10.0 2025-11-04 Zagreb
|
||||
-------------------------
|
||||
|
||||
* Make log mutex immune to raising logging functions.
|
||||
Thanks to Nathan Taylor for the report and the repro (#57).
|
||||
|
||||
v0.9.0 2025-07-08 Zagreb
|
||||
------------------------
|
||||
|
||||
|
|
@ -11,7 +17,7 @@ v0.9.0 2025-07-08 Zagreb
|
|||
* `Logs.format_reporter` and `Logs_fmt.reporter` replace a few format
|
||||
strings and `^^` uses by direct calls to `Format` primitives.
|
||||
* Requires OCaml >= 4.14.
|
||||
* Use Format.pp_print_text instead of your own.
|
||||
* Use Format.pp_print_text instead of our own.
|
||||
* Export `logs` from each sub library.
|
||||
|
||||
v0.8.0 2025-03-10 La Forclaz (VS)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
{0 Logs {%html: <span class="version">v0.9.0</span>%}}
|
||||
{0 Logs {%html: <span class="version">v0.10.0</span>%}}
|
||||
|
||||
Logs provides a logging infrastructure.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,21 @@
|
|||
===== 5.9.1 =====
|
||||
|
||||
====== Packaging ======
|
||||
|
||||
* lwt_ppx is compatible with newer versions of ppxlib. (Patrick Ferris, Kate Deplaix, Sora Morimoto, #1033)
|
||||
|
||||
====== Other ======
|
||||
|
||||
* Misc repository maintenance. (Sora Morimoto)
|
||||
|
||||
* Misc typo. (Kaustubh Maske Patil, #1056)
|
||||
|
||||
===== 5.9.1 =====
|
||||
|
||||
====== Fixes ======
|
||||
|
||||
* META files now carry version information. (Hugo Heuzard, #1042, #1053)
|
||||
|
||||
===== 5.9.0 =====
|
||||
|
||||
====== Additions ======
|
||||
|
|
@ -14,6 +32,12 @@
|
|||
|
||||
* Misc repository maintenance. (Sora Morimoto, Shon Feder, #1037, #1035)
|
||||
|
||||
===== 5.8.1 =====
|
||||
|
||||
====== Fixes ======
|
||||
|
||||
* META files now carry version information. (Hugo Heuzard, #1042, #1053)
|
||||
|
||||
===== 5.8.0 =====
|
||||
|
||||
====== Improvements ======
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue