diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | Doc/Zsh/contrib.yo | 80 | ||||
-rw-r--r-- | Functions/MIME/zsh-mime-handler | 21 | ||||
-rw-r--r-- | Functions/MIME/zsh-mime-setup | 89 |
4 files changed, 176 insertions, 22 deletions
diff --git a/ChangeLog b/ChangeLog index be1e5db11..10870961b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2005-10-25 Peter Stephenson <p.w.stephenson@ntlworld.com> + + * 21935: Documentation for 21933. + + * 21933: R. Ramkumar <ramk@cse.iitm.ernet.in>: + Functions/MIME/zsh-mime-handler, Functions/MIME/zsh-mime-setup: + add three styles to the MIME system. + 2005-10-24 Peter Stephenson <pws@csr.com> * 21931: 21913 means _hosts shouldn't complete for ping. diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo index 71980180e..5a70880ee 100644 --- a/Doc/Zsh/contrib.yo +++ b/Doc/Zsh/contrib.yo @@ -1370,19 +1370,17 @@ It is recommended that a trailing tt(*) (suitably quoted) be appended to style patterns in case the system is extended in future. Some examples are given below. startitem() -item(mime-types)( -A list of files in the format of tt(~/.mime.types) and -tt(/etc/mime.types) to be read during setup, replacing the default list -which consists of those two files. The context is tt(:mime:). -A tt(PLUS()) in the list will be replaced by the default files. +item(tt(current-shell))( +If this boolean style is true, the mailcap handler for the context in +question is run using the tt(eval) builtin instead of by starting a new +tt(sh) process. This is more efficient, but may not work in the occasional +cases where the mailcap handler uses strict POSIX syntax. ) -item(mailcap)( -A list of files in the format of tt(~/.mailcap) and -tt(/etc/mailcap) to be read during setup, replacing the default list -which consists of those two files. The context is tt(:mime:). -A tt(PLUS()) in the list will be replaced by the default files. +item(tt(flags))( +Defines flags to go with a handler; the context is as for the +tt(handler) style, and the format is as for the flags in tt(mailcap). ) -item(handler)( +item(tt(handler))( Specifies a handler for a suffix; the suffix is given by the context as tt(:mime:.)var(suffix)tt(:), and the format of the handler is exactly that in tt(mailcap). Note in particular the `tt(.)' and trailing colon @@ -1392,11 +1390,63 @@ the tt(flags) style should be set to include the word tt(needsterminal), or if the output is to be displayed through a pager (but not if the handler is itself a pager), it should include tt(copiousoutput). ) -item(flags)( -Defines flags to go with a handler; the context is as for the -tt(handler) style, and the format is as for the flags in tt(mailcap). +item(tt(mailcap))( +A list of files in the format of tt(~/.mailcap) and +tt(/etc/mailcap) to be read during setup, replacing the default list +which consists of those two files. The context is tt(:mime:). +A tt(PLUS()) in the list will be replaced by the default files. ) -item(pager)( +item(tt(mailcap-priorities))( +This style is used to resolve multiple mailcap entries for the same MIME +type. It consists of an array of the following elements, in descending +order of priority; later entries will be used if earlier entries are +unable to resolve the entries being compared. If none of the tests +resolve the entries, the first entry encountered is retained. + +startitem() +item(tt(files))( +The order of files (entries in the tt(mailcap) style) read. Earlier +files are preferred. (Note this does not resolve entries in the same file.) +) +item(tt(priority))( +The priority flag from the mailcap entry. The priority is an integer +from 0 to 9 with the default value being 5. +) +item(tt(flags))( +The test given by the tt(mailcap-prio-flags) option is used to resolve +entries. +) +item(tt(place))( +Later entries are preferred; as the entries are strictly ordered, this +test always succeeds. +) +enditem() + +Note that as this style is handled during initialisation, the context +is always tt(:mime:), with no discrimination by suffix. +) +item(tt(mailcap-prio-flags))( +This style is used when the keyword tt(flags) is encountered in the +list of tests specified by the tt(mailcap-priorities) style. +It should be set to a list of patterns, each of which is tested against +the flags specified in the mailcap entry (in other words, the sets of +assignments found with some entries in the mailcap file). Earlier +patterns in the list are preferred to later ones, and matched patterns +are preferred to unmatched ones. +) +item(tt(mime-types))( +A list of files in the format of tt(~/.mime.types) and +tt(/etc/mime.types) to be read during setup, replacing the default list +which consists of those two files. The context is tt(:mime:). +A tt(PLUS()) in the list will be replaced by the default files. +) +item(tt(never-background))( +If this boolean style is set, the handler for the given context is +always run in the foreground, even if the flags provided in the mailcap +entry suggest it need not be (for example, it doesnʼt require a +terminal). +) +item(tt(pager))( If set, will be used instead of tt($PAGER) or tt(more) to handle suffixes where the tt(copiousoutput) flag is set. The context is as for tt(handler), i.e. tt(:mime:.)var(suffix)tt(:) for handling diff --git a/Functions/MIME/zsh-mime-handler b/Functions/MIME/zsh-mime-handler index b64fd54cd..297b637be 100644 --- a/Functions/MIME/zsh-mime-handler +++ b/Functions/MIME/zsh-mime-handler @@ -44,13 +44,22 @@ local -a match mbegin mend suffix=$match[1] context=":mime:.${suffix}:" -local handler flags +local handler flags no_sh no_bg zstyle -s $context handler handler || handler="${zsh_mime_handlers[$suffix]}" zstyle -s $context flags flags || flags="${zsh_mime_flags[$suffix]}" +# Set to yes if we use eval instead of sh -c for complicated mailcap lines +# Can possibly break some mailcap entries which expect sh compatibility, +# is faster, as a new process is not spawned. +zstyle -T $context current-shell && no_sh=yes + +# Set to yes if the process shouldn't be backgrounded even if it doesn't need a +# terminal and display is set. +zstyle -T $context never-background && no_bg=yes + local -a files local hasmeta stdin @@ -82,7 +91,11 @@ if [[ $handler = *%s* ]]; then files=(${(q)argv}) zformat -f command $handler s:"$files" fi - execargs=(sh -c $command) + if [[ $no_sh = yes ]]; then + execargs=(eval $command) + else + execargs=(sh -c $command) + fi else # Simple command, one filename. # Split and add the file without extra quoting, @@ -95,7 +108,7 @@ if [[ $handler = *%s* ]]; then else # If there's no %s, the input is supposed to come from stdin. stdin=1 - if [[ -n $hasmeta ]]; then + if [[ -n $hasmeta && $no_sh != yes ]]; then execargs=(sh -c "$handler") else execargs=(${=handler}) @@ -113,7 +126,7 @@ if [[ $flags = *copiousoutput* ]]; then else $execargs | eval ${PAGER:-more} fi -elif [[ $flags = *needsterminal* || -z $DISPLAY ]]; then +elif [[ $no_bg = yes || $flags = *needsterminal* || -z $DISPLAY ]]; then # Needs a terminal, so run synchronously. # Obviously, if $DISPLAY is empty but the handler needs a # GUI we are in trouble anyway. However, it's possible for diff --git a/Functions/MIME/zsh-mime-setup b/Functions/MIME/zsh-mime-setup index d0149ba29..150d4c07f 100644 --- a/Functions/MIME/zsh-mime-setup +++ b/Functions/MIME/zsh-mime-setup @@ -157,10 +157,40 @@ fi unfunction mime-setup-add-type >&/dev/null } +local -a pats_prio o_prios +local o_overwrite sentinel +typeset -A type_prio_flags_map type_prio_src_map type_prio_mprio_map +integer src_id prio mprio + +# A list of keywords indicating the methods used to break ties amongst multiple +# entries. The following keywords are accepted: +# files: The order of files read: Entries from files read earlier are preferred +# (The default value of the variable is a list with this keyword alone) +# priority: The priority flag is matched in the entry. Can be a value from 0 to +# 9. The default priority is 5. Higher priorities are preferred. +# flags: See the mailcap-prio-flags option +# place: Always overrides. Useful for specifying that entries read later are +# preferred. +# +# As the program reads mailcap entries, if it encounters a duplicate +# entry, each of the keywords in the list are checked to see if the new +# entry can override the existing entry. If none of the keywords are able +# to decide whether the new entry should be preferred to the older one, the +# new entry is discarded. +zstyle -a :mime: mailcap-priorities o_prios || o_prios=(files) + +# This style is used as an argument for the flags test in mailcap-priorities. +# This is a list of patterns, each of which is tested against the flags for the +# mailcap entry. An match with a pattern ahead in the list is preferred as +# opposed to a match later in the list. An unmatched item is least preferred. +zstyle -a :mime: mailcap-prio-flags pats_prio + # Loop through files to find handlers for types. +((src_id = 0)) for file in $cap_files; do [[ -r $file ]] || continue + ((src_id = src_id + 1)) # Oh, great. We need to preserve backslashes inside the line, # but need to manage continuation lines. while read -r line; do @@ -197,13 +227,66 @@ for file in $cap_files; do # and remove any surrounding white space --- this might # make the handler empty. line=${${line##[[:space:]]#}%%[[:space:]]} - if [[ -z $type_handler_map[$type] ]]; then - if [[ -n $o_verbose ]]; then - print -r "Adding handler for type $type: + + ((prio = 0)) + for i in $pats_prio; do + # print -r "Comparing $i with '$flags'" >&2 + [[ $flags = ${~i} ]] && break + # print -r "Comparison failed" >&2 + ((prio = prio + 1)) + done + ((mprio=5)) + [[ $flags = (#b)*priority=([0-9])* ]] && mprio=$match[1] + sentinel=no + if [[ -n $type_handler_map[$type] ]]; then + for i in $o_prios; do + case $i in + (files) + if [[ $src_id -lt $type_prio_src_map[$type] ]]; then + sentinel=yes; break + elif [[ $src_id -gt $type_prio_src_map[$type] ]]; then + sentinel=no; break + fi + ;; + (priority) + if [[ $mprio -gt $type_prio_mprio_map[$type] ]]; then + sentinel=yes; break + elif [[ $mprio -lt $type_prio_mprio_map[$type] ]]; then + sentinel=no; break + fi + ;; + (flags) + if [[ $prio -lt $type_prio_flags_map[$type] ]]; then + sentinel=yes; break + elif [[ $prio -gt $type_prio_flags_map[$type] ]]; then + sentinel=no; break + fi + ;; + (place) + sentinel=yes + break + ;; + esac + done + else + sentinel=yes + fi + + if [[ $sentinel = yes ]]; then + if [[ -n $o_verbose ]]; then + if [[ -n $type_handler_map[$type] ]]; then + print -r "Overriding" >&2 + else + print -r "Adding" >&2 + fi + print -r " handler for type $type: $line" >&2 fi type_handler_map[$type]=$line type_flags_map[$type]=$flags + type_prio_src_map[$type]=$src_id + type_prio_flags_map[$type]=$prio + type_prio_mprio_map[$type]=$mprio if [[ -n $flags && -n $o_verbose ]]; then print -r " with flags $flags" >&2 fi |