#!/usr/bin/env perl use strict; use XXX; sub main { my ($cmd) = @_; my $input = do { local $/; <> }; my $input2 = do { local $/; <> }; my ($options_spec) = $input2 =~ m/ ^ GETOPT_SPEC="\\ $ (.*?) ^ " $/xsm; $options_spec =~ s/.*Options:\n--//s; my @options; for my $line (split m/\n/, $options_spec) { next unless $line =~ m/\S/; my $arg = 0; my ($key, $desc) = split ' ', $line, 2; if ($key =~ s/=$//) { $arg = 1; } my @keys = split m/,/, $key; push @options, { keys => \@keys, arg => $arg, desc => $desc }; } $input =~ s/.*?\n= Commands\n//s; $input =~ s/(.*?\n)==? .*/$1/s; my @list; my @subdir_cmds; while ($input =~ s/.*?^- (.*?\n)(?=- |== |\z)//ms) { my $text = $1; $text =~ /\A(.*)\n/ or die "Bad text '$text'"; my $usage = $1; $usage =~ s/\A`(.*)`\z/$1/ or die "Bad usage: '$text'"; my ($x1, $x2, $name) = split / +/, $usage; push @list, $name; if ($usage =~ m#\Q$name\E \[?\]?# and $name ne "init") { push @subdir_cmds, $name; } } @subdir_cmds = sort @subdir_cmds; @list = sort @list; if ($cmd eq "bash") { generate_bash(\@list, \@subdir_cmds, \@options); } else { generate_zsh(\@list, \@subdir_cmds, \@options); } } sub generate_zsh { my ($list, $subdir_cmds, $options) = @_; my $options_string = ''; for my $opt (@$options) { my $keys = $opt->{keys}; my $desc = $opt->{desc}; $desc =~ s/'/'"'"'/g; # examples: #'(-c --count)'{-c,--count}'[Number of list items to show]:count' \ #'--remote[Remote name (like "origin")]:remote' \ my $arg = ''; if ($opt->{arg}) { $arg = ":$keys->[0]"; } my @keystrings = map { (length $_ > 1 ? "--" : "-") . $_ } @$keys; if (@$keys == 1) { $options_string .= sprintf " '%s[%s]%s' \\\n", $keystrings[0], $desc, $arg; } elsif (@$keys > 1) { $options_string .= sprintf " '(%s)'{%s}'[%s]%s' \\\n", (join ' ', @keystrings), (join ',', @keystrings), $desc, $arg; } } print <<'...'; #compdef git-subrepo -P git\ ##subrepo #description perform git-subrepo operations # DO NOT EDIT. This file generated by pkg/bin/generate-completion.pl. if [[ -z $GIT_SUBREPO_ROOT ]]; then echo 'GIT_SUBREPO_ROOT is null; has `/path/to/git-subrepo/.rc` been sourced?' return 3 fi _git-subrepo() { typeset -A opt_args local curcontext="$curcontext" state line context _arguments -s \ '1: :->subcmd' \ '*: :->args' \ ... print <<"..."; $options_string && ret=0 case \$state in subcmd) compadd @$list ;; args) case \$line[1] in clone) _arguments -C \\ '1: :->subcmd' \\ '2: :->repo' \\ '*: :->subdir' \\ && ret=0 case \$state in subdir|repo) _files ;; esac ;; @{[ join '|', @$subdir_cmds ]}) _compadd_subdirs ;; init) _files ;; help) compadd @$list ;; esac ;; esac \} _compadd_subdirs() { local subrepos IFS=\$'\\n' set -A subrepos `git subrepo status -q` compadd -X "subrepos: " \$subrepos } ... } sub generate_bash { my ($list, $subdir_cmds, $options, $complete_fetch_limit) = @_; my $options_string = ''; for my $opt (@$options) { my $keys = $opt->{keys}; my $arg = ''; if ($opt->{arg}) { $arg = "="; } my @keystrings = map { (length $_ > 1 ? "--" : "-") . $_ } @$keys; for my $key (@keystrings) { $options_string .= " $key$arg"; } } print <<"..."; #!bash # DO NOT EDIT. This file generated by pkg/bin/generate-completion.pl. _git_subrepo() { local _opts="$options_string" local subcommands="@$list" local subdircommands="@$subdir_cmds" local subcommand="\$(__git_find_on_cmdline "\$subcommands")" if [ -z "\$subcommand" ]; then # no subcommand yet case "\$cur" in -*) __gitcomp "\$_opts" ;; *) __gitcomp "\$subcommands" esac else case "\$cur" in -*) __gitcomp "\$_opts" return ;; esac if [[ "\$subcommand" == "help" ]]; then __gitcomp "\$subcommands" return fi local subdircommand="\$(__git_find_on_cmdline "\$subdircommands")" if [ ! -z "\$subdircommand" ]; then local git_subrepos=`git subrepo status -q` __gitcomp "\$git_subrepos" fi fi } ... } main(shift);