about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--Doc/Zsh/contrib.yo80
-rw-r--r--Functions/MIME/zsh-mime-handler21
-rw-r--r--Functions/MIME/zsh-mime-setup89
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