File Coverage

blib/lib/Perinci/Sub/Complete.pm
Criterion Covered Total %
statement 316 497 63.5
branch 97 202 48.0
condition 52 83 62.6
subroutine 14 14 100.0
pod 4 4 100.0
total 483 800 60.3


line stmt bran cond sub pod time code
1              
2             use 5.010001;
3 1     1   34043 use strict;
  1         15  
4 1     1   7 use warnings;
  1         2  
  1         24  
5 1     1   4 use Log::ger;
  1         3  
  1         49  
6 1     1   6  
  1         1  
  1         9  
7             use Complete::Common qw(:all);
8 1     1   761 use Complete::Sah;
  1         359  
  1         177  
9 1     1   437 use Complete::Util qw(hashify_answer complete_array_elem complete_hash_key combine_answers modify_answer);
  1         7880  
  1         92  
10 1     1   13 use Exporter 'import';
  1         2  
  1         69  
11 1     1   7 use Perinci::Sub::Util qw(gen_modified_sub);
  1         2  
  1         28  
12 1     1   4  
  1         2  
  1         4239  
13             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
14             our $DATE = '2022-08-28'; # DATE
15             our $DIST = 'Perinci-Sub-Complete'; # DIST
16             our $VERSION = '0.945'; # VERSION
17              
18             our @EXPORT_OK = qw(
19             complete_from_schema
20             complete_arg_val
21             complete_arg_index
22             complete_arg_elem
23             complete_cli_arg
24             );
25             our %SPEC;
26              
27             $SPEC{':package'} = {
28             v => 1.1,
29             summary => 'Complete command-line argument using Rinci metadata',
30             };
31              
32             my %common_args_riap = (
33             riap_client => {
34             summary => 'Optional, to perform complete_arg_val to the server',
35             schema => 'obj*',
36             description => <<'_',
37              
38             When the argument spec in the Rinci metadata contains `completion` key, this
39             means there is custom completion code for that argument. However, if retrieved
40             from a remote server, sometimes the `completion` key no longer contains the code
41             (it has been cleansed into a string). Moreover, the completion code needs to run
42             on the server.
43              
44             If supplied this argument and te `riap_server_url` argument, the function will
45             try to request to the server (via Riap request `complete_arg_val`). Otherwise,
46             the function will just give up/decline completing.
47              
48             _
49             },
50             riap_server_url => {
51             summary => 'Optional, to perform complete_arg_val to the server',
52             schema => 'str*',
53             description => <<'_',
54              
55             See the `riap_client` argument.
56              
57             _
58             },
59             riap_uri => {
60             summary => 'Optional, to perform complete_arg_val to the server',
61             schema => 'str*',
62             description => <<'_',
63              
64             See the `riap_client` argument.
65              
66             _
67             },
68             );
69              
70             # backward compatibility, will be removed in the future
71             *complete_from_schema = \&Complete::Sah::complete_from_schema;
72             $SPEC{complete_from_schema} = $Complete::Sah::SPEC{complete_from_schema};
73              
74             $SPEC{complete_arg_val} = {
75             v => 1.1,
76             summary => 'Given argument name and function metadata, complete value',
77             description => <<'_',
78              
79             Will attempt to complete using the completion routine specified in the argument
80             specification (the `completion` property, or in the case of `complete_arg_elem`
81             function, the `element_completion` property), or if that is not specified, from
82             argument's schema using `complete_from_schema`.
83              
84             Completion routine will get `%args`, with the following keys:
85              
86             * `word` (str, the word to be completed)
87             * `arg` (str, the argument name which value is currently being completed)
88             * `index (int, only for the `complete_arg_elem` function, the index in the
89             argument array that is currently being completed, starts from 0)
90             * `args` (hash, the argument hash to the function, so far)
91              
92             as well as extra keys from `extras` (but these won't overwrite the above
93             standard keys).
94              
95             Completion routine should return a completion answer structure (described in
96             <pm:Complete>) which is either a hash or an array. The simplest form of answer
97             is just to return an array of strings. Completion routine can also return undef
98             to express declination.
99              
100             _
101             args => {
102             meta => {
103             summary => 'Rinci function metadata, must be normalized',
104             schema => 'hash*',
105             req => 1,
106             },
107             arg => {
108             summary => 'Argument name',
109             schema => 'str*',
110             req => 1,
111             },
112             word => {
113             summary => 'Word to be completed',
114             schema => ['str*', default => ''],
115             },
116             args => {
117             summary => 'Collected arguments so far, '.
118             'will be passed to completion routines',
119             schema => 'hash',
120             },
121             extras => {
122             summary => 'Add extra arguments to completion routine',
123             schema => 'hash',
124             description => <<'_',
125              
126             The keys from this `extras` hash will be merged into the final `%args` passed to
127             completion routines. Note that standard keys like `word`, `cword`, and so on as
128             described in the function description will not be overwritten by this.
129              
130             _
131             },
132              
133             %common_args_riap,
134             },
135             result_naked => 1,
136             result => {
137             schema => 'array', # XXX of => str*
138             },
139             };
140             my %args = @_;
141              
142 7     7 1 27 log_trace("[comp][periscomp] entering complete_arg_val, arg=<%s>", $args{arg});
143             my $fres;
144 7         20  
145 7         15 my $extras = $args{extras} // {};
146              
147 7   50     15 my $meta = $args{meta} or do {
148             log_trace("[comp][periscomp] meta is not supplied, declining");
149 7 50       17 goto RETURN_RES;
150 0         0 };
151 0         0 my $arg = $args{arg} or do {
152             log_trace("[comp][periscomp] arg is not supplied, declining");
153 7 50       12 goto RETURN_RES;
154 0         0 };
155 0         0 my $word = $args{word} // '';
156              
157 7   50     17 # XXX reject if meta's v is not 1.1
158              
159             my $args_prop = $meta->{args} // {};
160             my $arg_spec = $args_prop->{$arg} or do {
161 7   50     14 log_trace("[comp][periscomp] arg '$arg' is not specified in meta, declining");
162 7 50       12 goto RETURN_RES;
163 0         0 };
164 0         0  
165             my $static;
166             eval { # completion sub can die, etc.
167 7         10  
168 7         11 my $comp;
169             GET_COMP_ROUTINE:
170 7         8 {
171             $comp = $arg_spec->{completion};
172             if ($comp) {
173 7         10 log_trace("[comp][periscomp] using arg completion routine from arg spec's 'completion' property");
  7         9  
174 7 100       12 last GET_COMP_ROUTINE;
175 2         6 }
176 2         6 my $xcomp = $arg_spec->{'x.completion'};
177             if ($xcomp) {
178 5         8 if (ref($xcomp) eq 'CODE') {
179 5 50       9 $comp = $xcomp;
180 0 0       0 } else {
181 0         0 my ($submod, $xcargs);
182             if (ref($xcomp) eq 'ARRAY') {
183 0         0 $submod = $xcomp->[0];
184 0 0       0 $xcargs = $xcomp->[1];
185 0         0 } else {
186 0         0 $submod = $xcomp;
187             $xcargs = {};
188 0         0 }
189 0         0 my $mod = "Perinci::Sub::XCompletion::$submod";
190             require Module::Installed::Tiny;
191 0         0 if (Module::Installed::Tiny::module_installed($mod)) {
192 0         0 log_trace("[comp][periscomp] loading module %s ...", $mod);
193 0 0       0 my $mod_pm = $mod; $mod_pm =~ s!::!/!g; $mod_pm .= ".pm";
194 0         0 require $mod_pm;
195 0         0 my $fref = \&{"$mod\::gen_completion"};
  0         0  
  0         0  
196 0         0 log_trace("[comp][periscomp] invoking %s\::gen_completion(%s) ...", $mod, $xcargs);
197 0         0 $comp = $fref->(%$xcargs);
  0         0  
198 0         0 } else {
199 0         0 log_trace("[comp][periscomp] module %s is not installed, skipped", $mod);
200             }
201 0         0 }
202             if ($comp) {
203             log_trace("[comp][periscomp] using arg completion routine from arg spec's 'x.completion' attribute");
204 0 0       0 last GET_COMP_ROUTINE;
205 0         0 }
206 0         0 }
207             my $ent = $arg_spec->{'x.schema.entity'};
208             if ($ent) {
209 5         6 require Module::Installed::Tiny;
210 5 50       9 my $mod = "Perinci::Sub::ArgEntity::$ent";
211 0         0 if (Module::Installed::Tiny::module_installed($mod)) {
212 0         0 log_trace("[comp][periscomp] loading module %s ...", $mod);
213 0 0       0 my $mod_pm = $mod; $mod_pm =~ s!::!/!g; $mod_pm .= ".pm";
214 0         0 require $mod_pm;
215 0         0 if (defined &{"$mod\::complete_arg_val"}) {
  0         0  
  0         0  
216 0         0 log_trace("[comp][periscomp] invoking complete_arg_val() from %s ...", $mod);
217 0 0       0 $comp = \&{"$mod\::complete_arg_val"};
  0         0  
218 0         0 last GET_COMP_ROUTINE;
219 0         0 } else {
  0         0  
220 0         0 log_trace("[comp][periscomp] module %s doesn't define complete_arg_val(), skipped", $mod);
221             }
222 0         0 } else {
223             log_trace("[comp][periscomp] module %s not installed, skipped", $mod);
224             }
225 0         0 }
226             } # GET_COMP_ROUTINE
227              
228             if ($comp) {
229             if (ref($comp) eq 'CODE') {
230 7 100       12 my %cargs = (
231 2 50       8 %$extras,
    0          
232             word=>$word, arg=>$arg, args=>$args{args},
233             );
234             log_trace("[comp][periscomp] invoking arg completion routine with args (%s)", \%cargs);
235 2         12 $fres = $comp->(%cargs);
236 2         6 return; # from eval
237 2         10 } elsif (ref($comp) eq 'ARRAY') {
238 2         1521 # this is deprecated but will be supported for some time
239             log_trace("[comp][periscomp] using array specified in arg completion routine: %s", $comp);
240             $fres = complete_array_elem(array=>$comp, word=>$word);
241 0         0 $static++;
242 0         0 return; # from eval
243 0         0 }
244 0         0  
245             log_trace("[comp][periscomp] arg spec's 'completion' property is not a coderef or arrayref");
246             if ($args{riap_client} && $args{riap_server_url}) {
247 0         0 log_trace("[comp][periscomp] trying to perform complete_arg_val request to Riap server");
248 0 0 0     0 my $res = $args{riap_client}->request(
249 0         0 complete_arg_val => $args{riap_server_url},
250             {(uri=>$args{riap_uri}) x !!defined($args{riap_uri}),
251             arg=>$arg, word=>$word},
252 0         0 );
253             if ($res->[0] != 200) {
254             log_trace("[comp][periscomp] Riap request failed (%s), declining", $res);
255 0 0       0 return; # from eval
256 0         0 }
257 0         0 $fres = $res->[2];
258             return; # from eval
259 0         0 }
260 0         0  
261             log_trace("[comp][periscomp] declining");
262             return; # from eval
263 0         0 }
264 0         0  
265             my $fres_from_arg_examples;
266             COMPLETE_FROM_ARG_EXAMPLES:
267 5         6 {
268             my $egs = $arg_spec->{examples};
269             unless ($egs) {
270 5         6 log_trace("[comp][periscomp] arg spec does not specify examples");
  5         7  
271 5 100       11 last COMPLETE_FROM_ARG_EXAMPLES;
272 4         9 }
273 4         10 my @array;
274             my @summaries;
275 1         2 for my $eg (@$egs) {
276             if (ref $eg eq 'HASH') {
277 1         2 next unless defined $eg->{value};
278 2 100       37 next if ref $eg->{value};
279 1 50       4 push @array, $eg->{value};
280 1 50       3 push @summaries, $eg->{summary};
281 1         3 } else {
282 1         2 next unless defined $eg;
283             next if ref $eg;
284 1 50       4 push @array, $eg;
285 1 50       3 push @summaries, undef;
286 1         2 }
287 1         3 }
288             $fres_from_arg_examples = complete_array_elem(
289             word=>$word, array=>\@array, summaries=>\@summaries);
290 1         4 $static //= 1;
291             } # COMPLETE_FROM_ARG_EXAMPLES
292 1   50     91  
293             my $fres_from_schema;
294             COMPLETE_FROM_SCHEMA:
295 5         5 {
296             my $sch = $arg_spec->{schema};
297             unless ($sch) {
298 5         8 log_trace("[comp][periscomp] arg spec does not specify schema");
  5         7  
299 5 50       9 last COMPLETE_FROM_SCHEMA;
300 0         0 }
301 0         0 # XXX normalize schema if not normalized
302             $fres_from_schema = complete_from_schema(
303             arg=>$arg, extras=>$extras, schema=>$sch, word=>$word,
304 5         14 );
305             $static //= 1;
306             } # COMPLETE_FROM_SCHEMA
307 5   100     2917  
308             $fres = combine_answers(grep {defined} (
309             $fres_from_arg_examples,
310 5         9 $fres_from_schema,
  10         24  
311             ));
312             };
313             log_debug("[comp][periscomp] completion died: $@") if $@;
314             unless ($fres) {
315 7 50       48 log_trace("[comp][periscomp] no completion from metadata possible, declining");
316 7 50       12 goto RETURN_RES;
317 0         0 }
318 0         0  
319             $fres = hashify_answer($fres);
320             $fres->{static} //= $static && $word eq '' ? 1:0;
321 7         16 RETURN_RES:
322 7 100 66     66 log_trace("[comp][periscomp] leaving complete_arg_val, result=%s", $fres);
      100        
323 7         16 $fres;
324             }
325 7         26  
326             gen_modified_sub(
327             output_name => 'complete_arg_elem',
328             install_sub => 0,
329             base_name => 'complete_arg_val',
330             summary => 'Given argument name and function metadata, '.
331             'complete array element',
332             add_args => {
333             index => {
334             summary => 'Index of element to complete',
335             schema => ['str*'],
336             },
337             },
338             );
339             require Data::Sah::Normalize;
340              
341             my %args = @_;
342 3     3 1 18  
343             my $fres;
344 3         13  
345             log_trace("[comp][periscomp] entering complete_arg_elem, arg=<%s>, index=<%d>",
346 3         6 $args{arg}, $args{index});
347              
348             my $extras = $args{extras} // {};
349 3         10  
350             my $ourextras = {arg=>$args{arg}, args=>$args{args}};
351 3   50     13  
352             my $meta = $args{meta} or do {
353 3         9 log_trace("[comp][periscomp] meta is not supplied, declining");
354             goto RETURN_RES;
355 3 50       7 };
356 0         0 my $arg = $args{arg} or do {
357 0         0 log_trace("[comp][periscomp] arg is not supplied, declining");
358             goto RETURN_RES;
359 3 50       7 };
360 0         0 defined(my $index = $args{index}) or do {
361 0         0 log_trace("[comp][periscomp] index is not supplied, declining");
362             goto RETURN_RES;
363 3 50       8 };
364 0         0 my $word = $args{word} // '';
365 0         0  
366             # XXX reject if meta's v is not 1.1
367 3   50     7  
368             my $args_prop = $meta->{args} // {};
369             my $arg_spec = $args_prop->{$arg} or do {
370             log_trace("[comp][periscomp] arg '$arg' is not specified in meta, declining");
371 3   50     7 goto RETURN_RES;
372 3 50       8 };
373 0         0  
374 0         0 my $static;
375             eval { # completion sub can die, etc.
376              
377 3         4 my $elcomp;
378 3         4 GET_ELCOMP_ROUTINE:
379             {
380 3         5 $elcomp = $arg_spec->{element_completion};
381             if ($elcomp) {
382             log_trace("[comp][periscomp] using arg element completion routine from 'element_completion' property");
383 3         6 last GET_ELCOMP_ROUTINE;
  3         5  
384 3 100       6 }
385 2         5 my $xelcomp = $arg_spec->{'x.element_completion'};
386 2         6 if ($xelcomp) {
387             if (ref($xelcomp) eq 'CODE') {
388 1         2 $elcomp = $xelcomp;
389 1 50       11 } else {
390 0 0       0 my ($submod, $xcargs);
391 0         0 if (ref($xelcomp) eq 'ARRAY') {
392             $submod = $xelcomp->[0];
393 0         0 $xcargs = $xelcomp->[1];
394 0 0       0 } else {
395 0         0 $submod = $xelcomp;
396 0         0 $xcargs = {};
397             }
398 0         0 my $mod = "Perinci::Sub::XCompletion::$submod";
399 0         0 require Module::Installed::Tiny;
400             if (Module::Installed::Tiny::module_installed($mod)) {
401 0         0 log_trace("[comp][periscomp] loading module %s ...", $mod);
402 0         0 my $mod_pm = $mod; $mod_pm =~ s!::!/!g; $mod_pm .= ".pm";
403 0 0       0 require $mod_pm;
404 0         0 my $fref = \&{"$mod\::gen_completion"};
405 0         0 log_trace("[comp][periscomp] invoking %s\::gen_completion(%s) ...", $mod, $xcargs);
  0         0  
  0         0  
406 0         0 $elcomp = $fref->(%$xcargs);
407 0         0 } else {
  0         0  
408 0         0 log_trace("[comp][periscomp] module %s is not installed, skipped", $mod);
409 0         0 }
410             }
411 0         0 if ($elcomp) {
412             log_trace("[comp][periscomp] using arg element completion routine from 'x.element_completion' attribute");
413             last GET_ELCOMP_ROUTINE;
414 0 0       0 }
415 0         0 }
416 0         0 my $ent = $arg_spec->{'x.schema.element_entity'};
417             if ($ent) {
418             require Module::Installed::Tiny;
419 1         2 my $mod = "Perinci::Sub::ArgEntity::$ent";
420 1 50       2 if (Module::Installed::Tiny::module_installed($mod)) {
421 0         0 log_trace("[comp][periscomp] loading module %s ...", $mod);
422 0         0 my $mod_pm = $mod; $mod_pm =~ s!::!/!g; $mod_pm .= ".pm";
423 0 0       0 require $mod_pm;
424 0         0 if (defined &{"$mod\::complete_arg_val"}) {
425 0         0 log_trace("[comp][periscomp] invoking complete_arg_val() from %s ...", $mod);
  0         0  
  0         0  
426 0         0 $elcomp = \&{"$mod\::complete_arg_val"};
427 0 0       0 last GET_ELCOMP_ROUTINE;
  0         0  
428 0         0 } else {
429 0         0 log_trace("[comp][periscomp] module %s doesn't defined complete_arg_val(), skipped", $mod);
  0         0  
430 0         0 }
431             } else {
432 0         0 log_trace("[comp][periscomp] module %s is not installed, skipped", $mod);
433             }
434             }
435 0         0 } # GET_ELCOMP_ROUTINE
436              
437             $ourextras->{index} = $index;
438             if ($elcomp) {
439             if (ref($elcomp) eq 'CODE') {
440 3         6 my %cargs = (
441 3 100       6 %$extras,
442 2 50       6 %$ourextras,
    0          
443 2         11 word=>$word,
444             );
445             log_trace("[comp][periscomp] invoking arg element completion routine with args (%s)", \%cargs);
446             $fres = $elcomp->(%cargs);
447             return; # from eval
448 2         7 } elsif (ref($elcomp) eq 'ARRAY') {
449 2         10 log_trace("[comp][periscomp] using array specified in arg element completion routine: %s", $elcomp);
450 2         744 $fres = complete_array_elem(array=>$elcomp, word=>$word);
451             $static = $word eq '';
452 0         0 }
453 0         0  
454 0         0 log_trace("[comp][periscomp] arg spec's 'element_completion' property is not a coderef or ".
455             "arrayref");
456             if ($args{riap_client} && $args{riap_server_url}) {
457 0         0 log_trace("[comp][periscomp] trying to perform complete_arg_elem request to Riap server");
458             my $res = $args{riap_client}->request(
459 0 0 0     0 complete_arg_elem => $args{riap_server_url},
460 0         0 {(uri=>$args{riap_uri}) x !!defined($args{riap_uri}),
461             arg=>$arg, args=>$args{args}, word=>$word,
462             index=>$index},
463             );
464 0         0 if ($res->[0] != 200) {
465             log_trace("[comp][periscomp] Riap request failed (%s), declining", $res);
466             return; # from eval
467 0 0       0 }
468 0         0 $fres = $res->[2];
469 0         0 return; # from eval
470             }
471 0         0  
472 0         0 log_trace("[comp][periscomp] declining");
473             return; # from eval
474             } # if ($elcomp)
475 0         0  
476 0         0 my $sch = $arg_spec->{schema};
477             unless ($sch) {
478             log_trace("[comp][periscomp] arg spec does not specify schema, declining");
479 1         1 return; # from eval
480 1 50       4 };
481 0         0  
482 0         0 my $nsch = Data::Sah::Normalize::normalize_schema($sch);
483              
484             my ($type, $cs) = @$nsch;
485 1         3 if ($type ne 'array') {
486             log_trace("[comp][periscomp] can't complete element for non-array");
487 1         59 return; # from eval
488 1 50       3 }
489 0         0  
490 0         0 unless ($cs->{of}) {
491             log_trace("[comp][periscomp] schema does not specify 'of' clause, declining");
492             return; # from eval
493 1 50       4 }
494 0         0  
495 0         0 # normalize subschema because normalize_schema (as of 0.01) currently
496             # does not do it yet
497             my $elsch = Data::Sah::Normalize::normalize_schema($cs->{of});
498              
499             $fres = complete_from_schema(
500 1         2 schema=>$elsch, word=>$word,
501             schema_is_normalized=>1,
502 1         49 );
503             };
504             log_debug("[comp][periscomp] completion died: $@") if $@;
505             unless ($fres) {
506             log_trace("[comp][periscomp] no completion from metadata possible, declining");
507 3 50       251 goto RETURN_RES;
508 3 50       9 }
509 0         0  
510 0         0 $fres = hashify_answer($fres);
511             $fres->{static} //= $static && $word eq '' ? 1:0;
512             RETURN_RES:
513 3         7 log_trace("[comp][periscomp] leaving complete_arg_elem, result=%s", $fres);
514 3 50 33     33 $fres;
      66        
515 3         12 }
516              
517 3         14 $SPEC{complete_arg_index} = {
518             v => 1.1,
519             summary => 'Given argument name and function metadata, complete arg element index',
520             description => <<'_',
521              
522             This is only relevant for arguments which have `index_completion` property set
523             (currently only `hash` type arguments). When that property is not set, will
524             simply return undef.
525              
526             Completion routine will get `%args`, with the following keys:
527              
528             * `word` (str, the word to be completed)
529             * `arg` (str, the argument name which value is currently being completed)
530             * `args` (hash, the argument hash to the function, so far)
531              
532             as well as extra keys from `extras` (but these won't overwrite the above
533             standard keys).
534              
535             Completion routine should return a completion answer structure (described in
536             <pm:Complete>) which is either a hash or an array. The simplest form of answer
537             is just to return an array of strings. Completion routine can also return undef
538             to express declination.
539              
540             _
541             args => {
542             meta => {
543             summary => 'Rinci function metadata, must be normalized',
544             schema => 'hash*',
545             req => 1,
546             },
547             arg => {
548             summary => 'Argument name',
549             schema => 'str*',
550             req => 1,
551             },
552             word => {
553             summary => 'Word to be completed',
554             schema => ['str*', default => ''],
555             },
556             args => {
557             summary => 'Collected arguments so far, '.
558             'will be passed to completion routines',
559             schema => 'hash',
560             },
561             extras => {
562             summary => 'Add extra arguments to completion routine',
563             schema => 'hash',
564             description => <<'_',
565              
566             The keys from this `extras` hash will be merged into the final `%args` passed to
567             completion routines. Note that standard keys like `word`, `cword`, and so on as
568             described in the function description will not be overwritten by this.
569              
570             _
571             },
572              
573             %common_args_riap,
574             },
575             result_naked => 1,
576             result => {
577             schema => 'array', # XXX of => str*
578             },
579             };
580             require Data::Sah::Normalize;
581              
582             my %args = @_;
583              
584 3     3 1 17 my $fres;
585              
586 3         15 log_trace("[comp][periscomp] entering complete_arg_index, arg=<%s>",
587             $args{arg});
588 3         3  
589             my $extras = $args{extras} // {};
590              
591 3         11 my $ourextras = {arg=>$args{arg}, args=>$args{args}};
592              
593 3   50     10 my $meta = $args{meta} or do {
594             log_trace("[comp][periscomp] meta is not supplied, declining");
595 3         8 goto RETURN_RES;
596             };
597 3 50       8 my $arg = $args{arg} or do {
598 0         0 log_trace("[comp][periscomp] arg is not supplied, declining");
599 0         0 goto RETURN_RES;
600             };
601 3 50       6 my $word = $args{word} // '';
602 0         0  
603 0         0 # XXX reject if meta's v is not 1.1
604              
605 3   50     7 my $args_prop = $meta->{args} // {};
606             my $arg_spec = $args_prop->{$arg} or do {
607             log_trace("[comp][periscomp] arg '$arg' is not specified in meta, declining");
608             goto RETURN_RES;
609 3   50     7 };
610 3 50       8  
611 0         0 my $static;
612 0         0 eval { # completion sub can die, etc.
613              
614             my $idxcomp;
615 3         3 GET_IDXCOMP_ROUTINE:
616 3         4 {
617             $idxcomp = $arg_spec->{index_completion};
618 3         4 if ($idxcomp) {
619             log_trace("[comp][periscomp] using arg element index completion routine from 'index_completion' property");
620             last GET_IDXCOMP_ROUTINE;
621 3         6 }
  3         4  
622 3 100       7 } # GET_IDXCOMP_ROUTINE
623 1         4  
624 1         3 if ($idxcomp) {
625             if (ref($idxcomp) eq 'CODE') {
626             my %cargs = (
627             %$extras,
628 3 100       6 %$ourextras,
629 1 50       5 word=>$word,
    50          
630 0         0 );
631             log_trace("[comp][periscomp] invoking arg element index completion routine with args (%s)", \%cargs);
632             $fres = $idxcomp->(%cargs);
633             return; # from eval
634             } elsif (ref($idxcomp) eq 'ARRAY') {
635 0         0 log_trace("[comp][periscomp] using array specified in arg element index completion routine: %s", $idxcomp);
636 0         0 $fres = complete_array_elem(array=>$idxcomp, word=>$word);
637 0         0 $static = $word eq '';
638             }
639 1         3  
640 1         5 log_trace("[comp][periscomp] arg spec's 'index_completion' property is not a coderef or ".
641 1         134 "arrayref");
642             if ($args{riap_client} && $args{riap_server_url}) {
643             log_trace("[comp][periscomp] trying to perform complete_arg_index request to Riap server");
644 1         3 my $res = $args{riap_client}->request(
645             complete_arg_index => $args{riap_server_url},
646 1 0 33     6 {(uri=>$args{riap_uri}) x !!defined($args{riap_uri}),
647 0         0 arg=>$arg, args=>$args{args}, word=>$word},
648             );
649             if ($res->[0] != 200) {
650             log_trace("[comp][periscomp] Riap request failed (%s), declining", $res);
651 0         0 return; # from eval
652             }
653 0 0       0 $fres = $res->[2];
654 0         0 return; # from eval
655 0         0 }
656              
657 0         0 log_trace("[comp][periscomp] declining");
658 0         0 return; # from eval
659             } # if ($idxcomp)
660              
661 1         3 my $sch = $arg_spec->{schema};
662 1         3 unless ($sch) {
663             log_trace("[comp][periscomp] arg spec does not specify schema, declining");
664             return; # from eval
665 2         4 };
666 2 50       5  
667 0         0 my $nsch = Data::Sah::Normalize::normalize_schema($sch);
668 0         0  
669             my ($type, $cs) = @$nsch;
670             if ($type ne 'hash') {
671 2         6 log_trace("[comp][periscomp] can't complete element index for non-hash");
672             return; # from eval
673 2         184 }
674 2 50       6  
675 0         0 # collect known keys from some clauses
676 0         0 my %keys;
677             if ($cs->{keys}) {
678             $keys{$_}++ for keys %{ $cs->{keys} };
679             }
680 2         3 if ($cs->{indices}) {
681 2 50       4 $keys{$_}++ for keys %{ $cs->{indices} };
682 2         5 }
  2         8  
683             if ($cs->{req_keys}) {
684 2 50       5 $keys{$_}++ for @{ $cs->{req_keys} };
685 0         0 }
  0         0  
686             if ($cs->{allowed_keys}) {
687 2 50       5 $keys{$_}++ for @{ $cs->{allowed_keys} };
688 0         0 }
  0         0  
689              
690 2 50       4 # exclude keys that have been specified in collected args
691 2         4 for (keys %{$args{args}{$arg} // {}}) {
  2         8  
692             delete $keys{$_};
693             }
694              
695 2   100     3 $fres = complete_hash_key(word => $word, hash => \%keys);
  2         10  
696 1         2  
697             }; # eval
698             log_debug("[comp][periscomp] completion died: $@") if $@;
699 2         9 unless ($fres) {
700             log_trace("[comp][periscomp] no index completion from metadata possible, declining");
701             goto RETURN_RES;
702 3 50       221 }
703 3 50       7  
704 0         0 $fres = hashify_answer($fres);
705 0         0 $fres->{static} //= $static && $word eq '' ? 1:0;
706             RETURN_RES:
707             log_trace("[comp][periscomp] leaving complete_arg_index, result=%s", $fres);
708 3         7 $fres;
709 3 100 66     44 }
      66        
710 3         9  
711             $SPEC{complete_cli_arg} = {
712 3         11 v => 1.1,
713             summary => 'Complete command-line argument using Rinci function metadata',
714             description => <<'_',
715              
716             This routine uses <pm:Perinci::Sub::GetArgs::Argv> to generate <pm:Getopt::Long>
717             specification from arguments list in Rinci function metadata and common options.
718             Then, it will use <pm:Complete::Getopt::Long> to complete option names, option
719             values, as well as arguments.
720              
721             _
722             args => {
723             meta => {
724             summary => 'Rinci function metadata',
725             schema => 'hash*',
726             req => 1,
727             },
728             words => {
729             summary => 'Command-line arguments',
730             schema => ['array*' => {of=>'str*'}],
731             req => 1,
732             },
733             cword => {
734             summary => 'On which argument cursor is located (zero-based)',
735             schema => 'int*',
736             req => 1,
737             },
738             completion => {
739             summary => 'Supply custom completion routine',
740             description => <<'_',
741              
742             If supplied, instead of the default completion routine, this code will be called
743             instead. Will receive all arguments that <pm:Complete::Getopt::Long> will pass,
744             and additionally:
745              
746             * `arg` (str, the name of function argument)
747             * `args` (hash, the function arguments formed so far)
748             * `index` (int, if completing argument element value)
749              
750             _
751             schema => 'code*',
752             },
753             per_arg_json => {
754             summary => 'Will be passed to Perinci::Sub::GetArgs::Argv',
755             schema => 'bool',
756             },
757             per_arg_yaml => {
758             summary => 'Will be passed to Perinci::Sub::GetArgs::Argv',
759             schema => 'bool',
760             },
761             common_opts => {
762             summary => 'Common options',
763             description => <<'_',
764              
765             A hash where the values are hashes containing these keys: `getopt` (Getopt::Long
766             option specification), `handler` (Getopt::Long handler). Will be passed to
767             `get_args_from_argv()`. Example:
768              
769             {
770             help => {
771             getopt => 'help|h|?',
772             handler => sub { ... },
773             summary => 'Display help and exit',
774             },
775             version => {
776             getopt => 'version|v',
777             handler => sub { ... },
778             summary => 'Display version and exit',
779             },
780             }
781              
782             _
783             schema => ['hash*'],
784             },
785             extras => {
786             summary => 'Add extra arguments to completion routine',
787             schema => 'hash',
788             description => <<'_',
789              
790             The keys from this `extras` hash will be merged into the final `%args` passed to
791             completion routines. Note that standard keys like `word`, `cword`, and so on as
792             described in the function description will not be overwritten by this.
793              
794             _
795             },
796             func_arg_starts_at => {
797             schema => 'int*',
798             default => 0,
799             description => <<'_',
800              
801             This is a (temporary?) workaround for <pm:Perinci::CmdLine>. In an application
802             with subcommands (e.g. `cmd --verbose subcmd arg0 arg1 ...`), then `words` will
803             still contain the subcommand name. Positional function arguments then start at 1
804             not 0. This option allows offsetting function arguments.
805              
806             _
807             },
808             %common_args_riap,
809             },
810             result_naked => 1,
811             result => {
812             schema => 'hash*',
813             description => <<'_',
814              
815             You can use `format_completion` function in <pm:Complete::Bash> module to format
816             the result of this function for bash.
817              
818             _
819             },
820             };
821             require Complete::Getopt::Long;
822             require Perinci::Sub::GetArgs::Argv;
823              
824             my %args = @_;
825             my $meta = $args{meta} or die "Please specify meta";
826 24     24 1 105005 my $words = $args{words} or die "Please specify words";
827 24         1546 my $cword = $args{cword}; defined($cword) or die "Please specify cword";
828             my $copts = $args{common_opts} // {};
829 24         12318 my $comp = $args{completion};
830 24 50       65 my $extras = {
831 24 50       47 %{ $args{extras} // {} },
832 24 50       29 words => $args{words},
  24         60  
833 24   50     44 cword => $args{cword},
834 24         34 };
835              
836 24   100     105 my $fname = __PACKAGE__ . "::complete_cli_arg"; # XXX use __SUB__
837             my $fres;
838              
839 24         30 my $word = $words->[$cword];
840             my $args_prop = $meta->{args} // {};
841 24         50  
842 24         28 log_trace('[comp][periscomp] entering %s(), words=%s, cword=%d, word=<%s>',
843             $fname, $words, $cword, $word);
844 24         32  
845 24   50     48 my $ggls_res = Perinci::Sub::GetArgs::Argv::gen_getopt_long_spec_from_meta(
846             meta => $meta,
847 24         69 common_opts => $copts,
848             per_arg_json => $args{per_arg_json},
849             per_arg_yaml => $args{per_arg_yaml},
850             ignore_converted_code => 1,
851             );
852             die "Can't generate getopt spec from meta: $ggls_res->[0] - $ggls_res->[1]"
853             unless $ggls_res->[0] == 200;
854             $extras->{ggls_res} = $ggls_res;
855 24         110 my $gospec = $ggls_res->[2];
856             my $specmeta = $ggls_res->[3]{'func.specmeta'};
857 24 50       111695  
858             my $gares = Perinci::Sub::GetArgs::Argv::get_args_from_argv(
859 24         49 argv => [@$words],
860 24         32 meta => $meta,
861 24         32 strict => 0,
862             );
863 24         71  
864             my $copts_by_ospec = {};
865             for (keys %$copts) { $copts_by_ospec->{$copts->{$_}{getopt}}=$copts->{$_} }
866              
867             my $compgl_comp = sub {
868             log_trace("[comp][periscomp] entering completion routine (that we supply to Complete::Getopt::Long)");
869 24         148129 my %cargs = @_;
870 24         55 my $type = $cargs{type};
  24         55  
871             my $ospec = $cargs{ospec} // '';
872             my $word = $cargs{word};
873 21     21   23251  
874 21         119 my $fres;
875 21         34  
876 21   100     59 my %rargs = (
877 21         31 riap_server_url => $args{riap_server_url},
878             riap_uri => $args{riap_uri},
879 21         27 riap_client => $args{riap_client},
880             );
881              
882             $extras->{parsed_opts} = $cargs{parsed_opts};
883              
884             if (my $sm = $specmeta->{$ospec}) {
885 21         56 $cargs{type} = 'optval';
886             if ($sm->{arg}) {
887 21         30 log_trace("[comp][periscomp] completing option value for a known function argument, arg=<%s>, ospec=<%s>", $sm->{arg}, $ospec);
888             $cargs{arg} = $sm->{arg};
889 21 100       52 my $arg_spec = $args_prop->{$sm->{arg}} or goto RETURN_RES;
    50          
890 13         22 if ($comp) {
891 13 100       25 log_trace("[comp][periscomp] invoking routine supplied from 'completion' argument with args (%s)", \%cargs);
892 12         26 my $compres;
893 12         54 eval { $compres = $comp->(%cargs) };
894 12 50       35 log_debug("[comp][periscomp] completion died: $@") if $@;
895 12 100       22 log_trace("[comp][periscomp] result from 'completion' routine: %s", $compres);
896 1         3 if ($compres) {
897 1         2 $fres = $compres;
898 1         2 goto RETURN_RES;
  1         4  
899 1 50       6 }
900 1         2 }
901 1 50       4 if ($ospec =~ /\@$/) {
902 1         1 $fres = complete_arg_elem(
903 1         25 meta=>$meta, arg=>$sm->{arg}, args=>$gares->[2],
904             word=>$word, index=>$cargs{nth}, # XXX correct index
905             extras=>$extras, %rargs);
906 11 100       36 goto RETURN_RES;
    100          
907             } elsif ($ospec =~ /\%$/) {
908             if ($word =~ /(.*?)=(.*)/s) {
909             my $key = $1;
910 1         4 my $val = $2;
911 1         26 $fres = complete_arg_elem(
912             meta=>$meta, arg=>$sm->{arg}, args=>$gares->[2],
913 4 100       10 word=>$val, index=>$key,
914 1         8 extras=>$extras, %rargs);
915 1         3 modify_answer(answer=>$fres, prefix=>"$key=");
916             goto RETURN_RES;
917 1         4 } else {
918             $fres = complete_arg_index(
919             meta=>$meta, arg=>$sm->{arg}, args=>$gares->[2],
920 1         4 word=>$word, extras=>$extras, %rargs);
921 1         51 modify_answer(answer=>$fres, suffix=>"=");
922             $fres->{path_sep} = "=";
923             # XXX actually not entirely correct, we want normal
924 3         12 # escaping but without escaping "=", maybe we should
925             # allow customizing, e.g. esc_mode=normal, dont_esc="="
926 3         9 # (list of characters to not escape)
927 3         67 $fres->{esc_mode} = "none";
928             goto RETURN_RES;
929             }
930             } else {
931             $fres = complete_arg_val(
932 3         5 meta=>$meta, arg=>$sm->{arg}, args=>$gares->[2],
933 3         80 word=>$word, extras=>$extras, %rargs);
934             goto RETURN_RES;
935             }
936             } else {
937 6         25 log_trace("[comp][periscomp] completing option value for a common option, ospec=<%s>", $ospec);
938             $cargs{arg} = undef;
939 6         154 my $codata = $copts_by_ospec->{$ospec};
940             if ($comp) {
941             log_trace("[comp][periscomp] invoking routine supplied from 'completion' argument with args (%s)", \%cargs);
942 1         8 my $res;
943 1         3 eval { $res = $comp->(%cargs) };
944 1         1 log_debug("[comp][periscomp] completion died: $@") if $@;
945 1 50       4 if ($res) {
946 1         3 $fres = $res;
947 1         2 goto RETURN_RES;
948 1         3 }
  1         5  
949 1 50       5 }
950 1 50       3 if ($codata->{completion}) {
951 1         1 $cargs{arg} = undef;
952 1         25 log_trace("[comp][periscomp] completing with common option's 'completion' property with args (%s)", \%cargs);
953             my $res;
954             eval { $res = $codata->{completion}->(%cargs) };
955 0 0       0 log_debug("[comp][periscomp] completion died: $@") if $@;
956 0         0 if ($res) {
957 0         0 $fres = $res;
958 0         0 goto RETURN_RES;
959 0         0 }
  0         0  
960 0 0       0 }
961 0 0       0 if ($codata->{schema}) {
962 0         0 require Data::Sah::Normalize;
963 0         0 my $nsch = Data::Sah::Normalize::normalize_schema(
964             $codata->{schema});
965             log_trace("[comp][periscomp] completing with common option's schema");
966 0 0       0 $fres = complete_from_schema(
967 0         0 schema => $nsch, word=>$word,
968             schema_is_normalized=>1,
969 0         0 );
970 0         0 goto RETURN_RES;
971 0         0 }
972             goto RETURN_RES;
973             }
974             } elsif ($type eq 'arg') {
975 0         0 log_trace("[comp][periscomp] completing argument #%d", $cargs{argpos});
976             $cargs{type} = 'arg';
977 0         0  
978             my $pos = $cargs{argpos};
979             my $fasa = $args{func_arg_starts_at} // 0;
980 8         19  
981 8         19 # find if there is a non-slurpy argument with the exact position
982             for my $an (keys %$args_prop) {
983 8         11 my $arg_spec = $args_prop->{$an};
984 8   50     24 next unless !($arg_spec->{slurpy} // $arg_spec->{greedy}) &&
985             defined($arg_spec->{pos}) && $arg_spec->{pos} == $pos - $fasa;
986             log_trace("[comp][periscomp] this argument position is for non-slurpy function argument <%s>", $an);
987 8         29 $cargs{arg} = $an;
988 58         66 if ($comp) {
989             log_trace("[comp][periscomp] invoking routine supplied from 'completion' argument with args (%s)", \%cargs);
990 58 100 66     205 my $res;
      100        
      100        
991 2         6 eval { $res = $comp->(%cargs) };
992 2         20 log_debug("[comp][periscomp] completion died: $@") if $@;
993 2 100       7 if ($res) {
994 1         3 $fres = $res;
995 1         3 goto RETURN_RES;
996 1         26 }
  1         8  
997 1 50       6 }
998 1 50       4 $fres = complete_arg_val(
999 1         2 meta=>$meta, arg=>$an, args=>$gares->[2],
1000 1         25 word=>$word, extras=>$extras, %rargs);
1001             goto RETURN_RES;
1002             }
1003 1         4  
1004             # find if there is a slurpy argument which takes elements at that
1005             # position
1006 1         26 for my $an (sort {
1007             ($args_prop->{$b}{pos} // 9999) <=> ($args_prop->{$a}{pos} // 9999)
1008             } keys %$args_prop) {
1009             my $arg_spec = $args_prop->{$an};
1010             next unless ($arg_spec->{slurpy} // $arg_spec->{greedy}) &&
1011 6         23 defined($arg_spec->{pos}) && $arg_spec->{pos} <= $pos - $fasa;
1012 141   100     363 my $index = $pos - $fasa - $arg_spec->{pos};
      100        
1013             $cargs{arg} = $an;
1014 51         56 $cargs{index} = $index;
1015             log_trace("[comp][periscomp] this position is for slurpy function argument <%s>'s element[%d]", $an, $index);
1016 51 50 66     147 if ($comp) {
      66        
      66        
1017 3         6 log_trace("[comp][periscomp] invoking routine supplied from 'completion' argument with args (%s)", \%cargs);
1018 3         5 my $res;
1019 3         5 eval { $res = $comp->(%cargs) };
1020 3         9 log_debug("[comp][periscomp] completion died: $@") if $@;
1021 3 100       9 if ($res) {
1022 2         6 $fres = $res;
1023 2         4 goto RETURN_RES;
1024 2         4 }
  2         9  
1025 2 50       726 }
1026 2 50       5 $fres = complete_arg_elem(
1027 2         3 meta=>$meta, arg=>$an, args=>$gares->[2],
1028 2         50 word=>$word, index=>$index, extras=>$extras, %rargs);
1029             goto RETURN_RES;
1030             }
1031 1         5  
1032             log_trace("[comp][periscomp] there is no matching function argument at this position");
1033             if ($comp) {
1034 1         32 log_trace("[comp][periscomp] invoking routine supplied from 'completion' argument with args (%s)", \%cargs);
1035             my $res;
1036             eval { $res = $comp->(%cargs) };
1037 3         8 log_debug("[comp][periscomp] completion died: $@") if $@;
1038 3 100       10 if ($res) {
1039 2         5 $fres = $res;
1040 2         4 goto RETURN_RES;
1041 2         3 }
  2         9  
1042 2 50       9 }
1043 2 50       7 goto RETURN_RES;
1044 2         2 } else {
1045 2         50 log_trace("[comp][periscomp] completing option value for an unknown/ambiguous option, declining ...");
1046             # decline because there's nothing in Rinci metadata that can aid us
1047             goto RETURN_RES;
1048 1         47 }
1049             RETURN_RES:
1050 0         0 log_trace("[comp][periscomp] leaving completion routine (that we supply to Complete::Getopt::Long)");
1051             $fres;
1052 0         0 }; # completion routine
1053              
1054 21         52 $fres = Complete::Getopt::Long::complete_cli_arg(
1055             getopt_spec => $gospec,
1056 21         97 words => $words,
1057 24         151 cword => $cword,
1058             completion => $compgl_comp,
1059 24         73 extras => $extras,
1060             );
1061              
1062             RETURN_RES:
1063             log_trace('[comp][periscomp] leaving %s(), result=%s',
1064             $fname, $fres);
1065             $fres;
1066             }
1067 24         19226  
1068             1;
1069             # ABSTRACT: Complete command-line argument using Rinci metadata
1070 24         3153  
1071              
1072             =pod
1073              
1074             =encoding UTF-8
1075              
1076             =head1 NAME
1077              
1078             Perinci::Sub::Complete - Complete command-line argument using Rinci metadata
1079              
1080             =head1 VERSION
1081              
1082             This document describes version 0.945 of Perinci::Sub::Complete (from Perl distribution Perinci-Sub-Complete), released on 2022-08-28.
1083              
1084             =head1 SYNOPSIS
1085              
1086             See L<Perinci::CmdLine> or L<Perinci::CmdLine::Lite> or L<App::riap> which use
1087             this module.
1088              
1089             =head1 DESCRIPTION
1090              
1091             =head1 FUNCTIONS
1092              
1093              
1094             =head2 complete_arg_elem
1095              
1096             Usage:
1097              
1098             complete_arg_elem(%args) -> array
1099              
1100             Given argument name and function metadata, complete array element.
1101              
1102             Will attempt to complete using the completion routine specified in the argument
1103             specification (the C<completion> property, or in the case of C<complete_arg_elem>
1104             function, the C<element_completion> property), or if that is not specified, from
1105             argument's schema using C<complete_from_schema>.
1106              
1107             Completion routine will get C<%args>, with the following keys:
1108              
1109             =over
1110              
1111             =item * C<word> (str, the word to be completed)
1112              
1113             =item * C<arg> (str, the argument name which value is currently being completed)
1114              
1115             =item * C<index (int, only for the>complete_arg_elem` function, the index in the
1116             argument array that is currently being completed, starts from 0)
1117              
1118             =item * C<args> (hash, the argument hash to the function, so far)
1119              
1120             =back
1121              
1122             as well as extra keys from C<extras> (but these won't overwrite the above
1123             standard keys).
1124              
1125             Completion routine should return a completion answer structure (described in
1126             L<Complete>) which is either a hash or an array. The simplest form of answer
1127             is just to return an array of strings. Completion routine can also return undef
1128             to express declination.
1129              
1130             This function is not exported by default, but exportable.
1131              
1132             Arguments ('*' denotes required arguments):
1133              
1134             =over 4
1135              
1136             =item * B<arg>* => I<str>
1137              
1138             Argument name.
1139              
1140             =item * B<args> => I<hash>
1141              
1142             Collected arguments so far, will be passed to completion routines.
1143              
1144             =item * B<extras> => I<hash>
1145              
1146             Add extra arguments to completion routine.
1147              
1148             The keys from this C<extras> hash will be merged into the final C<%args> passed to
1149             completion routines. Note that standard keys like C<word>, C<cword>, and so on as
1150             described in the function description will not be overwritten by this.
1151              
1152             =item * B<index> => I<str>
1153              
1154             Index of element to complete.
1155              
1156             =item * B<meta>* => I<hash>
1157              
1158             Rinci function metadata, must be normalized.
1159              
1160             =item * B<riap_client> => I<obj>
1161              
1162             Optional, to perform complete_arg_val to the server.
1163              
1164             When the argument spec in the Rinci metadata contains C<completion> key, this
1165             means there is custom completion code for that argument. However, if retrieved
1166             from a remote server, sometimes the C<completion> key no longer contains the code
1167             (it has been cleansed into a string). Moreover, the completion code needs to run
1168             on the server.
1169              
1170             If supplied this argument and te C<riap_server_url> argument, the function will
1171             try to request to the server (via Riap request C<complete_arg_val>). Otherwise,
1172             the function will just give up/decline completing.
1173              
1174             =item * B<riap_server_url> => I<str>
1175              
1176             Optional, to perform complete_arg_val to the server.
1177              
1178             See the C<riap_client> argument.
1179              
1180             =item * B<riap_uri> => I<str>
1181              
1182             Optional, to perform complete_arg_val to the server.
1183              
1184             See the C<riap_client> argument.
1185              
1186             =item * B<word> => I<str> (default: "")
1187              
1188             Word to be completed.
1189              
1190              
1191             =back
1192              
1193             Return value: (array)
1194              
1195              
1196              
1197             =head2 complete_arg_index
1198              
1199             Usage:
1200              
1201             complete_arg_index(%args) -> array
1202              
1203             Given argument name and function metadata, complete arg element index.
1204              
1205             This is only relevant for arguments which have C<index_completion> property set
1206             (currently only C<hash> type arguments). When that property is not set, will
1207             simply return undef.
1208              
1209             Completion routine will get C<%args>, with the following keys:
1210              
1211             =over
1212              
1213             =item * C<word> (str, the word to be completed)
1214              
1215             =item * C<arg> (str, the argument name which value is currently being completed)
1216              
1217             =item * C<args> (hash, the argument hash to the function, so far)
1218              
1219             =back
1220              
1221             as well as extra keys from C<extras> (but these won't overwrite the above
1222             standard keys).
1223              
1224             Completion routine should return a completion answer structure (described in
1225             L<Complete>) which is either a hash or an array. The simplest form of answer
1226             is just to return an array of strings. Completion routine can also return undef
1227             to express declination.
1228              
1229             This function is not exported by default, but exportable.
1230              
1231             Arguments ('*' denotes required arguments):
1232              
1233             =over 4
1234              
1235             =item * B<arg>* => I<str>
1236              
1237             Argument name.
1238              
1239             =item * B<args> => I<hash>
1240              
1241             Collected arguments so far, will be passed to completion routines.
1242              
1243             =item * B<extras> => I<hash>
1244              
1245             Add extra arguments to completion routine.
1246              
1247             The keys from this C<extras> hash will be merged into the final C<%args> passed to
1248             completion routines. Note that standard keys like C<word>, C<cword>, and so on as
1249             described in the function description will not be overwritten by this.
1250              
1251             =item * B<meta>* => I<hash>
1252              
1253             Rinci function metadata, must be normalized.
1254              
1255             =item * B<riap_client> => I<obj>
1256              
1257             Optional, to perform complete_arg_val to the server.
1258              
1259             When the argument spec in the Rinci metadata contains C<completion> key, this
1260             means there is custom completion code for that argument. However, if retrieved
1261             from a remote server, sometimes the C<completion> key no longer contains the code
1262             (it has been cleansed into a string). Moreover, the completion code needs to run
1263             on the server.
1264              
1265             If supplied this argument and te C<riap_server_url> argument, the function will
1266             try to request to the server (via Riap request C<complete_arg_val>). Otherwise,
1267             the function will just give up/decline completing.
1268              
1269             =item * B<riap_server_url> => I<str>
1270              
1271             Optional, to perform complete_arg_val to the server.
1272              
1273             See the C<riap_client> argument.
1274              
1275             =item * B<riap_uri> => I<str>
1276              
1277             Optional, to perform complete_arg_val to the server.
1278              
1279             See the C<riap_client> argument.
1280              
1281             =item * B<word> => I<str> (default: "")
1282              
1283             Word to be completed.
1284              
1285              
1286             =back
1287              
1288             Return value: (array)
1289              
1290              
1291              
1292             =head2 complete_arg_val
1293              
1294             Usage:
1295              
1296             complete_arg_val(%args) -> array
1297              
1298             Given argument name and function metadata, complete value.
1299              
1300             Will attempt to complete using the completion routine specified in the argument
1301             specification (the C<completion> property, or in the case of C<complete_arg_elem>
1302             function, the C<element_completion> property), or if that is not specified, from
1303             argument's schema using C<complete_from_schema>.
1304              
1305             Completion routine will get C<%args>, with the following keys:
1306              
1307             =over
1308              
1309             =item * C<word> (str, the word to be completed)
1310              
1311             =item * C<arg> (str, the argument name which value is currently being completed)
1312              
1313             =item * C<index (int, only for the>complete_arg_elem` function, the index in the
1314             argument array that is currently being completed, starts from 0)
1315              
1316             =item * C<args> (hash, the argument hash to the function, so far)
1317              
1318             =back
1319              
1320             as well as extra keys from C<extras> (but these won't overwrite the above
1321             standard keys).
1322              
1323             Completion routine should return a completion answer structure (described in
1324             L<Complete>) which is either a hash or an array. The simplest form of answer
1325             is just to return an array of strings. Completion routine can also return undef
1326             to express declination.
1327              
1328             This function is not exported by default, but exportable.
1329              
1330             Arguments ('*' denotes required arguments):
1331              
1332             =over 4
1333              
1334             =item * B<arg>* => I<str>
1335              
1336             Argument name.
1337              
1338             =item * B<args> => I<hash>
1339              
1340             Collected arguments so far, will be passed to completion routines.
1341              
1342             =item * B<extras> => I<hash>
1343              
1344             Add extra arguments to completion routine.
1345              
1346             The keys from this C<extras> hash will be merged into the final C<%args> passed to
1347             completion routines. Note that standard keys like C<word>, C<cword>, and so on as
1348             described in the function description will not be overwritten by this.
1349              
1350             =item * B<meta>* => I<hash>
1351              
1352             Rinci function metadata, must be normalized.
1353              
1354             =item * B<riap_client> => I<obj>
1355              
1356             Optional, to perform complete_arg_val to the server.
1357              
1358             When the argument spec in the Rinci metadata contains C<completion> key, this
1359             means there is custom completion code for that argument. However, if retrieved
1360             from a remote server, sometimes the C<completion> key no longer contains the code
1361             (it has been cleansed into a string). Moreover, the completion code needs to run
1362             on the server.
1363              
1364             If supplied this argument and te C<riap_server_url> argument, the function will
1365             try to request to the server (via Riap request C<complete_arg_val>). Otherwise,
1366             the function will just give up/decline completing.
1367              
1368             =item * B<riap_server_url> => I<str>
1369              
1370             Optional, to perform complete_arg_val to the server.
1371              
1372             See the C<riap_client> argument.
1373              
1374             =item * B<riap_uri> => I<str>
1375              
1376             Optional, to perform complete_arg_val to the server.
1377              
1378             See the C<riap_client> argument.
1379              
1380             =item * B<word> => I<str> (default: "")
1381              
1382             Word to be completed.
1383              
1384              
1385             =back
1386              
1387             Return value: (array)
1388              
1389              
1390              
1391             =head2 complete_cli_arg
1392              
1393             Usage:
1394              
1395             complete_cli_arg(%args) -> hash
1396              
1397             Complete command-line argument using Rinci function metadata.
1398              
1399             This routine uses L<Perinci::Sub::GetArgs::Argv> to generate L<Getopt::Long>
1400             specification from arguments list in Rinci function metadata and common options.
1401             Then, it will use L<Complete::Getopt::Long> to complete option names, option
1402             values, as well as arguments.
1403              
1404             This function is not exported by default, but exportable.
1405              
1406             Arguments ('*' denotes required arguments):
1407              
1408             =over 4
1409              
1410             =item * B<common_opts> => I<hash>
1411              
1412             Common options.
1413              
1414             A hash where the values are hashes containing these keys: C<getopt> (Getopt::Long
1415             option specification), C<handler> (Getopt::Long handler). Will be passed to
1416             C<get_args_from_argv()>. Example:
1417              
1418             {
1419             help => {
1420             getopt => 'help|h|?',
1421             handler => sub { ... },
1422             summary => 'Display help and exit',
1423             },
1424             version => {
1425             getopt => 'version|v',
1426             handler => sub { ... },
1427             summary => 'Display version and exit',
1428             },
1429             }
1430              
1431             =item * B<completion> => I<code>
1432              
1433             Supply custom completion routine.
1434              
1435             If supplied, instead of the default completion routine, this code will be called
1436             instead. Will receive all arguments that L<Complete::Getopt::Long> will pass,
1437             and additionally:
1438              
1439             =over
1440              
1441             =item * C<arg> (str, the name of function argument)
1442              
1443             =item * C<args> (hash, the function arguments formed so far)
1444              
1445             =item * C<index> (int, if completing argument element value)
1446              
1447             =back
1448              
1449             =item * B<cword>* => I<int>
1450              
1451             On which argument cursor is located (zero-based).
1452              
1453             =item * B<extras> => I<hash>
1454              
1455             Add extra arguments to completion routine.
1456              
1457             The keys from this C<extras> hash will be merged into the final C<%args> passed to
1458             completion routines. Note that standard keys like C<word>, C<cword>, and so on as
1459             described in the function description will not be overwritten by this.
1460              
1461             =item * B<func_arg_starts_at> => I<int> (default: 0)
1462              
1463             This is a (temporary?) workaround for L<Perinci::CmdLine>. In an application
1464             with subcommands (e.g. C<cmd --verbose subcmd arg0 arg1 ...>), then C<words> will
1465             still contain the subcommand name. Positional function arguments then start at 1
1466             not 0. This option allows offsetting function arguments.
1467              
1468             =item * B<meta>* => I<hash>
1469              
1470             Rinci function metadata.
1471              
1472             =item * B<per_arg_json> => I<bool>
1473              
1474             Will be passed to Perinci::Sub::GetArgs::Argv.
1475              
1476             =item * B<per_arg_yaml> => I<bool>
1477              
1478             Will be passed to Perinci::Sub::GetArgs::Argv.
1479              
1480             =item * B<riap_client> => I<obj>
1481              
1482             Optional, to perform complete_arg_val to the server.
1483              
1484             When the argument spec in the Rinci metadata contains C<completion> key, this
1485             means there is custom completion code for that argument. However, if retrieved
1486             from a remote server, sometimes the C<completion> key no longer contains the code
1487             (it has been cleansed into a string). Moreover, the completion code needs to run
1488             on the server.
1489              
1490             If supplied this argument and te C<riap_server_url> argument, the function will
1491             try to request to the server (via Riap request C<complete_arg_val>). Otherwise,
1492             the function will just give up/decline completing.
1493              
1494             =item * B<riap_server_url> => I<str>
1495              
1496             Optional, to perform complete_arg_val to the server.
1497              
1498             See the C<riap_client> argument.
1499              
1500             =item * B<riap_uri> => I<str>
1501              
1502             Optional, to perform complete_arg_val to the server.
1503              
1504             See the C<riap_client> argument.
1505              
1506             =item * B<words>* => I<array[str]>
1507              
1508             Command-line arguments.
1509              
1510              
1511             =back
1512              
1513             Return value: (hash)
1514              
1515              
1516             You can use C<format_completion> function in L<Complete::Bash> module to format
1517             the result of this function for bash.
1518              
1519              
1520              
1521             =head2 complete_from_schema
1522              
1523             Usage:
1524              
1525             complete_from_schema(%args) -> [$status_code, $reason, $payload, \%result_meta]
1526              
1527             Complete a value from schema.
1528              
1529             Employ some heuristics to complete a value from Sah schema. For example, if
1530             schema is C<< [str =E<gt> in =E<gt> [qw/new open resolved rejected/]] >>, then we can
1531             complete from the C<in> clause. Or for something like C<< [int =E<gt> between =E<gt> [1,
1532             20]] >> we can complete using values from 1 to 20.
1533              
1534             This function is not exported by default, but exportable.
1535              
1536             Arguments ('*' denotes required arguments):
1537              
1538             =over 4
1539              
1540             =item * B<schema>* => I<any>
1541              
1542             Will be normalized, unless when C<schema_is_normalized> is set to true, in which
1543             case schema must already be normalized.
1544              
1545             =item * B<schema_is_normalized> => I<bool> (default: 0)
1546              
1547             =item * B<word>* => I<str> (default: "")
1548              
1549              
1550             =back
1551              
1552             Returns an enveloped result (an array).
1553              
1554             First element ($status_code) is an integer containing HTTP-like status code
1555             (200 means OK, 4xx caller error, 5xx function error). Second element
1556             ($reason) is a string containing error message, or something like "OK" if status is
1557             200. Third element ($payload) is the actual result, but usually not present when enveloped result is an error response ($status_code is not 2xx). Fourth
1558             element (%result_meta) is called result metadata and is optional, a hash
1559             that contains extra information, much like how HTTP response headers provide additional metadata.
1560              
1561             Return value: (any)
1562              
1563             =for Pod::Coverage ^(.+)$
1564              
1565             =head1 HOMEPAGE
1566              
1567             Please visit the project's homepage at L<https://metacpan.org/release/Perinci-Sub-Complete>.
1568              
1569             =head1 SOURCE
1570              
1571             Source repository is at L<https://github.com/perlancar/perl-Perinci-Sub-Complete>.
1572              
1573             =head1 SEE ALSO
1574              
1575             L<Complete>, L<Complete::Getopt::Long>
1576              
1577             L<Perinci::CmdLine>, L<Perinci::CmdLine::Lite>, L<App::riap>
1578              
1579             =head1 AUTHOR
1580              
1581             perlancar <perlancar@cpan.org>
1582              
1583             =head1 CONTRIBUTOR
1584              
1585             =for stopwords Steven Haryanto
1586              
1587             Steven Haryanto <stevenharyanto@gmail.com>
1588              
1589             =head1 CONTRIBUTING
1590              
1591              
1592             To contribute, you can send patches by email/via RT, or send pull requests on
1593             GitHub.
1594              
1595             Most of the time, you don't need to build the distribution yourself. You can
1596             simply modify the code, then test via:
1597              
1598             % prove -l
1599              
1600             If you want to build the distribution (e.g. to try to install it locally on your
1601             system), you can install L<Dist::Zilla>,
1602             L<Dist::Zilla::PluginBundle::Author::PERLANCAR>,
1603             L<Pod::Weaver::PluginBundle::Author::PERLANCAR>, and sometimes one or two other
1604             Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond
1605             that are considered a bug and can be reported to me.
1606              
1607             =head1 COPYRIGHT AND LICENSE
1608              
1609             This software is copyright (c) 2022, 2020, 2019, 2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011 by perlancar <perlancar@cpan.org>.
1610              
1611             This is free software; you can redistribute it and/or modify it under
1612             the same terms as the Perl 5 programming language system itself.
1613              
1614             =head1 BUGS
1615              
1616             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Perinci-Sub-Complete>
1617              
1618             When submitting a bug or request, please include a test-file or a
1619             patch to an existing test-file that illustrates the bug or desired
1620             feature.
1621              
1622             =cut