1 package App
::Codeowners
::Options
;
2 # ABSTRACT: Getopt and shell completion for App::Codeowners
8 use Getopt
::Long
2.39 ();
11 our $VERSION = '9999.999'; # VERSION
14 eval { require Pod
::Usage
};
16 my $ref = $VERSION eq '9999.999' ? 'master' : "v$VERSION";
17 my $exit = (@_ == 1 && $_[0] =~ /^\d+$/ && $_[0]) //
18 (@_ % 2 == 0 && {@_}->{'-exitval'}) // 2;
20 Online documentation is available at:
22 https://github.com/chazmcgarvey/git-codeowners/blob/$ref/README.md
24 Tip: To enable inline documentation, install the Pod::Usage module.
30 Pod
::Usage
::pod2usage
(@_);
36 'color|colour!' => (-t STDOUT
? 1 : 0), ## no critic (InputOutput::ProhibitInteractiveTest)
37 'format|f=s' => undef,
40 'shell-completion:s' => undef,
68 my @commands = sort keys %{$self->command_options};
75 if (my $command = $self->{command
}) {
76 @command_options = keys %{$self->command_options->{$command} || {}};
78 return (keys %{$self->early_options}, @command_options);
85 my $self = bless {}, $class;
87 my @args_copy = @args;
89 my $opts = $self->get_options(
91 spec
=> $self->early_options,
92 config
=> 'pass_through',
95 if ($ENV{CODEOWNERS_COMPLETIONS
}) {
96 $self->{command
} = $args[0] || '';
97 my $cword = $ENV{CWORD
};
98 my $cur = $ENV{CUR
} || '';
99 # Adjust cword to remove progname
100 while (0 < --$cword) {
101 last if $cur eq ($args_copy[$cword] || '');
103 $self->completions($cword, @args_copy);
107 if ($opts->{version
}) {
108 my $progname = path
($0)->basename;
109 print "${progname} ${VERSION}\n";
113 pod2usage
(-exitval
=> 0, -verbose
=> 99, -sections
=> [qw(NAME SYNOPSIS OPTIONS COMMANDS)]);
115 if ($opts->{manual
}) {
116 pod2usage
(-exitval
=> 0, -verbose
=> 2);
118 if (defined $opts->{shell_completion
}) {
119 $self->shell_completion($opts->{shell_completion
});
123 # figure out the command (or default to "show")
124 my $command = shift @args;
125 my $command_options = $self->command_options->{$command || ''};
126 if (!$command_options) {
127 unshift @args, $command if defined $command;
129 $command_options = $self->command_options->{$command};
132 my $more_opts = $self->get_options(
134 spec
=> $command_options,
137 %$self = (%$opts, %$more_opts, command
=> $command, args
=> \
@args);
143 my $command = $self->{command
};
144 my @commands = sort keys %{$self->command_options};
145 return if not grep { $_ eq $command } @commands;
146 $command =~ s/[^a-z]/_/g;
152 return @{$self->{args
} || []};
157 $options = $options->get_options(
159 spec
=> \
@expected_options,
160 callback
=> sub { my ($arg, $results) = @_; ... },
163 Convert command-line arguments to options
, based on specified rules
.
165 Returns a hashref of options
or C
<undef> if an error occurred
.
168 * C<args> - Arguments from the caller (e.g. C<@ARGV>).
169 * C<spec> - List of L<Getopt::Long> compatible option strings.
170 * C<callback> - Optional coderef to call for non-option arguments.
171 * C<config> - Optional L<Getopt::Long> configuration string.
177 my $args = {@_ == 1 && ref $_[0] eq 'HASH' ? %{$_[0]} : @_};
181 while (my ($opt, $default_value) = each %{$args->{spec
}}) {
182 my ($name) = $opt =~ /^([^=:!|]+)/;
184 $results{$name} = $default_value;
185 $options{$opt} = \
$results{$name};
188 if (my $fn = $args->{callback
}) {
189 $options{'<>'} = sub {
191 $fn->($arg, \
%results);
195 my $p = Getopt
::Long
::Parser-
>new;
196 $p->configure($args->{config
} || 'default');
197 return if !$p->getoptionsfromarray($args->{args
}, %options);
202 =method shell_completion
204 $options->shell_completion($shell_type);
206 Print shell code to C
<STDOUT
> for the
given type of shell
. When
eval'd, the shell code enables
207 completion for the F<git-codeowners> command.
211 sub shell_completion {
213 my $type = lc(shift || 'bash
');
215 if ($type eq 'bash
') {
217 # git-codeowners - Bash completion
218 # To use, eval this code:
219 # eval "$(git-codeowners --shell-completion)"
220 # This will work without the bash-completion package, but handling of colons
221 # in the completion word will work better with bash-completion installed and
224 local cur words cword
225 if declare -f _get_comp_words_by_ref >/dev/null
227 _get_comp_words_by_ref -n : cur cword words
229 words=("${COMP_WORDS[@]}")
234 COMPREPLY=($(CODEOWNERS_COMPLETIONS=1 CWORD="$cword" CUR="$cur" ${words[@]}))
235 # COMPREPLY=($(${words[0]} --completions "$cword" "${words[@]}"))
238 COMPREPLY=($(compgen -A "${COMPREPLY[0]}" -- "$cur"))
240 declare -f __ltrim_colon_completions >/dev/null && \
241 __ltrim_colon_completions "$cur"
244 complete -F _git_codeowners git-codeowners
248 # TODO - Would be nice to support Zsh
249 warn "No such shell completion: $type\n";
255 $options->completions($current_arg_index, @args);
257 Print completions to C
<STDOUT
> for the
given argument list
and cursor position
, and exit.
259 May also
exit with status
9 and a compgen action printed to C
<STDOUT
> to indicate that the shell
260 should generate its own completions
.
271 my $current = $words[$cword] || '';
272 my $prev = $words[$cword - 1] || '';
276 if ($prev eq '--format
' || $prev eq '-f
') {
277 $reply = $self->_completion_formats;
279 elsif ($current =~ /^-/) {
280 $reply = $self->_completion_options;
283 if (!$self->command) {
284 $reply = [$self->commands, @{$self->_completion_options([keys %{$self->early_options}])}];
293 print grep { /^\Q$current\E/ } @$reply;
297 sub _completion_options {
299 my $opts = shift || [$self->options];
303 for my $option (@$opts) {
304 my ($names, $op, $vtype) = $option =~ /^([^=:!]+)([=:!]?)(.*)$/;
305 my @names = split(/\|/, $names);
307 for my $name (@names) {
309 push @options, "--$name", "--no-$name";
312 if (length($name) > 1) {
313 push @options, "--$name";
316 push @options, "-$name";
322 return [sort @options];
325 sub _completion_formats { [qw(csv json json:pretty tsv yaml)] }