zsh.pl 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #!/usr/bin/perl
  2. # Generate ZSH completion
  3. use strict;
  4. use warnings;
  5. my $curl = $ARGV[0] || 'curl';
  6. my $regex = '\s+(?:(-[^\s]+),\s)?(--[^\s]+)\s([^\s.]+)?\s+(.*)';
  7. my @opts = parse_main_opts('--help', $regex);
  8. my $opts_str;
  9. $opts_str .= qq{ $_ \\\n} foreach (@opts);
  10. chomp $opts_str;
  11. my $tmpl = <<"EOS";
  12. #compdef curl
  13. # curl zsh completion
  14. local curcontext="\$curcontext" state state_descr line
  15. typeset -A opt_args
  16. local rc=1
  17. _arguments -C -S \\
  18. $opts_str
  19. '*:URL:_urls' && rc=0
  20. return rc
  21. EOS
  22. print $tmpl;
  23. sub parse_main_opts {
  24. my ($cmd, $regex) = @_;
  25. my @list;
  26. my @lines = call_curl($cmd);
  27. foreach my $line (@lines) {
  28. my ($short, $long, $arg, $desc) = ($line =~ /^$regex/) or next;
  29. my $option = '';
  30. $desc =~ s/'/'\\''/g if defined $desc;
  31. $desc =~ s/\[/\\\[/g if defined $desc;
  32. $desc =~ s/\]/\\\]/g if defined $desc;
  33. $option .= '{' . trim($short) . ',' if defined $short;
  34. $option .= trim($long) if defined $long;
  35. $option .= '}' if defined $short;
  36. $option .= '\'[' . trim($desc) . ']\'' if defined $desc;
  37. $option .= ":$arg" if defined $arg;
  38. $option .= ':_files'
  39. if defined $arg and ($arg eq 'FILE' || $arg eq 'DIR');
  40. push @list, $option;
  41. }
  42. # Sort longest first, because zsh won't complete an option listed
  43. # after one that's a prefix of it.
  44. @list = sort {
  45. $a =~ /([^=]*)/; my $ma = $1;
  46. $b =~ /([^=]*)/; my $mb = $1;
  47. length($mb) <=> length($ma)
  48. } @list;
  49. return @list;
  50. }
  51. sub trim { my $s = shift; $s =~ s/^\s+|\s+$//g; return $s };
  52. sub call_curl {
  53. my ($cmd) = @_;
  54. my $output = `"$curl" $cmd`;
  55. if ($? == -1) {
  56. die "Could not run curl: $!";
  57. } elsif ((my $exit_code = $? >> 8) != 0) {
  58. die "curl returned $exit_code with output:\n$output";
  59. }
  60. return split /\n/, $output;
  61. }