after-move cleanup

This commit is contained in:
Sven Wischnowsky 2001-04-02 13:04:04 +00:00
parent c6686513ef
commit 3d7263ff67
29 changed files with 1357 additions and 225 deletions

View file

@ -1,130 +0,0 @@
# So that this file can also be read with `.' or `source' ...
compaudit() { # Define and then call
# Audit the fpath to assure that it contains all the directories needed by
# the completion system, and that those directories are at least unlikely
# to contain dangerous files. This is far from perfect, as the modes or
# ownership of files or directories might change between the time of the
# audit and the time the function is executed.
# This function is designed to be called from compinit, which assumes that
# it is in the same directory, i.e., it can be autoloaded from the initial
# fpath as compinit was. Most local parameter names in this function must
# therefore be the same as those used in compinit.
emulate -L zsh
setopt extendedglob
# The positional parameters are the directories to check, else fpath.
if (( $# )); then
local _compdir=''
elif (( $#fpath == 0 )); then
print 'compaudit: No directories in $fpath, cannot continue' 1>&2
return 1
else
set -- $fpath
fi
# _i_check is defined by compinit; used here as a test for whether this
# function is running standalone or was called by compinit. If called
# by compinit, we use parameters that are defined in compinit's scope,
# otherwise we make them local here.
(( $+_i_check )) || {
local _i_q _i_line _i_file _i_fail=verbose
local -a _i_files _i_addfiles _i_wdirs _i_wfiles
local -a -U +h fpath
}
fpath=( $* )
# _compdir may be defined by the user; see the compinit documentation.
# If it isn't defined, we want it to point somewhere sensible, but the
# user is allowed to set it to empty to bypass the check below.
(( $+_compdir )) || {
local _compdir=${fpath[(r)*/$ZSH_VERSION/*]}
[[ -z $_compdir ]] && _compdir=$fpath[1]
[[ -d $_compdir/../Core ]] && _compdir=${_compdir:h}
}
_i_wdirs=()
_i_wfiles=()
_i_files=( ${^~fpath:/.}/^([^_]*|*~|*.zwc)(N) )
if [[ -n $_compdir ]]; then
if [[ $#_i_files -lt 20 || $_compdir = */Core || -d $_compdir/Core ]]; then
# Too few files: we need some more directories, or we need to check
# that all directories (not just Core) are present.
_i_addfiles=()
if [[ $_compdir = */Core ]]; then
# Add all the Completion subdirectories
_i_addfiles=(${_compdir:h}/*(/))
elif [[ -d $_compdir/Core ]]; then
# Likewise
_i_addfiles=(${_compdir}/*(/))
fi
for _i_line in {1..$#i_addfiles}; do
_i_file=${_i_addfiles[$_i_line]}
[[ -d $_i_file && -z ${fpath[(r)$_i_file]} ]] ||
_i_addfiles[$_i_line]=
done
fpath=($fpath $_i_addfiles)
_i_files=( ${^~fpath:/.}/^([^_]*|*~|*.zwc)(N) )
fi
fi
[[ $_i_fail == use ]] && return 0
# RedHat Linux "per-user groups" check. This is tricky, because it's very
# difficult to tell whether the sysadmin has put someone else into your
# "private" group (e.g., via the default group field in /etc/passwd, or
# by NFS group sharing with an untrustworthy machine). So we must assume
# that this has not happened, and pick the best group.
local GROUP GROUPMEM _i_pw _i_gid
while IFS=: read GROUP _i_pw _i_gid GROUPMEM; do
if (( UID == EUID )); then
[[ $GROUP == $LOGNAME ]] && break
else
(( _i_gid == EGID )) && break # Somewhat arbitrary
fi
done < /etc/group
# We search for:
# - world/group-writable directories in fpath not owned by root and the user
# - parent-directories of directories in fpath that are world/group-writable
# and not owned by root and the user (that would allow someone to put a
# digest file for one of the directories into the parent directory)
# - digest files for one of the directories in fpath not owned by root and
# the user
# - and for files in directories from fpath not owned by root and the user
# (including zwc files)
if [[ $GROUP == $LOGNAME && ( -z $GROUPMEM || $GROUPMEM == $LOGNAME ) ]]; then
_i_wdirs=( ${^fpath}(Nf:g+w:^g:${GROUP}:,f:o+w:,^u0u${EUID})
${^fpath}/..(Nf:g+w:^g:${GROUP}:,f:o+w:,^u0u${EUID}) )
else
_i_wdirs=( ${^fpath}(Nf:g+w:,f:o+w:,^u0u${EUID})
${^fpath}/..(Nf:g+w:,f:o+w:,^u0u${EUID}) )
fi
_i_wdirs=( $_i_wdirs ${^fpath}.zwc^([^_]*|*~)(N^u0u${EUID}) )
_i_wfiles=( ${^fpath}/^([^_]*|*~)(N^u0u${EUID}) )
case "${#_i_wdirs}:${#_i_wfiles}" in
(0:0) _i_q= ;;
(0:*) _i_q=files ;;
(*:0) _i_q=directories ;;
(*:*) _i_q='directories and files' ;;
esac
if [[ -n "$_i_q" ]]; then
[[ $_i_fail == verbose ]] && {
print There are insecure ${_i_q}: 1>&2
print -l - $_i_wdirs $_i_wfiles
}
return 1
fi
return 0
} # Define and then call
compaudit "$@"

View file

@ -1,24 +1,5 @@
#compdef dict
local expl dictresults dictwords j dict
_dictwords() {
[[ -z $words[CURRENT] ]] && return 1
dictresults=(${${(f)${"$(dict -m $words[CURRENT])":gs/
/ /}}:#[0-9]*matches found})
for j in ${dictresults}
do
dict=${j%%:*}
dictwords=(${(z)j#*:})
_wanted $dict expl "words from $dict" \
compadd -M 'm:{a-zA-Z}={A-Za-z} r:|=*' -a "$@" - dictwords
done
}
_arguments \
'(--host)-h[host]:dict server:_hosts' \
'(-h)--host:dict server:_hosts' \
@ -63,4 +44,4 @@ _arguments \
'--pipesize:buffer size:' \
'--client:client text:' \
'--debug:debug flag:(verbose raw scan parse pipe serial time)' \
':word:_dictwords'
':word:_dict_words'

View file

@ -1,5 +1,6 @@
DISTFILES_SRC='
.distfiles
_dict_words _mailboxes _perl_modules _tex
_diff_options _my_accounts _pids _texi
_dir_list _newsgroups _ports _tilde_files
_directories _other_accounts _printers _urls
@ -7,5 +8,4 @@ _domains _path_files _ps _user_at_host
_files _pdf _pspdf _users
_groups _perl_basepods _signals _users_on
_hosts _perl_builtin_funcs _tar_archive
_mailboxes _perl_modules _tex
'

View file

@ -1,9 +1,9 @@
DISTFILES_SRC='
.distfiles
_autoload _disable _kill _sched _typeset _zftp
_bindkey _echotc _mere _set _unhash _zle
_builtin _emulate _precommand _setopt _unsetopt _zmodload
_cd _enable _print _source _wait _zpty
_command _fc _prompt _stat _which _zstyle
_compdef _hash _read _trap _zcompile _zed
_autoload _disable _kill _sched _typeset _zed
_bindkey _echotc _mere _set _unhash _zftp
_builtin _emulate _precommand _setopt _unsetopt _zle
_cd _enable _print _source _wait _zmodload
_command _fc _prompt _stat _which _zpty
_compdef _hash _read _trap _zcompile _zstyle
'

View file

@ -43,7 +43,7 @@ fpath=( $* )
(( $+_compdir )) || {
local _compdir=${fpath[(r)*/$ZSH_VERSION/*]}
[[ -z $_compdir ]] && _compdir=$fpath[1]
[[ -d $_compdir/../Core ]] && _compdir=${_compdir:h}
### [[ -d $_compdir/../Base ]] && _compdir=${_compdir:h}
}
_i_wdirs=()
@ -51,14 +51,14 @@ _i_wfiles=()
_i_files=( ${^~fpath:/.}/^([^_]*|*~|*.zwc)(N) )
if [[ -n $_compdir ]]; then
if [[ $#_i_files -lt 20 || $_compdir = */Core || -d $_compdir/Core ]]; then
if [[ $#_i_files -lt 20 || $_compdir = */Base || -d $_compdir/Base ]]; then
# Too few files: we need some more directories, or we need to check
# that all directories (not just Core) are present.
# that all directories (not just Base) are present.
_i_addfiles=()
if [[ $_compdir = */Core ]]; then
if [[ $_compdir = */Base ]]; then
# Add all the Completion subdirectories
_i_addfiles=(${_compdir:h}/*(/))
elif [[ -d $_compdir/Core ]]; then
elif [[ -d $_compdir/Base ]]; then
# Likewise
_i_addfiles=(${_compdir}/*(/))
fi

View file

@ -1,8 +1,8 @@
# Initialisation for new style completion. This mainly contains some helper
# functions and aliases. Everything else is split into different files that
# functions and setup. Everything else is split into different files that
# will automatically be made autoloaded (see the end of this file). The
# names of the files that will be considered for autoloading are those that
# begin with an underscores (like `_setopt').
# begin with an underscores (like `_condition).
#
# The first line of each of these files is read and must indicate what
# should be done with its contents:

View file

@ -190,9 +190,9 @@ __ci_set_compdir() {
__ci_set_compdir $fpath
if [[ $compdir = */Core && -d $compdir/../Base ]]; then
if [[ -d $compdir/Base ]]; then
subdirs=1
compdir=${compdir:h}
### compdir=${compdir:h}
fi
if [[ -z $compdir ]]; then

View file

@ -14,8 +14,16 @@ allfuncs="`cd $sdir_top; echo ${allfuncs}`"
for file in $allfuncs; do
if test -f $sdir_top/$file; then
if test x$FUNCTIONS_SUBDIRS != x -a x$FUNCTIONS_SUBDIRS != xno; then
subdir="`echo $file | sed -e 's%/[^/]*$%%' -e 's%^Functions/%%'`"
instdir="$fndir/$subdir"
case "$file" in
Completion/*)
subdir="`echo $file | sed -e 's%/[^/]*/[^/]*$%%'`"
instdir="$fndir/$subdir"
;;
*)
subdir="`echo $file | sed -e 's%/[^/]*$%%' -e 's%^Functions/%%'`"
instdir="$fndir/$subdir"
;;
esac
else
instdir="$fndir"
fi

View file

@ -143,8 +143,8 @@ For incomplete installations, if tt(compinit) does not find enough files
beginning with an underscore (fewer than twenty) in the search path, it
will try to find more by adding the directory tt(_compdir) to the search
path. Furthermore, if the directory in question ends in the path segment
tt(Core), or has a subdirectory named tt(Core), tt(compinit) will add all
subdirectories of the directory where tt(Core) is to the path: this allows
tt(Base), or has a subdirectory named tt(Base), tt(compinit) will add all
subdirectories of the directory where tt(Base) is to the path: this allows
the functions to be in the same format as in the tt(zsh) source
distribution.
@ -317,7 +317,7 @@ do:
example(compdef _pids foo)
using the tt(_pids) function from the distribution to generate the
process identifiers. Not also the tt(_use_lo) function described
process identifiers. Not also the tt(_gnu_generic) function described
below, which can be used to complete options for commands that
understand the `tt(-)tt(-help)' option.
@ -823,7 +823,7 @@ values)
)
kindex(version, completion tag)
item(tt(version))(
used by tt(_call) to look up the command to run to determine the installed
used by tt(_call_program) to look up the command to run to determine the installed
version of various other commands (such as tt(diff) and tt(make)).
)
kindex(warnings, completion tag)
@ -2800,7 +2800,7 @@ cindex(completion system, utility functions)
Descriptions follow for utility functions that may be
useful when writing completion functions. Most of these reside in the
tt(Core) subdirectory. Like the example
tt(Base) subdirectory. Like the example
functions for commands in the distribution, the utility functions
generating matches all follow the convention of returning zero if they
generated completions and non-zero if no matching completions could be
@ -3344,14 +3344,14 @@ example(_example_caching_policy () {
(( $#oldp ))
})
)
findex(_call)
item(tt(_call) var(tag) var(string) ...)(
findex(_call_program)
item(tt(_call-program) var(tag) var(string) ...)(
This function is used in places where a command is called, making it
possible for the user to override the default command call. It looks up
the tt(command) style with the supplied var(tag). If the style is set, its
value is used as the command to execute.
In any case, the var(string)s from the call to tt(_call) or from the
In any case, the var(string)s from the call to tt(_call_program) or from the
style are concatenated with spaces between them and the resulting
string is evaluated. The return value is the return value of the
command called.
@ -3396,13 +3396,13 @@ All arguments after the requested field name are passed to
tt(compadd) when generating matches from the style value, or to
the functions for the fields if they are called.
)
findex(_compalso)
item(tt(_compalso) var(names) ...)(
findex(_contexts)
item(tt(_contexts) var(names) ...)(
This function looks up the definitions for the context and command
names given as arguments and calls the handler functions for them if
there is a definition (given with the tt(compdef) function). For
example, the function completing inside subscripts might use
`tt(_compalso -math-)' to include the completions generated for
`tt(_contexts -math-)' to include the completions generated for
mathematical environments.
)
findex(_describe)
@ -3483,13 +3483,13 @@ tt(file-patterns) style.
See tt(_path_files) below for a description of the full set of options
accepted by tt(_files).
)
findex(_funcall)
item(tt(_funcall) var(return) var(name) [ var(args) ... ])(
findex(_call_function)
item(tt(_call_function) var(return) var(name) [ var(args) ... ])(
If a function var(name) exists, it is called with the arguments
var(args). Unless it is the empty string or a single hyphen,
var(return) is taken as the name of a parameter and the return status
from the called function is stored in it.
The return value of tt(_funcall) itself is zero if the function
The return value of tt(_call_function) itself is zero if the function
var(name) exists and was called and non-zero otherwise.
)
findex(_message)
@ -3601,6 +3601,18 @@ allows the user to type upper-case letters which will match their
lower-case counterparts. All arguments passed to this function are
propagated unchanged to the tt(compadd) builtin.
)
findex(_options_set)
findex(_options_unset)
item(tt(_options_set) and tt(_options_unset))(
These functions complete only set or unset options, with the same
matching specification used in the tt(_options) function.
Note that you need to uncomment a few lines in the tt(_main_complete)
function for these functions to work properly. The lines in question
are used to store the option settings in effect before the completion
widget locally sets the options it needs. Hence these options are not
generally used by the completion system.
)
findex(_parameters)
item(tt(_parameters))(
This should be used to complete parameter names. tt(_parameters) can
@ -3781,18 +3793,6 @@ This function passes the `tt(-V)', `tt(-J)', `tt(-1)', `tt(-2)',
and `tt(-q)' options and their arguments to the tt(compadd) builtin
used to add the matches.
)
findex(_set_options)
findex(_unset_options)
item(tt(_set_options) and tt(_unset_options))(
These functions complete only set or unset options, with the same
matching specification used in the tt(_options) function.
Note that you need to uncomment a few lines in the tt(_main_complete)
function for these functions to work properly. The lines in question
are used to store the option settings in effect before the completion
widget locally sets the options it needs. Hence these options are not
generally used by the completion system.
)
findex(_setup)
item(tt(_setup) var(tag) [ var(group) ])(
This function expects a tag as its argument and sets up the special
@ -3857,17 +3857,17 @@ tt(curcontext) parameter. This allows tt(_tags) to be made to use a more
specific context name without having to change and reset the
tt(curcontext) parameter (which would otherwise have the same effect).
)
findex(_use_lo)
item(tt(_use_lo))(
findex(_gnu_generic)
item(tt(_gnu_generic))(
This function is a simple wrapper around the tt(_arguments) function
described above. It can be used to automatically complete long
options for commands that understand the `tt(-)tt(-help)' option
(`tt(_use_lo)' is for `use long options'). It is not intended to be
used from completion functions but as a top-level completion function
in its own right. For example, to enable option completion for the
commands tt(foo) and tt(bar), one would call:
options for commands that understand the `tt(-)tt(-help)' option.
It is not intended to be used from completion functions but as a
top-level completion function in its own right. For example, to
enable option completion for the commands tt(foo) and tt(bar), one
would call:
example(compdef _use_lo foo bar)
example(compdef _gnu_generic foo bar)
in one of the initialization files after the call to tt(compinit).
@ -3989,21 +3989,17 @@ it to some directory which appears earlier in your tt(fpath) than the
standard directory where it appears.
startitem()
item(tt(Core))(
The core scripts and functions. You will certainly need these, though will
item(tt(Base))(
The core functions and special completion widgets automatically bound
to keys. You will certainly need most of these, though will
probably not need to alter them. Many of these are documented above.
)
item(tt(Base))(
Other functions you will almost certainly want if you are going to use
any of the standard completion functions. You may want to edit some of
these files.
)
item(tt(Builtins))(
item(tt(Zsh))(
Functions for completing arguments of shell builtin commands and
utility functions for this. Some of these are also used by functions from
the tt(User) directory.
the tt(Unix) directory.
)
item(tt(User))(
item(tt(Unix))(
Functions for completing arguments of external commands and suites of
commands. They may need modifying for your system, although in many cases
some attempt is made to decide which version of a command is present. For
@ -4012,8 +4008,7 @@ it is running on, while completion for many other utilities try to decide
whether the GNU version of the command is in use, and hence whether the
tt(--help) option is supported..
)
item(tt(Commands))(
Functions which implement special types of completion to be bound to
keystrokes rather than called by context.
item(tt(X), tt(AIX), tt(BSD), ...)(
Completion and utility function for commands available only on some systems.
)
enditem()

View file

@ -657,6 +657,6 @@ subsect(Completion)
Completion of local and remote files, directories, sessions and bookmarks
is supported. The older, tt(compctl)-style completion is defined when
tt(zfinit) is called; support for the new widget-based completion system is
provided in the function tt(Completion/Builtins/_zftp), which should be
provided in the function tt(Completion/Zsh/Command/_zftp), which should be
installed with the other functions of the completion system and hence
should automatically be available.

View file

@ -401,13 +401,13 @@ Misc. remarks
completely different modes), it should allow users to define
functions that separately override the behavior for these
different types. This can easily be achieved by using the
`_funcall' utility function, as in:
`_call_function' utility function, as in:
_funcall ret _command_$subcommand && return ret
_call_function ret _command_$subcommand && return ret
This will try to call the function `_command_$subcommand' and if
it exists, it will be called and the completion function exits
with its exit status. After this call to `funcall' the completion
function would contain the code for the default way to generate
the matches.
with its exit status. After this call to `call_function' the
completion function would contain the code for the default way to
generate the matches.
See the `_rpm' and `_nslookup' files for examples.

View file

@ -1,3 +1,6 @@
DISTFILES_SRC='
.distfiles
allopt harden nslookup zkbd zstyle+
checkmail is-at-least run-help zmv
colors mere zed zrecompile
'

28
Functions/Misc/allopt Normal file
View file

@ -0,0 +1,28 @@
# This function lists options with the no's in front removed for
# improved comprehension, i.e. `norcs off' becomes `rcs on'.
# The format is otherwise like that with `kshoptionprint' set,
# i.e. you can see all options whether on or off.
# It can take a list of option names or parts thereof to search for
# via egrep.
#
# Written by Sweth Chandramouli with hacks by Bart Schaefer.
listalloptions () {
builtin setopt localoptions kshoptionprint
local OPT_NAME OPT_PAIR OPT_VALUE
for OPT_PAIR in "${(f)$(builtin setopt)}" ; do
OPT_VALUE=${OPT_PAIR##* }
OPT_NAME=${OPT_PAIR%% *}
if [[ ${OPT_NAME#no} != ${OPT_NAME} ]] ; then
OPT_VALUE=${(L)${${OPT_VALUE:s/on/OFF}:s/off/on}}
OPT_NAME=${OPT_NAME#no}
fi
echo "${(r:21:)OPT_NAME} ${OPT_VALUE}"
done
}
if [[ -n $@ ]]; then
listalloptions | egrep "${(j.|.)@}"
else
listalloptions
fi

26
Functions/Misc/checkmail Normal file
View file

@ -0,0 +1,26 @@
#! /usr/local/bin/zsh
#
# This autoloadable function checks the folders specified as arguments
# for new mails. The arguments are interpeted in exactly the same way
# as the mailpath special zsh parameter (see zshparam(1)).
#
# If no arguments are given mailpath is used. If mailpath is empty, $MAIL
# is used and if that is also empty, /var/spool/mail/$LOGNAME is used.
# This function requires zsh-3.0.1 or newer.
#
local file message
for file in "${@:-${mailpath[@]:-${MAIL:-/var/spool/mail/$LOGNAME}}}"
do
message="${${(M)file%%\?*}#\?}"
file="${file%%\?*}"
if [[ -d "$file" ]] then
file=( "$file"/**/*(.ND) )
if (($#file)) then
checkmail "${^file}\?$message"
fi
elif test -s "$file" -a -N "$file"; then # this also sets $_ to $file
print -r -- "${(e)message:-You have new mail.}"
fi
done

79
Functions/Misc/colors Normal file
View file

@ -0,0 +1,79 @@
# Put standard ANSI color codes in shell parameters for easy use.
# Note that some terminals do not support all combinations.
typeset -Ag color colour
color=(
# Attribute codes:
00 none
01 bold
02 faint 22 normal
03 standout 23 no-standout
04 underline 24 no-underline
05 blink 25 no-blink
07 reverse 27 no-reverse
08 conceal
# Text color codes:
30 black 40 bg-black
31 red 41 bg-red
32 green 42 bg-green
33 yellow 43 bg-yellow
34 blue 44 bg-blue
35 magenta 45 bg-magenta
36 cyan 46 bg-cyan
37 white 47 bg-white
39 default 49 bg-default
)
# A word about black and white: The "normal" shade of white is really a
# very pale grey on many terminals; to get truly white text, you have to
# use bold white, and to get a truly white background you have to use
# bold reverse white bg-xxx where xxx is your desired foreground color
# (and which means the foreground is also bold).
# Map in both directions; could do this with e.g. ${(k)colors[(i)normal]},
# but it's clearer to include them all both ways.
local k
for k in ${(k)color}; do color[${color[$k]}]=$k; done
# Add "fg-" keys for all the text colors, for clarity.
for k in ${color[(I)3?]}; do color[fg-${color[$k]}]=$k; done
# This is inaccurate, but the prompt theme system needs it.
color[grey]=${color[black]}
color[fg-grey]=${color[grey]}
color[bg-grey]=${color[bg-black]}
# Assistance for the color-blind.
colour=(${(kv)color}) # A case where ksh namerefs would be useful ...
# The following are terminal escape sequences used by colored prompt themes.
local lc=$'\e[' rc=m # Standard ANSI terminal escape values
typeset -Hg reset_color bold_color
reset_color="$lc${color[none]}$rc"
bold_color="$lc${color[bold]}$rc"
# Foreground
typeset -AHg fg fg_bold fg_no_bold
for k in ${(k)color[(I)fg-*]}; do
fg[${k#fg-}]="$lc${color[$k]}$rc"
fg_bold[${k#fg-}]="$lc${color[bold]};${color[$k]}$rc"
fg_no_bold[${k#fg-}]="$lc${color[normal]};${color[$k]}$rc"
done
# Background
typeset -AHg bg bg_bold bg_no_bold
for k in ${(k)color[(I)bg-*]}; do
bg[${k#bg-}]="$lc${color[$k]}$rc"
bg_bold[${k#bg-}]="$lc${color[bold]};${color[$k]}$rc"
bg_no_bold[${k#bg-}]="$lc${color[normal]};${color[$k]}$rc"
done

6
Functions/Misc/harden Normal file
View file

@ -0,0 +1,6 @@
#! /bin/sh
# harden a link (convert it to a singly linked file)
cp $1 $1.foo
rm $1
mv $1.foo $1

View file

@ -0,0 +1,38 @@
#
# Test whether $ZSH_VERSION (or some value of your choice, if a second argument
# is provided) is greater than or equal to x.y.z-r (in argument one). In fact,
# it'll accept any dot/dash-separated string of numbers as its second argument
# and compare it to the dot/dash-separated first argument. Leading non-number
# parts of a segment (such as the "zefram" in 3.1.2-zefram4) are not considered
# when the comparison is done; only the numbers matter. Any left-out segments
# in the first argument that are present in the version string compared are
# considered as zeroes, eg 3 == 3.0 == 3.0.0 == 3.0.0.0 and so on.
#
# Usage examples:
# is-at-least 3.1.6-15 && setopt NO_GLOBAL_RCS
# is-at-least 3.1.0 && setopt HIST_REDUCE_BLANKS
# is-at-least 586 $MACHTYPE && echo 'You could be running Mandrake!'
# is-at-least $ZSH_VERSION || print 'Something fishy here.'
emulate zsh ; setopt LOCAL_OPTIONS
local IFS=".-" min_cnt=0 ver_cnt=0 part min_ver version
min_ver=(${=1})
version=(${=2:-$ZSH_VERSION} 0)
while (( $min_cnt <= ${#min_ver} )); do
while [[ "$part" != <-> ]]; do
(( ++ver_cnt > ${#version} )) && return 0
part=${version[ver_cnt]##*[^0-9]}
done
while true; do
(( ++min_cnt > ${#min_ver} )) && return 0
[[ ${min_ver[min_cnt]} = <-> ]] && break
done
(( part > min_ver[min_cnt] )) && return 0
(( part < min_ver[min_cnt] )) && return 1
part=''
done

83
Functions/Misc/mere Normal file
View file

@ -0,0 +1,83 @@
# read a man page
setopt localoptions extendedglob
local manual="$1" col=col terminal=man magic line
# /usr/bin/col on SunOS 4 doesn't support -x.
if [[ -x /usr/5bin/col ]]; then
col=/usr/5bin/col;
fi
# SunOS 5 has no `man' terminal.
if [[ -d /usr/share/lib/nterm &&
! -e /usr/share/lib/nterm/tab.$terminal ]]; then
terminal=lp;
fi
# HP-UX has no `man' terminal.
if [[ -d /usr/share/lib/term &&
! -e /usr/share/lib/term/tab$terminal ]]; then
terminal=lp;
fi
# Unixware has no `man' terminal.
if [[ -d /usr/ucblib/doctools/nterm &&
! -e /usr/ucblib/doctools/nterm/tab.$terminal ]]; then
terminal=lp;
fi
# Solaris has SGML manuals.
if [[ -f /usr/lib/sgml/sgml2roff ]] &&
[[ "$(read -er < $manual)" = "<!DOCTYPE"* ]]; then
/usr/lib/sgml/sgml2roff $manual | {
read -r line
if [[ $line = ".so "* ]]; then
# There is no cascading .so directive.
# On Solaris 7, at least.
/usr/lib/sgml/sgml2roff ${line#.so }
else
print -lr - "$line"
cat
fi
}
else
read -u0 -k 2 magic < $manual
case $magic in
$'\037\235') zcat $manual;;
$'\037\213') gzip -dc $manual;;
*) cat $manual;;
esac
fi | (
# cd is required to work soelim called by nroff.
case $manual in
*/man/man*/*) cd ${manual:h:h};;
*/man/sman*/*) cd ${manual:h:h};;
esac
read -r line
# The first line beginning with '\" shows preprocessors.
# Unknown preprocessors is ignored.
if [[ $line = "'\\\" "* ]]; then
typeset -A filter
filter=(
e neqn
g grap
p pic
r refer
t tbl
v vgrind
)
eval ${(j:|:)${${(s::)line#\'\\\" }//(#m)?/$filter[$MATCH]}}
elif [[ $line = "'\\\"! "* ]]; then
typeset -A filter
filter=(
eqn neqn
)
eval ${(j:|:)${${${${(s:|:)line#\'\\\"! }# ##}% ##}//(#m)*/$filter[$MATCH]}}
else
print -lr - "$line"
cat
fi |
nroff -T$terminal -man | $col -x
) |
${=MANPAGER:-${PAGER:-more}} -s

48
Functions/Misc/nslookup Normal file
View file

@ -0,0 +1,48 @@
# Simple wrapper function for `nslookup'. With completion if you are using
# the function based completion system.
if [[ $argv[(I)-] -eq 0 && $argv[(I)[^-]*] -ne 0 ]]; then
command nslookup "$@"
return
fi
setopt localoptions localtraps completealiases
local tmp line compcontext=nslookup curcontext='nslookup:::' pmpt
local pager opager="$PAGER"
typeset +g -x PAGER=cat
zmodload -e zsh/zpty || zmodload -i zsh/zpty
trap 'return 130' INT
trap 'zpty -d nslookup' EXIT
pmpt=()
zstyle -s ':nslookup' prompt tmp && pmpt=(-p "$tmp")
zstyle -s ':nslookup' rprompt tmp && pmpt=("$pmpt[@]" -r "$tmp")
zstyle -s ':nslookup' pager tmp &&
[[ -z "$pager" ]] && pager="${opager:-more}"
(( $#pmpt )) || pmpt=(-p '> ')
zpty nslookup command nslookup "${(q)@}"
zpty -r nslookup line '*
> '
print -nr "$line"
while line=''; vared -he "$pmpt[@]" line; do
print -s "$line"
[[ "$line" = exit ]] && break
zpty -w nslookup "$line"
zpty -r nslookup line '*
> '
if [[ -n "$pager" && ${#${(f)line}} -gt LINES ]]; then
print -nr "$line" | eval "$pager"
else
print -nr "$line"
fi
done
zpty -w nslookup 'exit'

88
Functions/Misc/run-help Normal file
View file

@ -0,0 +1,88 @@
#!/usr/local/bin/zsh
#
# Figure out where to get the best help, and get it.
#
# Install this function by placing it in your FPATH and then
# adding to your .zshrc the lines:
# unalias run-help
# autoload run-help
#
emulate -R zsh
setopt localoptions
[[ $1 == "." ]] && 1="dot"
[[ $1 == ":" ]] && 1="colon"
# Check whether Util/helpfiles has been used to generate zsh help
if [[ $# == 0 || $1 == "-l" ]]
then
if [[ -n "${HELPDIR:-}" && -d $HELPDIR ]]
then
echo "Here is a list of topics for which special help is available:"
echo ""
print -rc $HELPDIR/*(:t)
else
echo "There is no list of special help topics available at this time."
fi
return 0
elif [[ -n "${HELPDIR:-}" && -r $HELPDIR/$1 && $1 != compctl ]]
then
${=PAGER:-more} $HELPDIR/$1
return $?
fi
# No zsh help; use "whence" to figure out where else we might look
local what places newline='
'
integer i=0 didman=0
places=( "${(@f)$(builtin whence -va $1)}" )
while ((i++ < $#places))
do
what=$places[$i]
builtin print -r $what
case $what in
(*( is an alias)*)
[[ ${what[(w)6]:t} != ${what[(w)1]} ]] && run-help ${what[(w)6]:t}
;;
(*( is a * function))
case ${what[(w)1]} in
(comp*) man zshcompsys;;
(zf*) man zshftpsys;;
(*) builtin functions ${what[(w)1]} | ${=PAGER:-more};;
esac;;
(*( is a * builtin))
case ${what[(w)1]} in
(compctl) man zshcompctl;;
(comp*) man zshcompwid;;
(bindkey|vared|zle) man zshzle;;
(*setopt) man zshoptions;;
(cap|getcap|setcap) ;&
(clone) ;&
(ln|mkdir|mv|rm|rmdir|sync) ;&
(sched) ;&
(stat) man zshmodules;;
(zftp) man zshftpsys;;
(*) man zshbuiltins;;
esac
;;
(*( is hashed to *))
man ${what[(w)-1]:t}
;;
(*( is a reserved word))
man zshmisc
;;
(*)
((! didman++)) && man $@
;;
esac
if ((i < $#places && ! didman))
then
builtin print -nP "%SPress any key for more help or q to quit%s"
builtin read -k what
[[ $what != $newline ]] && echo
[[ $what == [qQ] ]] && break
fi
done

70
Functions/Misc/zed Normal file
View file

@ -0,0 +1,70 @@
#
# zed
#
# No other shell could do this.
# Edit small files with the command line editor.
# Use ^X^W to save, ^C to abort.
# Option -f: edit shell functions. (Also if called as fned.)
#
# Completion: use
# compctl -f -x 'w[1,-f]' -F -- zed
#
local var fun cleanup
# We do not want timeout while we are editing a file
integer TMOUT=0
[[ $1 = -f || $0 = fned ]] && fun=1
[[ $1 = -(|-|f) ]] && shift
[[ -z "$1" ]] && echo 'Usage: "zed filename" or "zed -f function"' && return 1
local curcontext=zed:::
zstyle -m ":completion:zed:*" insert-tab '*' ||
zstyle ":completion:zed:*" insert-tab yes
# catch interrupts
cleanup="$(bindkey -L "^M"; bindkey -L -M emacs "^X^W"; bindkey -aL "ZZ"
echo "trap - INT EXIT"; trap)"
trap "return 130" INT
trap "$cleanup" EXIT
# don't mangle !'s
setopt localoptions nobanghist
bindkey "^M" self-insert-unmeta
# Depending on your stty's, you may be able to use ^J as accept-line, else:
bindkey -M emacs "^X^W" accept-line
bindkey -a "ZZ" accept-line
if ((fun)) then
var="$(functions $1)"
# If function is undefined but autoloadable, load it
if [[ $var = *\#\ undefined* ]] then
local dir
for dir in $fpath; do
if [[ -f $dir/$1 ]] then
var="$1() {
$(<$dir/$1)
}"
break
fi
done
elif [[ -z $var ]] then
var="$1() {
}"
fi
vared var && eval "$cleanup ;" function "$var"
else
[[ -f $1 ]] && var="$(<$1)"
while vared var
do
(print -r -- "$var" >| $1) && break
echo -n -e '\a'
done
fi
return 0
# End of zed

248
Functions/Misc/zkbd Normal file
View file

@ -0,0 +1,248 @@
#! /bin/zsh -f
[[ -o interactive ]] && {
local -i ARGC
(ARGC=0) 2>/dev/null || {
print -u2 ${0}: must be run as a function or shell script, not sourced
return 1
}
}
emulate -RL zsh
local zkbd term key seq
zkbd=${ZDOTDIR:-$HOME}/.zkbd
[[ -d $zkbd ]] || mkdir $zkbd || return 1
print 'typeset -g -A key\n' > $zkbd/$TERM.tmp || return 1
trap "unfunction getkey getseq; command rm -f $zkbd/$TERM.tmp" 0
trap "return 1" 1 2 15
getkey () {
local k='' i
for ((i=10; i>0; --i))
do
read -t -k 1 k && break
sleep 1
done
[[ -n $k ]] || return 1
[[ $k = $'\012' || $k = $'\015' || $k = ' ' ]] && return 0
print -Rn $k
}
getseq () {
trap "stty ${$(stty -g 2>/dev/null):-echo -raw}" 0 1 2 15
stty raw -echo
local k='' seq='' i
for ((i=10; i>0; --i))
do
read -t -k 1 k && break
sleep 1
done
[[ -n $k ]] || return 1
[[ $k = $'\012' || $k = $'\015' || $k = ' ' ]] && return 0
seq=$k
while read -t -k 1 k
do
seq=$seq$k
done
print -Rn ${(V)seq}
}
read term"?Enter current terminal type: [$TERM] "
[[ -n $term ]] && TERM=$term
cat <<\EOF
We will now test some features of your keyboard and terminal.
If you do not press the requested keys within 10 seconds, key reading will
abort. If your keyboard does not have a requested key, press Space to
skip to the next key.
EOF
local ctrl alt meta
print -n "Hold down Ctrl and press X: "
ctrl=$(getkey) || return 1
print
if [[ $ctrl != $'\030' ]]
then
print "Your keyboard does not have a working Ctrl key?"
print "Giving up ..."
return 1
else
print
fi
print "Your Meta key may have a Microsoft Windows logo on the cap."
print -n "Hold down Meta and press X: "
meta=$(getkey) || return 1
print
if [[ $meta == x ]]
then
print "Your keyboard or terminal does not recognize the Meta key."
unset meta
elif [[ $meta > $'\177' ]]
then
print "Your keyboard uses the Meta key to send high-order characters."
else
unset meta
fi
print
print -n "Hold down Alt and press X: "
alt=$(getkey) || return 1
print
if [[ $alt == x ]]
then
print "Your keyboard or terminal does not recognize the Alt key."
unset alt
elif [[ $alt == $meta ]]
then
print "Your keyboard does not distinguish Alt from Meta."
elif [[ $alt > $'\177' ]]
then
print "Your keyboard uses the Alt key to send high-order characters."
else
unset alt
fi
(( $+alt + $+meta == 0 )) && cat <<EOF
---------
Your current terminal and keyboard configuration does not appear to use
high-order characters. You may be able to enable the Meta or Alt keys
with a command such as
stty pass8
If you want to use these extra keys with zsh, try adding the above command
to your ${ZDOTDIR:-$HOME}/.zshrc file.
See also "man stty" or the documentation for your terminal or emulator.
EOF
(( $+alt || $+meta )) && cat <<EOF
---------
You may enable keybindings that use the \
${meta:+Meta}${meta:+${alt:+ and }}${alt:+Alt} key${meta:+${alt:+s}} \
by adding
bindkey -m
to your ${ZDOTDIR:-$HOME}/.zshrc file.
EOF
cat <<\EOF
---------
You will now be asked to press in turn each of the 12 function keys, then
the Backspace key, the 6 common keypad keys found on typical PC keyboards,
plus the 4 arrow keys, and finally the Menu key (near Ctrl on the right).
If your keyboard does not have the requested key, press Space to skip to
the next key.
Do not type ahead! Wait at least one second after pressing each key for
zsh to read the entire sequence and prompt for the next key. If a key
sequence does not echo within 2 seconds after you press it, that key may
not be sending any sequence at all. In this case zsh is not able to make
use of that key. Press Space to skip to the next key.
EOF
read -k 1 key"?Press any key when ready to begin: "
[[ $key != $'\n' ]] && print
cat <<\EOF
If you do not press a key within 10 seconds, key reading will abort.
If you make a mistake, stop typing and wait, then run this program again.
EOF
# There are 509 combinations of the following three arrays that represent
# possible keystrokes. (Actually, Sun keyboards don't have Meta or Menu,
# though some have R{1..12} keys as well, so really there are either 433
# or 517 combinations; but some X11 apps map Shift-F{1..11} to emulate the
# unmodified Sun keys, so really only the 345 PC combinations are usable.
# Let's not even get into distinguishing Left and Right Shift/Alt/Meta.)
# No one would ever want to type them all into this program (would they?),
# so by default ask for the 23 unmodified PC keys. If you uncomment more,
# you should fix the introductory text above.
local -a pckeys sunkeys modifiers
pckeys=(F{1..12}
Backspace Insert Home PageUp
Delete End PageDown
Up
Left Down Right
Menu
)
sunkeys=(Stop Again
Props Undo
Front Copy
Open Paste
Find Cut
Help
)
modifiers=(Shift- # Control- Alt- Meta-
# Control-Shift- Alt-Shift- Meta-Shift-
# Control-Alt- Control-Meta- Alt-Meta-
# Control-Alt-Shift- Control-Meta-Shift-
# Alt-Meta-Shift- Control-Alt-Meta-Shift-
)
exec 3>/dev/tty
for key in $pckeys # $^modifiers$^pckeys $sunkeys $^modifiers$^sunkeys
do
print -u3 -Rn "Press $key: "
seq="$(getseq)" || return 1
print "key[$key]='${(q)seq}'"
print -u3 -R $seq
done >> $zkbd/$TERM.tmp
source $zkbd/$TERM.tmp || return 1
if [[ "${key[Delete]}" == "${key[Backspace]}" ]]
then
print
print Warning: Backspace and Delete key both send "${(q)key[Delete]}"
else
if [[ "${key[Delete]}" != "^?" ]]
then
print
print Warning: Delete key sends "${(q)key[Delete]}" '(not ^?)'
fi
if [[ "${key[Backspace]}" != "^H" ]]
then
print
print Warning: Backspace sends "${(q)key[Backspace]}"
fi
fi
command mv $zkbd/$TERM.tmp $zkbd/$TERM-$VENDOR-$OSTYPE
cat <<EOF
Parameter assignments for the keys you typed have been written to the file:
$zkbd/$TERM-$VENDOR-$OSTYPE
You may read this file into ${ZDOTDIR:-$HOME}/.zshrc or another startup
file with the "source" or "." commands, then reference the \$key parameter
in bindkey commands, like this:
source ${zkbd/$HOME/~}/\$TERM-\$VENDOR-\$OSTYPE
[[ -n \${key[Left]} ]] && bindkey "\${key[Left]}" backward-char
[[ -n \${key[Right]} ]] && bindkey "\${key[Right]}" forward-char
# etc.
EOF

268
Functions/Misc/zmv Normal file
View file

@ -0,0 +1,268 @@
# function zmv {
# zmv, zcp, zln:
#
# This is a multiple move based on zsh pattern matching. To get the full
# power of it, you need a postgraduate degree in zsh. However, simple
# tasks work OK, so if that's all you need, here are some basic examples:
# zmv '(*).txt' '$1.lis'
# Rename foo.txt to foo.lis, etc. The parenthesis is the thing that
# gets replaced by the $1 (not the `*', as happens in mmv, and note the
# `$', not `=', so that you need to quote both words).
# zmv '(**/)(*).txt '$1$2.lis'
# The same, but scanning through subdirectories. The $1 becomes the full
# path. Note that you need to write it like this; you can't get away with
# '(**/*).txt'.
# zmv -w '**/*.txt' '$1$2.lis'
# This is the lazy version of the one above; zsh picks out the patterns
# for you. The catch here is that you don't need the / in the replacement
# pattern. (It's not really a catch, since $1 can be empty.)
# zmv -C '**/(*).txt' ~/save/'$1'.lis
# Copy, instead of move, all .txt files in subdirectories to .lis files
# in the single directory `~/save'. Note that the ~ was not quoted.
# You can test things safely by using the `-n' (no, not now) option.
# Clashes, where multiple files are renamed or copied to the same one, are
# picked up.
#
# Here's a more detailed description.
#
# Use zsh pattern matching to move, copy or link files, depending on
# the last two characters of the function name. The general syntax is
# zmv '<inpat>' '<outstring>'
# <inpat> is a globbing pattern, so it should be quoted to prevent it from
# immediate expansion, while <outstring> is a string that will be
# re-evaluated and hence may contain parameter substitutions, which should
# also be quoted. Each set of parentheses in <inpat> (apart from those
# around glob qualifiers, if you use the -Q option, and globbing flags) may
# be referred to by a positional parameter in <outstring>, i.e. the first
# (...) matched is given by $1, and so on. For example,
# zmv '([a-z])(*).txt' '${(C)1}$2.txt'
# renames algernon.txt to Algernon.txt, boris.txt to Boris.txt and so on.
# The original file matched can be referred to as $f in the second
# argument; accidental or deliberate use of other parameters is at owner's
# risk and is not covered by the (non-existent) guarantee.
#
# As usual in zsh, /'s don't work inside parentheses. There is a special
# case for (**/) and (***/): these have the expected effect that the
# entire relevant path will be substituted by the appropriate positional
# parameter.
#
# There is a shortcut avoiding the use of parenthesis with the option -w
# (with wildcards), which picks out any expressions `*', `?', `<range>'
# (<->, <1-10>, etc.), `[...]', possibly followed by `#'s, `**/', `***/', and
# automatically parenthesises them. (You should quote any ['s or ]'s which
# appear inside [...] and which do not come from ranges of the form
# `[:alpha:]'.) So for example, in
# zmv -w '[[:upper:]]*' '${(L)1}$2'
# the $1 refers to the expression `[[:upper:]]' and the $2 refers to
# `*'. Thus this finds any file with an upper case first character and
# renames it to one with a lowercase first character. Note that any
# existing parentheses are active, too, so you must count accordingly.
# Furthermore, an expression like '(?)' will be rewritten as '((?))' --- in
# other words, parenthesising of wildcards is independent of any existing
# parentheses.
#
# Any file whose name is not changed by the substitution is simply ignored.
# Any error --- a substitution resulted in an empty string, two
# substitutions gave the same result, the destination was an existing
# regular file and -f was not given --- causes the entire function to abort
# without doing anything.
#
# Options:
# -f force overwriting of destination files. Not currently passed
# down to the mv/cp/ln command due to vagaries of implementations
# (but you can use -o-f to do that).
# -i interactive: show each line to be executed and ask the user whether
# to execute it. Y or y will execute it, anything else will skip it.
# Note that you just need to type one character.
# -n no execution: print what would happen, but don't do it.
# -q Turn bare glob qualifiers off: now assumed by default, so this
# has no effect.
# -Q Force bare glob qualifiers on. Don't turn this on unless you are
# actually using glob qualifiers in a pattern (see below).
# -s symbolic, passed down to ln; only works with zln or z?? -L.
# -v verbose: print line as it's being executed.
# -o <optstring>
# <optstring> will be split into words and passed down verbatim
# to the cp, ln or mv called to perform the work. It will probably
# begin with a `-'.
# -p <program>
# Call <program> instead of cp, ln or mv. Whatever it does, it should
# at least understand the form '<program> -- <oldname> <newname>',
# where <oldname> and <newname> are filenames generated.
# -w Pick out wildcard parts of the pattern, as described above, and
# implicitly add parentheses for referring to them.
# -C
# -L
# -M Force cp, ln or mv, respectively, regardless of the name of the
# function.
#
# Bugs:
# Parenthesised expressions can be confused with glob qualifiers, for
# example a trailing '(*)' would be treated as a glob qualifier in
# ordinary globbing. This has proved so annoying that glob qualifiers
# are now turned off by default. To force the use of glob qualifiers,
# give the flag -Q.
#
# The second argument is re-evaluated in order to expand the parameters,
# so quoting may be a bit haphazard. In particular, a double quote
# will need an extra level of quoting.
#
# The pattern is always treated as an extendedglob pattern. This
# can also be interpreted as a feature.
#
# Unbugs:
# You don't need braces around the 1 in expressions like '$1t' as
# non-positional parameters may not start with a number, although
# paranoiacs like the author will probably put them there anyway.
emulate -RL zsh
setopt extendedglob
local f g args match mbegin mend files action myname tmpf opt exec
local opt_f opt_i opt_n opt_q opt_Q opt_s opt_M opt_C opt_L
local opt_o opt_p opt_v opt_w MATCH MBEGIN MEND
local pat repl errstr fpat hasglobqual opat
typeset -A from to
integer stat
while getopts ":o:p:MCLfinqQsvw" opt; do
if [[ $opt = "?" ]]; then
print -P "%N: unrecognized option: -$OPTARG" >&2
return 1
fi
eval "opt_$opt=${OPTARG:--$opt}"
done
(( OPTIND > 1 )) && shift $(( OPTIND - 1 ))
[[ -z $opt_Q ]] && setopt nobareglobqual
[[ -n $opt_M ]] && action=mv
[[ -n $opt_C ]] && action=cp
[[ -n $opt_L ]] && action=ln
[[ -n $opt_p ]] && action=$opt_p
if (( $# != 2 )); then
print -P "Usage:
%N oldpattern newpattern
where oldpattern contains parenthesis surrounding patterns which will
be replaced in turn by $1, $2, ... in newpattern. For example,
%N '(*).lis' '\$1.txt'
renames 'foo.lis' to 'foo.txt', 'my.old.stuff.lis' to 'my.old.stuff.txt',
and so on." >&2
return 1
fi
pat=$1
repl=$2
if [[ -z $action ]]; then
# We can't necessarily get the name of the function directly, because
# of no_function_argzero stupidity.
tmpf=${TMPPREFIX}zmv$$
print -P %N >$tmpf
myname=$(<$tmpf)
rm -f $tmpf
action=$myname[-2,-1]
if [[ $action != (cp|mv|ln) ]]; then
print "Action $action not recognised: must be cp, mv or ln." >&2
return 1
fi
fi
if [[ -n $opt_s && $action != ln ]]; then
print -P "%N: invalid option: -s" >&2
return 1
fi
if [[ -n $opt_w ]]; then
# Parenthesise all wildcards.
local newpat
# Well, this seems to work.
# The tricky bit is getting all forms of [...] correct, but as long
# as we require inactive bits to be backslashed its not so bad.
newpat="${pat//\
(#m)(\*\*#\/|[*?]|\<[0-9]#-[0-9]#\>|\[(\[:[a-z]##:\]|\\\[|\\\]|[^\[\]]##)##\])\##\
/($MATCH)}"
if [[ $newpat = $pat ]]; then
print -P "%N: warning: no wildcards were found" >&2
else
pat=$newpat
fi
fi
if [[ -n $opt_Q && $pat = (#b)(*)\([^\)\|\~]##\) ]]; then
hasglobqual=q
# strip off qualifiers for use as ordinary pattern
opat=$match[1]
fi
if [[ $pat = (#b)(*)\((\*\*##/)\)(*) ]]; then
fpat="$match[1]$match[2]$match[3]"
# Now make sure we do depth-first searching.
# This is so that the names of any files are altered before the
# names of the directories they are in.
if [[ -n $opt_Q && -n $hasglobqual ]]; then
fpat[-1]="odon)"
else
setopt bareglobqual
fpat="${fpat}(odon)"
fi
else
fpat=$pat
fi
files=(${~fpat})
[[ -n $hasglobqual ]] && pat=$opat
errs=()
for f in $files; do
if [[ $pat = (#b)(*)\(\*\*##/\)(*) ]]; then
# This looks like a recursive glob. This isn't good enough,
# because we should really enforce that $match[1] and $match[2]
# don't match slashes unless they were explicitly given. But
# it's a start. It's fine for the classic case where (**/) is
# at the start of the pattern.
pat="$match[1](*/|)$match[2]"
fi
[[ -e $f && $f = (#b)${~pat} ]] || continue
set -- "$match[@]"
eval g=\"$repl\"
if [[ -z $g ]]; then
errs=($errs "$f expanded to empty string")
elif [[ $f = $g ]]; then
# don't cause error: more useful just to skip
# errs=($errs "$f not altered by substitution")
[[ -n $opt_v ]] && print "$f not altered, ignored"
continue
elif [[ -n $from[$g] && ! -d $g ]]; then
errs=($errs "$f and $from[$g] both map to $g")
elif [[ -f $g && -z $opt_f ]]; then
errs=($errs "file exists: $g")
fi
from[$g]=$f
to[$f]=$g
done
if (( $#errs )); then
print -P "%N: error(s) in substitution:" >&2
print -l $errs >&2
return 1
fi
for f in $files; do
[[ -z $to[$f] ]] && continue
exec=($action ${=opt_o} $opt_s -- $f $to[$f])
[[ -n $opt_i$opt_n$opt_v ]] && print -- $exec
if [[ -n $opt_i ]]; then
read -q 'opt?Execute? ' || continue
fi
if [[ -z $opt_n ]]; then
$exec || stat=1
fi
done
return $stat
# }

244
Functions/Misc/zrecompile Normal file
View file

@ -0,0 +1,244 @@
# This tries to find wordcode files and automatically re-compile them if
# at least one of the original files is newer than the wordcode file.
# This will only work if the original files were added with their full
# paths or if the names stored in the wordcode files are relative to the
# directory where the wordcode file is.
#
# Arguments are the names of wordcode files and directories containing
# wordcode files that should be checked. If no arguments are given, the
# directories and wordcode files in $fpath are used.
#
# And then there are two options:
# -t: Only check if there are wordcode files that have to be
# re-compiled. The return status is zero if there are files
# that need to be re-compiled and non-zero otherwise.
# -q: Be quiet, i.e.: only set the return status.
# -p: If this is given, the arguments are interpreted differently:
# they should form one or more sets of arguments for zcompile,
# seperated by `--'. For example:
#
# zrecompile -p \
# -R ~/.zshrc -- \
# -M ~/.zcompdump -- \
# ~/zsh/comp.zwc ~/zsh/Completion/*/_* \
#
# This makes ~/.zshrc be compiled into ~/.zshrc.zwc if that doesn't
# exist or if it is older than ~/.zshrc. The wordcode file will be
# marked for reading instead of mapping. The same is done for
# ~/.zcompdump and ~/.zcompdump.zwc, but the wordcode file is marked
# for mapping. The last line re-creates the file ~/zsh/comp.zwc if
# any of the files matching the given pattern is newer than it.
#
# Without the -t option, the return status is zero if all wordcode files
# that needed re-compilation could be compiled and non-zero if compilation
# for at least one of the files failed.
setopt localoptions extendedglob noshwordsplit noksharrays
local opt check quiet zwc files re file pre ret map tmp mesg pats
tmp=()
while getopts ":tqp" opt; do
case $opt in
t) check=yes ;;
q) quiet=yes ;;
p) pats=yes ;;
*)
if [[ -n $pats ]]; then
tmp=( $tmp $OPTARG )
else
print -u2 zrecompile: bad option: -$OPTARG
return 1
fi
esac
done
shift OPTIND-${#tmp:-1}
if [[ -n $check ]]; then
ret=1
else
ret=0
fi
if [[ -n $pats ]]; then
local end num
while (( $# )); do
end=$argv[(i)--]
if [[ end -le $# ]]; then
files=( $argv[1,end-1] )
shift end
else
files=( $argv )
argv=()
fi
tmp=()
map=()
OPTIND=1
while getopts :MR opt $files; do
case $opt in
[MR]) map=( -$opt ) ;;
*) tmp=( $tmp $files[OPTIND] );;
esac
done
shift OPTIND-1 files
(( $#files )) || continue
files=( $files[1] ${files[2,-1]:#*(.zwc|~)} )
(( $#files )) || continue
zwc=${files[1]%.zwc}.zwc
shift 1 files
(( $#files )) || files=( ${zwc%.zwc} )
if [[ -f $zwc ]]; then
num=$(zcompile -t $zwc | wc -l)
if [[ num-1 -ne $#files ]]; then
re=yes
else
re=
for file in $files; do
if [[ $file -nt $zwc ]]; then
re=yes
break
fi
done
fi
else
re=yes
fi
if [[ -n $re ]]; then
if [[ -n $check ]]; then
# ... say so.
[[ -z $quiet ]] && print $zwc needs re-compilation
ret=0
else
# ... or do it.
[[ -z $quiet ]] && print -n "re-compiling ${zwc}: "
# If the file is mapped, it might be mapped right now, so keep the
# old file by renaming it.
if { [[ ! -f $zwc ]] || mv $zwc ${zwc}.old } &&
zcompile $map $tmp $zwc $files 2> /dev/null; then
[[ -z $quiet ]] && print succeeded
else
[[ -z $quiet ]] && print failed
ret=1
fi
fi
fi
done
return ret
fi
# Get the names of wordcode files.
if (( $# )); then
argv=( ${^argv}/*.zwc(ND) ${^argv}.zwc(ND) ${(M)argv:#*.zwc} )
else
argv=( ${^fpath}/*.zwc(ND) ${^fpath}.zwc(ND) ${(M)fpath:#*.zwc} )
fi
# We only handle *.zwc files. zcompile only handles *.zwc files. Everybody
# seems to handle only *.zwc files.
argv=( ${^argv%.zwc}.zwc )
for zwc; do
# Get the files in the wordcode file.
files=( ${(f)"$(zcompile -t $zwc)"} )
# See if the wordcode file will be mapped.
if [[ $files[1] = *\(mapped\)* ]]; then
map=-M
mesg='succeeded (old saved)'
else
map=-R
mesg=succeeded
fi
# Get the path prefix of the wordcode file to prepend it to names of
# original files that are relative pathnames.
if [[ $zwc = */* ]]; then
pre=${zwc%/*}/
else
pre=
fi
# Maybe this is even for an older version of the shell?
if [[ $files[1] != *$ZSH_VERSION ]]; then
re=yes
else
re=
fi
files=( ${pre}${^files[2,-1]:#/*} ${(M)files[2,-1]:#/*} )
# If the version is correct, compare the age of every original file
# to the age of the wordcode file.
[[ -z $re ]] &&
for file in $files; do
if [[ $file -nt $zwc ]]; then
re=yes
break
fi
done
if [[ -n $re ]]; then
# The wordcode files needs re-compilation...
if [[ -n $check ]]; then
# ... say so.
[[ -z $quiet ]] && print $zwc needs re-compilation
ret=0
else
# ... or do it.
[[ -z $quiet ]] && print -n "re-compiling ${zwc}: "
tmp=( ${^files}(N) )
# Here is the call to zcompile, but if we can't find all the original
# files, we don't try compilation.
if [[ $#tmp -ne $#files ]]; then
[[ -z $quiet ]] && print 'failed (missing files)'
ret=1
else
# If the file is mapped, it might be mapped right now, so keep the
# old file by renaming it.
if mv $zwc ${zwc}.old && zcompile $map $zwc $files 2> /dev/null; then
[[ -z $quiet ]] && print $mesg
else
[[ -z $quiet ]] && print failed
ret=1
fi
fi
fi
fi
done
return ret

35
Functions/Misc/zstyle+ Normal file
View file

@ -0,0 +1,35 @@
# This makes defining styles a bit simpler by using a single `+' as a
# special token that allows to append a context name to the previously
# used context name. Like this:
#
# zstyle+ ':foo:bar' style1 value1 \
# + ':baz' style2 value2 \
# + ':frob' style3 value3
#
# This defines style1 with value1 for the context :foo:bar as usual.
# But it also defines styles2 with value2 for the context :foo:bar:baz
# and style3 with value3 for :foo:bar:frob.
# Of course, any of the sub-contexts after the plus signs may be
# empty strings to re-use the previous context unchanged.
#
# If you don't want to change all your calls to `zstyle' to use
# `zstyle+' you can use an alias `alias zstyle=zstyle+' and make sure
# the completion functions are autoloaded without alias expansion (the
# -U option to the autoload builtin). The completion system normally
# loads its functions with without alias expansion.
case "$1" in
-*) zstyle "$@";;
*) setopt localoptions noksharrays
integer i
local context="$1"
1=''
for ((i=2; $#; ++i)); do
if [[ $i -gt $# || "$argv[i]" == '+' ]]; then
zstyle "$context${(@)argv[1,i-1]}"
shift "i > $# ? $# : i" # Stupid shift error on i > $#
i=1
fi
done;;
esac

View file

@ -293,11 +293,11 @@ to install them. For other modules, the functions will be installed if and
only if the module itself is installed. This will usually be what you
want; in particular, the zsh/complete and zsh/zftp modules are of much less
use without the associated functions. The functions listed with zsh/zle
are optional. however.
are optional, however.
You can also use the configure option --enable-function-subdirs to allow
shell functions to be installed into subdirectories of the function
directory, i.e. `Core/*' files will be installed into `FNDIR/Core', and so
directory, i.e. `Base/*' files will be installed into `FNDIR/Base, and so
on. This also initialises $fpath/$FPATH appropriately.
The option --enable-site-fndir controls whether to create and initialise

View file

@ -1,7 +1,7 @@
name=zsh/complete
link=either
load=yes
functions='Completion/Core/* Completion/Base/* Completion/Builtins/* Completion/User/* Completion/Commands/* Completion/Debian/* Completion/Linux/* Completion/Bsd/* Completion/AIX/* Completion/X/*'
functions='Completion/comp* Completion/*/*/*'
moddeps="zsh/zle"

13
Test/README Normal file
View file

@ -0,0 +1,13 @@
There are now different sections, expressed by the first letter in the
scripts names:
A: basic command parsing and execution
B: builtins
C: shell commands with special syntax
D: substititution
E: options
V: modules
W: builtin interactive commands and constructs
X: line editing
Y: completion
Z: separate systems and user contributions

View file

@ -63,7 +63,8 @@ fi
[[ $ZTST_srcdir = /* ]] || ZTST_srcdir="$ZTST_testdir/$ZTST_srcdir"
# Set the function autoload paths to correspond to this build of zsh.
fpath=( $ZTST_srcdir/../(Completion|Functions)/*~*/CVS(/) )
fpath=( $ZTST_srcdir/../Functions/*~*/CVS(/)
$ZTST_srcdir/../Completion/*/*~*/CVS(/) )
: ${TMPPREFIX:=/tmp/zsh}
# Temporary files for redirection inside tests.