xref: /aosp_15_r20/external/curl/scripts/completion.pl (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker#!/usr/bin/env perl
2*6236dae4SAndroid Build Coastguard Worker#***************************************************************************
3*6236dae4SAndroid Build Coastguard Worker#                                  _   _ ____  _
4*6236dae4SAndroid Build Coastguard Worker#  Project                     ___| | | |  _ \| |
5*6236dae4SAndroid Build Coastguard Worker#                             / __| | | | |_) | |
6*6236dae4SAndroid Build Coastguard Worker#                            | (__| |_| |  _ <| |___
7*6236dae4SAndroid Build Coastguard Worker#                             \___|\___/|_| \_\_____|
8*6236dae4SAndroid Build Coastguard Worker#
9*6236dae4SAndroid Build Coastguard Worker# Copyright (C) Daniel Stenberg, <[email protected]>, et al.
10*6236dae4SAndroid Build Coastguard Worker#
11*6236dae4SAndroid Build Coastguard Worker# This software is licensed as described in the file COPYING, which
12*6236dae4SAndroid Build Coastguard Worker# you should have received as part of this distribution. The terms
13*6236dae4SAndroid Build Coastguard Worker# are also available at https://curl.se/docs/copyright.html.
14*6236dae4SAndroid Build Coastguard Worker#
15*6236dae4SAndroid Build Coastguard Worker# You may opt to use, copy, modify, merge, publish, distribute and/or sell
16*6236dae4SAndroid Build Coastguard Worker# copies of the Software, and permit persons to whom the Software is
17*6236dae4SAndroid Build Coastguard Worker# furnished to do so, under the terms of the COPYING file.
18*6236dae4SAndroid Build Coastguard Worker#
19*6236dae4SAndroid Build Coastguard Worker# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20*6236dae4SAndroid Build Coastguard Worker# KIND, either express or implied.
21*6236dae4SAndroid Build Coastguard Worker#
22*6236dae4SAndroid Build Coastguard Worker# SPDX-License-Identifier: curl
23*6236dae4SAndroid Build Coastguard Worker#
24*6236dae4SAndroid Build Coastguard Worker###########################################################################
25*6236dae4SAndroid Build Coastguard Worker
26*6236dae4SAndroid Build Coastguard Workeruse strict;
27*6236dae4SAndroid Build Coastguard Workeruse warnings;
28*6236dae4SAndroid Build Coastguard Workeruse Getopt::Long();
29*6236dae4SAndroid Build Coastguard Workeruse Pod::Usage();
30*6236dae4SAndroid Build Coastguard Worker
31*6236dae4SAndroid Build Coastguard Workermy $curl = 'curl';
32*6236dae4SAndroid Build Coastguard Workermy $shell = 'zsh';
33*6236dae4SAndroid Build Coastguard Workermy $help = 0;
34*6236dae4SAndroid Build Coastguard WorkerGetopt::Long::GetOptions(
35*6236dae4SAndroid Build Coastguard Worker    'curl=s' => \$curl,
36*6236dae4SAndroid Build Coastguard Worker    'shell=s' => \$shell,
37*6236dae4SAndroid Build Coastguard Worker    'help' => \$help,
38*6236dae4SAndroid Build Coastguard Worker) or Pod::Usage::pod2usage();
39*6236dae4SAndroid Build Coastguard WorkerPod::Usage::pod2usage() if $help;
40*6236dae4SAndroid Build Coastguard Worker
41*6236dae4SAndroid Build Coastguard Workermy $regex = '\s+(?:(-[^\s]+),\s)?(--[^\s]+)\s*(\<.+?\>)?\s+(.*)';
42*6236dae4SAndroid Build Coastguard Workermy @opts = parse_main_opts('--help all', $regex);
43*6236dae4SAndroid Build Coastguard Worker
44*6236dae4SAndroid Build Coastguard Workerif ($shell eq 'fish') {
45*6236dae4SAndroid Build Coastguard Worker    print "# curl fish completion\n\n";
46*6236dae4SAndroid Build Coastguard Worker    print qq{$_ \n} foreach (@opts);
47*6236dae4SAndroid Build Coastguard Worker} elsif ($shell eq 'zsh') {
48*6236dae4SAndroid Build Coastguard Worker    my $opts_str;
49*6236dae4SAndroid Build Coastguard Worker
50*6236dae4SAndroid Build Coastguard Worker    $opts_str .= qq{  $_ \\\n} foreach (@opts);
51*6236dae4SAndroid Build Coastguard Worker    chomp $opts_str;
52*6236dae4SAndroid Build Coastguard Worker
53*6236dae4SAndroid Build Coastguard Workermy $tmpl = <<"EOS";
54*6236dae4SAndroid Build Coastguard Worker#compdef curl
55*6236dae4SAndroid Build Coastguard Worker
56*6236dae4SAndroid Build Coastguard Worker# curl zsh completion
57*6236dae4SAndroid Build Coastguard Worker
58*6236dae4SAndroid Build Coastguard Workerlocal curcontext="\$curcontext" state state_descr line
59*6236dae4SAndroid Build Coastguard Workertypeset -A opt_args
60*6236dae4SAndroid Build Coastguard Worker
61*6236dae4SAndroid Build Coastguard Workerlocal rc=1
62*6236dae4SAndroid Build Coastguard Worker
63*6236dae4SAndroid Build Coastguard Worker_arguments -C -S \\
64*6236dae4SAndroid Build Coastguard Worker$opts_str
65*6236dae4SAndroid Build Coastguard Worker  '*:URL:_urls' && rc=0
66*6236dae4SAndroid Build Coastguard Worker
67*6236dae4SAndroid Build Coastguard Workerreturn rc
68*6236dae4SAndroid Build Coastguard WorkerEOS
69*6236dae4SAndroid Build Coastguard Worker
70*6236dae4SAndroid Build Coastguard Worker    print $tmpl;
71*6236dae4SAndroid Build Coastguard Worker} else {
72*6236dae4SAndroid Build Coastguard Worker    die("Unsupported shell: $shell");
73*6236dae4SAndroid Build Coastguard Worker}
74*6236dae4SAndroid Build Coastguard Worker
75*6236dae4SAndroid Build Coastguard Workersub parse_main_opts {
76*6236dae4SAndroid Build Coastguard Worker    my ($cmd, $regex) = @_;
77*6236dae4SAndroid Build Coastguard Worker
78*6236dae4SAndroid Build Coastguard Worker    my @list;
79*6236dae4SAndroid Build Coastguard Worker    my @lines = call_curl($cmd);
80*6236dae4SAndroid Build Coastguard Worker
81*6236dae4SAndroid Build Coastguard Worker    foreach my $line (@lines) {
82*6236dae4SAndroid Build Coastguard Worker        my ($short, $long, $arg, $desc) = ($line =~ /^$regex/) or next;
83*6236dae4SAndroid Build Coastguard Worker
84*6236dae4SAndroid Build Coastguard Worker        my $option = '';
85*6236dae4SAndroid Build Coastguard Worker
86*6236dae4SAndroid Build Coastguard Worker        $arg =~ s/\:/\\\:/g if defined $arg;
87*6236dae4SAndroid Build Coastguard Worker
88*6236dae4SAndroid Build Coastguard Worker        $desc =~ s/'/'\\''/g if defined $desc;
89*6236dae4SAndroid Build Coastguard Worker        $desc =~ s/\[/\\\[/g if defined $desc;
90*6236dae4SAndroid Build Coastguard Worker        $desc =~ s/\]/\\\]/g if defined $desc;
91*6236dae4SAndroid Build Coastguard Worker        $desc =~ s/\:/\\\:/g if defined $desc;
92*6236dae4SAndroid Build Coastguard Worker
93*6236dae4SAndroid Build Coastguard Worker        if ($shell eq 'fish') {
94*6236dae4SAndroid Build Coastguard Worker            $option .= "complete --command curl";
95*6236dae4SAndroid Build Coastguard Worker            $option .= " --short-option '" . strip_dash(trim($short)) . "'"
96*6236dae4SAndroid Build Coastguard Worker                if defined $short;
97*6236dae4SAndroid Build Coastguard Worker            $option .= " --long-option '" . strip_dash(trim($long)) . "'"
98*6236dae4SAndroid Build Coastguard Worker                if defined $long;
99*6236dae4SAndroid Build Coastguard Worker            $option .= " --description '" . strip_dash(trim($desc)) . "'"
100*6236dae4SAndroid Build Coastguard Worker                if defined $desc;
101*6236dae4SAndroid Build Coastguard Worker        } elsif ($shell eq 'zsh') {
102*6236dae4SAndroid Build Coastguard Worker            $option .= '{' . trim($short) . ',' if defined $short;
103*6236dae4SAndroid Build Coastguard Worker            $option .= trim($long)  if defined $long;
104*6236dae4SAndroid Build Coastguard Worker            $option .= '}' if defined $short;
105*6236dae4SAndroid Build Coastguard Worker            $option .= '\'[' . trim($desc) . ']\'' if defined $desc;
106*6236dae4SAndroid Build Coastguard Worker
107*6236dae4SAndroid Build Coastguard Worker            if (defined $arg) {
108*6236dae4SAndroid Build Coastguard Worker                $option .= ":'$arg'";
109*6236dae4SAndroid Build Coastguard Worker                if ($arg =~ /<file ?(name)?>|<path>/) {
110*6236dae4SAndroid Build Coastguard Worker                    $option .= ':_files';
111*6236dae4SAndroid Build Coastguard Worker                } elsif ($arg =~ /<dir>/) {
112*6236dae4SAndroid Build Coastguard Worker                    $option .= ":'_path_files -/'";
113*6236dae4SAndroid Build Coastguard Worker                } elsif ($arg =~ /<url>/i) {
114*6236dae4SAndroid Build Coastguard Worker                    $option .= ':_urls';
115*6236dae4SAndroid Build Coastguard Worker                } elsif ($long =~ /ftp/ && $arg =~ /<method>/) {
116*6236dae4SAndroid Build Coastguard Worker                    $option .= ":'(multicwd nocwd singlecwd)'";
117*6236dae4SAndroid Build Coastguard Worker                } elsif ($arg =~ /<method>/) {
118*6236dae4SAndroid Build Coastguard Worker                    $option .= ":'(DELETE GET HEAD POST PUT)'";
119*6236dae4SAndroid Build Coastguard Worker                }
120*6236dae4SAndroid Build Coastguard Worker            }
121*6236dae4SAndroid Build Coastguard Worker        }
122*6236dae4SAndroid Build Coastguard Worker
123*6236dae4SAndroid Build Coastguard Worker        push @list, $option;
124*6236dae4SAndroid Build Coastguard Worker    }
125*6236dae4SAndroid Build Coastguard Worker
126*6236dae4SAndroid Build Coastguard Worker    # Sort longest first, because zsh won't complete an option listed
127*6236dae4SAndroid Build Coastguard Worker    # after one that's a prefix of it.
128*6236dae4SAndroid Build Coastguard Worker    @list = sort {
129*6236dae4SAndroid Build Coastguard Worker        $a =~ /([^=]*)/; my $ma = $1;
130*6236dae4SAndroid Build Coastguard Worker        $b =~ /([^=]*)/; my $mb = $1;
131*6236dae4SAndroid Build Coastguard Worker
132*6236dae4SAndroid Build Coastguard Worker        length($mb) <=> length($ma)
133*6236dae4SAndroid Build Coastguard Worker    } @list if $shell eq 'zsh';
134*6236dae4SAndroid Build Coastguard Worker
135*6236dae4SAndroid Build Coastguard Worker    return @list;
136*6236dae4SAndroid Build Coastguard Worker}
137*6236dae4SAndroid Build Coastguard Worker
138*6236dae4SAndroid Build Coastguard Workersub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s };
139*6236dae4SAndroid Build Coastguard Workersub strip_dash { my $s = shift; $s =~ s/^-+//g; return $s };
140*6236dae4SAndroid Build Coastguard Worker
141*6236dae4SAndroid Build Coastguard Workersub call_curl {
142*6236dae4SAndroid Build Coastguard Worker    my ($cmd) = @_;
143*6236dae4SAndroid Build Coastguard Worker    my $output = `"$curl" $cmd`;
144*6236dae4SAndroid Build Coastguard Worker    if ($? == -1) {
145*6236dae4SAndroid Build Coastguard Worker        die "Could not run curl: $!";
146*6236dae4SAndroid Build Coastguard Worker    } elsif ((my $exit_code = $? >> 8) != 0) {
147*6236dae4SAndroid Build Coastguard Worker        die "curl returned $exit_code with output:\n$output";
148*6236dae4SAndroid Build Coastguard Worker    }
149*6236dae4SAndroid Build Coastguard Worker    return split /\n/, $output;
150*6236dae4SAndroid Build Coastguard Worker}
151*6236dae4SAndroid Build Coastguard Worker
152*6236dae4SAndroid Build Coastguard Worker__END__
153*6236dae4SAndroid Build Coastguard Worker
154*6236dae4SAndroid Build Coastguard Worker=head1 NAME
155*6236dae4SAndroid Build Coastguard Worker
156*6236dae4SAndroid Build Coastguard Workercompletion.pl - Generates tab-completion files for various shells
157*6236dae4SAndroid Build Coastguard Worker
158*6236dae4SAndroid Build Coastguard Worker=head1 SYNOPSIS
159*6236dae4SAndroid Build Coastguard Worker
160*6236dae4SAndroid Build Coastguard Workercompletion.pl [options...]
161*6236dae4SAndroid Build Coastguard Worker
162*6236dae4SAndroid Build Coastguard Worker    --curl   path to curl executable
163*6236dae4SAndroid Build Coastguard Worker    --shell  zsh/fish
164*6236dae4SAndroid Build Coastguard Worker    --help   prints this help
165*6236dae4SAndroid Build Coastguard Worker
166*6236dae4SAndroid Build Coastguard Worker=cut
167