Home | History | Annotate | Download | only in scripts
      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