zsh-workers
 help / color / mirror / code / Atom feed
From: Haakon Riiser <haakon.riiser@fys.uio.no>
To: <zsh-workers@zsh.org>
Subject: Re: How to do completion of toggle flag sequences separated by +/-
Date: Tue, 03 May 2011 15:49:46 +0200	[thread overview]
Message-ID: <ed65cee7ceded421fc9f515d644e87cd@ulrik.uio.no> (raw)
In-Reply-To: <20110503112742.30ce4904@pwslap01u.europe.root.pri>

[-- Attachment #1: Type: text/plain, Size: 1333 bytes --]

 On Tue, 3 May 2011 11:27:42 +0100, Peter Stephenson 
 <Peter.Stephenson@csr.com> wrote:
> On Mon, 2 May 2011 11:16:06 +0200
> Haakon Riiser <haakon.riiser@fys.uio.no> wrote:
>>  By the way: When defining sub-functions inside a completion
>> function, is it recommended to test for their existence before
>> defining them? E.g.,
>>
>>  (( $+functions[_ffmpeg_foo] )) || _ffmpeg_foo() {
>>    ...
>>  }
>>
>>  I see this in a lot of completers included with zsh, and I assumed
>> it was done for performance reasons (although it seems strange that
>> the performance hit could be significant, considering that the code
>> is only executed once per TAB keypress).
>
> That's certainly normal, but I think it's less for performance 
> reasons
> than to allow you to overrided _ffmpeg_foo (or whatever) in another
> file.  Note that the (( ... )) expression is true even if _ffmpeg_foo 
> is
> marked for autoload.

 Ah, I see. Doesn't seem to be a reason not to do this then, so I used 
 the same convention for the other stuff I added.

 Attached to this email you will find a patch that implements toggle 
 flags using the method you posted earlier in this thread (thanks again 
 for that, btw). The ffmpeg completion function is pretty cryptic now, 
 but at least it should be very complete and _very_ future-proof. :)

-- 
  Haakon

[-- Attachment #2: ffmpeg-flags-completion.patch --]
[-- Type: text/x-patch, Size: 5232 bytes --]

Index: _ffmpeg
===================================================================
RCS file: /cvsroot/zsh/zsh/Completion/Unix/Command/_ffmpeg,v
retrieving revision 1.4
diff -u -1 -0 -r1.4 _ffmpeg
--- _ffmpeg	1 May 2011 15:46:47 -0000	1.4
+++ _ffmpeg	3 May 2011 13:41:48 -0000
@@ -36,41 +36,87 @@
     pix_fmts=($(_ffmpeg_list_pix_fmts))
     _wanted ffmpeg-pix-fmts expl 'set pixel format' compadd -a pix_fmts
 }
 
 (( $+functions[_ffmpeg_bsfs] )) || _ffmpeg_bsfs() {
     local bsfs
     bsfs=(${${(f)"$(_call_program bsfs $words[1] -bsfs 2>/dev/null)"}:#*:})
     _wanted ffmpeg-bsfs expl 'set bitstream filter' compadd -a bsfs
 }
 
+typeset -A _ffmpeg_flags
+
+(( $+functions[_ffmpeg_flag_options] )) || _ffmpeg_flag_options() {
+    local expl
+    _wanted options expl 'select flags' compadd -S '' -- {-,+}${^flag_options}
+}
+
+(( $+functions[_ffmpeg_more_flag_options] )) || _ffmpeg_more_flag_options() {
+    compset -p $1 && _ffmpeg_flag_options
+}
+
+(( $+functions[_ffmpeg_new_flag_options] )) || _ffmpeg_new_flag_options() {
+    compset -P '*' && _ffmpeg_flag_options
+}
+
+(( $+functions[_ffmpeg_flags] )) || _ffmpeg_flags() {
+    local -a flag_options
+    eval "flag_options=(\${=_ffmpeg_flags[$1]})"
+
+    local match mbegin mend
+    integer ret=1
+
+    if [[ $PREFIX = (#b)(*)[-+]([^-+]#) ]]; then 
+        if [[ -n ${flag_options[(R)$match[2]]} ]]; then
+            _ffmpeg_new_flag_options && ret=0
+        fi 
+        if [[ -n ${flag_options[(R)$match[2]?*]} ]]; then
+            _ffmpeg_more_flag_options ${#match[1]} && ret=0
+        fi
+    else
+        _ffmpeg_flag_options && ret=0
+    fi
+
+    return $ret
+}
+
+(( $+functions[_ffmpeg_register_lastopt_values] )) || _ffmpeg_register_lastopt_values() {
+    if (( lastopt_takesargs )); then
+        lastopt+=":$lastopt_description:"
+        if (( $#lastopt_values )); then
+            if [[ $lastopt_type == flags ]]; then
+                flagtype=${${lastopt%%:*}#-}
+                lastopt+="->$flagtype"
+                _ffmpeg_flags[$flagtype]="${lastopt_values[*]}"
+            else
+                lastopt+="(${lastopt_values[*]})"
+            fi
+        fi
+    fi
+    _ffmpeg_argspecs+=$lastopt
+}
+
 local -a _ffmpeg_argspecs
 {
     local lastopt
     local lastopt_description
     local lastopt_takesargs
+    local lastopt_type
     local -a lastopt_values
 
     _call_program options $words[1] -h 2>/dev/null | while IFS=$'\n' read -r; do
         if [[ $REPLY == -* ]]; then
-            if [[ -n $lastopt ]]; then
-                if (( lastopt_takesargs )); then
-                    lastopt+=":$lastopt_description:"
-                    if (( $#lastopt_values )); then
-                        lastopt+="(${lastopt_values[*]})"
-                    fi
-                fi
-                _ffmpeg_argspecs+=$lastopt
-            fi
+            [[ -n $lastopt ]] && _ffmpeg_register_lastopt_values
             lastopt=${REPLY%%[[:space:]]*}
             lastopt_description=${REPLY##-[^[:space:]]##[[:space:]]##}
-            if [[ $lastopt_description == '<'* ]]; then
+            if [[ $lastopt_description == (#b)'<'(?##)'>'* ]]; then
+                lastopt_type=$match[1]
                 lastopt_description=${lastopt_description##<[^[:space:]]##>[[:space:]]##[^[:space:]]##[[:space:]]#}
                 if [[ -z $lastopt_description ]]; then
                     lastopt_description=$lastopt
                 fi
                 lastopt_description=${lastopt_description//:/\\:}
             elif [[ $lastopt_description == [^[:space:]]##[[:space:]][[:space:]]* ]]; then
                 local example=${lastopt_description%% *}
                 example=${example//:/\\:}
                 lastopt_description=${lastopt_description##[^[:space:]]##[[:space:]]##}
                 lastopt_description=${lastopt_description//:/\\:}
@@ -106,29 +152,21 @@
                 fi
             fi
             lastopt_values=()
         elif [[ $REPLY == ' '* ]]; then
             REPLY=${REPLY##[[:space:]]##}
             REPLY=${REPLY%%[[:space:]]##*}
             lastopt_takesargs=1
             lastopt_values+=$REPLY
         fi
     done
-    if [[ -n $lastopt ]]; then
-        if (( lastopt_takesargs )); then
-            lastopt+=":$lastopt_description:"
-            if (( $#lastopt_values )); then
-                lastopt+="(${lastopt_values[*]})"
-            fi
-        fi
-        _ffmpeg_argspecs+=$lastopt
-    fi
+    [[ -n $lastopt ]] && _ffmpeg_register_lastopt_values
 }
 
 _arguments -S \
     "${_ffmpeg_argspecs[@]}" \
     '*:output file:_files' \
     && return 0
 
 [[ "$state" == "vfilters" ]] &&
     _values -s , -S = 'video filters' \
     'aspect:set aspect ratio (rational number X\:Y or decimal number):' \
@@ -146,11 +184,14 @@
     'nullsrc' \
     'nullsink' \
     && return 0
 
 [[ "$state" == "format" ]] &&
     _values -s : -S = 'convert input video to one of the specified pixel formats' $(_ffmpeg_list_pix_fmts) && return 0
 
 [[ "$state" == "noformat" ]] &&
     _values -s : -S = 'disable specified pixel formats by force' $(_ffmpeg_list_pix_fmts) && return 0
 
+[[ -n $state && -n $_ffmpeg_flags[$state] ]] &&
+    _ffmpeg_flags $state && return 0
+
 return 1

      reply	other threads:[~2011-05-03 13:50 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-01 10:16 Haakon Riiser
2011-05-01 16:18 ` Peter Stephenson
2011-05-02  9:16   ` Haakon Riiser
2011-05-03 10:27     ` Peter Stephenson
2011-05-03 13:49       ` Haakon Riiser [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ed65cee7ceded421fc9f515d644e87cd@ulrik.uio.no \
    --to=haakon.riiser@fys.uio.no \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).