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 = split /\n/, `"$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