Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

[ramk@xxxxxxxxxxxxxxxxx: Bug#335190: zsh: Enhancements to zsh-mime-handler]



----- Forwarded message from "R.Ramkumar" <ramk@xxxxxxxxxxxxxxxxx> -----

Just felt that there is much scope for customization in
zsh-mime-{handler,setup}. I have patched the files for the following
enhancements (thought that the additions were too small to merit
reporting them individually, so I am putting them together):

1. zsh-mime-setup: A mechanism for resolving conflicts when there
   are multiple entries in the mailcap files. Rather than using
   mailcap.order, it provides for generic mechanisms like matching
   flags for needsterminal and giving them priority, using the
   priority flag in the mailcap entry etc.

2. zsh-mime-handler: An option to prevent use of `eval' instead of
   `sh -c' for complex command patterns. I know these can possibly
   break if sh compatibility is assumed, but for those reasonably
   confident, this can save a new process spawn.

3. zsh-mime-handler: An option to never background the spawned
   processes.

I have documented the changes in the patch. The default behaviour
remains the same with the patch. These features need to be
explicitly activated using zstyle.

I am new to zsh scripting. So, it's very much possible that I've
messed up things. Please bear with me :)

Ramkumar.




diff -Naur orig/zsh-mime-handler new/zsh-mime-handler
--- orig/zsh-mime-handler	2005-10-22 00:25:38.000000000 +0530
+++ new/zsh-mime-handler	2005-10-22 18:07:52.000000000 +0530
@@ -44,13 +44,22 @@
 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 @@
       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 @@
 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 @@
   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 -Naur orig/zsh-mime-setup new/zsh-mime-setup
--- orig/zsh-mime-setup	2005-10-22 00:25:38.000000000 +0530
+++ new/zsh-mime-setup	2005-10-22 18:07:52.000000000 +0530
@@ -157,10 +157,39 @@
   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 +226,66 @@
       # 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


----- End forwarded message -----



Messages sorted by: Reverse Date, Date, Thread, Author