#!/usr/bin/perl # Generate ZSH completion use strict; use warnings; my $mpv = $ARGV[0] || 'mpv'; my @opts = parse_opts("$mpv --list-options", '^ (\-\-[^\s\*]*)\*?\s*(.*)', 1); my @ao = parse_opts("$mpv --ao=help", '^ ([^\s\:]*)\s*: (.*)'); my @vo = parse_opts("$mpv --vo=help", '^ ([^\s\:]*)\s*: (.*)'); my @af = parse_opts("$mpv --af=help", '^ ([^\s\:]*)\s*: (.*)'); my @vf = parse_opts("$mpv --vf=help", '^ ([^\s\:]*)\s*: (.*)'); my @protos = parse_opts("$mpv --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 .= qq{$_ } foreach (@protos); chomp $protos_str; my $profile_comp = <<'EOS'; 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 == 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 EOS chomp $profile_comp; my $tmpl = <<"EOS"; #compdef mpv # mpv zsh completion local curcontext="\$curcontext" state state_descr line typeset -A opt_args local rc=1 _arguments -C -S \\ $opts_str '*:files:->mfiles' && rc=0 case \$state in ao) local -a values values=( $ao_str ) _describe -t values 'audio outputs' values && rc=0 ;; vo) local -a values values=( $vo_str ) _describe -t values 'video outputs' values && rc=0 ;; af) local -a values values=( $af_str ) _describe -t values 'audio filters' values && rc=0 ;; vf) local -a values values=( $vf_str ) _describe -t values 'video filters' values && rc=0 ;; profile|profiles) $profile_comp ;; 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 -g \\ "*.(#i)(asf|asx|avi|flac|flv|m1v|m2p|m2v|m4v|mjpg|mka|mkv|mov|mp3|mp4|mpe|mpeg|mpg|ogg|ogm|ogv|qt|rm|ts|vob|wav|webm|wma|wmv)(-.)" && 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_opts { my ($cmd, $regex, $parsing_main_options) = @_; my @list; my @lines = split /\n/, `$cmd`; foreach my $line (@lines) { if ($line !~ /^$regex/) { next; } my $entry = $1; if ($parsing_main_options) { $entry .= '=-'; } if (defined $2) { my $desc = $2; $desc =~ s/\:/\\:/g; $entry .= ':' . $desc; } if ($parsing_main_options) { $entry .= ':'; $entry .= '->ao' if ($1 eq '--ao'); $entry .= '->vo' if ($1 eq '--vo'); $entry .= '->af' if ($1 eq '--af'); $entry .= '->vf' if ($1 eq '--vf'); $entry .= '->profiles' if ($1 eq '--profile'); $entry .= '->profile' if ($1 eq '--show-profile'); $entry .= '->files' if ($line =~ /\[file\]/); } push @list, $entry } if ($parsing_main_options) { @list = sort { $a =~ /(.*?)\:/; my $ma = $1; $b =~ /(.*?)\:/; my $mb = $1; length($mb) <=> length($ma) } @list; } return @list; }