···705705 Given an optional context determined from a partial command
706706 line parse and a token to complete it returns a list of
707707 completion directives or an error which is reported to
708708- end-users by using a protocol {!message}. *)
708708+ end-users by using a protocol {!message}.
709709+710710+ The context is [None] if no context was given to {!make} or if
711711+ the context failed to parse on the current command line. *)
709712710713 type 'a complete =
711714 | Complete : 'ctx Term.t option * ('ctx, 'a) func -> 'a complete (** *)
+129-103
vendor/opam/cmdliner/src/cmdliner_cline.ml
···2929 if not for_completion || not (has_complete_prefix s) then None else
3030 Some (get_token_to_complete s)
31313232-exception Completion_requested of Cmdliner_def.Complete.t
3333-3434-let comp_request ?after_dashdash cline ~token kind =
3535- let comp = Cmdliner_def.Complete.make ?after_dashdash cline ~token kind in
3636- raise (Completion_requested comp)
3737-3832(* Command lines *)
39334034let err_multi_opt_name_def name arg_info arg_info' =
···4438let arg_info_indexes arg_infos =
4539 (* from [args] returns a trie mapping the names of optional arguments to
4640 their arg_info, a list with all arg_info for positional arguments and
4747- a cmdline mapping each arg_info to an empty [arg]. *)
4141+ a Cmdliner_def.Cline.t mapping each arg_info to an empty [arg]. *)
4842 let rec loop optidx posidx cline = function
4943 | [] -> optidx, posidx, cline
5044 | arg_info :: l ->
···7367 option we could try to avoid mentioning names that have already be
7468 mentioned and that are not repeatable. Sometimes not being able to
7569 complete what we know exists ends up being more confusing than
7676- enlightening so we don't do that for now. *)
7070+ enlightening so we don't do that for now.
7171+7272+ Also the code is quite messy, perhaps we should cleanly separate
7373+ parsing for completion and parsing for evaluation. *)
77747875let is_opt s = String.length s > 1 && s.[0] = '-'
7976let is_short_opt s = String.length s = 2 && s.[0] = '-'
···111108 | true, l -> if List.mem short_opt l then l else short_opt :: l
112109113110let parse_opt_value ~for_completion cline arg_info name value args =
114114- (* Either we got a value glued in [value] or we need to get one in args *)
111111+ (* Either we got a value glued in [value] or we need to get one in [args]
112112+ in this case we need to take care of a possible completion token *)
115113 match Cmdliner_def.Arg_info.opt_kind arg_info with
116114 | Flag -> (* Flags have no values but we may get dash sharing in [value] *)
117115 begin match value with
118118- | None -> value, args
116116+ | None -> None, None, args
119117 | Some v when is_short_opt name -> (* short flag dash sharing *)
120120- None, ("-" ^ v) :: args
118118+ None, None, ("-" ^ v) :: args
121119 | Some _ -> (* an error but this is reported during typed parsing *)
122122- value, args
120120+ None, value, args
123121 end
124122 | _ ->
125123 match value with
126126- | Some _ -> value, args
124124+ | Some _ -> None, value, args
127125 | None -> (* Get it from the next argument. *)
128126 match args with
129129- | [] -> None, args
127127+ | [] -> None, None, args
130128 | v :: rest when for_completion && has_complete_prefix v ->
131129 let v = get_token_to_complete v in
132132- if is_opt v then (* not an option value *) None, args else
133133- comp_request cline ~token:v (Opt_value arg_info)
130130+ if is_opt v then (* not an option value *) None, None, args else
131131+ let comp =
132132+ Cmdliner_def.Complete.make ~token:v (Opt_value arg_info)
133133+ in
134134+ Some comp, None, rest
134135 | v :: rest ->
135135- if is_opt v then None, args else Some v, rest
136136+ if is_opt v then None, None, args else None, Some v, rest
136137137138let try_complete_opt_value cline arg_info name value args =
138139 (* At that point we found a matching option name so this should be mostly
···143144 | Some v when is_short_opt name ->
144145 (* short flag dash sharing, push the completion *)
145146 let args = (complete_prefix ^ "-" ^ v) :: args in
146146- None, args
147147+ None, None, args
147148 | Some v ->
148149 (* This is actually a parse error, flags have no value. We
149150 make it an option completion but the completions will
150151 eventually be empty (the prefix won't match) *)
151151- comp_request cline ~token:(name ^ v) Opt_name
152152+ Some (Cmdliner_def.Complete.make ~token:(name ^ v) Opt_name),
153153+ None, args
152154 | None ->
153155 (* We have in fact a fully completed flag turn it into an
154156 option completion. *)
155155- comp_request cline ~token:name Opt_name
157157+ Some (Cmdliner_def.Complete.make ~token:name Opt_name), None, args
156158 end
157159 | _ ->
158160 begin match value with
159159- | Some token -> comp_request cline ~token (Opt_value arg_info)
161161+ | Some token ->
162162+ Some (Cmdliner_def.Complete.make ~token (Opt_value arg_info)), None,
163163+ args
160164 | None ->
161165 (* We have a fully completed option name, we don't try to
162166 lookup what happens in the next argument which should
163167 hold the value if any, we just turn it into an option
164168 completion. *)
165165- comp_request cline ~token:name Opt_name
169169+ Some (Cmdliner_def.Complete.make ~token:name Opt_name), None, args
166170 end
167171168172let parse_opt_args
169173 ~peek_opts ~legacy_prefixes ~for_completion optidx cline args
170174 =
171171- (* returns an updated [cl] cmdline according to the options found in [args]
175175+ (* returns an updated [cline] cmdline according to the options found in [args]
172176 with the trie index [optidx]. Positional arguments are returned in order
173177 in a list. *)
174174- let rec loop errs k cline pargs = function
175175- | [] -> List.rev errs, cline, false, List.rev pargs
176176- | "--" :: args -> List.rev errs, cline, true, (List.rev_append pargs args)
178178+ let rec loop errs k comp cline pargs = function
179179+ | [] -> List.rev errs, comp, cline, false, List.rev pargs
180180+ | "--" :: args ->
181181+ List.rev errs, comp, cline, true, (List.rev_append pargs args)
177182 | s :: args ->
178183 let do_parse =
179184 is_opt s &&
···181186 if not (has_complete_prefix s) then true else
182187 is_opt_to_complete s)
183188 in
184184- if not do_parse then loop errs (k + 1) cline (s :: pargs) args else
189189+ if not do_parse then loop errs (k + 1) comp cline (s :: pargs) args else
185190 let name, value, is_completion = parse_opt_arg s in
186191 match Cmdliner_trie.find ~legacy_prefixes optidx name with
187192 | Ok arg_info ->
188188- let value, args =
193193+ let acomp, value, args =
189194 if is_completion
190195 then try_complete_opt_value cline arg_info name value args
191196 else parse_opt_value ~for_completion cline arg_info name value args
192197 in
198198+ let comp = match acomp with Some _ -> acomp | None -> comp in
193199 let arg : Cmdliner_def.Cline.arg =
194200 O ((k, name, value) ::
195201 Cmdliner_def.Cline.get_opt_arg cline arg_info)
196202 in
197203 let cline = Cmdliner_def.Cline.add arg_info arg cline in
198198- loop errs (k + 1) cline pargs args
204204+ loop errs (k + 1) comp cline pargs args
199205 | Error `Not_found when for_completion ->
200200- if not is_completion
201201- (* Drop the data, if the user thought this was an opt with
202202- an argument this may confuse positional args but there's
203203- not much we can do. *)
204204- then loop errs (k + 1) cline pargs args else
206206+ if not is_completion then
207207+ (* Drop the data, if the user thought this was an opt with
208208+ an argument this may confuse positional args but there's
209209+ not much we can do. *)
210210+ loop errs (k + 1) comp cline pargs args
211211+ else
205212 let token = name ^ Option.value ~default:"" value in
206206- comp_request cline ~token Opt_name
213213+ let comp = Some (Cmdliner_def.Complete.make ~token Opt_name) in
214214+ loop errs (k + 1) comp cline pargs args
207215 | Error `Not_found when peek_opts ->
208208- loop errs (k + 1) cline pargs args
216216+ loop errs (k + 1) comp cline pargs args
209217 | Error `Not_found ->
210218 let hints = hint_matching_opt optidx s in
211219 let err = Cmdliner_base.err_unknown ~kind:"option" ~hints name in
212212- loop (err :: errs) (k + 1) cline pargs args
220220+ loop (err :: errs) (k + 1) comp cline pargs args
213221 | Error `Ambiguous (* Only on legacy prefixes *) ->
214222 let ambs = Cmdliner_trie.ambiguities optidx name in
215223 let ambs = List.sort compare ambs in
216224 let err = Cmdliner_base.err_ambiguous ~kind:"option" name ~ambs in
217217- loop (err :: errs) (k + 1) cline pargs args
225225+ loop (err :: errs) (k + 1) comp cline pargs args
218226 in
219219- let errs, cline, has_dashdash, pargs = loop [] 0 cline [] args in
220220- if errs = [] then Ok (cline, has_dashdash, pargs) else
221221- let err = String.concat "\n" errs in
222222- Error (err, cline, has_dashdash, pargs)
227227+ let errs, comp, cline, has_dashdash, pargs = loop [] 0 None cline [] args in
228228+ if errs = [] then Ok (comp, cline, has_dashdash, pargs) else
229229+ match comp with
230230+ | Some _ -> Ok (comp, cline, has_dashdash, pargs)
231231+ | None ->
232232+ let err = String.concat "\n" errs in
233233+ Error (err, cline, has_dashdash, pargs)
234234+235235+(* Positional argument parsing *)
223236224237let take_range ~for_completion start stop l =
225225- let rec loop i acc = function
226226- | [] -> `Range (List.rev acc)
238238+ let rec loop i comp acc = function
239239+ | [] -> comp, (List.rev acc)
227240 | v :: vs ->
228228- if i < start then loop (i + 1) acc vs else
241241+ if i < start then loop (i + 1) comp acc vs else
229242 if i <= stop then match maybe_token_to_complete ~for_completion v with
230230- | Some prefix -> `Complete prefix
231231- | None -> loop (i + 1) (v :: acc) vs
232232- else `Range (List.rev acc)
243243+ | Some _ as comp -> loop (i + 1) comp (v :: acc) vs
244244+ | None -> loop (i + 1) comp (v :: acc) vs
245245+ else comp, List.rev acc
233246 in
234234- loop 0 [] l
247247+ loop 0 None [] l
235248236236-let process_pos_args ~for_completion posidx cline ~has_dashdash pargs =
237237- (* returns an updated [cl] cmdline in which each positional arg mentioned
238238- in the list index posidx, is given a value according the list
249249+let parse_pos_args ~for_completion posidx comp cline ~has_dashdash pargs =
250250+ (* returns an updated [cline] cmdline in which each positional arg mentioned
251251+ in the list index [posidx], is given a value according the list
239252 of positional arguments values [pargs]. *)
240253 if pargs = [] then
241254 let misses = List.filter Cmdliner_def.Arg_info.is_req posidx in
242242- if misses = [] then Ok cline else
243243- Error (Cmdliner_msg.err_pos_misses misses, cline)
255255+ if misses = [] then Ok (comp, cline) else
256256+ match comp with
257257+ | Some _ -> Ok (comp, cline)
258258+ | None -> Error (Cmdliner_msg.err_pos_misses misses, cline)
244259 else
245260 let last = List.length pargs - 1 in
246261 let pos rev k = if rev then last - k else k in
247247- let rec loop misses cline max_spec = function
248248- | [] -> misses, cline, max_spec
249249- | a :: al ->
250250- let apos = Cmdliner_def.Arg_info.pos_kind a in
262262+ let rec loop misses comp cline max_spec = function
263263+ | [] -> misses, comp, cline, max_spec
264264+ | arg_info :: al ->
265265+ let apos = Cmdliner_def.Arg_info.pos_kind arg_info in
251266 let rev = Cmdliner_def.Arg_info.pos_rev apos in
252267 let start = pos rev (Cmdliner_def.Arg_info.pos_start apos) in
253268 let stop = match Cmdliner_def.Arg_info.pos_len apos with
···255270 | Some n -> pos rev (Cmdliner_def.Arg_info.pos_start apos + n - 1)
256271 in
257272 let start, stop = if rev then stop, start else start, stop in
258258- let args = match take_range ~for_completion start stop pargs with
259259- | `Range args -> args
260260- | `Complete token ->
261261- let kind = Cmdliner_def.Complete.Opt_name_or_pos_value a in
262262- comp_request ~after_dashdash:has_dashdash cline ~token kind
273273+ let comp, args = match take_range ~for_completion start stop pargs with
274274+ | None, args -> comp, args
275275+ | Some token, args ->
276276+ let comp =
277277+ Cmdliner_def.Complete.make ~after_dashdash:has_dashdash ~token
278278+ (Opt_name_or_pos_value arg_info)
279279+ in
280280+ Some comp, args
263281 in
264282 let max_spec = max stop max_spec in
265265- let cline = Cmdliner_def.Cline.add a (P args) cline in
266266- let misses = match Cmdliner_def.Arg_info.is_req a && args = [] with
267267- | true -> a :: misses
283283+ let cline = Cmdliner_def.Cline.add arg_info (P args) cline in
284284+ let misses = match Cmdliner_def.Arg_info.is_req arg_info && args = [] with
285285+ | true -> arg_info :: misses
268286 | false -> misses
269287 in
270270- loop misses cline max_spec al
288288+ loop misses comp cline max_spec al
271289 in
272272- let misses, cline, max_spec = loop [] cline (-1) posidx in
273273- let consume_excess () =
274274- match take_range ~for_completion (max_spec + 1) last pargs with
275275- | `Range args -> args
276276- | `Complete token ->
277277- comp_request ~after_dashdash:has_dashdash cline ~token Opt_name
278278- in
290290+ let misses, comp, cline, max_spec = loop [] comp cline (-1) posidx in
279291 if misses <> [] then begin
280280- let _ : string list = consume_excess () in
292292+ if Option.is_some comp then Ok (comp, cline) else
281293 Error (Cmdliner_msg.err_pos_misses misses, cline)
282294 end else
283283- if last <= max_spec then Ok cline else
284284- Error (Cmdliner_msg.err_pos_excess (consume_excess ()), cline)
295295+ if last <= max_spec then Ok (comp, cline) else
296296+ if Option.is_some comp then Ok (comp, cline) else
297297+ let comp, excess = take_range ~for_completion (max_spec + 1) last pargs in
298298+ match comp with
299299+ | None -> Error (Cmdliner_msg.err_pos_excess excess, cline)
300300+ | Some token ->
301301+ let comp =
302302+ Cmdliner_def.Complete.make ~after_dashdash:has_dashdash ~token Opt_name
303303+ in
304304+ Ok (Some comp, cline)
285305286306let create ?(peek_opts = false) ~legacy_prefixes ~for_completion al args =
287287- try
288288- let optidx, posidx, cline = arg_info_indexes al in
289289- let r =
290290- parse_opt_args
291291- ~for_completion ~peek_opts ~legacy_prefixes optidx cline args
292292- in
293293- match r with
294294- | Ok (cline, has_dashdash, _) when peek_opts -> `Ok cline
295295- | Ok (cline, has_dashdash, pargs) ->
296296- let r =
297297- process_pos_args ~for_completion posidx cline ~has_dashdash pargs
298298- in
299299- if not for_completion
300300- then (match r with Ok v -> `Ok v | Error v -> `Error v)
301301- else begin
302302- (* Normally [Completion_requested] should have been raised. This
307307+ let optidx, posidx, cline = arg_info_indexes al in
308308+ match
309309+ parse_opt_args ~for_completion ~peek_opts ~legacy_prefixes optidx cline args
310310+ with
311311+ | Ok (comp, cline, _has_dashdash, _pargs) when peek_opts ->
312312+ begin match comp with
313313+ | None -> `Ok cline
314314+ | Some comp -> `Complete (comp, cline)
315315+ end
316316+ | Ok (comp, cline, has_dashdash, pargs) ->
317317+ begin match
318318+ parse_pos_args ~for_completion posidx comp cline ~has_dashdash pargs
319319+ with
320320+ | Ok (None, _) | Error _ when for_completion ->
321321+ (* Normally we should have found a completion token This
303322 may fail to happen if pos args are ill defined: we may miss the
304304- completion token. Just make sure we do a completion. N.B. *)
305305- match List.find_opt has_complete_prefix pargs with
323323+ completion token. Just make sure we do a completion. *)
324324+ begin match List.find_opt has_complete_prefix pargs with
306325 | None -> assert false
307326 | Some arg ->
308327 match maybe_token_to_complete ~for_completion:true arg with
309328 | None -> assert false
310329 | Some token ->
311311- comp_request
312312- ~after_dashdash:has_dashdash cline ~token Opt_name
313313- end
330330+ let comp =
331331+ Cmdliner_def.Complete.make
332332+ ~after_dashdash:has_dashdash ~token Opt_name
333333+ in
334334+ `Complete (comp, cline)
335335+ end
336336+ | Ok (None, cline) -> `Ok cline
337337+ | Ok (Some comp, cline) -> `Complete (comp, cline)
338338+ | Error v -> `Error v
339339+ end
314340 | Error (errs, cline, has_dashdash, pargs) ->
315315- let _ : _ result =
316316- process_pos_args ~for_completion posidx cline ~has_dashdash pargs
317317- in
318318- `Error (errs, cline)
319319- with Completion_requested c -> `Complete c
341341+ match
342342+ parse_pos_args ~for_completion posidx None cline ~has_dashdash pargs
343343+ with
344344+ | Ok (Some comp, cline) -> `Complete (comp, cline)
345345+ | _ -> `Error (errs, cline)
+1-1
vendor/opam/cmdliner/src/cmdliner_cline.mli
···1515 ?peek_opts:bool -> legacy_prefixes:bool -> for_completion:bool ->
1616 Cmdliner_def.Arg_info.Set.t -> string list ->
1717 [ `Ok of Cmdliner_def.Cline.t
1818- | `Complete of Cmdliner_def.Complete.t
1818+ | `Complete of Cmdliner_def.Complete.t * Cmdliner_def.Cline.t
1919 | `Error of string * Cmdliner_def.Cline.t ]
+4-5
vendor/opam/cmdliner/src/cmdliner_completion.ml
···6868 let options = Cmdliner_def.Arg_info.Set.elements set in
6969 Group ("Options", List.concat (List.map maybe_items options)) :: directives
70707171-let add_argument_value_directives directives eval arg_info comp =
7171+let add_argument_value_directives directives eval arg_info comp cline =
7272 let (Conv conv) =
7373 let arg_infos = Cmdliner_def.Cmd_info.args (Cmdliner_def.Eval.cmd eval) in
7474 Option.get (Cmdliner_def.Arg_info.Set.find_opt arg_info arg_infos)
···8080 let ctx = match ctx with
8181 | None -> None
8282 | Some ctx ->
8383- let cline = Cmdliner_def.Complete.cline comp in
8483 match (Cmdliner_term.parser ctx) eval cline with
8584 | Ok ctx -> Some ctx
8685 | Error _ -> None
···122121 in
123122 loop [] [] ~files:false ~dirs:false ~restart:false ~raw:None ds
124123125125-let output ~out_ppf ~err_ppf eval comp =
124124+let output ~out_ppf ~err_ppf eval comp cline =
126125 let subst = Cmdliner_def.Eval.doclang_subst eval in
127126 let dirs = add_subcommands_group ~err_ppf ~subst eval comp [] in
128127 let res = match Cmdliner_def.Complete.kind comp with
129128 | Opt_value arg_info ->
130130- add_argument_value_directives dirs eval arg_info comp
129129+ add_argument_value_directives dirs eval arg_info comp cline
131130 | Opt_name_or_pos_value arg_info ->
132131 let dirs = add_options_group ~err_ppf ~subst eval comp dirs in
133133- add_argument_value_directives dirs eval arg_info comp
132132+ add_argument_value_directives dirs eval arg_info comp cline
134133 | Opt_name ->
135134 `Directives (add_options_group ~err_ppf ~subst eval comp dirs)
136135 in
···544544 | Opt_name
545545546546 type t =
547547- { cline : Cline.t;
548548- token : string;
547547+ { token : string;
549548 after_dashdash : bool;
550549 subcmds : bool; (* Note this is adjusted in Cmdliner_eval *)
551550 kind : kind }
552551553553- let make ?(after_dashdash = false) ?(subcmds = false) cline ~token kind =
554554- { cline; token; after_dashdash; subcmds; kind; }
552552+ let make ?(after_dashdash = false) ?(subcmds = false) ~token kind =
553553+ { token; after_dashdash; subcmds; kind; }
555554556556- let cline c = c.cline
557555 let token c = c.token
558556 let after_dashdash c = c.after_dashdash
559557 let subcmds c = c.subcmds
+1-5
vendor/opam/cmdliner/src/cmdliner_def.mli
···295295 | Opt_name
296296297297 type t
298298- val make :
299299- ?after_dashdash:bool -> ?subcmds:bool -> Cline.t -> token:string -> kind ->
300300- t
301301-302302- val cline : t -> Cline.t
298298+ val make : ?after_dashdash:bool -> ?subcmds:bool -> token:string -> kind -> t
303299 val token : t -> string
304300 val after_dashdash : t -> bool
305301 val subcmds : t -> bool
+8-7
vendor/opam/cmdliner/src/cmdliner_eval.ml
···1515 | `Std_version ]
16161717type 'a eval_result =
1818- ('a, [ eval_result_error | `Complete of Cmdliner_def.Complete.t]) result
1818+ ('a, [ eval_result_error
1919+ | `Complete of Cmdliner_def.Complete.t * Cmdliner_def.Cline.t]) result
19202021let err_help s = "Term error, help requested for unknown command " ^ s
2122let err_argv = "argv array must have at least one element"
···9697 Cmdliner_msg.pp_version help_ppf eval; Ok `Version
9798 | `Parse err ->
9899 Cmdliner_msg.pp_usage_and_err err_ppf eval ~err; Error `Parse
9999- | `Complete comp ->
100100- Cmdliner_completion.output ~out_ppf:help_ppf ~err_ppf eval comp;
100100+ | `Complete (comp, cline) ->
101101+ Cmdliner_completion.output ~out_ppf:help_ppf ~err_ppf eval comp cline;
101102 Ok `Help
102103 | `Help (fmt, cmd_name) ->
103104 do_help ~env help_ppf err_ppf eval fmt cmd_name; Ok `Help
···221222 | Error (`Parse (try_stdopts, msg)) ->
222223 (* Command lookup error, we may still prioritize stdargs *)
223224 begin match cline with
224224- | `Complete comp -> Error (`Complete comp)
225225+ | `Complete c -> Error (`Complete c)
225226 | `Error (_, cl) | `Ok cl ->
226227 let stdopts =
227228 if try_stdopts
···234235 end
235236 | Error `Complete ->
236237 begin match cline with
237237- | `Complete comp ->
238238+ | `Complete (comp, cline) ->
238239 let comp = Cmdliner_def.Complete.add_subcmds comp in
239239- Error (`Complete comp)
240240+ Error (`Complete (comp, cline))
240241 | `Ok _ | `Error _ -> assert false
241242 end
242243 | Ok parser ->
243244 begin match cline with
244244- | `Complete comp -> Error (`Complete comp)
245245+ | `Complete c -> Error (`Complete c)
245246 | `Error (e, cl) ->
246247 begin match try_eval_stdopts ~catch eval cl help version with
247248 | Some e -> e