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