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