1 #!/usr/bin/env perl 2 3 # Generate ZSH completion 4 5 use strict; 6 use warnings; 7 8 my $curl = $ARGV[0] || 'curl'; 9 10 my $regex = '\s+(?:(-[^\s]+),\s)?(--[^\s]+)\s([^\s.]+)?\s+(.*)'; 11 my @opts = parse_main_opts('--help', $regex); 12 13 my $opts_str; 14 15 $opts_str .= qq{ $_ \\\n} foreach (@opts); 16 chomp $opts_str; 17 18 my $tmpl = <<"EOS"; 19 #compdef curl 20 21 # curl zsh completion 22 23 local curcontext="\$curcontext" state state_descr line 24 typeset -A opt_args 25 26 local rc=1 27 28 _arguments -C -S \\ 29 $opts_str 30 '*:URL:_urls' && rc=0 31 32 return rc 33 EOS 34 35 print $tmpl; 36 37 sub parse_main_opts { 38 my ($cmd, $regex) = @_; 39 40 my @list; 41 my @lines = call_curl($cmd); 42 43 foreach my $line (@lines) { 44 my ($short, $long, $arg, $desc) = ($line =~ /^$regex/) or next; 45 46 my $option = ''; 47 48 $desc =~ s/'/'\\''/g if defined $desc; 49 $desc =~ s/\[/\\\[/g if defined $desc; 50 $desc =~ s/\]/\\\]/g if defined $desc; 51 52 $option .= '{' . trim($short) . ',' if defined $short; 53 $option .= trim($long) if defined $long; 54 $option .= '}' if defined $short; 55 $option .= '\'[' . trim($desc) . ']\'' if defined $desc; 56 57 $option .= ":'$arg'" if defined $arg; 58 59 $option .= ':_files' 60 if defined $arg and ($arg eq '<file>' || $arg eq '<filename>' 61 || $arg eq '<dir>'); 62 63 push @list, $option; 64 } 65 66 # Sort longest first, because zsh won't complete an option listed 67 # after one that's a prefix of it. 68 @list = sort { 69 $a =~ /([^=]*)/; my $ma = $1; 70 $b =~ /([^=]*)/; my $mb = $1; 71 72 length($mb) <=> length($ma) 73 } @list; 74 75 return @list; 76 } 77 78 sub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s }; 79 80 sub call_curl { 81 my ($cmd) = @_; 82 my $output = `"$curl" $cmd`; 83 if ($? == -1) { 84 die "Could not run curl: $!"; 85 } elsif ((my $exit_code = $? >> 8) != 0) { 86 die "curl returned $exit_code with output:\n$output"; 87 } 88 return split /\n/, $output; 89 } 90