113498266Sopenharmony_ci#!/usr/bin/env perl 213498266Sopenharmony_ci#*************************************************************************** 313498266Sopenharmony_ci# _ _ ____ _ 413498266Sopenharmony_ci# Project ___| | | | _ \| | 513498266Sopenharmony_ci# / __| | | | |_) | | 613498266Sopenharmony_ci# | (__| |_| | _ <| |___ 713498266Sopenharmony_ci# \___|\___/|_| \_\_____| 813498266Sopenharmony_ci# 913498266Sopenharmony_ci# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 1013498266Sopenharmony_ci# 1113498266Sopenharmony_ci# This software is licensed as described in the file COPYING, which 1213498266Sopenharmony_ci# you should have received as part of this distribution. The terms 1313498266Sopenharmony_ci# are also available at https://curl.se/docs/copyright.html. 1413498266Sopenharmony_ci# 1513498266Sopenharmony_ci# You may opt to use, copy, modify, merge, publish, distribute and/or sell 1613498266Sopenharmony_ci# copies of the Software, and permit persons to whom the Software is 1713498266Sopenharmony_ci# furnished to do so, under the terms of the COPYING file. 1813498266Sopenharmony_ci# 1913498266Sopenharmony_ci# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 2013498266Sopenharmony_ci# KIND, either express or implied. 2113498266Sopenharmony_ci# 2213498266Sopenharmony_ci# SPDX-License-Identifier: curl 2313498266Sopenharmony_ci# 2413498266Sopenharmony_ci########################################################################### 2513498266Sopenharmony_ci 2613498266Sopenharmony_ciuse strict; 2713498266Sopenharmony_ciuse warnings; 2813498266Sopenharmony_ciuse Getopt::Long(); 2913498266Sopenharmony_ciuse Pod::Usage(); 3013498266Sopenharmony_ci 3113498266Sopenharmony_cimy $curl = 'curl'; 3213498266Sopenharmony_cimy $shell = 'zsh'; 3313498266Sopenharmony_cimy $help = 0; 3413498266Sopenharmony_ciGetopt::Long::GetOptions( 3513498266Sopenharmony_ci 'curl=s' => \$curl, 3613498266Sopenharmony_ci 'shell=s' => \$shell, 3713498266Sopenharmony_ci 'help' => \$help, 3813498266Sopenharmony_ci) or Pod::Usage::pod2usage(); 3913498266Sopenharmony_ciPod::Usage::pod2usage() if $help; 4013498266Sopenharmony_ci 4113498266Sopenharmony_cimy $regex = '\s+(?:(-[^\s]+),\s)?(--[^\s]+)\s*(\<.+?\>)?\s+(.*)'; 4213498266Sopenharmony_cimy @opts = parse_main_opts('--help all', $regex); 4313498266Sopenharmony_ci 4413498266Sopenharmony_ciif ($shell eq 'fish') { 4513498266Sopenharmony_ci print "# curl fish completion\n\n"; 4613498266Sopenharmony_ci print qq{$_ \n} foreach (@opts); 4713498266Sopenharmony_ci} elsif ($shell eq 'zsh') { 4813498266Sopenharmony_ci my $opts_str; 4913498266Sopenharmony_ci 5013498266Sopenharmony_ci $opts_str .= qq{ $_ \\\n} foreach (@opts); 5113498266Sopenharmony_ci chomp $opts_str; 5213498266Sopenharmony_ci 5313498266Sopenharmony_cimy $tmpl = <<"EOS"; 5413498266Sopenharmony_ci#compdef curl 5513498266Sopenharmony_ci 5613498266Sopenharmony_ci# curl zsh completion 5713498266Sopenharmony_ci 5813498266Sopenharmony_cilocal curcontext="\$curcontext" state state_descr line 5913498266Sopenharmony_citypeset -A opt_args 6013498266Sopenharmony_ci 6113498266Sopenharmony_cilocal rc=1 6213498266Sopenharmony_ci 6313498266Sopenharmony_ci_arguments -C -S \\ 6413498266Sopenharmony_ci$opts_str 6513498266Sopenharmony_ci '*:URL:_urls' && rc=0 6613498266Sopenharmony_ci 6713498266Sopenharmony_cireturn rc 6813498266Sopenharmony_ciEOS 6913498266Sopenharmony_ci 7013498266Sopenharmony_ci print $tmpl; 7113498266Sopenharmony_ci} else { 7213498266Sopenharmony_ci die("Unsupported shell: $shell"); 7313498266Sopenharmony_ci} 7413498266Sopenharmony_ci 7513498266Sopenharmony_cisub parse_main_opts { 7613498266Sopenharmony_ci my ($cmd, $regex) = @_; 7713498266Sopenharmony_ci 7813498266Sopenharmony_ci my @list; 7913498266Sopenharmony_ci my @lines = call_curl($cmd); 8013498266Sopenharmony_ci 8113498266Sopenharmony_ci foreach my $line (@lines) { 8213498266Sopenharmony_ci my ($short, $long, $arg, $desc) = ($line =~ /^$regex/) or next; 8313498266Sopenharmony_ci 8413498266Sopenharmony_ci my $option = ''; 8513498266Sopenharmony_ci 8613498266Sopenharmony_ci $arg =~ s/\:/\\\:/g if defined $arg; 8713498266Sopenharmony_ci 8813498266Sopenharmony_ci $desc =~ s/'/'\\''/g if defined $desc; 8913498266Sopenharmony_ci $desc =~ s/\[/\\\[/g if defined $desc; 9013498266Sopenharmony_ci $desc =~ s/\]/\\\]/g if defined $desc; 9113498266Sopenharmony_ci $desc =~ s/\:/\\\:/g if defined $desc; 9213498266Sopenharmony_ci 9313498266Sopenharmony_ci if ($shell eq 'fish') { 9413498266Sopenharmony_ci $option .= "complete --command curl"; 9513498266Sopenharmony_ci $option .= " --short-option '" . strip_dash(trim($short)) . "'" 9613498266Sopenharmony_ci if defined $short; 9713498266Sopenharmony_ci $option .= " --long-option '" . strip_dash(trim($long)) . "'" 9813498266Sopenharmony_ci if defined $long; 9913498266Sopenharmony_ci $option .= " --description '" . strip_dash(trim($desc)) . "'" 10013498266Sopenharmony_ci if defined $desc; 10113498266Sopenharmony_ci } elsif ($shell eq 'zsh') { 10213498266Sopenharmony_ci $option .= '{' . trim($short) . ',' if defined $short; 10313498266Sopenharmony_ci $option .= trim($long) if defined $long; 10413498266Sopenharmony_ci $option .= '}' if defined $short; 10513498266Sopenharmony_ci $option .= '\'[' . trim($desc) . ']\'' if defined $desc; 10613498266Sopenharmony_ci 10713498266Sopenharmony_ci if (defined $arg) { 10813498266Sopenharmony_ci $option .= ":'$arg'"; 10913498266Sopenharmony_ci if ($arg =~ /<file ?(name)?>|<path>/) { 11013498266Sopenharmony_ci $option .= ':_files'; 11113498266Sopenharmony_ci } elsif ($arg =~ /<dir>/) { 11213498266Sopenharmony_ci $option .= ":'_path_files -/'"; 11313498266Sopenharmony_ci } elsif ($arg =~ /<url>/i) { 11413498266Sopenharmony_ci $option .= ':_urls'; 11513498266Sopenharmony_ci } elsif ($long =~ /ftp/ && $arg =~ /<method>/) { 11613498266Sopenharmony_ci $option .= ":'(multicwd nocwd singlecwd)'"; 11713498266Sopenharmony_ci } elsif ($arg =~ /<method>/) { 11813498266Sopenharmony_ci $option .= ":'(DELETE GET HEAD POST PUT)'"; 11913498266Sopenharmony_ci } 12013498266Sopenharmony_ci } 12113498266Sopenharmony_ci } 12213498266Sopenharmony_ci 12313498266Sopenharmony_ci push @list, $option; 12413498266Sopenharmony_ci } 12513498266Sopenharmony_ci 12613498266Sopenharmony_ci # Sort longest first, because zsh won't complete an option listed 12713498266Sopenharmony_ci # after one that's a prefix of it. 12813498266Sopenharmony_ci @list = sort { 12913498266Sopenharmony_ci $a =~ /([^=]*)/; my $ma = $1; 13013498266Sopenharmony_ci $b =~ /([^=]*)/; my $mb = $1; 13113498266Sopenharmony_ci 13213498266Sopenharmony_ci length($mb) <=> length($ma) 13313498266Sopenharmony_ci } @list if $shell eq 'zsh'; 13413498266Sopenharmony_ci 13513498266Sopenharmony_ci return @list; 13613498266Sopenharmony_ci} 13713498266Sopenharmony_ci 13813498266Sopenharmony_cisub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s }; 13913498266Sopenharmony_cisub strip_dash { my $s = shift; $s =~ s/^-+//g; return $s }; 14013498266Sopenharmony_ci 14113498266Sopenharmony_cisub call_curl { 14213498266Sopenharmony_ci my ($cmd) = @_; 14313498266Sopenharmony_ci my $output = `"$curl" $cmd`; 14413498266Sopenharmony_ci if ($? == -1) { 14513498266Sopenharmony_ci die "Could not run curl: $!"; 14613498266Sopenharmony_ci } elsif ((my $exit_code = $? >> 8) != 0) { 14713498266Sopenharmony_ci die "curl returned $exit_code with output:\n$output"; 14813498266Sopenharmony_ci } 14913498266Sopenharmony_ci return split /\n/, $output; 15013498266Sopenharmony_ci} 15113498266Sopenharmony_ci 15213498266Sopenharmony_ci__END__ 15313498266Sopenharmony_ci 15413498266Sopenharmony_ci=head1 NAME 15513498266Sopenharmony_ci 15613498266Sopenharmony_cicompletion.pl - Generates tab-completion files for various shells 15713498266Sopenharmony_ci 15813498266Sopenharmony_ci=head1 SYNOPSIS 15913498266Sopenharmony_ci 16013498266Sopenharmony_cicompletion.pl [options...] 16113498266Sopenharmony_ci 16213498266Sopenharmony_ci --curl path to curl executable 16313498266Sopenharmony_ci --shell zsh/fish 16413498266Sopenharmony_ci --help prints this help 16513498266Sopenharmony_ci 16613498266Sopenharmony_ci=cut 167