summaryrefslogtreecommitdiff
path: root/Functions/MIME
diff options
context:
space:
mode:
Diffstat (limited to 'Functions/MIME')
-rw-r--r--Functions/MIME/zsh-mime-handler21
-rw-r--r--Functions/MIME/zsh-mime-setup89
2 files changed, 103 insertions, 7 deletions
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