mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-12 01:11:27 +02:00
19053 modified, c.f. 19056
This commit is contained in:
parent
cd89b92a0d
commit
3efb2ec394
6 changed files with 677 additions and 2 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
2003-09-14 Peter Stephenson <pws@pwstephenson.fsnet.co.uk>
|
||||||
|
|
||||||
|
* 19053 modified c.f. 19056: Functions/MIME, Doc/Zsh/contrib.yo:
|
||||||
|
Functions using suffix aliases for handling suffixes mailcap
|
||||||
|
style.
|
||||||
|
|
||||||
2003-09-14 Clint Adams <clint@zsh.org>
|
2003-09-14 Clint Adams <clint@zsh.org>
|
||||||
|
|
||||||
* 19076: Src/Modules/terminfo.c: don't call setupterm
|
* 19076: Src/Modules/terminfo.c: don't call setupterm
|
||||||
|
|
|
@ -13,6 +13,7 @@ startmenu()
|
||||||
menu(Utilities)
|
menu(Utilities)
|
||||||
menu(Prompt Themes)
|
menu(Prompt Themes)
|
||||||
menu(ZLE Functions)
|
menu(ZLE Functions)
|
||||||
|
menu(MIME functions)
|
||||||
menu(Other Functions)
|
menu(Other Functions)
|
||||||
endmenu()
|
endmenu()
|
||||||
|
|
||||||
|
@ -344,7 +345,7 @@ normally call a theme's setup function directly.
|
||||||
)
|
)
|
||||||
enditem()
|
enditem()
|
||||||
|
|
||||||
texinode(ZLE Functions)(Other Functions)(Prompt Themes)(User Contributions)
|
texinode(ZLE Functions)(MIME Functions)(Prompt Themes)(User Contributions)
|
||||||
sect(ZLE Functions)
|
sect(ZLE Functions)
|
||||||
|
|
||||||
subsect(Widgets)
|
subsect(Widgets)
|
||||||
|
@ -955,7 +956,159 @@ whether the tt(widget) style is used.
|
||||||
)
|
)
|
||||||
enditem()
|
enditem()
|
||||||
|
|
||||||
texinode(Other Functions)()(ZLE Functions)(User Contributions)
|
texinode(MIME Functions)(Other Functions)(ZLE Functions)(User Contributions)
|
||||||
|
sect(MIME Functions)
|
||||||
|
|
||||||
|
Three functions are available to provide handling of files recognised by
|
||||||
|
extension, for example to dispatch a file tt(text.ps) when executed as a
|
||||||
|
command to an appropriate viewer.
|
||||||
|
|
||||||
|
startitem()
|
||||||
|
xitem(tt(zsh-mime-setup [-flv]))
|
||||||
|
item(tt(zsh-mime-handler))(
|
||||||
|
These two functions use the files tt(~/.mime.types) and tt(/etc/mime.types),
|
||||||
|
which associate types and extensions, as well as tt(~/.mailcap) and
|
||||||
|
tt(/etc/mailcap) files, which associate types and the programs that
|
||||||
|
handle them. These are provided on many systems with the Multimedia
|
||||||
|
Internet Mail Extensions.
|
||||||
|
|
||||||
|
To enable the system, the function tt(zsh-mime-setup) should be
|
||||||
|
autoloaded and run. This allows files with extensions to be treated
|
||||||
|
as executable; such files be completed by the function completion system.
|
||||||
|
The function tt(zsh-mime-handler) should not need to be called by the
|
||||||
|
user.
|
||||||
|
|
||||||
|
The system works by setting up suffix aliases with `tt(alias -s)'.
|
||||||
|
Suffix aliases already installed by the user will not be overwritten.
|
||||||
|
|
||||||
|
Repeated calls to tt(zsh-mime-setup) do not override the existing
|
||||||
|
mapping between suffixes and executable files unless the option tt(-f)
|
||||||
|
is given. Note, however, that this does not override existing suffix
|
||||||
|
aliases assigned to handlers other than tt(zsh-mime-handler).
|
||||||
|
Calling tt(zsh-mime-setup) with the option tt(-l) lists the existing
|
||||||
|
mapping without altering it. Calling tt(zsh-mime-setup) with the option
|
||||||
|
tt(-v) causes verbose output to be shown during the setup operation.
|
||||||
|
|
||||||
|
The system respects the tt(mailcap) flags tt(needsterminal) and
|
||||||
|
tt(copiousoutput), see manref(mailcap)(4).
|
||||||
|
|
||||||
|
The functions use the following styles, which are defined with the
|
||||||
|
tt(zstyle) builtin command (\
|
||||||
|
ifzman(see zmanref(zshmodules))\
|
||||||
|
ifnzman(noderef(The zsh/zutil Module))). They should be defined
|
||||||
|
before tt(zsh-mime-setup) is run. The contexts used all
|
||||||
|
start with tt(:mime:), with additional components in some cases.
|
||||||
|
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:).
|
||||||
|
)
|
||||||
|
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:).
|
||||||
|
)
|
||||||
|
item(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
|
||||||
|
to distinguish this use of the context. This overrides any handler
|
||||||
|
specified by the tt(mailcap) files. If the handler requires a terminal,
|
||||||
|
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(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
|
||||||
|
a file with the given var(suffix).
|
||||||
|
)
|
||||||
|
enditem()
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
example(zstyle ':mime:*' mailcap ~/.mailcap /usr/local/etc/mailcap
|
||||||
|
zstyle ':mime:.txt' handler less %s
|
||||||
|
zstyle ':mime:.txt' flags needsterminal)
|
||||||
|
|
||||||
|
When tt(zsh-mime-setup) is subsequently run, it will look for
|
||||||
|
tt(mailcap) entries in the two files given. Files of suffix tt(.txt)
|
||||||
|
will be handled by running `tt(less) var(file.txt)'. The flag
|
||||||
|
tt(needsterminal) is set to show that this program must run attached to a
|
||||||
|
terminal.
|
||||||
|
|
||||||
|
As there are several steps to dispatching a command, the following
|
||||||
|
should be checked if attempting to execute a file by extension
|
||||||
|
tt(.)var(ext) does not have the expected effect.
|
||||||
|
starteit()
|
||||||
|
eit()(
|
||||||
|
The command `tt(alias -s) var(ext)' should show
|
||||||
|
`tt(ps=zsh-mime-handler)'. If it shows something else, another suffix
|
||||||
|
alias was already installed and was not overwritten. If it shows
|
||||||
|
nothing, no handler was installed: this is most likely because no
|
||||||
|
handler was found in the tt(.mime.types) and tt(mailcap) combination for
|
||||||
|
tt(.ext) files. In that case, appropriate handling should be added to
|
||||||
|
tt(~/.mime.types) and tt(mailcap).
|
||||||
|
)
|
||||||
|
eit()(
|
||||||
|
If the extension is handled by tt(zsh-mime-handler) but the file is
|
||||||
|
not opened correctly, either the handler defined for the type is
|
||||||
|
incorrect, or the flags associated with it are in appropriate. Running
|
||||||
|
tt(zsh-mime-setup -l) will show the handler and, if there are any, the
|
||||||
|
flags. A tt(%s) in the handler is replaced by the file (suitably quoted
|
||||||
|
if necessary). Check that the handler program listed lists and can
|
||||||
|
be run in the way shown. Also check that the flags tt(needsterminal) or
|
||||||
|
tt(copiousoutput) are set if the handler needs to be run under a
|
||||||
|
terminal; the second flag is used if the output should be sent to a pager.
|
||||||
|
An example of a suitable tt(mailcap) entry for such a program is:
|
||||||
|
|
||||||
|
example(text/html; /usr/bin/lynx '%s'; needsterminal)
|
||||||
|
)
|
||||||
|
endeit()
|
||||||
|
)
|
||||||
|
item(tt(pick-web-browser))(
|
||||||
|
This function is separate from the two MIME functions described above
|
||||||
|
and can be assigned directly to a suffix:
|
||||||
|
|
||||||
|
example(autoload -U pick-web-browser
|
||||||
|
alias -s html=pick-web-browser)
|
||||||
|
|
||||||
|
It is provided as an intelligent front end to dispatch a web browser.
|
||||||
|
It will check if an X Windows display is available, and if so
|
||||||
|
if there is already a browser running which can accept a remote
|
||||||
|
connection. In that case, the file will be displayed in that browser;
|
||||||
|
you should check explicitly if it has appeared in the running browser's
|
||||||
|
window. Otherwise, it will start a new browser according to a builtin
|
||||||
|
set of preferences.
|
||||||
|
|
||||||
|
Alternatively, tt(pick-web-browser) can be run as a zsh script.
|
||||||
|
|
||||||
|
Two styles are available to customize the choice of browsers:
|
||||||
|
tt(x-browsers) when running under the X Windows System, and
|
||||||
|
tt(tty-browsers) otherwise. These are arrays in decreasing order
|
||||||
|
of preference consiting of the command name under which to start the
|
||||||
|
browser. They are looked up in the context tt(:mime:) (which may
|
||||||
|
be extended in future, so appending `tt(*)' is recommended). For
|
||||||
|
example,
|
||||||
|
|
||||||
|
example(zstyle ':mime:*' x-browsers opera konqueror netscape)
|
||||||
|
|
||||||
|
specifies that tt(pick-web-browser) should first look for a runing
|
||||||
|
instance of Opera, Konqueror or Netscape, in that order, and if it
|
||||||
|
fails to find any should attempt to start Opera.
|
||||||
|
)
|
||||||
|
enditem()
|
||||||
|
|
||||||
|
texinode(Other Functions)()(MIME Functions)(User Contributions)
|
||||||
sect(Other Functions)
|
sect(Other Functions)
|
||||||
|
|
||||||
There are a large number of helpful functions in the tt(Functions/Misc)
|
There are a large number of helpful functions in the tt(Functions/Misc)
|
||||||
|
|
3
Functions/MIME/.distfiles
Normal file
3
Functions/MIME/.distfiles
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
DISTFILES_SRC='
|
||||||
|
zsh-mime-setup zsh-mime-handler pick-web-browser
|
||||||
|
'
|
112
Functions/MIME/pick-web-browser
Normal file
112
Functions/MIME/pick-web-browser
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
# Function to find a web browser to run on a URL or file.
|
||||||
|
# Can also be run as a script. It is suitable for use as
|
||||||
|
# a suffix alias:
|
||||||
|
# alias -s html=pick-web-browser
|
||||||
|
#
|
||||||
|
# The single argument is the URL or file name which may be of any type.
|
||||||
|
# The only processing which occurs is that if the argument is a file,
|
||||||
|
# it is converted into a URL. As the function takes account of
|
||||||
|
# any necessary conversions to the file name (for example, if it
|
||||||
|
# contains spaces), it is generally preferable to pass in raw file
|
||||||
|
# names rather than convert them to URLs elsewhere.
|
||||||
|
#
|
||||||
|
# The function takes account of the fact that many X Windows browsers
|
||||||
|
# which are already running on the current display can take a command
|
||||||
|
# to pass the URL to that process for handling. A typical sign
|
||||||
|
# that this has happened is that apparently nothing happens --- you
|
||||||
|
# need to check the browser window.
|
||||||
|
#
|
||||||
|
# If no $DISPLAY is set, the function tries to start a terminal-based
|
||||||
|
# browser instead.
|
||||||
|
|
||||||
|
emulate -L zsh
|
||||||
|
setopt extendedglob cbases nonomatch
|
||||||
|
|
||||||
|
local -a xbrowsers ttybrowsers
|
||||||
|
|
||||||
|
# X Windows browsers which might be running and can accept
|
||||||
|
# a remote URL. You can change the order of preference.
|
||||||
|
# If none is already running, starts the first in the array.
|
||||||
|
zstyle -a :mime: x-browsers xbrowsers ||
|
||||||
|
xbrowsers=(mozilla netscape opera konqueror)
|
||||||
|
# Preferred command line browser. Used if there is on $DISPLAY set.
|
||||||
|
zstyle -a :mime: tty-browsers ttybrowsers ||
|
||||||
|
ttybrowsers=(links lynx)
|
||||||
|
# Characters in addition to alphanumerics which can appear literally
|
||||||
|
# in a URL. `-' should be the first if it appears, so append others
|
||||||
|
# to the end.
|
||||||
|
litc="-_./"
|
||||||
|
|
||||||
|
local -a windows remoteargs match mbegin mend
|
||||||
|
local url browser
|
||||||
|
|
||||||
|
url=$1
|
||||||
|
if [[ -f $url ]]; then
|
||||||
|
if [[ $url = *[^-_[:alnum:]]* ]]; then
|
||||||
|
# Convert special characters into hex escapes.
|
||||||
|
local sofar
|
||||||
|
while [[ $url = (#b)([${litc}[:alnum:]]#)([^${litc}[:alnum:]])(*) ]]
|
||||||
|
do
|
||||||
|
sofar+="$match[1]%${$(( [#16] ##$match[2] ))##0x}"
|
||||||
|
url=$match[3]
|
||||||
|
done
|
||||||
|
url="$sofar$url"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Turn this into a local URL
|
||||||
|
if [[ $url = /* ]]; then
|
||||||
|
url=file://$url
|
||||||
|
else
|
||||||
|
url=file://$PWD/$url
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [[ -n $DISPLAY ]]; then
|
||||||
|
# X Windows running
|
||||||
|
|
||||||
|
# Get the name of all windows running; use the internal name, not
|
||||||
|
# the friendly name, which is less useful.
|
||||||
|
#
|
||||||
|
# The nasty but portable version.
|
||||||
|
# The nice but non-portable version uses Perl, even though perl
|
||||||
|
# is more portable.
|
||||||
|
# windows=(${(f)"$(xwininfo -root -all |
|
||||||
|
# sed -ne 's/.*".*": ("\(.*\)" ".*").*/\1/p' |sort | uniq)"})
|
||||||
|
|
||||||
|
windows=(${(f)"$(xwininfo -root -all |
|
||||||
|
perl -ne '/.*"(.*)": \("(.*)" "(.*)"\).*/ and $w{$2} = 1;
|
||||||
|
END { print join("\n", keys %w), "\n" }')"})
|
||||||
|
|
||||||
|
# Is any browser we've heard of running?
|
||||||
|
for browser in $xbrowsers; do
|
||||||
|
if [[ $windows[(I)(#i)$browser] -ne 0 ]]; then
|
||||||
|
if [[ $browser = konqueror ]]; then
|
||||||
|
# I'm sure there's documentation for this somewhere...
|
||||||
|
dcop $(dcop|grep konqueror) default openBrowserWindow $url
|
||||||
|
else
|
||||||
|
# Mozilla bells and whistles are described at:
|
||||||
|
# http://www.mozilla.org/unix/remote.html
|
||||||
|
$browser -remote "openURL($url)"
|
||||||
|
fi
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Start our preferred X Windows browser in the background.
|
||||||
|
for browser in $xbrowsers; do
|
||||||
|
if eval "[[ =$browser != \\=$browser ]]"; then
|
||||||
|
# The following is to make the job text more readable.
|
||||||
|
eval ${(q)browser} ${(q)url} "&"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
# Start up dumb terminal browser.
|
||||||
|
for browser in $ttybrowsers; do
|
||||||
|
if eval "[[ =$browser != \\=$browser ]]"; then
|
||||||
|
$browser $url
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
142
Functions/MIME/zsh-mime-handler
Normal file
142
Functions/MIME/zsh-mime-handler
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
# Handler for MIME types using associative arrays
|
||||||
|
# zsh_mime_handlers and zsh_mime_flags set up by zsh-mime-setup.
|
||||||
|
#
|
||||||
|
# The only flags it handles are copiousoutput and needsterminal.
|
||||||
|
# copiousoutput is assumed to imply needsterminal. Apart from
|
||||||
|
# those, it tries to be a bit cunning about quoting, which
|
||||||
|
# can be a nightmare in MIME handling. If it sees something like
|
||||||
|
# netscape %s
|
||||||
|
# and it only has one file to handle (the usual case then it will handle it
|
||||||
|
# internally just by appending a file.)
|
||||||
|
#
|
||||||
|
# Anything else is handled by passing to sh -c, which is the only think
|
||||||
|
# with a high probability of working. If it sees something with
|
||||||
|
# quotes, e.g.
|
||||||
|
# /usr/bin/links "%s"
|
||||||
|
# it will assume someone else has tried to fix the quoting problem and not
|
||||||
|
# do that. If it sees something with no quotes but other metacharacters,
|
||||||
|
# e.g.
|
||||||
|
# cat %s | handler
|
||||||
|
# then it will do any quoting and pass the result to sh -c.
|
||||||
|
# So for example if the argument is "My File", the command executed
|
||||||
|
# is supposedly
|
||||||
|
# sh -c 'cat My\ File | handler'
|
||||||
|
#
|
||||||
|
# This note is mostly here so you can work out what I tried to do when
|
||||||
|
# it goes horribly wrong.
|
||||||
|
|
||||||
|
emulate -L zsh
|
||||||
|
setopt extendedglob cbases
|
||||||
|
|
||||||
|
# We need zformat from zsh/zutil for %s replacement.
|
||||||
|
zmodload -i zsh/zutil
|
||||||
|
|
||||||
|
# Always called with a filename argument first.
|
||||||
|
# There might be other arguments; don't really know what to do
|
||||||
|
# with these, but if they came from e.g. `*.ps' then we might
|
||||||
|
# just as well pass them all down. However, we just take the
|
||||||
|
# suffix from the first since that's what invoked us via suffix -s.
|
||||||
|
|
||||||
|
local suffix context
|
||||||
|
local -a match mbegin mend
|
||||||
|
|
||||||
|
[[ $1 = (#b)*.([^.]##) ]] || return 1
|
||||||
|
suffix=$match[1]
|
||||||
|
context=":mime:.${suffix}:"
|
||||||
|
|
||||||
|
local handler flags
|
||||||
|
|
||||||
|
zstyle -s $context handler handler ||
|
||||||
|
handler="${zsh_mime_handlers[$suffix]}"
|
||||||
|
zstyle -s $context flags flags ||
|
||||||
|
flags="${zsh_mime_flags[$suffix]}"
|
||||||
|
|
||||||
|
local -a files
|
||||||
|
local hasmeta stdin
|
||||||
|
|
||||||
|
# See if the handler has shell metacharacters in.
|
||||||
|
# Don't count whitespace since we can split that when it's unquoted.
|
||||||
|
if [[ $handler = *[\\\;\*\?\|\"\'\`\$]* ]]; then
|
||||||
|
hasmeta=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local -a execargs
|
||||||
|
|
||||||
|
if [[ $handler = *%s* ]]; then
|
||||||
|
# We need to replace %s with the file(s).
|
||||||
|
local command
|
||||||
|
if [[ -n $hasmeta || $# -gt 1 ]]; then
|
||||||
|
# The handler is complicated, either due to special
|
||||||
|
# characters or multiple files. We are going to pass it
|
||||||
|
# down to sh, since it's probably written for sh syntax.
|
||||||
|
#
|
||||||
|
# See if it's a good idea to quote the filename(s).
|
||||||
|
# It isn't if there are already quotes in the handler, since
|
||||||
|
# that means somebody already tried to take account of that.
|
||||||
|
if [[ $handler = *[\'\"]* ]]; then
|
||||||
|
# Probably we ought not even to handle multiple
|
||||||
|
# arguments, but at least the error message ought
|
||||||
|
# to make it obvious what's going on.
|
||||||
|
zformat -f command $handler s:"$argv"
|
||||||
|
else
|
||||||
|
files=(${(q)argv})
|
||||||
|
zformat -f command $handler s:"$files"
|
||||||
|
fi
|
||||||
|
execargs=(sh -c $command)
|
||||||
|
else
|
||||||
|
# Simple command, one filename.
|
||||||
|
# Split and add the file without extra quoting,
|
||||||
|
# since later we will just execute the array as is.
|
||||||
|
for command in ${=handler}; do
|
||||||
|
zformat -f command $command s:"$1"
|
||||||
|
execargs+=($command)
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# If there's no %s, the input is supposed to come from stdin.
|
||||||
|
stdin=1
|
||||||
|
if [[ -n $hasmeta ]]; then
|
||||||
|
execargs=(sh -c "$handler")
|
||||||
|
else
|
||||||
|
execargs=(${=handler})
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Now execute the command in the appropriate fashion.
|
||||||
|
if [[ $flags = *copiousoutput* ]]; then
|
||||||
|
# We need to page the output.
|
||||||
|
# Careful in case PAGER is a set of commands and arguments.
|
||||||
|
local -a pager
|
||||||
|
zstyle -a $context pager pager || pager=(${=PAGER:-more})
|
||||||
|
if [[ -n $stdin ]]; then
|
||||||
|
cat $argv | $execargs | $pager
|
||||||
|
else
|
||||||
|
$execargs | eval ${PAGER:-more}
|
||||||
|
fi
|
||||||
|
elif [[ $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
|
||||||
|
# the handler to be smart about this, like pick-web-browser,
|
||||||
|
# and even if it just produces an error message it's better to
|
||||||
|
# have it run synchronously.
|
||||||
|
if [[ -n $stdin ]]; then
|
||||||
|
cat $argv | $execargs
|
||||||
|
else
|
||||||
|
$execargs
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Doesn't need a terminal and we have a $DISPLAY, so run
|
||||||
|
# it in the background. sh probably isn't smart enough to
|
||||||
|
# exec the last command in the list, but it's not a big deal.
|
||||||
|
#
|
||||||
|
# The following Rococo construction is to try to make
|
||||||
|
# the job output for the backgrounded command descriptive.
|
||||||
|
# Otherwise it's equivalent to removing the eval and all the quotes,
|
||||||
|
# including the (q) flags.
|
||||||
|
if [[ -n $stdin ]]; then
|
||||||
|
eval cat ${(q)argv} "|" ${(q)execargs} "&"
|
||||||
|
else
|
||||||
|
eval ${(q)execargs} "&"
|
||||||
|
fi
|
||||||
|
fi
|
259
Functions/MIME/zsh-mime-setup
Normal file
259
Functions/MIME/zsh-mime-setup
Normal file
|
@ -0,0 +1,259 @@
|
||||||
|
emulate -L zsh
|
||||||
|
setopt extendedglob cbases
|
||||||
|
|
||||||
|
local opt o_verbose o_list
|
||||||
|
|
||||||
|
autoload -U zsh-mime-handler
|
||||||
|
|
||||||
|
while getopts "flv" opt; do
|
||||||
|
case $opt in
|
||||||
|
# List: show existing suffixes and their handlers then exit.
|
||||||
|
(l)
|
||||||
|
o_list=1
|
||||||
|
;;
|
||||||
|
|
||||||
|
# Verbose; print diagnostics to stdout.
|
||||||
|
(v)
|
||||||
|
o_verbose=1
|
||||||
|
;;
|
||||||
|
|
||||||
|
# Force; discard any existing settings before reading.
|
||||||
|
(f)
|
||||||
|
unset -m zsh_mime_\*
|
||||||
|
;;
|
||||||
|
|
||||||
|
(*)
|
||||||
|
[[ $opt = \? ]] || print -r "Option $opt not handled, complain" >&2
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
(( OPTIND > 1 )) && shift $(( OPTIND - 1 ))
|
||||||
|
|
||||||
|
|
||||||
|
if [[ -n $o_list ]]; then
|
||||||
|
# List and return.
|
||||||
|
for suffix in ${(ko)zsh_mime_handlers}; do
|
||||||
|
print ${(r.10.)suffix}${zsh_mime_handlers[$suffix]}
|
||||||
|
if [[ -n ${zsh_mime_flags[$suffix]} ]]; then
|
||||||
|
print " flags: ${zsh_mime_flags[$suffix]}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Handler for each suffix.
|
||||||
|
(( ${+zsh_mime_handlers} )) || typeset -gA zsh_mime_handlers
|
||||||
|
# Corresponding flags, if any, for handler
|
||||||
|
(( ${+zsh_mime_flags} )) || typeset -gA zsh_mime_flags
|
||||||
|
|
||||||
|
# Internal maps read from MIME configuration files.
|
||||||
|
# Note we don't remember the types, just the mappings from suffixes
|
||||||
|
# to handlers and their flags.
|
||||||
|
typeset -A suffix_type_map type_handler_map type_flags_map
|
||||||
|
|
||||||
|
local -a type_files cap_files array match mbegin mend
|
||||||
|
local file line type suffix exts elt flags line2
|
||||||
|
|
||||||
|
# Customizable list of files to examine.
|
||||||
|
zstyle -a :mime: mime-types type_files ||
|
||||||
|
type_files=(~/.mime.types /etc/mime.types)
|
||||||
|
zstyle -a :mime: mailcap cap_files ||
|
||||||
|
cap_files=(~/.mailcap /etc/mailcap)
|
||||||
|
|
||||||
|
TRAPEXIT() { unfunction mime-setup-add-type >&/dev/null; return 0; }
|
||||||
|
|
||||||
|
mime-setup-add-type() {
|
||||||
|
local type suffix
|
||||||
|
local -a array
|
||||||
|
|
||||||
|
type=$1
|
||||||
|
shift
|
||||||
|
|
||||||
|
while (( $# )); do
|
||||||
|
# `.ps' instead of `ps' has been noted
|
||||||
|
suffix=${1##.}
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [[ -z $suffix_type_map[$suffix] ]]; then
|
||||||
|
[[ -n $o_verbose ]] &&
|
||||||
|
print -r "Adding type $type for $suffix" >&2
|
||||||
|
suffix_type_map[$suffix]=$type
|
||||||
|
else
|
||||||
|
# Skip duplicates.
|
||||||
|
array=(${=suffix_type_map[$suffix]})
|
||||||
|
if [[ ${array[(I)$type]} -eq 0 ]]; then
|
||||||
|
[[ -n $o_verbose ]] &&
|
||||||
|
print -r "Appending type $type for already defined $suffix" >&2
|
||||||
|
suffix_type_map[$suffix]+=" $type"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Loop through files to find suffixes for MIME types.
|
||||||
|
# Earlier entries take precedence, so the files need to be listed
|
||||||
|
# with the user's own first. This also means pre-existing
|
||||||
|
# values in suffix_type_map are respected.
|
||||||
|
for file in $type_files; do
|
||||||
|
[[ -r $file ]] || continue
|
||||||
|
|
||||||
|
# For once we rely on the fact that read handles continuation
|
||||||
|
# lines ending in backslashes, i.e. there's no -r.
|
||||||
|
while read line; do
|
||||||
|
# Skip blank or comment lines.
|
||||||
|
[[ $line = [[:space:]]#(\#*|) ]] && continue
|
||||||
|
|
||||||
|
# There are two types of line you find in MIME type files.
|
||||||
|
# The original simple sort contains the type name then suffixes
|
||||||
|
# separated by whitespace. However, Netscape insists
|
||||||
|
# on adding lines with backslash continuation with
|
||||||
|
# key="value" pairs. So we'd better handle both.
|
||||||
|
if [[ $line = *=* ]]; then
|
||||||
|
# Gory.
|
||||||
|
# This relies on the fact that a typical entry:
|
||||||
|
# type=video/x-mpeg2 desc="MPEG2 Video" exts="mpv2,mp2v"
|
||||||
|
# looks like a parameter assignment. However, we really
|
||||||
|
# don't want to be screwed up by future extensions,
|
||||||
|
# so we split the elements to an array and pick out the
|
||||||
|
# ones we're interested in.
|
||||||
|
type= exts=
|
||||||
|
|
||||||
|
# Syntactically split line to preserve quoted words.
|
||||||
|
array=(${(z)line})
|
||||||
|
for elt in $array; do
|
||||||
|
if [[ $elt = (type|exts)=* ]]; then
|
||||||
|
eval $elt
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Get extensions by splitting on comma
|
||||||
|
array=(${(s.,.)exts})
|
||||||
|
|
||||||
|
[[ -n $type ]] && mime-setup-add-type $type $array
|
||||||
|
else
|
||||||
|
# Simple.
|
||||||
|
mime-setup-add-type ${=line}
|
||||||
|
fi
|
||||||
|
done <$file
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
# Loop through files to find handlers for types.
|
||||||
|
for file in $cap_files; do
|
||||||
|
[[ -r $file ]] || continue
|
||||||
|
|
||||||
|
# Oh, great. We need to preserve backslashes inside the line,
|
||||||
|
# but need to manage continuation lines.
|
||||||
|
while read -r line; do
|
||||||
|
# Skip blank or comment lines.
|
||||||
|
[[ $line = [[:space:]]#(\#*|) ]] && continue
|
||||||
|
|
||||||
|
while [[ $line = (#b)(*)\\ ]]; do
|
||||||
|
line=$match[1]
|
||||||
|
read -r line2 || break
|
||||||
|
line+=$line2
|
||||||
|
done
|
||||||
|
|
||||||
|
# Guess what, this file has a completely different format.
|
||||||
|
# See mailcap(4).
|
||||||
|
# The biggest unpleasantness here is that the fields are
|
||||||
|
# delimited by semicolons, but the command field, which
|
||||||
|
# is the one we want to extract, may itself contain backslashed
|
||||||
|
# semicolons.
|
||||||
|
if [[ $line = (#b)[[:space:]]#([^[:space:]\;]##)[[:space:]]#\;(*) ]]
|
||||||
|
then
|
||||||
|
# this is the only form we can handle, but there's no point
|
||||||
|
# issuing a warning for other forms.
|
||||||
|
type=$match[1]
|
||||||
|
line=$match[2]
|
||||||
|
# See if it has flags after the command.
|
||||||
|
if [[ $line = (#b)(([^\;\\]|\\\;|\\[^\;])#)\;(*) ]]; then
|
||||||
|
line=$match[1]
|
||||||
|
flags=$match[3]
|
||||||
|
else
|
||||||
|
flags=
|
||||||
|
fi
|
||||||
|
# Remove quotes from semicolons
|
||||||
|
line=${line//\\\;/\;}
|
||||||
|
# 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:
|
||||||
|
$line" >&2
|
||||||
|
fi
|
||||||
|
type_handler_map[$type]=$line
|
||||||
|
type_flags_map[$type]=$flags
|
||||||
|
if [[ -n $flags && -n $o_verbose ]]; then
|
||||||
|
print -r " with flags $flags" >&2
|
||||||
|
fi
|
||||||
|
elif [[ -n $o_verbose ]]; then
|
||||||
|
print -r "Skipping handler for already defined type $type:
|
||||||
|
$line" >&2
|
||||||
|
if [[ -n $flags ]]; then
|
||||||
|
print -r " with flags $flags" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done <$file
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
|
# Check for styles which override whatever is in the file.
|
||||||
|
# We need to make sure there is a handler set up; for some
|
||||||
|
# uses we may need to defer checking styles until zsh-mime-handler.
|
||||||
|
# How much we need to do here is a moot point.
|
||||||
|
zstyle -L | while read line; do
|
||||||
|
array=(${(Q)${(z)line}})
|
||||||
|
if [[ $array[3] = (handler|flags) && \
|
||||||
|
$array[2] = (#b):mime:.([^:]##):(*) ]]; then
|
||||||
|
suffix=$match[1]
|
||||||
|
# Make sure there is a suffix alias set up for this.
|
||||||
|
alias -s $suffix >&/dev/null || alias -s $suffix=zsh-mime-handler
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Now associate the suffixes directly with handlers.
|
||||||
|
# We just look for the first one with a handler.
|
||||||
|
# If there is no handler, we don't bother registering an alias
|
||||||
|
# for the suffix.
|
||||||
|
|
||||||
|
for suffix line in ${(kv)suffix_type_map}; do
|
||||||
|
# Skip if we already have a handler.
|
||||||
|
[[ -n $zsh_mime_handlers[$suffix] ]] && continue
|
||||||
|
|
||||||
|
# Split the space-separated list of types.
|
||||||
|
array=(${=line})
|
||||||
|
|
||||||
|
# Find the first type with a handler.
|
||||||
|
line2=
|
||||||
|
for type in $array; do
|
||||||
|
line2=${type_handler_map[$type]}
|
||||||
|
[[ -n $line2 ]] && break
|
||||||
|
done
|
||||||
|
|
||||||
|
# See if there is a generic type/* handler.
|
||||||
|
# TODO: do we need to consider other forms of wildcard?
|
||||||
|
if [[ -z $line2 ]]; then
|
||||||
|
for type in $array; do
|
||||||
|
type="${type%%/*}/*"
|
||||||
|
line2=${type_handler_map[$type]}
|
||||||
|
[[ -n $line2 ]] && break
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n $line2 ]]; then
|
||||||
|
# Found a type with a handler.
|
||||||
|
# Install the zsh handler as an alias, but never override
|
||||||
|
# existing suffix handling.
|
||||||
|
alias -s $suffix >&/dev/null || alias -s $suffix=zsh-mime-handler
|
||||||
|
|
||||||
|
zsh_mime_handlers[$suffix]=$line2
|
||||||
|
zsh_mime_flags[$suffix]=$type_flags_map[$type]
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
true
|
Loading…
Reference in a new issue