This commit is contained in:
c-cube 2025-11-26 00:50:10 +00:00
parent 09bb1db5c8
commit 247371f990
47 changed files with 1921 additions and 379 deletions

View file

@ -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.
*/
*/

View file

@ -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.
*/
*/

File diff suppressed because one or more lines are too long

View 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> &#x00BB; <a href="../../../index.html">cmdliner</a> &#x00BB; <a href="../../index.html">Cmdliner</a> &#x00BB; <a href="../index.html">Arg</a> &#x00BB; 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">&#45;&gt;</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">&#45;&gt;</span></span> <span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</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">&#45;&gt;</span></span>
<span><span class="label">docv</span>:string <span class="arrow">&#45;&gt;</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">&#45;&gt;</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">&#45;&gt;</span></span>
<span>unit <span class="arrow">&#45;&gt;</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">&#45;&gt;</span></span>
<span><span class="optlabel">?docv</span>:string <span class="arrow">&#45;&gt;</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">&#45;&gt;</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">&#45;&gt;</span></span>
<span><span><span class="type-var">'a</span> <a href="#type-t">t</a></span> <span class="arrow">&#45;&gt;</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">&#45;&gt;</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">&#45;&gt;</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">&#45;&gt;</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">&#45;&gt;</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

View file

@ -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> &#x00BB; <a href="../../../index.html">cmdliner</a> &#x00BB; <a href="../../index.html">Cmdliner</a> &#x00BB; <a href="../index.html">Cmd</a> &#x00BB; 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">&#45;&gt;</span></span> <span><span class="optlabel">?docs</span>:string <span class="arrow">&#45;&gt;</span></span> <span><span class="optlabel">?doc</span>:string <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-var">var</a> <span class="arrow">&#45;&gt;</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>&quot;undocumented&quot;</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> &#x00BB; <a href="../../../index.html">cmdliner</a> &#x00BB; <a href="../../index.html">Cmdliner</a> &#x00BB; <a href="../index.html">Cmd</a> &#x00BB; 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">&#45;&gt;</span></span>
<span><span class="optlabel">?docs</span>:<a href="../../Manpage/index.html#type-section_name">Manpage.section_name</a> <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?doc</span>:string <span class="arrow">&#45;&gt;</span></span>
<span><a href="#type-var">var</a> <span class="arrow">&#45;&gt;</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>&quot;See option $(opt).&quot;</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">&#45;&gt;</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

View file

@ -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> &#x00BB; <a href="../../../index.html">cmdliner</a> &#x00BB; <a href="../../index.html">Cmdliner</a> &#x00BB; <a href="../index.html">Term</a> &#x00BB; 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">&#45;&gt;</span></span> <span><span>(<span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'b</span>)</span> <span class="arrow">&#45;&gt;</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">&#45;&gt;</span></span> <span><span><span class="type-var">'b</span> <a href="../index.html#type-t">t</a></span> <span class="arrow">&#45;&gt;</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> &#x00BB; <a href="../../../index.html">cmdliner</a> &#x00BB; <a href="../../index.html">Cmdliner</a> &#x00BB; <a href="../index.html">Term</a> &#x00BB; 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">&#45;&gt;</span></span> <span><span>(<span><span class="type-var">'a</span> <span class="arrow">&#45;&gt;</span></span> <span class="type-var">'b</span>)</span> <span class="arrow">&#45;&gt;</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">&#45;&gt;</span></span> <span><span><span class="type-var">'b</span> <a href="../index.html#type-t">t</a></span> <span class="arrow">&#45;&gt;</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

View file

@ -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> &#x00BB; <a href="../index.html">cmdliner</a> &#x00BB; 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> &#x00BB; <a href="../index.html">cmdliner</a> &#x00BB; 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>

View 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> &#x00BB; <a href="../index.html">cmdliner</a> &#x00BB; 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>

View 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> &#x00BB; <a href="../index.html">cmdliner</a> &#x00BB; 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>

View 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> &#x00BB; <a href="../index.html">cmdliner</a> &#x00BB; 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>

View 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> &#x00BB; <a href="../index.html">cmdliner</a> &#x00BB; 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>

View 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> &#x00BB; <a href="../index.html">cmdliner</a> &#x00BB; 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>

View 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> &#x00BB; <a href="../index.html">cmdliner</a> &#x00BB; 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>

View 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> &#x00BB; <a href="../index.html">cmdliner</a> &#x00BB; 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>

View 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> &#x00BB; <a href="../index.html">cmdliner</a> &#x00BB; 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>

View 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> &#x00BB; <a href="../index.html">cmdliner</a> &#x00BB; 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>

View 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> &#x00BB; <a href="../index.html">cmdliner</a> &#x00BB; 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>

View 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> &#x00BB; <a href="../index.html">cmdliner</a> &#x00BB; 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>

View 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> &#x00BB; <a href="../index.html">cmdliner</a> &#x00BB; 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
View 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
View file

36
cmdliner/_doc-dir/README.md Executable file → Normal file
View 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
View 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.

View 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
View 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
View 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
View 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
View 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

File diff suppressed because one or more lines are too long

View file

@ -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> &#x00BB; <a href="index.html">cmdliner</a> &#x00BB; 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> &#x00BB; <a href="index.html">cmdliner</a> &#x00BB; 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 -&gt; &quot;always&quot; | Once -&gt; &quot;once&quot; | Never -&gt; &quot;never&quot;
let rm prompt recurse files =
let rm ~prompt ~recurse files =
Printf.printf &quot;prompt = %s\nrecurse = %B\nfiles = %s\n&quot;
(prompt_str prompt) recurse (String.concat &quot;, &quot; files)
(* Command line interface *)
open Cmdliner
open Cmdliner.Term.Syntax
let files = Arg.(non_empty &amp; pos_all file [] &amp; info [] ~docv:&quot;FILE&quot;)
let prompt =
@ -36,29 +37,30 @@ let recursive =
let doc = &quot;Remove directories and their contents recursively.&quot; in
Arg.(value &amp; flag &amp; info [&quot;r&quot;; &quot;R&quot;; &quot;recursive&quot;] ~doc)
let cmd =
let rm_cmd =
let doc = &quot;Remove files or directories&quot; in
let man = [
`S Manpage.s_description;
`P &quot;$(tname) removes each specified $(i,FILE). By default it does not
`P &quot;$(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)).&quot;;
`P &quot;To remove a file whose name starts with a $(b,-), for example
$(b,-foo), use one of these commands:&quot;;
`Pre &quot;$(mname) $(b,-- -foo)&quot;; `Noblank;
`Pre &quot;$(mname) $(b,./-foo)&quot;;
`P &quot;$(tname) removes symbolic links, not the files referenced by the
`Pre &quot;$(cmd) $(b,-- -foo)&quot;; `Noblank;
`Pre &quot;$(cmd) $(b,./-foo)&quot;;
`P &quot;$(cmd.name) removes symbolic links, not the files referenced by the
links.&quot;;
`S Manpage.s_bugs; `P &quot;Report bugs to &lt;bugs@example.org&gt;.&quot;;
`S Manpage.s_see_also; `P &quot;$(b,rmdir)(1), $(b,unlink)(2)&quot; ]
in
let info = Cmd.info &quot;rm&quot; ~version:&quot;v1.3.0&quot; ~doc ~man in
Cmd.v info Term.(const rm $ prompt $ recursive $ files)
Cmd.make (Cmd.info &quot;rm&quot; ~version:&quot;v2.0.0&quot; ~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 &gt; 1 in
if many &amp;&amp; (not (Sys.file_exists dest) || not (Sys.is_directory dest))
then `Error (false, dest ^ &quot;: not a directory&quot;) 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 = &quot;Print file names as they are copied.&quot; in
@ -92,21 +95,22 @@ let dest =
let docv = &quot;DEST&quot; in
Arg.(required &amp; pos ~rev:true 0 (some string) None &amp; info [] ~docv ~doc)
let cmd =
let cp_cmd =
let doc = &quot;Copy files&quot; in
let man_xrefs =
[ `Tool &quot;mv&quot;; `Tool &quot;scp&quot;; `Page (&quot;umask&quot;, 2); `Page (&quot;symlink&quot;, 7) ]
[`Tool &quot;mv&quot;; `Tool &quot;scp&quot;; `Page (&quot;umask&quot;, 2); `Page (&quot;symlink&quot;, 7)]
in
let man =
[ `S Manpage.s_bugs;
`P &quot;Email them to &lt;bugs@example.org&gt;.&quot;; ]
let man = [
`S Manpage.s_bugs;
`P &quot;Email them to &lt;bugs@example.org&gt;.&quot;; ]
in
let info = Cmd.info &quot;cp&quot; ~version:&quot;v1.3.0&quot; ~doc ~man ~man_xrefs in
Cmd.v info Term.(ret (const cp $ verbose $ recurse $ force $ srcs $ dest))
Cmd.make (Cmd.info &quot;cp&quot; ~version:&quot;v2.0.0&quot; ~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 &quot;%d&quot; k else str &quot;+%d&quot;
let follow_str = function Name -&gt; &quot;name&quot; | Descriptor -&gt; &quot;descriptor&quot;
let verb_str = function Verbose -&gt; &quot;verbose&quot; | Quiet -&gt; &quot;quiet&quot;
let tail lines follow verb pid files =
let tail ~lines ~follow ~verb ~pid files =
Printf.printf
&quot;lines = %s\nfollow = %s\nverb = %s\npid = %s\nfiles = %s\n&quot;
(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 &lt;&gt; &quot;&quot; &amp;&amp; s.[0] &lt;&gt; '+'
then Ok (true, int_of_string s)
else Ok (false, int_of_string (String.sub s 1 (String.length s - 1)))
with Failure _ -&gt; Error (`Msg &quot;unable to parse integer&quot;)
with Failure _ -&gt; Error &quot;unable to parse integer&quot;
in
let print ppf p = Format.fprintf ppf &quot;%s&quot; (loc_str p) in
Arg.conv ~docv:&quot;N&quot; (parse, print)
let pp ppf p = Format.fprintf ppf &quot;%s&quot; (loc_str p) in
Arg.Conv.make ~docv:&quot;N&quot; ~parser ~pp ()
let lines =
let doc = &quot;Output the last $(docv) lines or use $(i,+)$(docv) to start \
@ -171,24 +176,24 @@ let pid =
let files = Arg.(value &amp; (pos_all non_dir_file []) &amp; info [] ~docv:&quot;FILE&quot;)
let cmd =
let tail_cmd =
let doc = &quot;Display the last part of a file&quot; in
let man = [
`S Manpage.s_description;
`P &quot;$(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 &quot;$(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.&quot;;
`S Manpage.s_bugs;
`P &quot;Report them to &lt;bugs@example.org&gt;.&quot;;
`S Manpage.s_see_also;
`P &quot;$(b,cat)(1), $(b,head)(1)&quot; ]
in
let info = Cmd.info &quot;tail&quot; ~version:&quot;v1.3.0&quot; ~doc ~man in
Cmd.v info Term.(const tail $ lines $ follow $ verb $ pid $ files)
Cmd.make (Cmd.info &quot;tail&quot; ~version:&quot;v2.0.0&quot; ~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 -&gt; `Help (`Pager, None) (* help about the program. *)
| Some topic -&gt;
let topics = &quot;topics&quot; :: &quot;patterns&quot; :: &quot;environment&quot; :: cmds in
let conv, _ = Cmdliner.Arg.enum (List.rev_map (fun s -&gt; (s, s)) topics) in
match conv topic with
| `Error e -&gt; `Error (false, e)
| `Ok t when t = &quot;topics&quot; -&gt; List.iter print_endline topics; `Ok ()
| `Ok t when List.mem t cmds -&gt; `Help (man_format, Some t)
| `Ok t -&gt;
let conv = Cmdliner.Arg.enum (List.rev_map (fun s -&gt; (s, s)) topics) in
let parse = Cmdliner.Arg.Conv.parser conv in
match parse topic with
| Error e -&gt; `Error (false, e)
| Ok t when t = &quot;topics&quot; -&gt; List.iter print_endline topics; `Ok ()
| Ok t when List.mem t cmds -&gt; `Help (man_format, Some t)
| Ok t -&gt;
let page = (topic, 7, &quot;&quot;, &quot;&quot;, &quot;&quot;), [`S topic; `P &quot;Say something&quot;;] 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 &quot;These options are common to all commands.&quot;;
`S &quot;MORE HELP&quot;;
`P &quot;Use $(mname) $(i,COMMAND) --help for help on a single command.&quot;;`Noblank;
`P &quot;Use $(mname) $(b,help patterns) for help on patch matching.&quot;; `Noblank;
`P &quot;Use $(mname) $(b,help environment) for help on environment variables.&quot;;
`P &quot;Use $(tool) $(i,COMMAND) --help for help on a single command.&quot;;`Noblank;
`P &quot;Use $(tool) $(b,help patterns) for help on patch matching.&quot;; `Noblank;
`P &quot;Use $(tool) $(b,help environment) for help on environment variables.&quot;;
`S Manpage.s_bugs; `P &quot;Check bug reports at http://bugs.example.org.&quot;;]
(* Options common to all commands *)
@ -254,7 +261,7 @@ let copts_t =
Arg.(last &amp; vflag_all [Normal] [quiet; verbose])
in
let prehook =
let doc = &quot;Specify command to run before this $(mname) command.&quot; in
let doc = &quot;Specify command to run before this $(tool) command.&quot; in
Arg.(value &amp; opt (some string) None &amp; info [&quot;prehook&quot;] ~docs ~doc)
in
Term.(const copts $ debug $ verb $ prehook)
@ -276,8 +283,9 @@ let initialize_cmd =
existing files and subdirectories become …&quot;;
`Blocks help_secs; ]
in
let info = Cmd.info &quot;initialize&quot; ~doc ~sdocs ~man in
Cmd.v info Term.(const initialize $ copts_t $ repodir)
Cmd.make (Cmd.info &quot;initialize&quot; ~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 &quot;Creates a patch from changes in the working tree. If you specify
a set of files &quot;;
a set of files…&quot;;
`Blocks help_secs; ]
in
let info = Cmd.info &quot;record&quot; ~doc ~sdocs ~man in
Cmd.v info
Term.(const record $ copts_t $ pname $ author $ all $ ask_deps $ files)
Cmd.make (Cmd.info &quot;record&quot; ~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 &quot;Prints help about darcs commands and other subjects…&quot;;
`Blocks help_secs; ]
in
let info = Cmd.info &quot;help&quot; ~doc ~man in
Cmd.v info
Term.(ret (const help $ copts_t $ Arg.man_format $ Term.choice_names $
topic))
Cmd.make (Cmd.info &quot;help&quot; ~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 = &quot;a revision control system&quot; in
let man = help_secs in
let info = Cmd.info &quot;darcs&quot; ~version:&quot;v1.3.0&quot; ~doc ~sdocs ~man in
let info = Cmd.info &quot;darcs&quot; ~version:&quot;v2.0.0&quot; ~doc ~sdocs ~man in
let default = Term.(ret (const (fun _ -&gt; `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>

View file

@ -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> &#x00BB; 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> &#x00BB; 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

View file

@ -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> &#x00BB; <a href="index.html">cmdliner</a> &#x00BB; 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 &quot;Revolt!&quot;</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> &#x00BB; <a href="index.html">cmdliner</a> &#x00BB; 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 &quot;Revolt!&quot;</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 &quot;revolt&quot;) 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>&quot;revolt&quot;</code> (this name will be used in error reporting and documentation generation), without command line arguments, that just prints <code>&quot;Revolt!&quot;</code> on <code>stdout</code>.</p><pre class="language-ocaml"><code>&gt; 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 &quot;revolt&quot;) 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>&quot;revolt&quot;</code> (this name will be used in error reporting and documentation generation), without command line arguments, that just prints <code>&quot;Revolt!&quot;</code> on <code>stdout</code>.</p><pre class="language-sh"><code>&gt; ocamlfind ocamlopt -linkpkg -package cmdliner -o revolt revolt.ml
&gt; ./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>&quot;Revolt!&quot;</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 &quot;Revolt!&quot;
open Cmdliner
open Cmdliner.Term.Syntax
let cmd_revolt =
Cmd.make (Cmd.info &quot;revolt&quot;) @@
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>&quot;Revolt!&quot;</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 = &quot;Repeat the message $(docv) times.&quot; in
Arg.(value &amp; opt int 10 &amp; info [&quot;c&quot;; &quot;count&quot;] ~docv:&quot;COUNT&quot; ~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 &amp; opt int 10 &amp; info [&quot;c&quot;; &quot;count&quot;] ~doc ~docv:&quot;COUNT&quot;)</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 = &quot;Overrides the default message to print.&quot; in
Cmd.Env.info &quot;CHORUS_MSG&quot; ~doc
in
let doc = &quot;The message to print.&quot; in
Arg.(value &amp; pos 0 string &quot;Revolt!&quot; &amp; info [] ~env ~docv:&quot;MSG&quot; ~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>&quot;Revolt!&quot;</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 = &quot;print a customizable message repeatedly&quot; in
Arg.(value &amp; pos 0 string &quot;Revolt!&quot; &amp; info [] ~env ~doc ~docv:&quot;MSG&quot;)</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>&quot;Revolt!&quot;</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 = &quot;Print a customizable message repeatedly&quot; in
let man = [
`S Manpage.s_bugs;
`P &quot;Email bug reports to &lt;bugs@example.org&gt;.&quot; ]
in
let info = Cmd.info &quot;chorus&quot; ~version:&quot;%%VERSION%%&quot; ~doc ~man in
Cmd.v info chorus_t
Cmd.make (Cmd.info &quot;chorus&quot; ~version:&quot;v2.0.0&quot; ~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>&gt; 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>&gt; ocamlfind ocamlopt -linkpkg -package cmdliner -o chorus chorus.ml
&gt; ./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 &lt;bugs@example.org&gt;.</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 &lt;bugs@example.org&gt;.</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>

View file

@ -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>

View file

@ -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

View file

@ -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

View file

@ -11,7 +11,7 @@
Logs.warn (fun m -&gt; m &quot;Something bad may happen in the future.&quot;);
if Logs.err_count () &gt; 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 &quot;tool&quot;) @@
let env = Cmd.Env.info &quot;TOOL_VERBOSITY&quot; 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 = &quot;The message to output.&quot; in
Arg.(value &amp; pos 0 string &quot;Hello horrible world!&quot; &amp; info [] ~doc)
in
setup_log ~style_renderer ~level;
hello msg
let msg =
let doc = &quot;The message to output.&quot; in
Arg.(value &amp; pos 0 string &quot;Hello horrible world!&quot; &amp; info [] ~doc)
let main () =
let cmd = Cmd.make (Cmd.info &quot;tool&quot;) 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>

View file

@ -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)

View file

@ -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.

View file

@ -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