Source file cmdliner_info.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
module Exit = struct
type code = int
let ok = 0
let some_error = 123
let cli_error = 124
let internal_error = 125
type info =
{ codes : code * code;
doc : string;
docs : string; }
let info
?(docs = Cmdliner_manpage.s_exit_status) ?(doc = "undocumented") ?max min
=
let max = match max with None -> min | Some max -> max in
{ codes = (min, max); doc; docs }
let info_codes i = i.codes
let info_code i = fst i.codes
let info_doc i = i.doc
let info_docs i = i.docs
let info_order i0 i1 = compare i0.codes i1.codes
let defaults =
[ info ok ~doc:"on success.";
info some_error
~doc:"on indiscriminate errors reported on standard error.";
info cli_error ~doc:"on command line parsing errors.";
info internal_error ~doc:"on unexpected internal errors (bugs)."; ]
end
module Env = struct
type var = string
type info =
{ id : int;
deprecated : string option;
var : string;
doc : string;
docs : string; }
let info
?deprecated
?(docs = Cmdliner_manpage.s_environment) ?(doc = "See option $(opt).") var
=
{ id = Cmdliner_base.uid (); deprecated; var; doc; docs }
let info_deprecated i = i.deprecated
let info_var i = i.var
let info_doc i = i.doc
let info_docs i = i.docs
let info_compare i0 i1 = Int.compare i0.id i1.id
module Set = Set.Make (struct type t = info let compare = info_compare end)
end
module Arg = struct
type absence = Err | Val of string Lazy.t | Doc of string
type opt_kind = Flag | Opt | Opt_vopt of string
type pos_kind =
{ pos_rev : bool;
pos_start : int;
pos_len : int option }
let pos ~rev:pos_rev ~start:pos_start ~len:pos_len =
{ pos_rev; pos_start; pos_len}
let pos_rev p = p.pos_rev
let pos_start p = p.pos_start
let pos_len p = p.pos_len
type t =
{ id : int;
deprecated : string option;
absent : absence;
env : Env.info option;
doc : string;
docv : string;
docs : string;
pos : pos_kind;
opt_kind : opt_kind;
opt_names : string list;
opt_all : bool; }
let dumb_pos = pos ~rev:false ~start:(-1) ~len:None
let v ?deprecated ?(absent = "") ?docs ?(docv = "") ?(doc = "") ?env names =
let dash n = if String.length n = 1 then "-" ^ n else "--" ^ n in
let opt_names = List.map dash names in
let docs = match docs with
| Some s -> s
| None ->
match names with
| [] -> Cmdliner_manpage.s_arguments
| _ -> Cmdliner_manpage.s_options
in
{ id = Cmdliner_base.uid (); deprecated; absent = Doc absent;
env; doc; docv; docs; pos = dumb_pos; opt_kind = Flag; opt_names;
opt_all = false; }
let id a = a.id
let deprecated a = a.deprecated
let absent a = a.absent
let env a = a.env
let doc a = a.doc
let docv a = a.docv
let docs a = a.docs
let pos_kind a = a.pos
let opt_kind a = a.opt_kind
let opt_names a = a.opt_names
let opt_all a = a.opt_all
let opt_name_sample a =
let rec find = function
| [] -> List.hd a.opt_names
| n :: ns -> if (String.length n) > 2 then n else find ns
in
find a.opt_names
let make_req a = { a with absent = Err }
let make_all_opts a = { a with opt_all = true }
let make_opt ~absent ~kind:opt_kind a = { a with absent; opt_kind }
let make_opt_all ~absent ~kind:opt_kind a =
{ a with absent; opt_kind; opt_all = true }
let make_pos ~pos a = { a with pos }
let make_pos_abs ~absent ~pos a = { a with absent; pos }
let is_opt a = a.opt_names <> []
let is_pos a = a.opt_names = []
let is_req a = a.absent = Err
let pos_cli_order a0 a1 =
let c = compare (a0.pos.pos_rev) (a1.pos.pos_rev) in
if c <> 0 then c else
if a0.pos.pos_rev
then compare a1.pos.pos_start a0.pos.pos_start
else compare a0.pos.pos_start a1.pos.pos_start
let rev_pos_cli_order a0 a1 = pos_cli_order a1 a0
let compare a0 a1 = Int.compare a0.id a1.id
module Set = Set.Make (struct type nonrec t = t let compare = compare end)
end
module Cmd = struct
type t =
{ name : string;
version : string option;
deprecated : string option;
doc : string;
docs : string;
sdocs : string;
exits : Exit.info list;
envs : Env.info list;
man : Cmdliner_manpage.block list;
man_xrefs : Cmdliner_manpage.xref list;
args : Arg.Set.t;
has_args : bool;
children : t list; }
let v
?deprecated ?(man_xrefs = [`Main]) ?(man = []) ?(envs = [])
?(exits = Exit.defaults) ?(sdocs = Cmdliner_manpage.s_common_options)
?(docs = Cmdliner_manpage.s_commands) ?(doc = "") ?version name
=
{ name; version; deprecated; doc; docs; sdocs; exits;
envs; man; man_xrefs; args = Arg.Set.empty;
has_args = true; children = [] }
let name t = t.name
let version t = t.version
let deprecated t = t.deprecated
let doc t = t.doc
let docs t = t.docs
let stdopts_docs t = t.sdocs
let exits t = t.exits
let envs t = t.envs
let man t = t.man
let man_xrefs t = t.man_xrefs
let args t = t.args
let has_args t = t.has_args
let children t = t.children
let add_args t args = { t with args = Arg.Set.union args t.args }
let with_children cmd ~args ~children =
let has_args, args = match args with
| None -> false, cmd.args
| Some args -> true, Arg.Set.union args cmd.args
in
{ cmd with has_args; args; children }
end
module Eval = struct
type t =
{ cmd : Cmd.t;
parents : Cmd.t list;
env : string -> string option;
err_ppf : Format.formatter }
let v ~cmd ~parents ~env ~err_ppf = { cmd; parents; env; err_ppf }
let cmd e = e.cmd
let parents e = e.parents
let env_var e v = e.env v
let err_ppf e = e.err_ppf
let main e = match List.rev e.parents with [] -> e.cmd | m :: _ -> m
let with_cmd ei cmd = { ei with cmd }
end