Skip to content
Permalink
Browse files

scripts/completion.pl: also generate fish completion file

This is the renamed script formerly known as zsh.pl

Closes #3545
  • Loading branch information...
simon04 authored and bagder committed Feb 10, 2019
1 parent 15cbf8d commit e075b2149b5d287b30718b31bee5ba80aba3da94
Showing with 179 additions and 99 deletions.
  1. +1 −0 .gitignore
  2. +2 −2 Makefile.am
  3. +25 −0 configure.ac
  4. +17 −5 scripts/Makefile.am
  5. +134 −0 scripts/completion.pl
  6. +0 −92 scripts/zsh.pl
@@ -53,6 +53,7 @@ mkinstalldirs
tags
test-driver
scripts/_curl
scripts/curl.fish
curl_fuzzer
curl_fuzzer_seed_corpus.zip
libstandaloneengine.a
@@ -155,9 +155,9 @@ WINBUILD_DIST = winbuild/BUILD.WINDOWS.txt winbuild/gen_resp_file.bat \
winbuild/MakefileBuild.vc winbuild/Makefile.vc

EXTRA_DIST = CHANGES COPYING maketgz Makefile.dist curl-config.in \
RELEASE-NOTES buildconf libcurl.pc.in MacOSX-Framework scripts/zsh.pl \
RELEASE-NOTES buildconf libcurl.pc.in MacOSX-Framework \
scripts/updatemanpages.pl $(CMAKE_DIST) $(VC_DIST) $(WINBUILD_DIST) \
lib/libcurl.vers.in buildconf.bat scripts/coverage.sh
lib/libcurl.vers.in buildconf.bat scripts/coverage.sh scripts/completion.pl

CLEANFILES = $(VC6_LIBDSP) $(VC6_SRCDSP) $(VC7_LIBVCPROJ) $(VC7_SRCVCPROJ) \
$(VC71_LIBVCPROJ) $(VC71_SRCVCPROJ) $(VC8_LIBVCPROJ) $(VC8_SRCVCPROJ) \
@@ -3412,6 +3412,31 @@ case "$OPT_ZSH_FPATH" in
;;
esac

dnl **********************************************************************
dnl Check for fish completion path
dnl **********************************************************************

OPT_FISH_FPATH=default
AC_ARG_WITH(fish-functions-dir,
AC_HELP_STRING([--with-fish-functions-dir=PATH],[Install fish completions to PATH])
AC_HELP_STRING([--without-fish-functions-dir],[Do not install fish completions]),
[OPT_FISH_FPATH=$withval])
case "$OPT_FISH_FPATH" in
no)
dnl --without-fish-functions-dir option used
;;
default|yes)
dnl --with-fish-functions-dir option used without path
FISH_FUNCTIONS_DIR="$datarootdir/fish/completions"
AC_SUBST(FISH_FUNCTIONS_DIR)
;;
*)
dnl --with-fish-functions-dir option used with path
FISH_FUNCTIONS_DIR="$withval"
AC_SUBST(FISH_FUNCTIONS_DIR)
;;
esac

dnl **********************************************************************
dnl Back to "normal" configuring
dnl **********************************************************************
@@ -20,26 +20,38 @@
#
###########################################################################
ZSH_FUNCTIONS_DIR = @ZSH_FUNCTIONS_DIR@
FISH_FUNCTIONS_DIR = @FISH_FUNCTIONS_DIR@
PERL = @PERL@

ZSH_COMPLETION_FUNCTION_FILENAME = _curl
FISH_COMPLETION_FUNCTION_FILENAME = curl.fish

CLEANFILES = $(ZSH_COMPLETION_FUNCTION_FILENAME)
CLEANFILES = $(ZSH_COMPLETION_FUNCTION_FILENAME) $(FISH_COMPLETION_FUNCTION_FILENAME)

all-local: $(ZSH_COMPLETION_FUNCTION_FILENAME)
all-local: $(ZSH_COMPLETION_FUNCTION_FILENAME) $(FISH_COMPLETION_FUNCTION_FILENAME)

$(ZSH_COMPLETION_FUNCTION_FILENAME): zsh.pl
$(ZSH_COMPLETION_FUNCTION_FILENAME): completion.pl
if CROSSCOMPILING
@echo "NOTICE: we can't generate zsh completion when cross-compiling!"
else # if not cross-compiling:
@if ! test -x "$(PERL)"; then echo "No perl: can't install zsh.pl"; exit 0; fi
$(PERL) $(srcdir)/zsh.pl $(top_builddir)/src/curl$(EXEEXT) > $@
@if ! test -x "$(PERL)"; then echo "No perl: can't install completion.pl"; exit 0; fi
$(PERL) $(srcdir)/completion.pl --curl $(top_builddir)/src/curl$(EXEEXT) --shell zsh > $@
endif

$(FISH_COMPLETION_FUNCTION_FILENAME): completion.pl
if CROSSCOMPILING
@echo "NOTICE: we can't generate fish completion when cross-compiling!"
else # if not cross-compiling:
@if ! test -x "$(PERL)"; then echo "No perl: can't install completion.pl"; exit 0; fi
$(PERL) $(srcdir)/completion.pl --curl $(top_builddir)/src/curl$(EXEEXT) --shell fish > $@
endif

install-data-local:
if CROSSCOMPILING
@echo "NOTICE: we can't install zsh completion when cross-compiling!"
else # if not cross-compiling:
$(MKDIR_P) $(DESTDIR)$(ZSH_FUNCTIONS_DIR)
$(MKDIR_P) $(DESTDIR)$(FISH_FUNCTIONS_DIR)
$(INSTALL_DATA) $(ZSH_COMPLETION_FUNCTION_FILENAME) $(DESTDIR)$(ZSH_FUNCTIONS_DIR)/$(ZSH_COMPLETION_FUNCTION_FILENAME)
$(INSTALL_DATA) $(FISH_COMPLETION_FUNCTION_FILENAME) $(DESTDIR)$(FISH_FUNCTIONS_DIR)/$(FISH_COMPLETION_FUNCTION_FILENAME)
endif
@@ -0,0 +1,134 @@
#!/usr/bin/env perl

use strict;
use warnings;
use Getopt::Long();
use Pod::Usage();

my $curl = 'curl';
my $shell = 'zsh';
my $help = 0;
Getopt::Long::GetOptions(
'curl=s' => \$curl,
'shell=s' => \$shell,
'help' => \$help,
) or Pod::Usage::pod2usage();
Pod::Usage::pod2usage() if $help;

my $regex = '\s+(?:(-[^\s]+),\s)?(--[^\s]+)\s*(\<.+?\>)?\s+(.*)';
my @opts = parse_main_opts('--help', $regex);

if ($shell eq 'fish') {
print "# curl fish completion\n\n";
print qq{$_ \n} foreach (@opts);
} elsif ($shell eq 'zsh') {
my $opts_str;

$opts_str .= qq{ $_ \\\n} foreach (@opts);
chomp $opts_str;

my $tmpl = <<"EOS";
#compdef curl
# curl zsh completion
local curcontext="\$curcontext" state state_descr line
typeset -A opt_args
local rc=1
_arguments -C -S \\
$opts_str
'*:URL:_urls' && rc=0
return rc
EOS

print $tmpl;
} else {
die("Unsupported shell: $shell");
}

sub parse_main_opts {
my ($cmd, $regex) = @_;

my @list;
my @lines = call_curl($cmd);

foreach my $line (@lines) {
my ($short, $long, $arg, $desc) = ($line =~ /^$regex/) or next;

my $option = '';

$arg =~ s/\:/\\\:/g if defined $arg;

$desc =~ s/'/'\\''/g if defined $desc;
$desc =~ s/\[/\\\[/g if defined $desc;
$desc =~ s/\]/\\\]/g if defined $desc;
$desc =~ s/\:/\\\:/g if defined $desc;

if ($shell eq 'fish') {
$option .= "complete --command curl";
$option .= " --short-option '" . strip_dash(trim($short)) . "'"
if defined $short;
$option .= " --long-option '" . strip_dash(trim($long)) . "'"
if defined $long;
$option .= " --description '" . strip_dash(trim($desc)) . "'"
if defined $desc;
} elsif ($shell eq 'zsh') {
$option .= '{' . trim($short) . ',' if defined $short;
$option .= trim($long) if defined $long;
$option .= '}' if defined $short;
$option .= '\'[' . trim($desc) . ']\'' if defined $desc;

$option .= ":'$arg'" if defined $arg;

$option .= ':_files'
if defined $arg and ($arg eq '<file>' || $arg eq '<filename>'
|| $arg eq '<dir>');
}

push @list, $option;
}

# Sort longest first, because zsh won't complete an option listed
# after one that's a prefix of it.
@list = sort {
$a =~ /([^=]*)/; my $ma = $1;
$b =~ /([^=]*)/; my $mb = $1;

length($mb) <=> length($ma)
} @list if $shell eq 'zsh';

return @list;
}

sub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s };
sub strip_dash { my $s = shift; $s =~ s/^-+//g; return $s };

sub call_curl {
my ($cmd) = @_;
my $output = `"$curl" $cmd`;
if ($? == -1) {
die "Could not run curl: $!";
} elsif ((my $exit_code = $? >> 8) != 0) {
die "curl returned $exit_code with output:\n$output";
}
return split /\n/, $output;
}

__END__
=head1 NAME
completion.pl - Generates tab-completion files for various shells
=head1 SYNOPSIS
completion.pl [options...]
--curl path to curl executable
--shell zsh/fish
--help prints this help
=cut

This file was deleted.

Oops, something went wrong.

0 comments on commit e075b21

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.