mirror of
https://github.com/mpv-player/mpv
synced 2024-12-29 02:22:19 +00:00
f8cc184134
wscript calls them directly, and thus are probably part of the build system. They seem to be fully covered by relicensing agreements.
284 lines
6.6 KiB
Prolog
Executable File
284 lines
6.6 KiB
Prolog
Executable File
#!/usr/bin/perl
|
|
|
|
# Generate ZSH completion
|
|
|
|
#
|
|
# This file is part of mpv.
|
|
#
|
|
# mpv is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU Lesser General Public
|
|
# License as published by the Free Software Foundation; either
|
|
# version 2.1 of the License, or (at your option) any later version.
|
|
#
|
|
# mpv is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Lesser General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
# License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
use strict;
|
|
use warnings;
|
|
use warnings FATAL => 'uninitialized';
|
|
|
|
my $mpv = $ARGV[0] || 'mpv';
|
|
|
|
my @opts = parse_main_opts('--list-options', '^ (\-\-[^\s\*]*)\*?\s*(.*)');
|
|
|
|
die "Couldn't find any options" unless (@opts);
|
|
|
|
my @ao = parse_opts('--ao=help', '^ ([^\s\:]*)\s*: (.*)');
|
|
my @vo = parse_opts('--vo=help', '^ ([^\s\:]*)\s*: (.*)');
|
|
|
|
my @af = parse_opts('--af=help', '^ ([^\s\:]*)\s*: (.*)');
|
|
my @vf = parse_opts('--vf=help', '^ ([^\s\:]*)\s*: (.*)');
|
|
|
|
my @protos = parse_opts('--list-protocols', '^ ([^\s]*)');
|
|
|
|
my ($opts_str, $ao_str, $vo_str, $af_str, $vf_str, $protos_str);
|
|
|
|
$opts_str .= qq{ '$_' \\\n} foreach (@opts);
|
|
chomp $opts_str;
|
|
|
|
$ao_str .= qq{ '$_' \\\n} foreach (@ao);
|
|
chomp $ao_str;
|
|
|
|
$vo_str .= qq{ '$_' \\\n} foreach (@vo);
|
|
chomp $vo_str;
|
|
|
|
$af_str .= qq{ '$_' \\\n} foreach (@af);
|
|
chomp $af_str;
|
|
|
|
$vf_str .= qq{ '$_' \\\n} foreach (@vf);
|
|
chomp $vf_str;
|
|
|
|
$protos_str = join(' ', @protos);
|
|
|
|
my $runtime_completions = <<'EOS';
|
|
profile|show-profile)
|
|
local -a profiles
|
|
local current
|
|
for current in "${(@f)$($words[1] --profile=help)}"; do
|
|
current=${current//\*/\\\*}
|
|
current=${current//\:/\\\:}
|
|
current=${current//\[/\\\[}
|
|
current=${current//\]/\\\]}
|
|
if [[ $current =~ $'\t'([^$'\t']*)$'\t'(.*) ]]; then
|
|
if [[ -n $match[2] ]]; then
|
|
current="$match[1][$match[2]]"
|
|
else
|
|
current="$match[1]"
|
|
fi
|
|
profiles=($profiles $current)
|
|
fi
|
|
done
|
|
if [[ $state == show-profile ]]; then
|
|
# For --show-profile, only one allowed
|
|
if (( ${#profiles} > 0 )); then
|
|
_values 'profile' $profiles && rc=0
|
|
fi
|
|
else
|
|
# For --profile, multiple allowed
|
|
profiles=($profiles 'help[list profiles]')
|
|
_values -s , 'profile(s)' $profiles && rc=0
|
|
fi
|
|
;;
|
|
|
|
audio-device)
|
|
local -a audio_devices
|
|
local current
|
|
for current in "${(@f)$($words[1] --audio-device=help)}"; do
|
|
current=${current//\*/\\\*}
|
|
current=${current//\:/\\\:}
|
|
current=${current//\[/\\\[}
|
|
current=${current//\]/\\\]}
|
|
if [[ $current =~ ' '\'([^\']*)\'' \('(.*)'\)' ]]; then
|
|
audio_devices=($audio_devices "$match[1][$match[2]]")
|
|
fi
|
|
done
|
|
audio_devices=($audio_devices 'help[list audio devices]')
|
|
_values 'audio device' $audio_devices && rc=0
|
|
;;
|
|
EOS
|
|
chomp $runtime_completions;
|
|
|
|
my $tmpl = <<"EOS";
|
|
#compdef mpv
|
|
|
|
# For customization, see:
|
|
# https://github.com/mpv-player/mpv/wiki/Zsh-completion-customization
|
|
|
|
local curcontext="\$curcontext" state state_descr line
|
|
typeset -A opt_args
|
|
|
|
local -a match mbegin mend
|
|
local MATCH MBEGIN MEND
|
|
|
|
# By default, don't complete URLs unless no files match
|
|
local -a tag_order
|
|
zstyle -a ":completion:*:*:\$service:*" tag-order tag_order || \
|
|
zstyle ":completion:*:*:\$service:*" tag-order '!urls'
|
|
|
|
local rc=1
|
|
|
|
_arguments -C -S \\
|
|
$opts_str
|
|
'*:files:->mfiles' && rc=0
|
|
|
|
case \$state in
|
|
ao)
|
|
_values -s , 'audio outputs' \\
|
|
$ao_str
|
|
&& rc=0
|
|
;;
|
|
|
|
vo)
|
|
_values -s , 'video outputs' \\
|
|
$vo_str
|
|
&& rc=0
|
|
;;
|
|
|
|
af)
|
|
_values -s , 'audio filters' \\
|
|
$af_str
|
|
&& rc=0
|
|
;;
|
|
|
|
vf)
|
|
_values -s , 'video filters' \\
|
|
$vf_str
|
|
&& rc=0
|
|
;;
|
|
|
|
$runtime_completions
|
|
|
|
files)
|
|
compset -P '*,'
|
|
compset -S ',*'
|
|
_files -r ',/ \\t\\n\\-' && rc=0
|
|
;;
|
|
|
|
mfiles)
|
|
local expl
|
|
_tags files urls
|
|
while _tags; do
|
|
_requested files expl 'media file' _files && rc=0
|
|
if _requested urls; then
|
|
while _next_label urls expl URL; do
|
|
_urls "\$expl[@]" && rc=0
|
|
compadd -S '' "\$expl[@]" $protos_str && rc=0
|
|
done
|
|
fi
|
|
(( rc )) || return 0
|
|
done
|
|
;;
|
|
esac
|
|
|
|
return rc
|
|
EOS
|
|
|
|
print $tmpl;
|
|
|
|
sub parse_main_opts {
|
|
my ($cmd, $regex) = @_;
|
|
|
|
my @list;
|
|
my @lines = call_mpv($cmd);
|
|
|
|
foreach my $line (@lines) {
|
|
my ($name, $desc) = ($line =~ /^$regex/) or next;
|
|
|
|
next if ($desc eq 'removed' || $desc eq 'alias');
|
|
|
|
if ($desc =~ /^Flag/) {
|
|
|
|
push @list, $name;
|
|
|
|
$name =~ /^--(.*)/;
|
|
if ($1 !~ /^(\{|\}|v|list-options|really-quiet|no-.*)$/) {
|
|
push @list, "--no-$1";
|
|
}
|
|
|
|
} elsif ($desc =~ /^Print/) {
|
|
|
|
push @list, $name;
|
|
|
|
} else {
|
|
|
|
# Option takes argument
|
|
|
|
my $entry = $name;
|
|
|
|
$desc =~ s/\:/\\:/g;
|
|
$entry .= "=-:$desc:";
|
|
|
|
if ($desc =~ /^Choices\\: ([^(]*)/) {
|
|
my $choices = $1;
|
|
$choices =~ s/ +$//; # strip trailing space
|
|
$entry .= "($choices)";
|
|
|
|
# If "no" is one of the choices, it can also be
|
|
# negated like a flag (--no-whatever).
|
|
if ($choices =~ /\bno\b/) {
|
|
$name =~ s/^--/--no-/;
|
|
push @list, $name;
|
|
}
|
|
} elsif ($line =~ /\[file\]/) {
|
|
$entry .= '->files';
|
|
} elsif ($name =~ /^--(ao|vo|af|vf|profile|show-profile|audio-device)$/) {
|
|
$entry .= "->$1";
|
|
}
|
|
push @list, $entry;
|
|
}
|
|
}
|
|
|
|
# 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;
|
|
|
|
return @list;
|
|
}
|
|
|
|
sub parse_opts {
|
|
my ($cmd, $regex) = @_;
|
|
|
|
my @list;
|
|
my @lines = call_mpv($cmd);
|
|
|
|
foreach my $line (@lines) {
|
|
if ($line !~ /^$regex/) {
|
|
next;
|
|
}
|
|
|
|
my $entry = $1;
|
|
|
|
if (defined $2) {
|
|
my $desc = $2;
|
|
$desc =~ s/\:/\\:/g;
|
|
$entry .= "[$desc]";
|
|
}
|
|
|
|
push @list, $entry
|
|
}
|
|
|
|
return @list;
|
|
}
|
|
|
|
sub call_mpv {
|
|
my ($cmd) = @_;
|
|
my $output = `"$mpv" --no-config $cmd`;
|
|
if ($? == -1) {
|
|
die "Could not run mpv: $!";
|
|
} elsif ((my $exit_code = $? >> 8) != 0) {
|
|
die "mpv returned $exit_code with output:\n$output";
|
|
}
|
|
return split /\n/, $output;
|
|
}
|