File Coverage

blib/lib/Complete/Getopt/Long.pm
Criterion Covered Total %
statement 257 344 74.7
branch 125 232 53.8
condition 61 83 73.4
subroutine 10 10 100.0
pod 1 1 100.0
total 454 670 67.7


line stmt bran cond sub pod time code
1              
2             use 5.010001;
3 1     1   9292 use strict;
  1         3  
4 1     1   4 use warnings;
  1         2  
  1         18  
5 1     1   4 use Log::ger;
  1         1  
  1         19  
6 1     1   4  
  1         1  
  1         4  
7             use Exporter 'import';
8 1     1   164  
  1         2  
  1         3229  
9             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
10             our $DATE = '2022-08-28'; # DATE
11             our $DIST = 'Complete-Getopt-Long'; # DIST
12             our $VERSION = '0.481'; # VERSION
13              
14             our @EXPORT_OK = qw(
15             complete_cli_arg
16             );
17              
18             our %SPEC;
19              
20             our $COMPLETE_GETOPT_LONG_TRACE=$ENV{COMPLETE_GETOPT_LONG_TRACE} // 0;
21             our $COMPLETE_GETOPT_LONG_DEFAULT_ENV = $ENV{COMPLETE_GETOPT_LONG_DEFAULT_ENV} // 1;
22             our $COMPLETE_GETOPT_LONG_DEFAULT_FILE = $ENV{COMPLETE_GETOPT_LONG_DEFAULT_FILE} // 1;
23              
24             require Complete::Env;
25             require Complete::File;
26 1     1   1199 require Complete::Util;
27 1         1715  
28 1         1730 my %args = @_;
29             my $word = $args{word} // '';
30 1         7  
31 1   50     5 my $fres;
32             log_trace('[compgl] entering default completion routine') if $COMPLETE_GETOPT_LONG_TRACE;
33 1         2  
34 1 50       3 # try completing '$...' with shell variables
35             if ($word =~ /\A\$/ && $COMPLETE_GETOPT_LONG_DEFAULT_ENV) {
36             log_trace('[compgl] completing shell variable') if $COMPLETE_GETOPT_LONG_TRACE;
37 1 0 33     3 {
38 0 0       0 my $compres = Complete::Env::complete_env(
39             word=>$word);
40 0         0 last unless @$compres;
  0         0  
41             $fres = {words=>$compres, esc_mode=>'shellvar'};
42 0 0       0 goto RETURN_RES;
43 0         0 }
44 0         0 # if empty, fallback to searching file
45             }
46              
47             # try completing '~foo' with user dir (appending / if user's home exists)
48             if ($word =~ m!\A~([^/]*)\z! && $COMPLETE_GETOPT_LONG_DEFAULT_FILE) {
49             log_trace("[compgl] completing userdir, user=%s", $1) if $COMPLETE_GETOPT_LONG_TRACE;
50 1 0 33     3 {
51 0 0       0 eval { require Unix::Passwd::File };
52             last if $@;
53 0         0 my $res = Unix::Passwd::File::list_users(detail=>1);
  0         0  
  0         0  
54 0 0       0 last unless $res->[0] == 200;
55 0         0 my $compres = Complete::Util::complete_array_elem(
56 0 0       0 array=>[map {"~" . $_->{user} . ((-d $_->{home}) ? "/":"")}
57             @{ $res->[2] }],
58 0 0       0 word=>$word,
59 0         0 );
  0         0  
60             last unless @$compres;
61             $fres = {words=>$compres, path_sep=>'/'};
62 0 0       0 goto RETURN_RES;
63 0         0 }
64 0         0 # if empty, fallback to searching file
65             }
66              
67             # try completing '~/blah' or '~foo/blah' as if completing file, but do not
68             # expand ~foo (this is supported by complete_file(), so we just give it off
69             # to the routine)
70             if ($word =~ m!\A(~[^/]*)/! && $COMPLETE_GETOPT_LONG_DEFAULT_FILE) {
71             log_trace("[compgl] completing file, path=<%s>", $word) if $COMPLETE_GETOPT_LONG_TRACE;
72 1 0 33     3 $fres = Complete::Util::hashify_answer(
73 0 0       0 Complete::File::complete_file(word=>$word),
74 0         0 {path_sep=>'/'}
75             );
76             goto RETURN_RES;
77             }
78 0         0  
79             # try completing something that contains wildcard with glob. for
80             # convenience, we add '*' at the end so that when user type [AB] it is
81             # treated like [AB]*.
82             require String::Wildcard::Bash;
83             if (String::Wildcard::Bash::contains_wildcard($word) && $COMPLETE_GETOPT_LONG_DEFAULT_FILE) {
84 1         1003 log_trace("[compgl] completing with wildcard glob, glob=<%s>", "$word*") if $COMPLETE_GETOPT_LONG_TRACE;
85 1 0 33     1433 {
86 0 0       0 my $compres = [glob("$word*")];
87             last unless @$compres;
88 0         0 for (@$compres) {
  0         0  
89 0 0       0 $_ .= "/" if (-d $_);
90 0         0 }
91 0 0       0 $fres = {words=>$compres, path_sep=>'/'};
92             goto RETURN_RES;
93 0         0 }
94 0         0 # if empty, fallback to searching file
95             }
96              
97             if ($COMPLETE_GETOPT_LONG_DEFAULT_FILE) {
98             log_trace("[compgl] completing with file, file=<%s>", $word) if $COMPLETE_GETOPT_LONG_TRACE;
99 1 50       23 $fres = Complete::Util::hashify_answer(
100 1 50       3 Complete::File::complete_file(word=>$word),
101 1         4 {path_sep=>'/'}
102             );
103             }
104              
105             RETURN_RES:
106             log_trace("[compgl] leaving default completion routine, result=%s", $fres) if $COMPLETE_GETOPT_LONG_TRACE;
107             $fres;
108 1 50       17769 }
109 1         5  
110             # return the possible options. if there is only one candidate (unambiguous
111             # expansion) then scalar will be returned. otherwise, an array of candidates
112             # will be returned.
113             my ($opt, $opts) = @_;
114             my %candidates;
115             for (sort {length($a)<=>length($b)} keys %$opts) {
116 41     41   68 next unless index($_, $opt) == 0;
117 41         46 $candidates{$_} = $opts->{$_};
118 41         155 last if $opt eq $_;
  1189         1319  
119 274 100       451 }
120 108         159 \%candidates;
121 108 100       172 }
122              
123 41         90 # mark an option (and all its aliases) as seen
124             my ($seen_opts, $opt, $opts) = @_;
125             my $opthash = $opts->{$opt};
126             return unless $opthash;
127             my $ospec = $opthash->{ospec};
128 48     48   79 for (keys %$opts) {
129 48         72 my $v = $opts->{$_};
130 48 50       77 $seen_opts->{$_}++ if $v->{ospec} eq $ospec;
131 48         52 }
132 48         158 }
133 632         666  
134 632 100       993 $SPEC{complete_cli_arg} = {
135             v => 1.1,
136             summary => 'Complete command-line argument using '.
137             'Getopt::Long specification',
138             description => <<'_',
139              
140             This routine can complete option names, where the option names are retrieved
141             from <pm:Getopt::Long> specification. If you provide completion routine in
142             `completion`, you can also complete _option values_ and _arguments_.
143              
144             Note that this routine does not use <pm:Getopt::Long> (it does its own parsing)
145             and currently is not affected by Getopt::Long's configuration. Its behavior
146             mimics Getopt::Long under these configuration: `no_ignore_case`, `bundling` (or
147             `no_bundling` if the `bundling` option is turned off). Which I think is the
148             sensible default. This routine also does not currently support `auto_help` and
149             `auto_version`, so you'll need to add those options specifically if you want to
150             recognize `--help/-?` and `--version`, respectively.
151              
152             _
153             args => {
154             getopt_spec => {
155             summary => 'Getopt::Long specification',
156             schema => 'array*',
157             req => 1,
158             },
159             completion => {
160             summary =>
161             'Completion routine to complete option value/argument',
162             schema => 'code*',
163             description => <<'_',
164              
165             Completion code will receive a hash of arguments (`%args`) containing these
166             keys:
167              
168             * `type` (str, what is being completed, either `optval`, or `arg`)
169             * `word` (str, word to be completed)
170             * `cword` (int, position of words in the words array, starts from 0)
171             * `opt` (str, option name, e.g. `--str`; undef if we're completing argument)
172             * `ospec` (str, Getopt::Long option spec, e.g. `str|S=s`; undef when completing
173             argument)
174             * `argpos` (int, argument position, zero-based; undef if type='optval')
175             * `nth` (int, the number of times this option has seen before, starts from 0
176             that means this is the first time this option has been seen; undef when
177             type='arg')
178             * `seen_opts` (hash, all the options seen in `words`)
179             * `parsed_opts` (hash, options parsed the standard/raw way)
180              
181             as well as all keys from `extras` (but these won't override the above keys).
182              
183             and is expected to return a completion answer structure as described in
184             `Complete` which is either a hash or an array. The simplest form of answer is
185             just to return an array of strings. The various `complete_*` function like those
186             in <pm:Complete::Util> or the other `Complete::*` modules are suitable to use
187             here.
188              
189             Completion routine can also return undef to express declination, in which case
190             the default completion routine will then be consulted. The default routine
191             completes from shell environment variables (`$FOO`), Unix usernames (`~foo`),
192             and files/directories.
193              
194             Example:
195              
196             use Complete::Unix qw(complete_user);
197             use Complete::Util qw(complete_array_elem);
198             complete_cli_arg(
199             getopt_spec => [
200             'help|h' => sub{...},
201             'format=s' => \$format,
202             'user=s' => \$user,
203             ],
204             completion => sub {
205             my %args = @_;
206             my $word = $args{word};
207             my $ospec = $args{ospec};
208             if ($ospec && $ospec eq 'format=s') {
209             complete_array_elem(array=>[qw/json text xml yaml/], word=>$word);
210             } else {
211             complete_user(word=>$word);
212             }
213             },
214             );
215              
216             _
217             },
218             words => {
219             summary => 'Command line arguments, like @ARGV',
220             description => <<'_',
221              
222             See function `parse_cmdline` in <pm:Complete::Bash> on how to produce this (if
223             you're using bash).
224              
225             _
226             schema => 'array*',
227             req => 1,
228             },
229             cword => {
230             summary =>
231             "Index in words of the word we're trying to complete",
232             description => <<'_',
233              
234             See function `parse_cmdline` in <pm:Complete::Bash> on how to produce this (if
235             you're using bash).
236              
237             _
238             schema => 'int*',
239             req => 1,
240             },
241             extras => {
242             summary => 'Add extra arguments to completion routine',
243             schema => 'hash',
244             description => <<'_',
245              
246             The keys from this `extras` hash will be merged into the final `%args` passed to
247             completion routines. Note that standard keys like `type`, `word`, and so on as
248             described in the function description will not be overwritten by this.
249              
250             _
251             },
252             bundling => {
253             schema => 'bool*',
254             default => 1,
255             'summary.alt.bool.not' => 'Turn off bundling',
256             description => <<'_',
257              
258             If you turn off bundling, completion of short-letter options won't support
259             bundling (e.g. `-b<tab>` won't add more single-letter options), but single-dash
260             multiletter options can be recognized. Currently only those specified with a
261             single dash will be completed. For example if you have `-foo=s` in your option
262             specification, `-f<tab>` can complete it.
263              
264             This can be used to complete old-style programs, e.g. emacs which has options
265             like `-nw`, `-nbc` etc (but also have double-dash options like
266             `--no-window-system` or `--no-blinking-cursor`).
267              
268             _
269             },
270             },
271             result_naked => 1,
272             result => {
273             schema => ['any*' => of => ['hash*', 'array*']],
274             description => <<'_',
275              
276             You can use `format_completion` function in <pm:Complete::Bash> module to format
277             the result of this function for bash.
278              
279             _
280             },
281             };
282             require Complete::Util;
283             require Getopt::Long::Util;
284              
285             my %args = @_;
286              
287 35     35 1 124601 my $fname = __PACKAGE__ . "::complete_cli_arg"; # XXX use __SUB__
288 35         5924 my $fres;
289              
290 35         1838 $args{words} or die "Please specify words";
291             my @words = @{ $args{words} };
292 35         60 defined(my $cword = $args{cword}) or die "Please specify cword";
293 35         41 my $gospec = $args{getopt_spec} or die "Please specify getopt_spec";
294             my $comp = $args{completion};
295 35 50       78 my $extras = $args{extras} // {};
296 35         46 my $bundling = $args{bundling} // 1;
  35         69  
297 35 50       76 my %parsed_opts;
298 35 50       60  
299 35         56 # backward compatibility: gospec was expected to be a hash, now an array
300 35   100     113 if (ref $gospec eq 'HASH') {
301 35   100     82 my $ary_gospec = [];
302 35         42 for (keys %$gospec) {
303             push @$ary_gospec, $_;
304             push @$ary_gospec, $gospec->{$_} if ref $gospec->{$_};
305 35 100       77 }
306 1         2 $gospec = $ary_gospec;
307 1         3 }
308 2         4  
309 2 50       5 log_trace('[compgl] entering %s(), words=%s, cword=%d, word=<%s>',
310             $fname, \@words, $cword, $words[$cword]) if $COMPLETE_GETOPT_LONG_TRACE;
311 1         2  
312             # strip hash storage from getopt_spec
313             shift @$gospec if ref $gospec->[0] eq 'HASH';
314 35 50       60  
315             # parse all options first & supply default completion routine
316             my %opts;
317             my $i = -1;
318 35 100       73 while (++$i <= $#{$gospec}) {
319             my $ospec = $gospec->[$i];
320             my $dest = $i+1 <= $#{$gospec} && ref $gospec->[$i+1] ?
321 35         39 splice(@$gospec, $i+1, 1) : undef;
322 35         36  
323 35         45 my $res = Getopt::Long::Util::parse_getopt_long_opt_spec($ospec)
  248         450  
324 213         288 or die "Can't parse option spec '$ospec'";
325 213 100 100     261 next if $res->{is_arg};
326             $res->{min_vals} //= $res->{type} ? 1 : 0;
327             $res->{max_vals} //= $res->{type} || $res->{opttype} ? 1:0;
328 213 50       418 for my $o0 (@{ $res->{opts} }) {
329             my @ary = $res->{is_neg} && length($o0) > 1 ?
330 213 50       8664 ([$o0, 0], ["no$o0",1], ["no-$o0",1]) : ([$o0,0]);
331 213 100 66     750 for my $elem (@ary) {
332 213 100 100     782 my $o = $elem->[0];
      66        
333 213         232 my $is_neg = $elem->[1];
  213         337  
334 363 100 100     937 my $k = length($o)==1 ||
335             (!$bundling && $res->{dash_prefix} eq '-') ?
336 363         478 "-$o" : "--$o";
337 411         555 $opts{$k} = {
338 411         436 name => $k,
339             ospec => $ospec,
340 411 100 100     1158 dest => $dest,
341             parsed => $res,
342 411         1512 is_neg => $is_neg,
343             };
344             }
345             }
346             }
347             my @optnames = sort keys %opts;
348              
349             my $code_get_summary = sub {
350             # currently we only extract summaries from Rinci metadata and
351             # Perinci::CmdLine object
352 35         245 return unless $extras;
353             my $ggls_res = $extras->{ggls_res};
354             return unless $ggls_res;
355             my $r = $extras->{r};
356             return unless $r;
357 169 50   169   233 my $cmdline = $extras->{cmdline};
358 169         192  
359 169 50       360 my $optname = shift;
360 0         0 my $ospec = $opts{$optname}{ospec};
361 0 0       0 return unless $ospec; # shouldn't happen
362 0         0 my $specmeta = $ggls_res->[3]{'func.specmeta'};
363             my $ospecmeta = $specmeta->{$ospec};
364 0         0  
365 0         0 return $ospecmeta->{summary} if defined $ospecmeta->{summary};
366 0 0       0  
367 0         0 if ($ospecmeta->{is_alias}) {
368 0         0 my $real_ospecmeta = $specmeta->{ $ospecmeta->{alias_for} };
369             my $real_opt = $real_ospecmeta->{parsed}{opts}[0];
370 0 0       0 $real_opt = length($real_opt) == 1 ? "-$real_opt" : "--$real_opt";
371             return "Alias for $real_opt";
372 0 0       0 }
373 0         0  
374 0         0 if (defined(my $coptname = $ospecmeta->{common_opt})) {
375 0 0       0 # it's a common Perinci::CmdLine option
376 0         0 my $coptspec = $cmdline ? $cmdline->{common_opts}{$coptname} :
377             $r->{common_opts} ? $r->{common_opts}{$coptname} : undef;
378             #use DD; dd $coptspec;
379 0 0       0 return unless $coptspec;
380              
381             my $summ;
382 0 0       0 # XXX translate
    0          
383             if ($opts{$optname}{is_neg}) {
384 0 0       0 $summ = $coptspec->{"summary.alt.bool.not"};
385             return $summ if defined $summ;
386 0         0 my $pos_opt = $ospecmeta->{pos_opts}[0];
387             $pos_opt = length($pos_opt) == 1 ? "-$pos_opt" : "--$pos_opt";
388 0 0       0 return "The opposite of $pos_opt";
389 0         0 } else {
390 0 0       0 $summ = $coptspec->{"summary.alt.bool.yes"};
391 0         0 return $summ if defined $summ;
392 0 0       0 $summ = $coptspec->{"summary"};
393 0         0 return $summ if defined $summ;
394             }
395 0         0 } else {
396 0 0       0 # it's option from function argument
397 0         0 my $arg = $ospecmeta->{arg};
398 0 0       0 my $argspec = $extras->{r}{meta}{args}{$arg};
399             #use DD; dd $argspec;
400              
401             my $summ;
402 0         0 # XXX translate
403 0         0 #use DD; dd {optname=>$optname, ospecmeta=>$ospecmeta};
404             if ($ospecmeta->{is_neg}) {
405             $summ = $argspec->{"summary.alt.bool.not"};
406 0         0 return $summ if defined $summ;
407             my $pos_opt = $ospecmeta->{pos_opts}[0];
408             $pos_opt = length($pos_opt) == 1 ? "-$pos_opt" : "--$pos_opt";
409 0 0       0 return "The opposite of $pos_opt";
410 0         0 } else {
411 0 0       0 $summ = $argspec->{"summary.alt.bool.yes"};
412 0         0 return $summ if defined $summ;
413 0 0       0 $summ = $argspec->{"summary"};
414 0         0 return $summ if defined $summ;
415             }
416 0         0 }
417 0 0       0  
418 0         0 return;
419 0 0       0 };
420              
421             my %seen_opts;
422              
423 0         0 # for each word (each element in this array), we try to find out whether
424 35         254 # it's supposed to complete option name, or option value, or argument, or
425             # separator (or more than one of them). plus some other information.
426 35         71 #
427             # each element is a hash. if hash contains 'optname' key then it expects an
428             # option name. if hash contains 'optval' key then it expects an option
429             # value.
430             #
431             # 'short_only' means that the word is not to be completed with long option
432             # name, only (bundle of) one-letter option names.
433              
434             my @expects;
435              
436             $i = -1;
437             my $argpos = 0;
438              
439             WORD:
440             while (1) {
441 35         41 last WORD if ++$i >= @words;
442 35         38 my $word = $words[$i];
443             #say "D:i=$i, word=$word, ~~\@words=",~~@words;
444              
445 35         41 if ($word eq '--' && $i != $cword) {
446 80 100       167 $expects[$i] = {separator=>1};
447 48         85 while (1) {
448             $i++;
449             last WORD if $i >= @words;
450 48 50 66     91 $expects[$i] = {arg=>1, argpos=>$argpos++};
451 0         0 }
452 0         0 }
453 0         0  
454 0 0       0 if ($word =~ /\A-/) {
455 0         0  
456             # check if it is a (bundle) of short option names
457             SHORT_OPTS:
458             {
459 48 100       144 # it's not a known short option
460             last unless $opts{"-".substr($word,1,1)};
461              
462             # not a bundle, regard as only a single short option name
463             last unless $bundling;
464              
465 41 100       46 # expand bundle
  41         113  
466             my $j = $i;
467             my $rest = substr($word, 1);
468 12 100       22 my @inswords;
469             my $encounter_equal_sign;
470             EXPAND:
471 11         13 while (1) {
472 11         16 $rest =~ s/(.)// or last;
473 11         14 my $opt = "-$1";
474             my $opthash = $opts{$opt};
475             unless ($opthash) {
476 11         11 # we encounter an unknown option, doubt that this is a
477 27 100       78 # bundle of short option name, it could be someone
478 20         38 # typing --long as -long
479 20         27 @inswords = ();
480 20 50       30 $expects[$i]{short_only} = 0;
481             $rest = $word;
482             last EXPAND;
483             }
484 0         0 if ($opthash->{parsed}{max_vals}) {
485 0         0 # stop after an option that requires value
486 0         0 _mark_seen(\%seen_opts, $opt, \%opts);
487 0         0  
488             if ($i == $j) {
489 20 100       38 $words[$i] = $opt;
490             } else {
491 4         8 push @inswords, $opt;
492             $j++;
493 4 100       9 }
494 2         4  
495             my $expand;
496 2         12 if (length $rest) {
497 2         3 $expand++;
498             # complete -Sfoo^ is completing option value
499             $expects[$j > $i ? $j+1 : $j+2]{do_complete_optname} = 0;
500 4         5 $expects[$j > $i ? $j+1 : $j+2]{optval} = $opt;
501 4 100       9 } else {
502 2         3 # complete -S^ as [-S] to add space
503             $expects[$j > $i ? $j-1 : $j]{optname} = $opt;
504 2 100       14 $expects[$j > $i ? $j-1 : $j]{comp_result} = [
505 2 100       7 substr($word, 0, length($word)-length($rest))];
506             }
507              
508 2 100       16 if ($rest =~ s/\A=//) {
509             $encounter_equal_sign++;
510 2 100       10 }
511              
512             if ($expand) {
513 4 50       9 push @inswords, "=", $rest;
514 0         0 $j+=2;
515             }
516             last EXPAND;
517 4 100       8 }
518 2         4 # continue splitting
519 2         3 _mark_seen(\%seen_opts, $opt, \%opts);
520             if ($i == $j) {
521 4         8 $words[$i] = $opt;
522             } else {
523             push @inswords, $opt;
524 16         31 }
525 16 100       42 $j++;
526 9         12 }
527              
528 7         11 #use DD; print "D:inswords: "; dd \@inswords;
529              
530 16         19 my $prefix = $encounter_equal_sign ? '' :
531             substr($word, 0, length($word)-length($rest));
532             splice @words, $i+1, 0, @inswords;
533             for (0..@inswords) {
534             $expects[$i+$_]{prefix} = $prefix;
535 11 50       23 $expects[$i+$_]{word} = $rest;
536             }
537 11         28 $cword += @inswords;
538 11         26 $i += @inswords;
539 24         55 $word = $words[$i];
540 24         41 $expects[$i]{short_only} //= 1;
541             } # SHORT_OPTS
542 11         13  
543 11         13 # split --foo=val -> --foo, =, val
544 11         19 SPLIT_EQUAL:
545 11   50     39 {
546             if ($word =~ /\A(--?[^=]+)(=)(.*)/) {
547             splice @words, $i, 1, $1, $2, $3;
548             $word = $1;
549             $cword += 2 if $cword >= $i;
550             }
551 41 100       53 }
  41         89  
552 4         14  
553 4         9 my $opt = $word;
554 4 50       18 my $matching_opts = _matching_opts($opt, \%opts);
555              
556             if (keys(%$matching_opts) == 1) {
557             my $opthash = $matching_opts->{ (keys %$matching_opts)[0] };
558 41         59 $opt = $opthash->{name};
559 41         73 $expects[$i]{optname} = $opt;
560             my $nth = $seen_opts{$opt} // 0;
561 41 100       93 $expects[$i]{nth} = $nth;
562 28         53 _mark_seen(\%seen_opts, $opt, \%opts);
563 28         45  
564 28         58 my $min_vals = $opthash->{parsed}{min_vals};
565 28   100     69 my $max_vals = $opthash->{parsed}{max_vals};
566 28         35 #say "D:min_vals=$min_vals, max_vals=$max_vals";
567 28         57  
568             # detect = after --opt
569 28         53 if ($i+1 < @words && $words[$i+1] eq '=') {
570 28         31 $i++;
571             $expects[$i] = {separator=>1, optval=>$opt, word=>'', nth=>$nth};
572             # force expecting a value due to =
573             $min_vals = 1;
574 28 100 100     107 $max_vals = $min_vals if $max_vals < $min_vals;
575 3         5 }
576 3         9  
577             for (1 .. $min_vals) {
578 3         5 $i++;
579 3 100       6 last WORD if $i >= @words;
580             $expects[$i]{optval} = $opt;
581             $expects[$i]{nth} = $nth;
582 28         57 push @{ $parsed_opts{$opt} }, $words[$i];
583 16         33 }
584 16 100       33 for (1 .. $max_vals-$min_vals) {
585 13         28 last if $i+$_ >= @words;
586 13         25 last if $words[$i+$_] =~ /\A-/; # a new option
587 13         19 $expects[$i+$_]{optval} = $opt; # but can also be optname
  13         41  
588             $expects[$i]{nth} = $nth;
589 25         95 push @{ $parsed_opts{$opt} }, $words[$i+$_];
590 1 50       4 }
591 1 50       3 } else {
592 1         3 # an unknown or still ambiguous option, assume it doesn't
593 1         2 # require argument, unless it's --opt= or --opt=foo
594 1         2 $opt = undef;
  1         4  
595             $expects[$i]{optname} = $opt;
596             my $possible_optnames = [sort keys %$matching_opts];
597             $expects[$i]{possible_optnames} = $possible_optnames;
598              
599 13         14 # detect = after --opt
600 13         26 if ($i+1 < @words && $words[$i+1] eq '=') {
601 13         52 $i++;
602 13         22 $expects[$i] = {separator=>1, optval=>undef, possible_optnames=>$possible_optnames, word=>''};
603             if ($i+1 < @words) {
604             $i++;
605 13 100 100     53 $expects[$i]{optval} = $opt;
606 1         2 $expects[$i]{possible_optnames} = $possible_optnames;
607 1         3 }
608 1 50       3 }
609 1         2 }
610 1         1 } else {
611 1         4 $expects[$i]{optname} = '';
612             $expects[$i]{arg} = 1;
613             $expects[$i]{argpos} = $argpos++;
614             }
615             }
616 7         14  
617 7         10 my $exp = $expects[$cword];
618 7         17 my $word = $exp->{word} // $words[$cword];
619              
620             #use DD; say "D:opts: "; dd \%opts;
621             #use DD; print "D:words: "; dd \@words;
622 35         72 #say "D:cword: $cword";
623 35   100     99 #use DD; print "D:expects: "; dd \@expects;
624             #use DD; print "D:seen_opts: "; dd \%seen_opts;
625             #use DD; print "D:parsed_opts: "; dd \%parsed_opts;
626             #use DD; print "D:exp: "; dd $exp;
627             #use DD; say "D:word:<$word>";
628              
629             my @answers;
630              
631             # complete option names
632             {
633             last if $word =~ /\A[^-]/;
634 35         50 last unless exists $exp->{optname};
635             last if defined($exp->{do_complete_optname}) &&
636             !$exp->{do_complete_optname};
637             if ($exp->{comp_result}) {
638 35 100       70 push @answers, $exp->{comp_result};
639 33 100       59 last;
640             }
641 26 50 33     47 #say "D:completing option names";
642 26 100       41 my $opt = $exp->{optname};
643 2         3 my @o;
644 2         3 my @osumms;
645             my $o_has_summaries;
646             for my $optname (@optnames) {
647 24         31 my $repeatable = 0;
648 24         41 next if $exp->{short_only} && $optname =~ /\A--/;
649             if ($seen_opts{$optname}) {
650 24         0 my $opthash = $opts{$optname};
651 24         38 my $parsed = $opthash->{parsed};
652 247         272 my $dest = $opthash->{dest};
653 247 100 100     443 if (ref $dest eq 'ARRAY') {
654 197 100       270 $repeatable = 1;
655 34         39 } elsif ($parsed->{desttype} || $parsed->{is_inc}) {
656 34         42 $repeatable = 1;
657 34         44 }
658 34 100 66     126 }
    100          
659 1         1 # skip options that have been specified and not repeatable
660             #use DD; dd {'$_'=>$_, seen=>$seen_opts{$_}, repeatable=>$repeatable, opt=>$opt};
661 3         5 next if $seen_opts{$optname} && !$repeatable && (
662             # long option has been specified
663             (!$opt || $opt ne $optname) ||
664             # short option (in a bundle) has been specified
665             (defined($exp->{prefix}) &&
666             index($exp->{prefix}, substr($opt, 1, 1)) >= 0));
667             if (defined $exp->{prefix}) {
668             my $o = $optname; $o =~ s/\A-//;
669             push @o, "$exp->{prefix}$o";
670             } else {
671 197 100 100     391 push @o, $optname;
      66        
      100        
672 169 100       210 }
673 18         22 my $summ = $code_get_summary->($optname) // '';
  18         37  
674 18         33 if (length $summ) {
675             $o_has_summaries = 1;
676 151         192 push @osumms, $summ;
677             } else {
678 169   50     223 push @osumms, '';
679 169 50       230 }
680 0         0 }
681 0         0 #use DD; dd \@o;
682             #use DD; dd \@osumms;
683 169         244 my $compres = Complete::Util::complete_array_elem(
684             array => \@o, word => $word,
685             (summaries => \@osumms) x !!$o_has_summaries,
686             );
687             log_trace('[compgl] adding result from option names, '.
688 24         69 'matching options=%s', $compres) if $COMPLETE_GETOPT_LONG_TRACE;
689             push @answers, $compres;
690             if (!exists($exp->{optval}) && !exists($exp->{arg})) {
691             $fres = {words=>$compres, esc_mode=>'option'};
692 24 50       3264 goto RETURN_RES;
693             }
694 24         32 }
695 24 100 100     88  
696 17         40 # complete option value
697 17         215 {
698             last unless exists($exp->{optval});
699             #say "D:completing option value";
700             my $opt = $exp->{optval};
701             my $opthash; $opthash = $opts{$opt} if $opt;
702             my %compargs = (
703 35 100       35 %$extras,
  18         32  
704             type=>'optval', words=>\@words, cword=>$args{cword},
705 10         13 word=>$word, opt=>($opt // $exp->{possible_optnames}), ospec=>$opthash->{ospec},
706 10 100       11 argpos=>undef, nth=>$exp->{nth}, seen_opts=>\%seen_opts,
  10         20  
707             parsed_opts=>\%parsed_opts,
708             );
709             my $compres;
710             if ($comp) {
711 10   66     87 log_trace("[compgl] invoking routine supplied from 'completion' argument to complete option value, option=<%s>", $opt) if $COMPLETE_GETOPT_LONG_TRACE;
712             $compres = $comp->(%compargs);
713             Complete::Util::modify_answer(answer=>$compres, prefix=>$exp->{prefix})
714 10         16 if defined $exp->{prefix};
715 10 50       25 log_trace('[compgl] adding result from routine: %s', $compres) if $COMPLETE_GETOPT_LONG_TRACE;
716 10 50       17 }
717 10         43 if (!$compres || !$comp) {
718             $compres = _default_completion(%compargs);
719 10 100       244 Complete::Util::modify_answer(answer=>$compres, prefix=>$exp->{prefix})
720 10 50       47 if defined $exp->{prefix};
721             log_trace('[compgl] adding result from default '.
722 10 50 33     28 'completion routine') if $COMPLETE_GETOPT_LONG_TRACE;
723 0         0 }
724             push @answers, $compres;
725 0 0       0 }
726 0 0       0  
727             # complete argument
728             {
729 10         30 last unless exists($exp->{arg});
730             my %compargs = (
731             %$extras,
732             type=>'arg', words=>\@words, cword=>$args{cword},
733             word=>$word, opt=>undef, ospec=>undef,
734 18 100       18 argpos=>$exp->{argpos}, seen_opts=>\%seen_opts,
  18         25  
  18         36  
735             parsed_opts=>\%parsed_opts,
736             );
737             log_trace('[compgl] invoking \'completion\' routine '.
738             'to complete argument') if $COMPLETE_GETOPT_LONG_TRACE;
739 7         39 my $compres; $compres = $comp->(%compargs) if $comp;
740             if (!defined $compres) {
741             $compres = _default_completion(%compargs);
742 7 50       13 log_trace('[compgl] adding result from default '.
743             'completion routine: %s', $compres) if $COMPLETE_GETOPT_LONG_TRACE;
744 7 100       9 }
  7         27  
745 7 100       23 push @answers, $compres;
746 1         7 }
747 1 50       3  
748             log_trace("[compgl] combining result from %d source(s)", scalar @answers) if $COMPLETE_GETOPT_LONG_TRACE;
749             $fres = Complete::Util::combine_answers(@answers) // [];
750 7         19  
751             RETURN_RES:
752             log_trace("[compgl] leaving %s(), result=%s", $fname, $fres) if $COMPLETE_GETOPT_LONG_TRACE;
753 18 50       33 $fres;
754 18   50     38 }
755              
756 35 50       879 1;
757             # ABSTRACT: Complete command-line argument using Getopt::Long specification
758 35         704  
759              
760             =pod
761              
762             =encoding UTF-8
763              
764             =head1 NAME
765              
766             Complete::Getopt::Long - Complete command-line argument using Getopt::Long specification
767              
768             =head1 VERSION
769              
770             This document describes version 0.481 of Complete::Getopt::Long (from Perl distribution Complete-Getopt-Long), released on 2022-08-28.
771              
772             =head1 SYNOPSIS
773              
774             See L<Getopt::Long::Complete> for an easy way to use this module.
775              
776             =head1 DESCRIPTION
777              
778             =head1 FUNCTIONS
779              
780              
781             =head2 complete_cli_arg
782              
783             Usage:
784              
785             complete_cli_arg(%args) -> hash|array
786              
787             Complete command-line argument using Getopt::Long specification.
788              
789             This routine can complete option names, where the option names are retrieved
790             from L<Getopt::Long> specification. If you provide completion routine in
791             C<completion>, you can also complete I<option values> and I<arguments>.
792              
793             Note that this routine does not use L<Getopt::Long> (it does its own parsing)
794             and currently is not affected by Getopt::Long's configuration. Its behavior
795             mimics Getopt::Long under these configuration: C<no_ignore_case>, C<bundling> (or
796             C<no_bundling> if the C<bundling> option is turned off). Which I think is the
797             sensible default. This routine also does not currently support C<auto_help> and
798             C<auto_version>, so you'll need to add those options specifically if you want to
799             recognize C<--help/-?> and C<--version>, respectively.
800              
801             This function is not exported by default, but exportable.
802              
803             Arguments ('*' denotes required arguments):
804              
805             =over 4
806              
807             =item * B<bundling> => I<bool> (default: 1)
808              
809             If you turn off bundling, completion of short-letter options won't support
810             bundling (e.g. C<< -bE<lt>tabE<gt> >> won't add more single-letter options), but single-dash
811             multiletter options can be recognized. Currently only those specified with a
812             single dash will be completed. For example if you have C<-foo=s> in your option
813             specification, C<< -fE<lt>tabE<gt> >> can complete it.
814              
815             This can be used to complete old-style programs, e.g. emacs which has options
816             like C<-nw>, C<-nbc> etc (but also have double-dash options like
817             C<--no-window-system> or C<--no-blinking-cursor>).
818              
819             =item * B<completion> => I<code>
820              
821             Completion routine to complete option valueE<sol>argument.
822              
823             Completion code will receive a hash of arguments (C<%args>) containing these
824             keys:
825              
826             =over
827              
828             =item * C<type> (str, what is being completed, either C<optval>, or C<arg>)
829              
830             =item * C<word> (str, word to be completed)
831              
832             =item * C<cword> (int, position of words in the words array, starts from 0)
833              
834             =item * C<opt> (str, option name, e.g. C<--str>; undef if we're completing argument)
835              
836             =item * C<ospec> (str, Getopt::Long option spec, e.g. C<str|S=s>; undef when completing
837             argument)
838              
839             =item * C<argpos> (int, argument position, zero-based; undef if type='optval')
840              
841             =item * C<nth> (int, the number of times this option has seen before, starts from 0
842             that means this is the first time this option has been seen; undef when
843             type='arg')
844              
845             =item * C<seen_opts> (hash, all the options seen in C<words>)
846              
847             =item * C<parsed_opts> (hash, options parsed the standard/raw way)
848              
849             =back
850              
851             as well as all keys from C<extras> (but these won't override the above keys).
852              
853             and is expected to return a completion answer structure as described in
854             C<Complete> which is either a hash or an array. The simplest form of answer is
855             just to return an array of strings. The various C<complete_*> function like those
856             in L<Complete::Util> or the other C<Complete::*> modules are suitable to use
857             here.
858              
859             Completion routine can also return undef to express declination, in which case
860             the default completion routine will then be consulted. The default routine
861             completes from shell environment variables (C<$FOO>), Unix usernames (C<~foo>),
862             and files/directories.
863              
864             Example:
865              
866             use Complete::Unix qw(complete_user);
867             use Complete::Util qw(complete_array_elem);
868             complete_cli_arg(
869             getopt_spec => [
870             'help|h' => sub{...},
871             'format=s' => \$format,
872             'user=s' => \$user,
873             ],
874             completion => sub {
875             my %args = @_;
876             my $word = $args{word};
877             my $ospec = $args{ospec};
878             if ($ospec && $ospec eq 'format=s') {
879             complete_array_elem(array=>[qw/json text xml yaml/], word=>$word);
880             } else {
881             complete_user(word=>$word);
882             }
883             },
884             );
885              
886             =item * B<cword>* => I<int>
887              
888             Index in words of the word we're trying to complete.
889              
890             See function C<parse_cmdline> in L<Complete::Bash> on how to produce this (if
891             you're using bash).
892              
893             =item * B<extras> => I<hash>
894              
895             Add extra arguments to completion routine.
896              
897             The keys from this C<extras> hash will be merged into the final C<%args> passed to
898             completion routines. Note that standard keys like C<type>, C<word>, and so on as
899             described in the function description will not be overwritten by this.
900              
901             =item * B<getopt_spec>* => I<array>
902              
903             Getopt::Long specification.
904              
905             =item * B<words>* => I<array>
906              
907             Command line arguments, like @ARGV.
908              
909             See function C<parse_cmdline> in L<Complete::Bash> on how to produce this (if
910             you're using bash).
911              
912              
913             =back
914              
915             Return value: (hash|array)
916              
917              
918             You can use C<format_completion> function in L<Complete::Bash> module to format
919             the result of this function for bash.
920              
921             =head1 ENVIRONMENT
922              
923             =head2 COMPLETE_GETOPT_LONG_TRACE
924              
925             Bool. If set to true, will generated more log statements for debugging (at the
926             trace level).
927              
928             =head2 COMPLETE_GETOPT_LONG_DEFAULT_ENV
929              
930             Bool. Default true. Can be set to false to disable completing from environment
931             variable in default completion.
932              
933             =head2 COMPLETE_GETOPT_LONG_DEFAULT_FILE
934              
935             Bool. Default true. Can be set to false to disable completing from filesystem
936             (file and directory names) in default completion.
937              
938             =head1 HOMEPAGE
939              
940             Please visit the project's homepage at L<https://metacpan.org/release/Complete-Getopt-Long>.
941              
942             =head1 SOURCE
943              
944             Source repository is at L<https://github.com/perlancar/perl-Complete-Getopt-Long>.
945              
946             =head1 SEE ALSO
947              
948             L<Getopt::Long::Complete>
949              
950             L<Complete>
951              
952             L<Complete::Bash>
953              
954             Other modules related to bash shell tab completion: L<Bash::Completion>,
955             L<Getopt::Complete>.
956              
957             L<Perinci::CmdLine> - an alternative way to easily create command-line
958             applications with completion feature.
959              
960             =head1 AUTHOR
961              
962             perlancar <perlancar@cpan.org>
963              
964             =head1 CONTRIBUTORS
965              
966             =for stopwords Mary Ehlers Steven Haryanto
967              
968             =over 4
969              
970             =item *
971              
972             Mary Ehlers <regina.verb.ae@gmail.com>
973              
974             =item *
975              
976             Steven Haryanto <stevenharyanto@gmail.com>
977              
978             =back
979              
980             =head1 CONTRIBUTING
981              
982              
983             To contribute, you can send patches by email/via RT, or send pull requests on
984             GitHub.
985              
986             Most of the time, you don't need to build the distribution yourself. You can
987             simply modify the code, then test via:
988              
989             % prove -l
990              
991             If you want to build the distribution (e.g. to try to install it locally on your
992             system), you can install L<Dist::Zilla>,
993             L<Dist::Zilla::PluginBundle::Author::PERLANCAR>,
994             L<Pod::Weaver::PluginBundle::Author::PERLANCAR>, and sometimes one or two other
995             Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond
996             that are considered a bug and can be reported to me.
997              
998             =head1 COPYRIGHT AND LICENSE
999              
1000             This software is copyright (c) 2022, 2020, 2019, 2017, 2016, 2015, 2014 by perlancar <perlancar@cpan.org>.
1001              
1002             This is free software; you can redistribute it and/or modify it under
1003             the same terms as the Perl 5 programming language system itself.
1004              
1005             =head1 BUGS
1006              
1007             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Complete-Getopt-Long>
1008              
1009             When submitting a bug or request, please include a test-file or a
1010             patch to an existing test-file that illustrates the bug or desired
1011             feature.
1012              
1013             =cut