mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-01-01 05:16:05 +01:00
pws-18
This commit is contained in:
parent
53d36e795b
commit
ea0ddb0fc6
39 changed files with 1870 additions and 858 deletions
|
@ -1,4 +1,4 @@
|
|||
#compdef -k complete-word \C-xc
|
||||
#compdef -k complete-word \C-xC
|
||||
|
||||
# Function to correct a filename. Can be used as a completion widget,
|
||||
# or as a function in its own right, in which case it will print the
|
||||
|
|
|
@ -3,10 +3,23 @@
|
|||
# Simple completion front-end implementing spelling correction.
|
||||
# The maximum number of errors is set quite high, and
|
||||
# the numeric prefix can be used to specify a different value.
|
||||
#
|
||||
# If configurations keys with the prefix `correctword_' are
|
||||
# given they override those starting with `correct_'.
|
||||
|
||||
local oca="$compconfig[correct_accept]"
|
||||
compconfig[correct_accept]=6n
|
||||
local oco="$compconfig[correct_original]"
|
||||
local ocp="$compconfig[correct_prompt]"
|
||||
local oci="$compconfig[correct_insert]"
|
||||
|
||||
compconfig[correct_accept]="${compconfig[correctword_accept]-6n}"
|
||||
compconfig[correct_original]="${compconfig[correctword_original]-$oco}"
|
||||
compconfig[correct_prompt]="${compconfig[correctword_prompt]-$ocp}"
|
||||
compconfig[correct_insert]="${compconfig[correctword_insert]}"
|
||||
|
||||
_main_complete _correct
|
||||
|
||||
compconfig[correct_accept]=$oca
|
||||
compconfig[correct_accept]="$oca"
|
||||
compconfig[correct_original]="$oco"
|
||||
compconfig[correct_prompt]="$ocp"
|
||||
compconfig[correct_insert]="$oci"
|
||||
|
|
|
@ -42,14 +42,32 @@
|
|||
|
||||
# If we got the `-d'-flag, we will automatically dump the new state (at
|
||||
# the end).
|
||||
# `-f dir' is used to pass down the directory where this file was
|
||||
# found. This is necessary if functionargzero is not set.
|
||||
# If we were given an argument, this will be taken as the name of the
|
||||
# file in which to store the dump.
|
||||
|
||||
if [[ "$1" = -d ]]; then
|
||||
_i_autodump=1
|
||||
shift
|
||||
else
|
||||
_i_autodump=0
|
||||
_i_fdir=''
|
||||
_i_dumpfile=''
|
||||
_i_autodump=0
|
||||
while [[ $1 = -[df] ]]; do
|
||||
if [[ "$1" = -d ]]; then
|
||||
_i_autodump=1
|
||||
shift
|
||||
if [[ -n "$1" && "$1" != -[df] ]]; then
|
||||
_i_dumpfile="$1"
|
||||
shift
|
||||
fi
|
||||
elif [[ "$1" = -f ]]; then
|
||||
# Used by compinstall to pass down directory where compinit was found
|
||||
shift
|
||||
_i_fdir="$1"
|
||||
shift
|
||||
fi
|
||||
done
|
||||
# Get the directory if we don't have it already and we can
|
||||
if [[ -z "$_i_fdir" && -o functionargzero && $0 = */* ]]; then
|
||||
_i_fdir=${0:h}
|
||||
fi
|
||||
|
||||
# The associative array containing the definitions for the commands.
|
||||
|
@ -63,9 +81,19 @@ _patcomps=()
|
|||
typeset -A compconfig
|
||||
|
||||
# Standard initialisation for `compconfig'.
|
||||
|
||||
(( $# )) && compconfig[dumpfile]="$1"
|
||||
[[ -z "$compconfig[dumpfile]" ]] && compconfig[dumpfile]="$0.dump"
|
||||
if [[ -n $_i_dumpfile ]]; then
|
||||
# Explicitly supplied dumpfile.
|
||||
compconfig[dumpfile]="$_i_dumpfile"
|
||||
elif [[ -o functionargzero ]]; then
|
||||
# We can deduce it from the name of this script
|
||||
compconfig[dumpfile]="$0.dump"
|
||||
elif [[ -n $_i_fdir ]]; then
|
||||
# We were told what directory to use.
|
||||
compconfig[dumpfile]="$_i_fdir/compinit.dump"
|
||||
else
|
||||
# Now we're stuck, but we'd better do something.
|
||||
compconfig[dumpfile]="$HOME/.compinit.dump"
|
||||
fi
|
||||
|
||||
compconfig[correct_accept]=2n
|
||||
compconfig[correct_prompt]='correct to:'
|
||||
|
@ -180,9 +208,15 @@ compdef() {
|
|||
*)
|
||||
# For commands store the function name in the `_comps'
|
||||
# associative array, command names as keys.
|
||||
for i; do
|
||||
[[ -z "$new" || "${+_comps[$i]}" -eq 0 ]] && _comps[$i]="$func"
|
||||
done
|
||||
if [[ -z "$new" ]]; then
|
||||
for i; do
|
||||
_comps[$i]="$func"
|
||||
done
|
||||
else
|
||||
for i; do
|
||||
[[ "${+_comps[$i]}" -eq 0 ]] && _comps[$i]="$func"
|
||||
done
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
else
|
||||
|
@ -265,8 +299,24 @@ compconf() {
|
|||
# Now we automatically make the definition files autoloaded.
|
||||
|
||||
typeset -U _i_files
|
||||
_i_files=( ${^~fpath}/_(|*[^~])(N:t) )
|
||||
_i_initname=$0
|
||||
_i_files=( ${^~fpath:/.}/_(|*[^~])(N:t) )
|
||||
if [[ $#_i_files -lt 20 ]]; then
|
||||
# Too few files: we need some more directories
|
||||
# Assume that we need to add the compinit directory to fpath.
|
||||
if [[ -n $_i_fdir ]]; then
|
||||
if [[ $_i_fdir = */Core ]]; then
|
||||
# Add all the Completion subdirectories
|
||||
fpath=(${_i_fdir:h}/*(/) $fpath)
|
||||
elif [[ -d $_i_fdir/Core ]]; then
|
||||
# Likewise
|
||||
fpath=(${_i_fdir}/*(/) $fpath)
|
||||
else
|
||||
fpath=($_i_fdir $fpath)
|
||||
fi
|
||||
_i_files=( ${^~fpath:/.}/_(|*[^~])(N:t) )
|
||||
fi
|
||||
fi
|
||||
|
||||
_i_done=''
|
||||
|
||||
# If we have a dump file, load it.
|
||||
|
@ -286,38 +336,45 @@ if [[ -z "$_i_done" ]]; then
|
|||
read -rA _i_line < $_i_file
|
||||
_i_tag=$_i_line[1]
|
||||
shift _i_line
|
||||
if [[ $_i_tag = '#compdef' ]]; then
|
||||
case $_i_tag in
|
||||
(\#compdef)
|
||||
if [[ $_i_line[1] = -[pk] ]]; then
|
||||
compdef ${_i_line[1]}a "${_i_file:t}" "${(@)_i_line[2,-1]}"
|
||||
else
|
||||
compdef -na "${_i_file:t}" "${_i_line[@]}"
|
||||
fi
|
||||
elif [[ $_i_tag = '#autoload' ]]; then
|
||||
;;
|
||||
(\#autoload)
|
||||
autoload ${_i_file:t}
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
done
|
||||
|
||||
bindkey |
|
||||
while read -rA _i_line; do
|
||||
if [[ "$_i_line[2]" = complete-word ||
|
||||
"$_i_line[2]" = delete-char-or-list ||
|
||||
"$_i_line[2]" = expand-or-complete ||
|
||||
"$_i_line[2]" = expand-or-complete-prefix ||
|
||||
"$_i_line[2]" = list-choices ||
|
||||
"$_i_line[2]" = menu-complete ||
|
||||
"$_i_line[2]" = menu-expand-or-complete ||
|
||||
"$_i_line[2]" = reverse-menu-complete ]]; then
|
||||
case "$_i_line[2]" in
|
||||
(complete-word) ;&
|
||||
(delete-char-or-list) ;&
|
||||
(expand-or-complete) ;&
|
||||
(expand-or-complete-prefix) ;&
|
||||
(list-choices) ;&
|
||||
(menu-complete) ;&
|
||||
(menu-expand-or-complete) ;&
|
||||
(reverse-menu-complete)
|
||||
zle -C _complete_$_i_line[2] $_i_line[2] _main_complete
|
||||
bindkey "${_i_line[1][2,-2]}" _complete_$_i_line[2]
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
unset _i_dir _i_line _i_file _i_tag
|
||||
|
||||
# If autodumping was requested, do it now.
|
||||
|
||||
(( _i_autodump )) && builtin . ${_i_initname:h}/compdump
|
||||
if [[ -n ${_i_fdir} && $_i_autodump = 1 ]]; then
|
||||
builtin . ${_i_fdir}/compdump
|
||||
fi
|
||||
fi
|
||||
|
||||
unset _i_files _i_initname _i_done _i_autodump
|
||||
unset _i_files _i_initname _i_done _i_autodump _i_fdir _i_dumpfile
|
||||
|
|
|
@ -1,49 +1,129 @@
|
|||
# This script is to be run by a user to setup the new function based
|
||||
# This script is to be run by a user to set up the new function based
|
||||
# completion system. The functions themselves are assumed to be already
|
||||
# available in some directory; they should have been installed with the
|
||||
# the shell (except we haven't written that yet).
|
||||
#
|
||||
# Run it as a script under zsh and answer the questions.
|
||||
# You can run it as `zsh compinstall $FPATH' and it will be able to check
|
||||
# your function path for the completion functions.
|
||||
# Source this script (e.g. `. /path/compinstall') and answer the questions.
|
||||
#
|
||||
# Normally, this will alter ~/.zshrc (or wherever ZDOTDIR puts it),
|
||||
# but you can make that unwritable and it will leave the lines in a
|
||||
# temporary file instead.
|
||||
#
|
||||
# You can use this script to modify what compinstall previously
|
||||
# added to ~/.zshrc.
|
||||
# Normally, this will alter ~/.zshrc (or wherever ZDOTDIR puts it), but you
|
||||
# can make that unwritable and it will leave the lines in a temporary file
|
||||
# instead. It doesn't matter if .zshrc didn't exist before. If your
|
||||
# .zshrc usually exits before the end, then you should take the code added
|
||||
# by compinstall and put it (including the comment lines at the start and
|
||||
# end) at the point you want it to be executed. If you run compinstall
|
||||
# again it will find and replace those lines, so you can use this script to
|
||||
# modify what compinstall previously added to ~/.zshrc.
|
||||
#
|
||||
# It is safe to abort with ^C any time you are being prompted for
|
||||
# information; your .zshrc will not be altered.
|
||||
#
|
||||
# To do:
|
||||
# - Maybe this should be sourced, then it can check the user's current
|
||||
# setup better. But then there is a potentially horrendous option
|
||||
# setting/resetting problem. (Maybe we need another way of doing that.)
|
||||
# - Should probably offer to set different options for _approximate than
|
||||
# for _complete if both are used.
|
||||
# - Could add code for setting other completers and options.
|
||||
# - Could add keys for context-sensitive help.
|
||||
# - Probably should allow a set of directories to be added to $fpath,
|
||||
# like Core, Base, etc.
|
||||
|
||||
# In case a startup script changed options
|
||||
# Save the options. We will need to trap ^C to make sure they get
|
||||
# restored properly.
|
||||
typeset -A _ci_options
|
||||
_ci_options=($(setopt kshoptionprint;setopt))
|
||||
[[ -o kshoptionprint ]] || _ci_options[kshoptionprint]=off
|
||||
[[ -o monitor ]] && _ci_options[monitor]=on
|
||||
[[ -o zle ]] && _ci_options[zle]=on
|
||||
|
||||
emulate zsh
|
||||
|
||||
[[ -n $1 ]] && FPATH=$1
|
||||
TRAPINT() {
|
||||
unsetopt ${(k)_ci_options[(R)off]}
|
||||
setopt ${(k)_ci_options[(R)on]}
|
||||
|
||||
for f in $fpath; do
|
||||
if [[ $f != . && -f $f/compinit && -f $f/compdump ]]; then
|
||||
fdir=$f
|
||||
break
|
||||
unset _ci_options _ci_f _ci_fdir _ci_files _ci_dumpfile _ci_lines
|
||||
unset _ci_type _ci_completer _ci_accept _ci_cprompt _ci_startline
|
||||
unset _ci_endline _ci_ifile _ci_tmpf _ci_defaults _ci_compconf _ci_warn
|
||||
unset _ci_dtype _ci_existing _ci_line
|
||||
|
||||
if (( $1 )); then
|
||||
print Aborted.
|
||||
unfunction TRAPINT
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
if [[ -z $fdir ]]; then
|
||||
|
||||
# Look for the defaults.
|
||||
_ci_startline='# The following lines were added by compinstall'
|
||||
_ci_endline='# End of lines added by compinstall'
|
||||
|
||||
_ci_ifile=${ZDOTDIR:-~}/.zshrc
|
||||
_ci_lines=''
|
||||
_ci_existing=''
|
||||
|
||||
typeset -A _ci_defaults
|
||||
if [[ -f $_ci_ifile ]]; then
|
||||
# This assumes the lines haven't been altered by the user too much
|
||||
# after they were added.
|
||||
_ci_compconf=0
|
||||
sed -n "/^$_ci_startline/,/^$_ci_endline/p" $_ci_ifile |
|
||||
while read -rA _ci_line; do
|
||||
if (( $_ci_compconf )); then
|
||||
# parse a compconf component as first argument
|
||||
if [[ $_ci_line[-1] == \\ ]]; then
|
||||
_ci_line=(${_ci_line[1,-2]})
|
||||
else
|
||||
_ci_compconf=0
|
||||
fi
|
||||
if [[ $_ci_line[1] = *=* ]]; then
|
||||
_ci_f="${${_ci_line[*]}#*=}"
|
||||
if [[ $_ci_f = \'*\' ]]; then
|
||||
# strip quotes
|
||||
_ci_f=${_ci_f[2,-2]//\'\\\'\'/\'}
|
||||
fi
|
||||
_ci_defaults[${_ci_line[1]%%\=*}]=$_ci_f
|
||||
fi
|
||||
_ci_existing="${_ci_existing} $_ci_line
|
||||
"
|
||||
elif [[ $_ci_line[1] = . && $_ci_line[2] = */compinit ]]; then
|
||||
# parse the line sourcing compinit
|
||||
[[ $_ci_line[3] = -f ]] && _ci_fdir=$_ci_line[4]
|
||||
[[ $_ci_line[-2] = -d ]] && _ci_dumpfile=$_ci_line[-1]
|
||||
elif [[ $_ci_line[1] = compconf ]]; then
|
||||
# parse a compconf component as second argument (should be completer)
|
||||
[[ $_ci_line[2] = completer=* ]] &&
|
||||
_ci_completer=${_ci_line[2]#completer=}
|
||||
[[ $_ci_line[-1] == \\ ]] && _ci_compconf=1
|
||||
_ci_existing="${_ci_existing}$_ci_line
|
||||
"
|
||||
elif [[ $_ci_line[1] != \#* ]]; then
|
||||
if [[ -z $_ci_warn ]]; then
|
||||
_ci_warn=1
|
||||
print "Warning: existing lines in compinstall setup not understood:"
|
||||
fi
|
||||
print - $_ci_line
|
||||
_ci_existing="${_ci_existing}$_ci_line
|
||||
"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Find out where the completion functions are kept.
|
||||
|
||||
if [[ -z $_ci_fdir || ! -f $_ci_f/compinit || ! -f $_ci_f/compdump ]]; then
|
||||
for _ci_f in $fpath; do
|
||||
if [[ $_ci_f != . && -f $_ci_f/compinit && -f $_ci_f/compdump ]]; then
|
||||
_ci_fdir=$_ci_f
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ -z $_ci_fdir || ! -d ${~_ci_fdir} ]]; then
|
||||
print "Trying to find where the completion functions are..."
|
||||
if [[ $0 = */* && -f $0:h/compinit && -f $0:h/compdump ]]; then
|
||||
fdir=$0:h
|
||||
if [[ $0 = */* && -o functionargzero &&
|
||||
-f $0:h/compinit && -f $0:h/compdump ]]; then
|
||||
_ci_fdir=$0:h
|
||||
print "Using my directory, $_ci_fdir"
|
||||
else
|
||||
# more guesses?
|
||||
print \
|
||||
|
@ -51,22 +131,26 @@ if [[ -z $fdir ]]; then
|
|||
installed. If they are not installed, you will need to find them in the
|
||||
Completion/* directories of the zsh distribution and install them yourself,
|
||||
or insult your system manager for incompetence."
|
||||
vared -c fdir
|
||||
while [[ ! -d ${~fdir} || ! -f ${~fdir}/compinit ||
|
||||
! -f ${~fdir}/compdump ]]; do
|
||||
vared -c _ci_fdir
|
||||
while [[ ! -d ${~_ci_fdir} || ! -f ${~_ci_fdir}/compinit ||
|
||||
! -f ${~_ci_fdir}/compdump ]]; do
|
||||
print "I can't find them in that directory. Try again or abort."
|
||||
vared fdir
|
||||
vared _ci_fdir
|
||||
done
|
||||
fi
|
||||
eval "fpath=($fdir \$fpath)"
|
||||
fdir=${fdir/#$HOME/\~}
|
||||
lines="fpath=($fdir \$fpath)\n"
|
||||
else
|
||||
print "Found completion functions in your fpath, will not alter it."
|
||||
print "Keeping existing completion directiory $_ci_fdir"
|
||||
fi
|
||||
|
||||
files=( ${^~fpath:/.}/_(|*[^~])(N:t) )
|
||||
if [[ $#files -lt 20 ]]; then
|
||||
# Check if this is in fpath already, else put it there (with ~'s expanded).
|
||||
_ci_f=${~_ci_fdir}
|
||||
[[ -z ${fpath[(r)$_ci_f]} ]] && fpath=($_ci_f $fpath)
|
||||
# Contract $HOME to ~ in the parameter to be used for writing.
|
||||
_ci_fdir=${_ci_fdir/#$HOME/\~}
|
||||
|
||||
# Now check the fpath, ignoring the directory .
|
||||
_ci_files=( ${^~fpath:/.}/_(|*[^~])(N:t) )
|
||||
if [[ $#_ci_files -lt 20 ]]; then
|
||||
print "
|
||||
Hmmm, completion functions seem a bit thin on the ground. There should
|
||||
be lots of files with names beginning with an underscore (_). You should
|
||||
|
@ -75,12 +159,20 @@ look and see what's happened to these.
|
|||
read
|
||||
fi
|
||||
|
||||
if [[ -w ${~fdir} && ( ! -f ${~fdir}/compinit.dump ||
|
||||
-w ${~fdir}/compinit.dump ) ]]
|
||||
|
||||
# Set up the dumpfile
|
||||
_ci_dtype=existing
|
||||
if [[ -z $_ci_dumpfile ]]; then
|
||||
_ci_dumpfile="${_ci_fdir}/compinit.dump"
|
||||
_ci_dtype=standard
|
||||
fi
|
||||
|
||||
if [[ -w ${~_ci_dumpfile:h} && ( ! -f ${~_ci_dumpfile} ||
|
||||
-w ${~_ci_dumpfile} ) ]]
|
||||
then
|
||||
print "
|
||||
Using standard dumpfile
|
||||
${~fdir}/compinit.dump
|
||||
Using $_ci_dtype dumpfile
|
||||
${_ci_dumpfile}
|
||||
to speed up initialisation.
|
||||
[Hit return to continue]"
|
||||
read
|
||||
|
@ -88,23 +180,30 @@ else
|
|||
print "
|
||||
I will force completion to dump its status, which will speed up the shell's
|
||||
start-up considerably. However, I can't write the file I'd like to, namely
|
||||
$fdir/compinit.dump. Please edit a replacement."
|
||||
dumpfile='~/.compinit.dump'
|
||||
vared dumpfile
|
||||
while ! touch ${~dumpfile} >& /dev/null; do
|
||||
${_ci_dumpfile}. Please edit a replacement."
|
||||
_ci_dumpfile='~/.compinit.dump'
|
||||
vared _ci_dumpfile
|
||||
while ! touch ${~_ci_dumpfile} >& /dev/null; do
|
||||
print "Sorry, I can't write that either. Try again."
|
||||
vared dumpfile
|
||||
vared _ci_dumpfile
|
||||
done
|
||||
[[ -s $dumpfile ]] || rm -f $dumpfile
|
||||
dumpfile=" $dumpfile"
|
||||
[[ -s $_ci_dumpfile ]] || rm -f $_ci_dumpfile
|
||||
fi
|
||||
|
||||
fdir=${fdir/#$HOME/\~}
|
||||
|
||||
lines="${lines}. $fdir/compinit -d$dumpfile\n"
|
||||
_ci_lines="${_ci_lines}. $_ci_fdir/compinit -f $_ci_fdir -d"
|
||||
[[ $_ci_dtype != standard ]] && _ci_lines="${_ci_lines} $_ci_dumpfile"
|
||||
_ci_lines="${_ci_lines}
|
||||
"
|
||||
|
||||
|
||||
print "
|
||||
Would you like to set some more advanced options? Otherwise, you
|
||||
can re-run compinstall later to set these. [n]"
|
||||
|
||||
# The whole of the next part should be indented, but I can't be bothered.
|
||||
if read -q; then
|
||||
|
||||
print "
|
||||
In addition to completion, zsh can also perform correction of the
|
||||
current word, or approximate completion, i.e. completion where the part of
|
||||
the word typed so far can be corrected; or it can try correction, then
|
||||
|
@ -112,105 +211,155 @@ approximate completion if that fails. Would you like:
|
|||
0: Just ordinary completion
|
||||
C: Correction
|
||||
A: Approximate completion
|
||||
B: Both?
|
||||
Please type one of the keys above:"
|
||||
while read -k type; do
|
||||
print
|
||||
case $type in
|
||||
0*) completer=_complete
|
||||
break
|
||||
;;
|
||||
[cC]*) completer=_complete:_correct
|
||||
break
|
||||
;;
|
||||
[aA]*) completer=_complete:_approximate
|
||||
break;
|
||||
;;
|
||||
[bB]*) completer=_complete:_correct:_approximate
|
||||
break
|
||||
;;
|
||||
*) print Try again
|
||||
;;
|
||||
esac
|
||||
done
|
||||
B: Both"
|
||||
if [[ -n $_ci_completer ]]; then
|
||||
print " Default: use the current completer:\n$_ci_completer"
|
||||
else
|
||||
print "Please type one of the keys above."
|
||||
fi
|
||||
while read -k _ci_type; do
|
||||
print
|
||||
case $_ci_type in
|
||||
0*) _ci_completer=_complete
|
||||
break
|
||||
;;
|
||||
[cC]*) _ci_completer=_complete:_correct
|
||||
break
|
||||
;;
|
||||
[aA]*) _ci_completer=_complete:_approximate
|
||||
break;
|
||||
;;
|
||||
[bB]*) _ci_completer=_complete:_correct:_approximate
|
||||
break
|
||||
;;
|
||||
*) [[ -n $_ci_completer ]] && break
|
||||
print Try again
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
lines="${lines}compconf completer=$completer"
|
||||
_ci_lines="${_ci_lines}compconf completer=$_ci_completer"
|
||||
|
||||
|
||||
if [[ $completer = *(correct|approx)* ]]; then
|
||||
print "
|
||||
Correction and approximation will normally allow up to two errors,
|
||||
and you will be able to use a numeric prefix (e.g. <Esc>4) to allow
|
||||
more. The standard prompt is \`correct to:'. Do you want to change
|
||||
any of this? [n]"
|
||||
if read -q; then
|
||||
print "Number of errors to accept normally (0 is OK):"
|
||||
read accept
|
||||
while [[ $accept != <-> ]]; do
|
||||
read accept"?Please enter a number: "
|
||||
done
|
||||
print \
|
||||
if [[ $_ci_completer = *(correct|approx)* ]]; then
|
||||
_ci_accept=${_ci_defaults[correct_accept]}
|
||||
_ci_cprompt=${_ci_defaults[correct_prompt]}
|
||||
print "
|
||||
Correction and approximation will allow up to ${${_ci_accept:-2}%%[^0-9]*} \
|
||||
errors. "
|
||||
case $_ci_accept in
|
||||
*n*!*|*!*n) print "A numeric prefix, if not 1, will cause correction \
|
||||
not to be done."
|
||||
;;
|
||||
*n*) print "A numeric prefix gives the maximum number of errors which \
|
||||
will be accepted."
|
||||
;;
|
||||
*) print "The numeric prefix will not be used."
|
||||
esac
|
||||
print "The correction prompt is \`${_ci_cprompt:-correct to:}'.
|
||||
Do you want to change any of this? [n]"
|
||||
if read -q; then
|
||||
print "Number of errors to accept normally (0 is OK):"
|
||||
_ci_accept=${_ci_accept%%[^0-9]*}
|
||||
vared _ci_accept
|
||||
while [[ $_ci_accept != <-> ]]; do
|
||||
print "Please enter a number:"
|
||||
vared _ci_accept
|
||||
done
|
||||
print \
|
||||
"How would you like the numeric prefix to be treated:
|
||||
0: Not used by correction
|
||||
U: Used to given the number of errors
|
||||
U: The number gives the largest number of errors which will be
|
||||
accepted when correcting
|
||||
I: If present, and not 1, do not perform correction?
|
||||
Please type one of the keys above:"
|
||||
while read -k type; do
|
||||
print
|
||||
case $type in
|
||||
0*) break
|
||||
;;
|
||||
[uU]*) accept="${accept}n"
|
||||
break
|
||||
;;
|
||||
[Ii]*) accept="${accept}!n"
|
||||
break
|
||||
;;
|
||||
*) print Try again
|
||||
;;
|
||||
esac
|
||||
done
|
||||
lines="$lines \\\\
|
||||
correct_accept='$accept'"
|
||||
print "
|
||||
while read -k _ci_type; do
|
||||
print
|
||||
case $_ci_type in
|
||||
0*) break
|
||||
;;
|
||||
[uU]*) _ci_accept="${_ci_accept}n"
|
||||
break
|
||||
;;
|
||||
[Ii]*) _ci_accept="${_ci_accept}!n"
|
||||
break
|
||||
;;
|
||||
*) print Try again
|
||||
;;
|
||||
esac
|
||||
done
|
||||
print "
|
||||
Instead of the prompt \`correct to:', you can have no prompt, or a
|
||||
prompt of your choosing which can display the number of errors found by
|
||||
containing the string \`%e'. Do you wish to change the correction
|
||||
prompt? [n]"
|
||||
if read -q; then
|
||||
cprompt=''
|
||||
print "Edit a new prompt (may be empty):"
|
||||
vared cprompt
|
||||
lines="$lines \\\\
|
||||
correct_prompt='${cprompt//\'/\'\\\'\'}'"
|
||||
if read -q; then
|
||||
print "Edit a new prompt (may be empty):"
|
||||
vared _ci_cprompt
|
||||
[[ -z $_ci_cprompt ]] && _ci_cprompt=':empty:'
|
||||
fi
|
||||
fi
|
||||
if [[ -n $_ci_accept ]]; then
|
||||
_ci_lines="$_ci_lines \\
|
||||
correct_accept='$_ci_accept'"
|
||||
unset '_ci_defaults[correct_accept]'
|
||||
fi
|
||||
if [[ -n $_ci_cprompt ]]; then
|
||||
_ci_cprompt=${_ci_cprompt##:empty:}
|
||||
_ci_lines="$_ci_lines \\
|
||||
correct_prompt='${_ci_cprompt//\'/\'\\\'\'}'"
|
||||
unset '_ci_defaults[correct_prompt]'
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
lines="$lines\n"
|
||||
_ci_warn=''
|
||||
for _ci_f in ${(k)_ci_defaults}; do
|
||||
if [[ -z $_ci_warn ]]; then
|
||||
print "
|
||||
(Keeping other existing configuration settings...)"
|
||||
_ci_warn=1
|
||||
fi
|
||||
_ci_lines="$_ci_lines \\
|
||||
${_ci_f}='${_ci_defaults[$_ci_f]//\'/\'\\\'\'}'"
|
||||
done
|
||||
|
||||
_ci_lines="$_ci_lines
|
||||
"
|
||||
|
||||
startline='# The following lines were added by compinstall'
|
||||
endline='# End of lines added by compinstall'
|
||||
|
||||
ifile=${ZDOTDIR:-~}/.zshrc
|
||||
[[ -f $ifile ]] || touch $ifile
|
||||
tmpf=${TMPPPREFIX:-/tmp/zsh}compinstall$$
|
||||
|
||||
if [[ ! -w $ifile ]]; then
|
||||
print "\nI can't write to $ifile. I will leave the lines to add in
|
||||
\`$tmpf' and you must add them by hand."
|
||||
print "\n$startline\n$lines\n$endline" >$tmpf
|
||||
return 0
|
||||
fi
|
||||
|
||||
if grep $endline $ifile >& /dev/null; then
|
||||
print -- "$startline\n$lines$endline" >$tmpf
|
||||
sed -e "/^$endline/r $tmpf
|
||||
/^$startline/,/^$endline/d" $ifile >${tmpf}2 && mv ${tmpf}2 $ifile &&
|
||||
print "\nSuccesfully modified old compinstall lines in $ifile."
|
||||
rm -f $tmpf ${tmpf}2
|
||||
else
|
||||
print "\n$startline\n$lines\n$endline" >>$ifile &&
|
||||
print "\nSuccessfully appended lines to $ifile."
|
||||
|
||||
if [[ -n $_ci_existing ]]; then
|
||||
print -nr "
|
||||
I will retain the following lines from the existing completion setup:
|
||||
$_ci_existing"
|
||||
_ci_lines="$_ci_lines${_ci_existing}"
|
||||
fi
|
||||
|
||||
fi # End of advanced options
|
||||
|
||||
|
||||
[[ -f $_ci_ifile ]] || touch $_ci_ifile
|
||||
_ci_tmpf=${TMPPPREFIX:-/tmp/zsh}compinstall$$
|
||||
|
||||
if [[ ! -w $_ci_ifile ]]; then
|
||||
print "\nI can't write to $_ci_ifile. I will leave the lines to add in
|
||||
\`$_ci_tmpf' and you must add them by hand."
|
||||
print -r - "$_ci_startline
|
||||
$_ci_lines$_ci_endline" >$_ci_tmpf
|
||||
elif grep $_ci_endline $_ci_ifile >& /dev/null; then
|
||||
print -r - "$_ci_startline
|
||||
$_ci_lines$_ci_endline" >$_ci_tmpf
|
||||
sed -e "/^$_ci_endline/r $_ci_tmpf
|
||||
/^$_ci_startline/,/^$_ci_endline/d" $_ci_ifile >${_ci_tmpf}2 &&
|
||||
mv ${_ci_tmpf}2 $_ci_ifile &&
|
||||
print "\nSuccesfully modified old compinstall lines in $_ci_ifile."
|
||||
rm -f $_ci_tmpf ${_ci_tmpf}2
|
||||
else
|
||||
print -r - "$_ci_startline
|
||||
$_ci_lines$_ci_endline" >>$_ci_ifile &&
|
||||
print "\nSuccessfully appended lines to $_ci_ifile."
|
||||
fi
|
||||
|
||||
TRAPINT 0
|
||||
|
||||
return 0
|
||||
|
|
|
@ -27,5 +27,5 @@
|
|||
# This must also serve as a shell script, so do not add spaces around the
|
||||
# `=' signs.
|
||||
|
||||
VERSION=3.1.5-pws-17
|
||||
VERSION_DATE='April 30, 1999'
|
||||
VERSION=3.1.5-pws-18
|
||||
VERSION_DATE='May 8, 1999'
|
||||
|
|
|
@ -318,10 +318,13 @@ cindex(file, history)
|
|||
tt(fc -R) reads the history from the given file,
|
||||
tt(fc -W) writes the history out to the given file,
|
||||
and tt(fc -A) appends the history out to the given file.
|
||||
If the tt(-I) option is added, only those
|
||||
events that are new since last incremental append (write) to
|
||||
the history file are appended (written).
|
||||
In any case the file will have no more than tt($SAVEHIST)
|
||||
If no filename is specified, the tt($HISTFILE) is assumed.
|
||||
If the tt(-I) option is added to tt(-R), only those events that are
|
||||
not already contained within the internal history list are added.
|
||||
If the tt(-I) option is added to tt(-A) or tt(-W), only those
|
||||
events that are new since last incremental append/write to
|
||||
the history file are appended/written.
|
||||
In any case, the created file will have no more than tt($SAVEHIST)
|
||||
entries.
|
||||
)
|
||||
findex(fg)
|
||||
|
@ -1169,30 +1172,26 @@ Equivalent to tt(whence -c).
|
|||
findex(zmodload)
|
||||
cindex(modules, loading)
|
||||
cindex(loading modules)
|
||||
xitem(tt(zmodload) [ tt(-iL) ] [ var(name) ... ])
|
||||
xitem(tt(zmodload) tt(-u) [ tt(-i) ] var(name) ...)
|
||||
xitem(tt(zmodload) tt(-d) [ tt(-L) ] [ var(name) [ var(dep) ... ] ])
|
||||
xitem(tt(zmodload) tt(-du) var(name) [ var(dep) ... ])
|
||||
xitem(tt(zmodload) tt(-a) [ tt(-iL) ] [ var(name) [ var(builtin) ... ] ])
|
||||
xitem(tt(zmodload) tt(-au) [ tt(-i) ] var(builtin) ...)
|
||||
xitem(tt(zmodload) tt(-c) [ tt(-iI) ] var(name) [ var(cond) ... ])
|
||||
xitem(tt(zmodload) tt(-cu) [ tt(-iI) ] var(cond) ...)
|
||||
xitem(tt(zmodload) tt(-c) [ tt(-IL) ])
|
||||
xitem(tt(zmodload) tt(-p) [ tt(-i) ] var(name) [ var(parameter) ... ])
|
||||
xitem(tt(zmodload) tt(-pu) [ tt(-i) ] var(parameter) ... ])
|
||||
item(tt(zmodload) tt(-p) [ tt(-L) ])(
|
||||
xitem(tt(zmodload) [ tt(-dL) ] [ ... ])
|
||||
xitem(tt(zmodload) [ tt(-a) [ tt(-bcp) [ tt(-I) ] ] ] [ tt(-iL) ] ...)
|
||||
item(tt(zmodload) tt(-u) [ tt(-abcdp) [ tt(-I) ] ] [ tt(-iL) ] ...)(
|
||||
tt(zmodload) performs operations relating to zsh's loadable modules.
|
||||
This feature is not available on all operating systems,
|
||||
or on all installations on a particular operating system.
|
||||
|
||||
In the simplest case,
|
||||
tt(zmodload) loads a binary module. The module must be in a file with a
|
||||
name consisting of the specified var(name) followed by a standard suffix,
|
||||
usually `tt(.so)'. If this can't be found, the var(name) is tried without
|
||||
the suffix.
|
||||
If the module to be loaded is already loaded and the tt(-i)
|
||||
option is given, the duplicate module is ignored. Otherwise
|
||||
tt(zmodload) prints an error message.
|
||||
Without arguments all currently loaded binary modules are printed.
|
||||
The tt(-L) option causes this list to be in the form of a series of
|
||||
tt(zmodload) commands. Forms with arguments are:
|
||||
|
||||
startitem()
|
||||
xitem(tt(zmodload) [ tt(-i) ] var(name) ... )
|
||||
item(tt(zmodload) tt(-u) [ tt(-i) ] var(name) ...)(
|
||||
In the simplest case, tt(zmodload) loads a binary module. The module must
|
||||
be in a file with a name consisting of the specified var(name) followed by
|
||||
a standard suffix, usually `tt(.so)'. If this can't be found, the
|
||||
var(name) is tried without the suffix. If the module to be loaded is
|
||||
already loaded and the tt(-i) option is given, the duplicate module is
|
||||
ignored. Otherwise tt(zmodload) prints an error message.
|
||||
|
||||
The var(name)d module is searched for in the same way a command is, using
|
||||
tt($module_path) instead of tt($path). If var(name) contains a `tt(/)',
|
||||
|
@ -1209,55 +1208,66 @@ unloaded (or was never loaded).
|
|||
Each module has a boot and a cleanup function. The module
|
||||
will not be loaded if its boot function fails. Similarly a module
|
||||
can only be unloaded if its cleanup function runs successfully.
|
||||
)
|
||||
xitem(tt(zmodload) tt(-d) [ tt(-L) ] [ var(name) ])
|
||||
xitem(tt(zmodload) tt(-d) var(name) var(dep) ...)
|
||||
item(tt(zmodload) tt(-ud) var(name) [ var(dep) ... ])(
|
||||
The tt(-d) option can be used to specify module dependencies. The modules
|
||||
named in the second and subsequent arguments will be loaded before the
|
||||
module named in the first argument.
|
||||
|
||||
Without arguments all currently loaded binary modules are printed.
|
||||
The tt(-L) option causes this list to be in the form of a series of
|
||||
tt(zmodload) commands.
|
||||
With tt(-d) and one argument, all dependencies for that module are listed.
|
||||
With tt(-d) and no arguments, all module dependencies are listed. This
|
||||
listing is by default in a Makefile-like format. The tt(-L) option
|
||||
changes this format to a list of tt(zmodload -d) commands.
|
||||
|
||||
The tt(-d) option can be used to specify module dependencies.
|
||||
This operation is idempotent regardless of the tt(-i) option.
|
||||
The modules named in the second and subsequent arguments will be
|
||||
loaded before the module named in the first argument.
|
||||
If tt(-d) and tt(-u) are both used, dependencies are removed. If only one
|
||||
argument is given, all dependencies for that module are removed.
|
||||
)
|
||||
xitem(tt(zmodload) tt(-ab) [ tt(-L) ])
|
||||
xitem(tt(zmodload) tt(-ab) [ tt(-i) ] var(name) [ var(builtin) ... ])
|
||||
item(tt(zmodload) tt(-ub) [ tt(-i) ] var(builtin) ...)(
|
||||
The tt(-ab) option defines autoloaded builtins. It defines the specified
|
||||
var(builtin)s. When any of those builtins is called, the module specified
|
||||
in the first argument is loaded. If only the var(name) is given, one
|
||||
builtin is defined, with the same name as the module. tt(-i) suppresses
|
||||
the error if the builtin is already defined or autoloaded, regardless of
|
||||
which module it came from.
|
||||
|
||||
With tt(-d) and one
|
||||
argument, all dependencies for that module are listed. With tt(-d) and no
|
||||
arguments, all module dependencies are listed.
|
||||
This listing is by default in a Makefile-like format.
|
||||
The tt(-L) option changes this format to a list of
|
||||
tt(zmodload -d) commands.
|
||||
With tt(-ab) and no arguments, all autoloaded builtins are listed, with the
|
||||
module name (if different) shown in parentheses after the builtin name.
|
||||
The tt(-L) option changes this format to a list of tt(zmodload -a)
|
||||
commands.
|
||||
|
||||
If tt(-d) and tt(-u) are both used, dependencies are removed.
|
||||
This operation is idempotent regardless of the tt(-i) option.
|
||||
If only one argument is given, all dependencies for that module are removed.
|
||||
|
||||
The tt(-a) option defines autoloaded builtins. It defines the
|
||||
specified var(builtin)s. When any of those builtins is called, the module
|
||||
specified in the first argument is loaded. If only one argument is given,
|
||||
one builtin is defined, with the same name as the module.
|
||||
tt(-i) suppresses the error if the builtin is already defined or
|
||||
autoloaded, regardless of which module it came from.
|
||||
|
||||
With tt(-a) and no arguments, all
|
||||
autoloaded builtins are listed, with the module name (if different)
|
||||
shown in parentheses after the builtin name. The tt(-L) option changes
|
||||
this format to a list of tt(zmodload -a) commands.
|
||||
|
||||
If tt(-a) is used
|
||||
together with the tt(-u) option it removes builtins defined with
|
||||
tt(zmodload -a). This is only possible if the builtin is not yet
|
||||
loaded. tt(-i) suppresses the error if the builtin is already
|
||||
If tt(-b) is used together with the tt(-u) option, it removes builtins
|
||||
previously defined with tt(-ab). This is only possible if the builtin is
|
||||
not yet loaded. tt(-i) suppresses the error if the builtin is already
|
||||
removed (or never existed).
|
||||
|
||||
The tt(-c) option is used to define autoloaded condition codes. The
|
||||
)
|
||||
xitem(tt(zmodload) tt(-ac) [ tt(-IL) ])
|
||||
xitem(tt(zmodload) tt(-ac) [ tt(-iI) ] var(name) [ var(cond) ... ])
|
||||
item(tt(zmodload) tt(-uc) [ tt(-iI) ] var(cond) ...)(
|
||||
The tt(-ac) option is used to define autoloaded condition codes. The
|
||||
var(cond) strings give the names of the conditions defined by the
|
||||
module. The optional tt(-I) option is used to define infix condition
|
||||
names. Without this option prefix condition names are defined.
|
||||
|
||||
Together with the tt(-u) option definitions for autoloaded conditions
|
||||
are removed. If given no condition names all defined names are listed
|
||||
(as a series of tt(zmodload) commands if the tt(-L) option is given).
|
||||
If given no condition names, all defined names are listed (as a series of
|
||||
tt(zmodload) commands if the tt(-L) option is given).
|
||||
|
||||
The tt(-p) option is like the tt(-c) option, but makes tt(zmodload)
|
||||
work on autoloaded parameters instead of condition codes.
|
||||
The tt(-uc) option removes definitions for autoloaded conditions.
|
||||
)
|
||||
xitem(tt(zmodload) tt(-ap) [ tt(-L) ])
|
||||
xitem(tt(zmodload) tt(-ap) [ tt(-i) ] var(name) [ var(parameter) ... ])
|
||||
item(tt(zmodload) tt(-up) [ tt(-i) ] var(parameter) ...)(
|
||||
The tt(-p) option is like the tt(-b) and tt(-c) options, but makes
|
||||
tt(zmodload) work on autoloaded parameters instead.
|
||||
)
|
||||
xitem(tt(zmodload) tt(-a) [ tt(-L) ])
|
||||
xitem(tt(zmodload) tt(-a) [ tt(-i) ] var(name) [ var(builtin) ... ])
|
||||
item(tt(zmodload) tt(-ua) [ tt(-i) ] var(builtin) ...)(
|
||||
Equivalent to tt(-ab) and tt(-ub).
|
||||
)
|
||||
enditem()
|
||||
)
|
||||
enditem()
|
||||
|
|
|
@ -49,14 +49,42 @@ endmenu()
|
|||
texinode(Initialisation)(Control Functions)()(Completion System)
|
||||
sect(Initialisation)
|
||||
|
||||
The script tt(compinstall) can be run by a user to set up the completion
|
||||
system for use. It will usually insert code into tt(.zshrc), although if
|
||||
that is not writeable it will save it in another file and tell you that
|
||||
file's locations. Note that it is up to you to make sure that the lines
|
||||
added to tt(.zshrc) are actually run; you may, for example, need to move
|
||||
them to an earlier place in the file if tt(.zshrc) usually returns early.
|
||||
So long as you keep them all together (including the comment lines at the
|
||||
start and finish), you can rerun tt(compinstall) and it will correctly
|
||||
locate and modify these lines. Note, however, that any code you add to
|
||||
this section by hand is likely to be lost if you rerun tt(compinstall).
|
||||
|
||||
You can run it as `tt(source )var(<path>)tt(/compinstall)' or
|
||||
`tt(. )var(<path>)tt(/compinstall)', where var(<path>) is where the
|
||||
completion functions are stored. It will ask you various questions about
|
||||
how you would like completion set up. It is in two parts; the basic part
|
||||
locates the completion files and decides where to put your personal
|
||||
dumpfile, used to speed up initialisation after the first time. After
|
||||
that, you will be asked if you wish to go on to the advanced set-up; if you
|
||||
answer tt(n), you can rerun tt(compinstall) later without having to
|
||||
re-enter any of the basic settings.
|
||||
|
||||
You can abort the installation any time you are being prompted for
|
||||
information, and your tt(.zshrc) will not be altered at all.
|
||||
|
||||
subsect(Use of compinit)
|
||||
|
||||
This section describes the use of tt(compinit) to initialize completion for
|
||||
the current session when run directly by the user; if you have run
|
||||
tt(compinstall) it will be called automatically from your tt(.zshrc).
|
||||
|
||||
To initialise the system, the script tt(compinit) should be sourced with
|
||||
`tt(source )var(<path>)tt(/compinit)' or
|
||||
`tt(. )var(<path>)tt(/compinit)'. This will define a few utility functions,
|
||||
arrange for all the necessary shell functions to be autoloaded, and will
|
||||
then re-bind all keys that do completion to use the new system.
|
||||
|
||||
subsect(Arguments)
|
||||
|
||||
To speed up the running of tt(compinit), it can be made to produce a dumped
|
||||
configuration which will be read in on future invocations. The easiest way
|
||||
to do this is by adding the option tt(-d) whenever tt(compinit) is sourced.
|
||||
|
@ -65,6 +93,15 @@ but with tt(.dump) appended to the end; alternatively, an explicit file
|
|||
name can be given following the tt(-d). On the next call to tt(compinit
|
||||
-d), the dumped file will be read instead.
|
||||
|
||||
The other option accepted by tt(compinit) is tt(-f var(dir)), which gives
|
||||
the directory in which tt(compinit) resides. If you source tt(compinit) by
|
||||
its full pathname, and the option tt(FUNCTION_ARGZERO) is set, as it is by
|
||||
default unless tt(zsh) is emulating tt(sh) or tt(ksh), this is unnecessary
|
||||
as tt(compinit) can deduce the directory for itself. It is used in two
|
||||
ways: to find the program tt(compdump) used by the tt(-d) option, and to
|
||||
check if the directory should be added to the function search path to find
|
||||
the completion functions (see below).
|
||||
|
||||
If the number of completion files changes, tt(compinit) will recognise this
|
||||
and produce a new dump file. However, if the name of a function or the
|
||||
arguments in the first line of a tt(#compdef) funcion (as described below)
|
||||
|
@ -80,8 +117,18 @@ subsect(Autoloaded files)
|
|||
|
||||
The convention for autoloaded functions used in completion is that they
|
||||
start with an underscore; as already mentioned, the tt(fpath/FPATH)
|
||||
parameter must contain the directory in which they are stored. When
|
||||
tt(compinit) is sourced, it searches all such files accessible via
|
||||
parameter must contain the directory in which they are stored. 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 its own
|
||||
directory to the search path. If you keep all the completion files in this
|
||||
directory, this means you never have to alter tt(fpath/FPATH) yourself.
|
||||
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
|
||||
the functions to be in the same format as in the tt(zsh) source
|
||||
distribution.
|
||||
|
||||
When tt(compinit) is sourced, it searches all such files accessible via
|
||||
tt(fpath/FPATH) and reads the first line of each of them. This line should
|
||||
contain one of the tags described below. Files whose first line does not
|
||||
start with one of these tags are not considered to be part of the
|
||||
|
|
|
@ -717,18 +717,24 @@ If multiple nested tt(${...}) forms are present, substitution is
|
|||
performed from the inside outwards. At each level, the substitution takes
|
||||
account of whether the current value is a scalar or an array, whether the
|
||||
whole substitution is in double quotes, and what flags are supplied to the
|
||||
current level of substitution; the flags are not propagated up to enclosing
|
||||
substitutions. The value passed back to an enclosing substitution is
|
||||
always an array, which however will consist of one word if the value was
|
||||
not itself an array. All the following steps take place where applicable
|
||||
at all levels of substitution.
|
||||
current level of substitution, just as if the nested substitution were the
|
||||
outermost. The flags are not propagated up to enclosing
|
||||
substitutions; the nested subsitution will return either a scalar or an
|
||||
array as determined by the flags, possibly adjusted for quoting. All the
|
||||
following steps take place where applicable at all levels of substitution.
|
||||
Note that, unless the tt((P)) flag is present, the flags and any subscripts
|
||||
apply directly to the value of the nested substitution; for example, the
|
||||
expansion tt(${${foo}}) behaves exactly the same as tt(${foo}).
|
||||
)
|
||||
item(tt(2.) em(Parameter Subscripting))(
|
||||
If the value is a raw parameter reference with a subscript, such as
|
||||
tt(${)var(var)tt([3]}), the effect of subscripting is applied directly to
|
||||
the parameter. If the parameter is an array, any second subscript,
|
||||
indexing on the character in the word, may appear,
|
||||
e.g. tt(${)var(var)tt([1][2]}).
|
||||
the parameter. Subscripts are evaluated left to right; subsequent
|
||||
subscripts apply to the scalar or array value yielded by the previous
|
||||
subscript. Thus if tt(var) is an array, tt(${var[1][2]}) is the second
|
||||
character of the first word, but tt(${var[2,4][2]}) is the entire third
|
||||
word (the second word of the range of words two through four of the
|
||||
original array). Any number of subscripts may appear.
|
||||
)
|
||||
item(tt(3.) em(Parameter Name Replacement))(
|
||||
The effect of any tt((P)) flag, which treats the value so far as a
|
||||
|
@ -746,6 +752,10 @@ item(tt(5.) em(Nested Subscripting))(
|
|||
Any remaining subscript (i.e. of a nested substitution) is evaluated at
|
||||
this point, based on whether the value is an array or a scalar; if it was
|
||||
an array, a second subscript for the character in the word may also appear.
|
||||
Note that tt(${foo[2,4][2]}) is thus equivalent to tt(${${foo[2,4]}[2]})
|
||||
and also to tt("${${(@)foo[2,4]}[2]}") (the nested substitution returns an
|
||||
array in both cases), but not to tt("${${foo[2,4]}[2]}") (the nested
|
||||
substitution returns a scalar because of the quotes).
|
||||
)
|
||||
item(tt(6.) em(Modifiers))(
|
||||
Any modifiers, as specified by a trailing tt(#), tt(%), tt(/)
|
||||
|
@ -798,20 +808,17 @@ Suppose that tt($foo) contains the array tt(LPAR()bar baz)tt(RPAR()):
|
|||
|
||||
startitem()
|
||||
item(tt("${(@)${foo}[1]}"))(
|
||||
This produces the result tt(bar baz). First, the inner substitution
|
||||
This produces the result tt(b). First, the inner substitution
|
||||
tt("${foo}"), which has no array (tt(@)) flag, produces a single word
|
||||
result. The outer substitution tt("${(@)...[1]}") acts on this result as
|
||||
if it were a one word array, because of the array flag, so the result is
|
||||
just that single word.
|
||||
result tt("bar baz"). The outer substitution tt("${(@)...[1]}") detects
|
||||
that this is a scalar, so that (despite the tt((@)) flag) the subscript
|
||||
picks the first character.
|
||||
)
|
||||
item(tt("${${(@)foo}[1]}"))(
|
||||
The produces the result tt(b). In this case, the inner substitution
|
||||
The produces the result tt(bar). In this case, the inner substitution
|
||||
tt("${(@)foo}") produces the array tt(LPAR()bar baz)tt(RPAR()). The outer
|
||||
substitution tt("${...[1]}"), however, has no array flag, so that it joins
|
||||
the array it has to a single word and indexes as if it were a string. Note
|
||||
that this is not identical to the case tt("${foo[1]}"), since here the
|
||||
expression tt(foo[1]) is recognised immediately as an index into an array,
|
||||
so that the result in that case is tt(bar).
|
||||
substitution tt("${...[1]}") detects that this is an array and picks the
|
||||
first word. This is similar to the simple case tt("${foo[1]}").
|
||||
)
|
||||
enditem()
|
||||
|
||||
|
|
|
@ -302,9 +302,10 @@ always produces named directory expansion.)
|
|||
pindex(EXTENDED_HISTORY)
|
||||
cindex(history, timestamping)
|
||||
item(tt(EXTENDED_HISTORY))(
|
||||
Save beginning and ending timestamps to the history file.
|
||||
The format of these timestamps is
|
||||
`tt(:)var(<beginning time>)tt(:)var(<ending time>)tt(:)var(<command>)'.
|
||||
Save each command's beginning timestamp (in seconds since the epoch)
|
||||
and the duration (in seconds) to the history file. The format of
|
||||
this prefixed data is
|
||||
`tt(:)var(<beginning time>)tt(:)var(<elapsed seconds>)tt(:)var(<command>)'.
|
||||
)
|
||||
pindex(FLOW_CONTROL)
|
||||
cindex(flow control)
|
||||
|
@ -405,6 +406,20 @@ item(tt(HIST_BEEP))(
|
|||
Beep when an attempt is made to access a history entry which
|
||||
isn't there.
|
||||
)
|
||||
pindex(HIST_EXPIRE_DUPS_FIRST)
|
||||
cindex(history, expiring duplicates)
|
||||
item(tt(HIST_EXPIRE_DUPS_FIRST))(
|
||||
If the history needs to be trimmed to add a new line, setting this
|
||||
option will cause the oldest duplicate history line to be lost before
|
||||
losing a unique line from the internal history list.
|
||||
)
|
||||
pindex(HIST_IGNORE_ALL_DUPS)
|
||||
cindex(history, ignoring all duplicates)
|
||||
item(tt(HIST_IGNORE_ALL_DUPS) (tt(-h)))(
|
||||
If a new command line being added to the history list duplicates an
|
||||
older one, the older command is removed from the list (even if it is
|
||||
not the previous event).
|
||||
)
|
||||
pindex(HIST_IGNORE_DUPS)
|
||||
cindex(history, ignoring duplicates)
|
||||
item(tt(HIST_IGNORE_DUPS) (tt(-h)))(
|
||||
|
@ -426,6 +441,11 @@ item(tt(HIST_NO_STORE))(
|
|||
Remove the tt(history) (tt(fc -l)) command from
|
||||
the history when invoked.
|
||||
)
|
||||
pindex(HIST_SAVE_NO_DUPS)
|
||||
item(tt(HIST_SAVE_NO_DUPS))(
|
||||
When writing out the history file, older commands that duplicate
|
||||
newer ones are omitted.
|
||||
)
|
||||
pindex(HIST_REDUCE_BLANKS)
|
||||
item(tt(HIST_REDUCE_BLANKS))(
|
||||
Remove superfluous blanks from each command line
|
||||
|
@ -459,6 +479,15 @@ of tt(exit) or tt(logout) instead.
|
|||
However, ten consecutive EOFs will cause the shell to exit anyway,
|
||||
to avoid the shell hanging if its tty goes away.
|
||||
)
|
||||
pindex(INCREMENTAL_APPEND_HISTORY)
|
||||
cindex(history, incremental appending to a file)
|
||||
item(tt(INCREMENTAL_APPEND_HISTORY))(
|
||||
This options works like APPEND_HISTORY except that new history lines
|
||||
are added to the tt($HISTFILE) when they finish running, rather than
|
||||
waiting until the shell is killed. The file is periodically trimmed
|
||||
to the number of lines specified by tt($SAVEHIST), but can exceed this
|
||||
value between trimmings.
|
||||
)
|
||||
pindex(INTERACTIVE)
|
||||
item(tt(INTERACTIVE) (tt(-i), ksh: tt(-i)))(
|
||||
This is an interactive shell. This option is set upon initialisation if
|
||||
|
@ -798,6 +827,28 @@ This avoids the problem of reflexively answering `yes' to the query
|
|||
when one didn't really mean it. The wait and query can always be
|
||||
avoided by expanding the `tt(*)' in ZLE (with tab).
|
||||
)
|
||||
pindex(SHARE_HISTORY)
|
||||
cindex(share history)
|
||||
cindex(history, sharing)
|
||||
item(tt(SHARE_HISTORY))(
|
||||
|
||||
This option both imports new commands from the history file, and also
|
||||
causes your typed commands to be appended to the history file (like
|
||||
specifiying tt(INCREMENTAL_APPEND_HISTORY)). The history lines are also
|
||||
output with timestamps ala tt(EXTENDED_HISTORY) (which makes it easier to
|
||||
find the spot where we left off reading the file after it gets re-written).
|
||||
|
||||
By default, history movement commands visit the imported lines as well as
|
||||
the local lines, but you can toggle this on and off with the
|
||||
set-local-history zle binding. It is also possible to create a zle
|
||||
widget that will make some commands ignore imported commands, and some
|
||||
include them.
|
||||
|
||||
If you find that you want more control over when commands
|
||||
get imported, you may wish to turn tt(SHARE_HISTORY) off,
|
||||
tt(INCREMENTAL_APPEND_HISTORY) on, and then manually import
|
||||
commands whenever you need them using `fc -RI'.
|
||||
)
|
||||
pindex(SH_FILE_EXPANSION)
|
||||
cindex(sh, expansion style)
|
||||
cindex(expansion style, sh)
|
||||
|
|
|
@ -43,14 +43,14 @@ zstrtorlimt(const char *s, char **t, int base)
|
|||
{
|
||||
rlim_t ret = 0;
|
||||
|
||||
if (!base)
|
||||
if (!base) {
|
||||
if (*s != '0')
|
||||
base = 10;
|
||||
else if (*++s == 'x' || *s == 'X')
|
||||
base = 16, s++;
|
||||
else
|
||||
base = 8;
|
||||
|
||||
}
|
||||
if (base <= 10)
|
||||
for (; *s >= '0' && *s < ('0' + base); s++)
|
||||
ret = ret * base + *s - '0';
|
||||
|
|
|
@ -47,7 +47,7 @@ Cmlist cmatcher;
|
|||
void (*makecompparamsptr) _((void));
|
||||
|
||||
/**/
|
||||
void (*comp_setunsetptr) _((int, int));
|
||||
void (*comp_setunsetptr) _((unsigned int, unsigned int));
|
||||
|
||||
/* pointers to functions required by compctl and defined by zle */
|
||||
|
||||
|
@ -147,6 +147,7 @@ createcompctltable(void)
|
|||
compctltab->hash = hasher;
|
||||
compctltab->emptytable = emptyhashtable;
|
||||
compctltab->filltable = NULL;
|
||||
compctltab->cmpnodes = strcmp;
|
||||
compctltab->addnode = addhashnode;
|
||||
compctltab->getnode = gethashnode2;
|
||||
compctltab->getnode2 = gethashnode2;
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
"send-break", sendbreak, 0
|
||||
"set-mark-command", setmarkcommand, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
|
||||
"spell-word", spellword, 0
|
||||
"set-local-history", setlocalhistory, 0
|
||||
"transpose-chars", transposechars, 0
|
||||
"transpose-words", transposewords, 0
|
||||
"undefined-key", undefinedkey, 0
|
||||
|
|
|
@ -47,27 +47,16 @@ int lastcol;
|
|||
/**/
|
||||
int histline;
|
||||
|
||||
/* the last line in the history (the current one), metafied */
|
||||
|
||||
/**/
|
||||
char *curhistline;
|
||||
#define ZLETEXT(X) ((X)->zle_text ? (X)->zle_text : (X)->text)
|
||||
|
||||
/**/
|
||||
void
|
||||
remember_edits(void)
|
||||
{
|
||||
if (histline == curhist) {
|
||||
zsfree(curhistline);
|
||||
curhistline = metafy((char *) line, ll, META_DUP);
|
||||
}
|
||||
else {
|
||||
Histent ent = gethistent(histline);
|
||||
|
||||
if (metadiffer(ent->zle_text ? ent->zle_text : ent->text,
|
||||
(char *) line, ll)) {
|
||||
zsfree(ent->zle_text);
|
||||
ent->zle_text = metafy((char *) line, ll, META_DUP);
|
||||
}
|
||||
Histent ent = quietgethist(histline);
|
||||
if (metadiffer(ZLETEXT(ent), (char *) line, ll)) {
|
||||
zsfree(ent->zle_text);
|
||||
ent->zle_text = metafy((char *) line, ll, META_DUP);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,11 +64,11 @@ remember_edits(void)
|
|||
void
|
||||
forget_edits(void)
|
||||
{
|
||||
int i;
|
||||
Histent he;
|
||||
|
||||
for (i = 0; i < histentct; i++) {
|
||||
zsfree(histentarr[i].zle_text);
|
||||
histentarr[i].zle_text = NULL;
|
||||
for (he = hist_ring; he; he = up_histent(he)) {
|
||||
zsfree(he->zle_text);
|
||||
he->zle_text = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,16 +76,12 @@ forget_edits(void)
|
|||
void
|
||||
uphistory(void)
|
||||
{
|
||||
if (zmult < 0) {
|
||||
zmult = -zmult;
|
||||
downhistory();
|
||||
zmult = -zmult;
|
||||
} else if(!zle_goto_hist(histline - zmult) && isset(HISTBEEP))
|
||||
if (!zle_goto_hist(histline, -zmult) && isset(HISTBEEP))
|
||||
feep();
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
static int
|
||||
upline(void)
|
||||
{
|
||||
int n = zmult;
|
||||
|
@ -159,7 +144,6 @@ viuplineorhistory(void)
|
|||
vifirstnonblank();
|
||||
}
|
||||
|
||||
|
||||
/**/
|
||||
void
|
||||
uplineorsearch(void)
|
||||
|
@ -181,7 +165,7 @@ uplineorsearch(void)
|
|||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
static int
|
||||
downline(void)
|
||||
{
|
||||
int n = zmult;
|
||||
|
@ -268,26 +252,22 @@ downlineorsearch(void)
|
|||
void
|
||||
acceptlineanddownhistory(void)
|
||||
{
|
||||
char *s;
|
||||
Histent he;
|
||||
|
||||
if (!(s = zle_get_event(histline + 1))) {
|
||||
if (!(he = movehistent(quietgethist(histline), 1, HIST_FOREIGN))) {
|
||||
feep();
|
||||
return;
|
||||
}
|
||||
pushnode(bufstack, ztrdup(s));
|
||||
pushnode(bufstack, ztrdup(ZLETEXT(he)));
|
||||
done = 1;
|
||||
stackhist = histline + 1;
|
||||
stackhist = he->histnum;
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
downhistory(void)
|
||||
{
|
||||
if (zmult < 0) {
|
||||
zmult = -zmult;
|
||||
uphistory();
|
||||
zmult = -zmult;
|
||||
} else if(!zle_goto_hist(histline + zmult) && isset(HISTBEEP))
|
||||
if (!zle_goto_hist(histline, zmult) && isset(HISTBEEP))
|
||||
feep();
|
||||
}
|
||||
|
||||
|
@ -298,7 +278,7 @@ static char *srch_str;
|
|||
void
|
||||
historysearchbackward(void)
|
||||
{
|
||||
int hl = histline;
|
||||
Histent he;
|
||||
int n = zmult;
|
||||
char *s;
|
||||
|
||||
|
@ -308,7 +288,7 @@ historysearchbackward(void)
|
|||
zmult = n;
|
||||
return;
|
||||
}
|
||||
if (hl == curhist || hl != srch_hl || cs != srch_cs || mark != 0
|
||||
if (histline == curhist || histline != srch_hl || cs != srch_cs || mark != 0
|
||||
|| memcmp(srch_str, line, histpos) != 0) {
|
||||
zfree(srch_str, histpos);
|
||||
for (histpos = 0; histpos < ll && !iblank(line[histpos]); histpos++) ;
|
||||
|
@ -317,28 +297,29 @@ historysearchbackward(void)
|
|||
srch_str = zalloc(histpos);
|
||||
memcpy(srch_str, line, histpos);
|
||||
}
|
||||
for (;;) {
|
||||
hl--;
|
||||
if (!(s = zle_get_event(hl))) {
|
||||
feep();
|
||||
return;
|
||||
}
|
||||
he = quietgethist(histline);
|
||||
while ((he = movehistent(he, -1, hist_skip_flags))) {
|
||||
if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP)
|
||||
continue;
|
||||
s = ZLETEXT(he);
|
||||
if (metadiffer(s, srch_str, histpos) < 0 &&
|
||||
metadiffer(s, srch_str, ll)) {
|
||||
if (--n <= 0)
|
||||
break;
|
||||
if (--n <= 0) {
|
||||
zle_setline(he);
|
||||
srch_hl = histline;
|
||||
srch_cs = cs;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
zle_goto_hist(hl);
|
||||
srch_hl = hl;
|
||||
srch_cs = cs;
|
||||
feep();
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
historysearchforward(void)
|
||||
{
|
||||
int hl = histline;
|
||||
Histent he;
|
||||
int n = zmult;
|
||||
char *s;
|
||||
|
||||
|
@ -348,7 +329,7 @@ historysearchforward(void)
|
|||
zmult = n;
|
||||
return;
|
||||
}
|
||||
if (hl == curhist || hl != srch_hl || cs != srch_cs || mark != 0
|
||||
if (histline == curhist || histline != srch_hl || cs != srch_cs || mark != 0
|
||||
|| memcmp(srch_str, line, histpos) != 0) {
|
||||
zfree(srch_str, histpos);
|
||||
for (histpos = 0; histpos < ll && !iblank(line[histpos]); histpos++) ;
|
||||
|
@ -357,20 +338,22 @@ historysearchforward(void)
|
|||
srch_str = zalloc(histpos);
|
||||
memcpy(srch_str, line, histpos);
|
||||
}
|
||||
for (;;) {
|
||||
hl++;
|
||||
if (!(s = zle_get_event(hl))) {
|
||||
feep();
|
||||
return;
|
||||
he = quietgethist(histline);
|
||||
while ((he = movehistent(he, 1, hist_skip_flags))) {
|
||||
if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP)
|
||||
continue;
|
||||
s = ZLETEXT(he);
|
||||
if (metadiffer(s, srch_str, histpos) < (he->histnum == curhist) &&
|
||||
metadiffer(s, srch_str, ll)) {
|
||||
if (--n <= 0) {
|
||||
zle_setline(he);
|
||||
srch_hl = histline;
|
||||
srch_cs = cs;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (metadiffer(s, srch_str, histpos) < (hl == curhist) &&
|
||||
metadiffer(s, srch_str, ll))
|
||||
if (--n <= 0)
|
||||
break;
|
||||
}
|
||||
zle_goto_hist(hl);
|
||||
srch_hl = hl;
|
||||
srch_cs = cs;
|
||||
feep();
|
||||
}
|
||||
|
||||
/**/
|
||||
|
@ -387,7 +370,7 @@ beginningofbufferorhistory(void)
|
|||
void
|
||||
beginningofhistory(void)
|
||||
{
|
||||
if (!zle_goto_hist(firsthist()) && isset(HISTBEEP))
|
||||
if (!zle_goto_hist(firsthist(), 0) && isset(HISTBEEP))
|
||||
feep();
|
||||
}
|
||||
|
||||
|
@ -405,7 +388,7 @@ endofbufferorhistory(void)
|
|||
void
|
||||
endofhistory(void)
|
||||
{
|
||||
zle_goto_hist(curhist);
|
||||
zle_goto_hist(curhist, 0);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
@ -419,7 +402,7 @@ insertlastword(void)
|
|||
/* multiple calls will now search back through the history, pem */
|
||||
static char *lastinsert;
|
||||
static int lasthist, lastpos;
|
||||
int evhist = curhist - 1, save;
|
||||
int evhist = addhistnum(curhist, -1, HIST_FOREIGN), save;
|
||||
|
||||
if (lastinsert) {
|
||||
int lastlen = ztrlen(lastinsert);
|
||||
|
@ -428,7 +411,7 @@ insertlastword(void)
|
|||
if (lastpos <= pos &&
|
||||
lastlen == pos - lastpos &&
|
||||
memcmp(lastinsert, (char *)&line[lastpos], lastlen) == 0) {
|
||||
evhist = --lasthist;
|
||||
evhist = addhistnum(lasthist, -1, HIST_FOREIGN);
|
||||
cs = lastpos;
|
||||
foredel(pos - cs);
|
||||
}
|
||||
|
@ -464,41 +447,37 @@ insertlastword(void)
|
|||
}
|
||||
|
||||
/**/
|
||||
char *
|
||||
qgetevent(int ev)
|
||||
void
|
||||
zle_setline(Histent he)
|
||||
{
|
||||
return ((ev == curhist) ? curhistline : quietgetevent(ev));
|
||||
}
|
||||
|
||||
/**/
|
||||
char *
|
||||
zle_get_event(int ev)
|
||||
{
|
||||
Histent ent;
|
||||
|
||||
if (ev == curhist)
|
||||
return curhistline;
|
||||
if (! (ent = quietgethist(ev)))
|
||||
return NULL;
|
||||
if (ent->zle_text)
|
||||
return ent->zle_text;
|
||||
return ent->text;
|
||||
}
|
||||
|
||||
/**/
|
||||
static int
|
||||
zle_goto_hist(int ev)
|
||||
{
|
||||
char *t;
|
||||
|
||||
remember_edits();
|
||||
if(!(t = zle_get_event(ev)))
|
||||
return 0;
|
||||
mkundoent();
|
||||
histline = ev;
|
||||
setline(t);
|
||||
histline = he->histnum;
|
||||
setline(ZLETEXT(he));
|
||||
setlastline();
|
||||
clearlist = 1;
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
setlocalhistory(void)
|
||||
{
|
||||
if (zmod.flags & MOD_MULT) {
|
||||
hist_skip_flags = zmult? HIST_FOREIGN : 0;
|
||||
}
|
||||
else {
|
||||
hist_skip_flags ^= HIST_FOREIGN;
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
zle_goto_hist(int ev, int n)
|
||||
{
|
||||
Histent he = movehistent(quietgethist(ev), n, hist_skip_flags);
|
||||
if (!he)
|
||||
return 0;
|
||||
zle_setline(he);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -603,6 +582,7 @@ static struct isrch_spot {
|
|||
|
||||
static int max_spot = 0;
|
||||
|
||||
/**/
|
||||
#ifdef MODULE
|
||||
|
||||
/**/
|
||||
|
@ -612,6 +592,7 @@ free_isrch_spots(void)
|
|||
zfree(isrch_spots, max_spot * sizeof(*isrch_spots));
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif /* MODULE */
|
||||
|
||||
/**/
|
||||
|
@ -665,13 +646,15 @@ doisearch(int dir)
|
|||
char *okeymap = curkeymapname;
|
||||
static char *previous_search = NULL;
|
||||
static int previous_search_len = 0;
|
||||
Histent he;
|
||||
|
||||
clearlist = 1;
|
||||
|
||||
strcpy(ibuf, ISEARCH_PROMPT);
|
||||
memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
|
||||
remember_edits();
|
||||
s = zle_get_event(hl);
|
||||
he = quietgethist(hl);
|
||||
s = ZLETEXT(he);
|
||||
selectkeymap("main", 1);
|
||||
pos = metalen(s, cs);
|
||||
for (;;) {
|
||||
|
@ -705,15 +688,14 @@ doisearch(int dir)
|
|||
if (!skip_line && ((sbuf[0] == '^') ?
|
||||
(t = metadiffer(s, sbuf + 1, sbptr - 1) < sens ? s : NULL) :
|
||||
(t = hstrnstr(s, pos, sbuf, sbptr, dir, sens)))) {
|
||||
zle_goto_hist(hl);
|
||||
zle_setline(he);
|
||||
pos = t - s;
|
||||
cs = ztrsub(t, s) + (dir == 1? sbptr - (sbuf[0]=='^') : 0);
|
||||
nomatch = 0;
|
||||
statusline = ibuf + NORM_PROMPT_POS;
|
||||
break;
|
||||
}
|
||||
hl += dir;
|
||||
if (!(s = zle_get_event(hl))) {
|
||||
if (!(he = movehistent(he, dir, hist_skip_flags))) {
|
||||
if (sbptr == (int)isrch_spots[top_spot-1].len
|
||||
&& (isrch_spots[top_spot-1].flags & ISS_FAILING))
|
||||
top_spot--;
|
||||
|
@ -723,13 +705,17 @@ doisearch(int dir)
|
|||
feep();
|
||||
nomatch = 1;
|
||||
}
|
||||
s = last_line;
|
||||
he = quietgethist(hl);
|
||||
s = ZLETEXT(he);
|
||||
skip_line = 0;
|
||||
statusline = ibuf;
|
||||
break;
|
||||
}
|
||||
hl = he->histnum;
|
||||
s = ZLETEXT(he);
|
||||
pos = dir == 1? 0 : strlen(s);
|
||||
skip_line = !strcmp(last_line, s);
|
||||
skip_line = isset(HISTFINDNODUPS)? !!(he->flags & HIST_DUP)
|
||||
: !strcmp(last_line, s);
|
||||
}
|
||||
} else {
|
||||
top_spot = 0;
|
||||
|
@ -743,8 +729,9 @@ doisearch(int dir)
|
|||
if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak)) {
|
||||
int i;
|
||||
get_isrch_spot(0, &hl, &pos, &i, &sbptr, &dir, &nomatch);
|
||||
s = zle_get_event(hl);
|
||||
zle_goto_hist(hl);
|
||||
he = quietgethist(hl);
|
||||
zle_setline(he);
|
||||
s = ZLETEXT(he);
|
||||
cs = i;
|
||||
break;
|
||||
}
|
||||
|
@ -769,10 +756,11 @@ doisearch(int dir)
|
|||
statusline = ibuf;
|
||||
skip_pos = 1;
|
||||
}
|
||||
s = zle_get_event(hl);
|
||||
he = quietgethist(hl);
|
||||
s = ZLETEXT(he);
|
||||
if (nomatch || !sbptr || (sbptr == 1 && sbuf[0] == '^')) {
|
||||
int i = cs;
|
||||
zle_goto_hist(hl);
|
||||
zle_setline(he);
|
||||
cs = i;
|
||||
}
|
||||
memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
|
||||
|
@ -874,42 +862,35 @@ doisearch(int dir)
|
|||
void
|
||||
acceptandinfernexthistory(void)
|
||||
{
|
||||
int t0;
|
||||
char *s;
|
||||
Histent he;
|
||||
|
||||
done = 1;
|
||||
for (t0 = histline - 2;; t0--) {
|
||||
if (!(s = qgetevent(t0)))
|
||||
for (he = movehistent(quietgethist(histline), -2, HIST_FOREIGN);
|
||||
he; he = movehistent(he, -1, HIST_FOREIGN)) {
|
||||
if (!metadiffer(ZLETEXT(he), (char *) line, ll)) {
|
||||
he = movehistent(he, 1, HIST_FOREIGN);
|
||||
pushnode(bufstack, ztrdup(ZLETEXT(he)));
|
||||
stackhist = he->histnum;
|
||||
return;
|
||||
if (!metadiffer(s, (char *) line, ll))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!(s = qgetevent(t0 + 1)))
|
||||
return;
|
||||
pushnode(bufstack, ztrdup(s));
|
||||
stackhist = t0 + 1;
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
infernexthistory(void)
|
||||
{
|
||||
int t0;
|
||||
char *s;
|
||||
Histent he;
|
||||
|
||||
for (t0 = histline - 2;; t0--) {
|
||||
if (!(s = qgetevent(t0))) {
|
||||
feep();
|
||||
for (he = movehistent(quietgethist(histline), -2, HIST_FOREIGN);
|
||||
he; he = movehistent(he, -1, HIST_FOREIGN)) {
|
||||
if (!metadiffer(ZLETEXT(he), (char *) line, ll)) {
|
||||
he = movehistent(he, 1, HIST_FOREIGN);
|
||||
zle_setline(he);
|
||||
return;
|
||||
}
|
||||
if (! metadiffer(s, (char *) line, ll))
|
||||
break;
|
||||
}
|
||||
if (!(s = qgetevent(t0 + 1))) {
|
||||
feep();
|
||||
return;
|
||||
}
|
||||
zle_goto_hist(t0 + 1);
|
||||
feep();
|
||||
}
|
||||
|
||||
/**/
|
||||
|
@ -925,7 +906,7 @@ vifetchhistory(void)
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (!zle_goto_hist((zmod.flags & MOD_MULT) ? zmult : curhist) &&
|
||||
if (!zle_goto_hist((zmod.flags & MOD_MULT) ? zmult : curhist, 0) &&
|
||||
isset(HISTBEEP))
|
||||
feep();
|
||||
}
|
||||
|
@ -1041,7 +1022,8 @@ vihistorysearchbackward(void)
|
|||
void
|
||||
virepeatsearch(void)
|
||||
{
|
||||
int hl = histline, t0;
|
||||
Histent he;
|
||||
int t0;
|
||||
int n = zmult;
|
||||
char *s;
|
||||
|
||||
|
@ -1054,23 +1036,21 @@ virepeatsearch(void)
|
|||
visrchsense = -visrchsense;
|
||||
}
|
||||
t0 = strlen(visrchstr);
|
||||
for (;;) {
|
||||
hl += visrchsense;
|
||||
if (!(s = zle_get_event(hl))) {
|
||||
feep();
|
||||
return;
|
||||
he = quietgethist(histline);
|
||||
while ((he = movehistent(he, visrchsense, hist_skip_flags))) {
|
||||
if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP)
|
||||
continue;
|
||||
s = ZLETEXT(he);
|
||||
if (metadiffer(s, (char *) line, ll)
|
||||
&& (*visrchstr == '^'? strncmp(s, visrchstr + 1, t0 - 1) == 0
|
||||
: hstrnstr(s, 0, visrchstr, t0, 1, 1) != 0)) {
|
||||
if (--n <= 0) {
|
||||
zle_setline(he);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!metadiffer(s, (char *) line, ll))
|
||||
continue;
|
||||
if (*visrchstr == '^') {
|
||||
if (strncmp(s, visrchstr + 1, t0 - 1) != 0)
|
||||
continue;
|
||||
} else if (!hstrnstr(s, 0, visrchstr, t0, 1, 1))
|
||||
continue;
|
||||
if (--n <= 0)
|
||||
break;
|
||||
}
|
||||
zle_goto_hist(hl);
|
||||
feep();
|
||||
}
|
||||
|
||||
/**/
|
||||
|
@ -1090,8 +1070,8 @@ virevrepeatsearch(void)
|
|||
void
|
||||
historybeginningsearchbackward(void)
|
||||
{
|
||||
Histent he;
|
||||
int cpos = cs; /* save cursor position */
|
||||
int hl = histline;
|
||||
int n = zmult;
|
||||
char *s;
|
||||
|
||||
|
@ -1101,20 +1081,21 @@ historybeginningsearchbackward(void)
|
|||
zmult = n;
|
||||
return;
|
||||
}
|
||||
for (;;) {
|
||||
hl--;
|
||||
if (!(s = zle_get_event(hl))) {
|
||||
feep();
|
||||
return;
|
||||
}
|
||||
he = quietgethist(histline);
|
||||
while ((he = movehistent(he, -1, hist_skip_flags))) {
|
||||
if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP)
|
||||
continue;
|
||||
s = ZLETEXT(he);
|
||||
if (metadiffer(s, (char *)line, cs) < 0 &&
|
||||
metadiffer(s, (char *)line, ll))
|
||||
if (--n <= 0)
|
||||
break;
|
||||
metadiffer(s, (char *)line, ll)) {
|
||||
if (--n <= 0) {
|
||||
zle_setline(he);
|
||||
cs = cpos;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zle_goto_hist(hl);
|
||||
cs = cpos;
|
||||
feep();
|
||||
}
|
||||
|
||||
/* Extra function added by A.R. Iano-Fletcher. */
|
||||
|
@ -1124,8 +1105,8 @@ historybeginningsearchbackward(void)
|
|||
void
|
||||
historybeginningsearchforward(void)
|
||||
{
|
||||
Histent he;
|
||||
int cpos = cs; /* save cursor position */
|
||||
int hl = histline;
|
||||
int n = zmult;
|
||||
char *s;
|
||||
|
||||
|
@ -1135,18 +1116,19 @@ historybeginningsearchforward(void)
|
|||
zmult = n;
|
||||
return;
|
||||
}
|
||||
for (;;) {
|
||||
hl++;
|
||||
if (!(s = zle_get_event(hl))) {
|
||||
feep();
|
||||
return;
|
||||
he = quietgethist(histline);
|
||||
while ((he = movehistent(he, 1, hist_skip_flags))) {
|
||||
if (isset(HISTFINDNODUPS) && he->flags & HIST_DUP)
|
||||
continue;
|
||||
s = ZLETEXT(he);
|
||||
if (metadiffer(s, (char *)line, cs) < (he->histnum == curhist) &&
|
||||
metadiffer(s, (char *)line, ll)) {
|
||||
if (--n <= 0) {
|
||||
zle_setline(he);
|
||||
cs = cpos;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (metadiffer(s, (char *)line, cs) < (hl == curhist) &&
|
||||
metadiffer(s, (char *)line, ll))
|
||||
if (--n <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
zle_goto_hist(hl);
|
||||
cs = cpos;
|
||||
feep();
|
||||
}
|
||||
|
|
|
@ -130,6 +130,7 @@ createkeymapnamtab(void)
|
|||
keymapnamtab->hash = hasher;
|
||||
keymapnamtab->emptytable = emptyhashtable;
|
||||
keymapnamtab->filltable = NULL;
|
||||
keymapnamtab->cmpnodes = strcmp;
|
||||
keymapnamtab->addnode = addhashnode;
|
||||
keymapnamtab->getnode = gethashnode2;
|
||||
keymapnamtab->getnode2 = gethashnode2;
|
||||
|
@ -172,6 +173,7 @@ newkeytab(char *kmname)
|
|||
ht->hash = hasher;
|
||||
ht->emptytable = emptyhashtable;
|
||||
ht->filltable = NULL;
|
||||
ht->cmpnodes = strcmp;
|
||||
ht->addnode = addhashnode;
|
||||
ht->getnode = gethashnode2;
|
||||
ht->getnode2 = gethashnode2;
|
||||
|
|
|
@ -111,6 +111,10 @@ int prefixflag;
|
|||
/**/
|
||||
int feepflag;
|
||||
|
||||
#ifdef FIONREAD
|
||||
static int delayzsetterm;
|
||||
#endif
|
||||
|
||||
/* set up terminal */
|
||||
|
||||
/**/
|
||||
|
@ -119,12 +123,30 @@ zsetterm(void)
|
|||
{
|
||||
struct ttyinfo ti;
|
||||
|
||||
#if defined(CLOBBERS_TYPEAHEAD) && defined(FIONREAD)
|
||||
#if defined(FIONREAD)
|
||||
int val;
|
||||
|
||||
ioctl(SHTTY, FIONREAD, (char *)&val);
|
||||
if (val)
|
||||
if (val) {
|
||||
/*
|
||||
* Problems can occur on some systems when switching from
|
||||
* canonical to non-canonical input. The former is usually
|
||||
* set while running programmes, but the latter is necessary
|
||||
* for zle. If there is input in canonical mode, then we
|
||||
* need to read it without setting up the terminal. Furthermore,
|
||||
* while that input gets processed there may be more input
|
||||
* being typed (i.e. further typeahead). This means that
|
||||
* we can't set up the terminal for zle *at all* until
|
||||
* we are sure there is no more typeahead to come. So
|
||||
* if there is typeahead, we set the flag delayzsetterm.
|
||||
* Then getkey() performs another FIONREAD call; if that is
|
||||
* 0, we have finally used up all the typeahead, and it is
|
||||
* safe to alter the terminal, which we do at that point.
|
||||
*/
|
||||
delayzsetterm = 1;
|
||||
return;
|
||||
} else
|
||||
delayzsetterm = 0;
|
||||
#endif
|
||||
|
||||
/* sanitize the tty */
|
||||
|
@ -298,7 +320,19 @@ getkey(int keytmout)
|
|||
if (kungetct)
|
||||
ret = STOUC(kungetbuf[--kungetct]);
|
||||
else {
|
||||
if (keytmout) {
|
||||
#ifdef FIONREAD
|
||||
if (delayzsetterm) {
|
||||
int val;
|
||||
ioctl(SHTTY, FIONREAD, (char *)&val);
|
||||
if (!val)
|
||||
zsetterm();
|
||||
}
|
||||
#endif
|
||||
if (keytmout
|
||||
#ifdef FIONREAD
|
||||
&& ! delayzsetterm
|
||||
#endif
|
||||
) {
|
||||
if (keytimeout > 500)
|
||||
exp100ths = 500;
|
||||
else if (keytimeout > 0)
|
||||
|
@ -461,7 +495,6 @@ zleread(char *lp, char *rp, int flags)
|
|||
undoing = 1;
|
||||
line = (unsigned char *)zalloc((linesz = 256) + 2);
|
||||
virangeflag = lastcmd = done = cs = ll = mark = 0;
|
||||
curhistline = NULL;
|
||||
vichgflag = 0;
|
||||
viinsbegin = 0;
|
||||
statusline = NULL;
|
||||
|
@ -542,7 +575,6 @@ zleread(char *lp, char *rp, int flags)
|
|||
zleactive = no_restore_tty = 0;
|
||||
alarm(0);
|
||||
} LASTALLOC;
|
||||
zsfree(curhistline);
|
||||
freeundo();
|
||||
if (eofsent) {
|
||||
free(line);
|
||||
|
|
|
@ -476,17 +476,10 @@ vigotomark(void)
|
|||
feep();
|
||||
return;
|
||||
}
|
||||
if (curhist != vimarkline[ch]) {
|
||||
char *s;
|
||||
|
||||
remember_edits();
|
||||
if (!(s = qgetevent(vimarkline[ch]))) {
|
||||
vimarkline[ch] = 0;
|
||||
feep();
|
||||
return;
|
||||
}
|
||||
histline = vimarkline[ch];
|
||||
setline(s);
|
||||
if (curhist != vimarkline[ch] && !zle_goto_hist(vimarkline[ch], 0)) {
|
||||
vimarkline[ch] = 0;
|
||||
feep();
|
||||
return;
|
||||
}
|
||||
cs = vimarkcs[ch];
|
||||
if (cs > ll)
|
||||
|
|
|
@ -64,6 +64,7 @@ createthingytab(void)
|
|||
thingytab->hash = hasher;
|
||||
thingytab->emptytable = emptythingytab;
|
||||
thingytab->filltable = NULL;
|
||||
thingytab->cmpnodes = strcmp;
|
||||
thingytab->addnode = addhashnode;
|
||||
thingytab->getnode = gethashnode;
|
||||
thingytab->getnode2 = gethashnode2;
|
||||
|
@ -356,7 +357,7 @@ bin_zle(char *name, char **args, char *ops, int func)
|
|||
|
||||
/* check number of arguments */
|
||||
for(n = 0; args[n]; n++) ;
|
||||
if(!op->o && n != 1) {
|
||||
if(!op->o && n != 1 && n != 2) {
|
||||
zerrnam(name, "wrong number of arguments", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
@ -515,17 +516,31 @@ static int
|
|||
bin_zle_call(char *name, char **args, char *ops, char func)
|
||||
{
|
||||
Thingy t;
|
||||
struct modifier modsave;
|
||||
|
||||
if(!zleactive || incompctlfunc || incompfunc) {
|
||||
zerrnam(name, "widgets can only be called when ZLE is active",
|
||||
NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (args[1]) {
|
||||
modsave = zmod;
|
||||
if (isdigit(*args[1])) {
|
||||
zmod.mult = atoi(args[1]);
|
||||
zmod.flags |= MOD_MULT;
|
||||
}
|
||||
else {
|
||||
zmod.mult = 1;
|
||||
zmod.flags &= ~MOD_MULT;
|
||||
}
|
||||
}
|
||||
t = rthingy(args[0]);
|
||||
PERMALLOC {
|
||||
execzlefunc(t);
|
||||
} LASTALLOC;
|
||||
unrefthingy(t);
|
||||
if (args[1])
|
||||
zmod = modsave;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -578,6 +578,10 @@ static char *varname;
|
|||
|
||||
static int insubscr;
|
||||
|
||||
/* Parameter pointer for completing keys of an assoc array. */
|
||||
|
||||
static Param keypm;
|
||||
|
||||
/* 1 if we are completing in a quoted string (or inside `...`) */
|
||||
|
||||
/**/
|
||||
|
@ -1364,9 +1368,15 @@ get_comp_string(void)
|
|||
zsfree(varname);
|
||||
varname = ztrdup(tt);
|
||||
*s = sav;
|
||||
if (skipparens(Inbrack, Outbrack, &s) > 0 || s > tt + cs - wb)
|
||||
s = NULL, inwhat = IN_MATH, insubscr = 1;
|
||||
else if (*s == '=' && cs > wb + (s - tt)) {
|
||||
if (skipparens(Inbrack, Outbrack, &s) > 0 || s > tt + cs - wb) {
|
||||
s = NULL;
|
||||
inwhat = IN_MATH;
|
||||
if ((keypm = (Param) paramtab->getnode(paramtab, varname)) &&
|
||||
(keypm->flags & PM_HASHED))
|
||||
insubscr = 2;
|
||||
else
|
||||
insubscr = 1;
|
||||
} else if (*s == '=' && cs > wb + (s - tt)) {
|
||||
s++;
|
||||
wb += s - tt;
|
||||
t0 = STRING;
|
||||
|
@ -1424,11 +1434,15 @@ get_comp_string(void)
|
|||
zsfree(varname);
|
||||
varname = ztrdup(nb);
|
||||
*ne = sav;
|
||||
if ((keypm = (Param) paramtab->getnode(paramtab,
|
||||
varname)) &&
|
||||
(keypm->flags & PM_HASHED))
|
||||
insubscr = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inwhat == IN_MATH) {
|
||||
if (compfunc) {
|
||||
if (compfunc || insubscr == 2) {
|
||||
int lev;
|
||||
char *p;
|
||||
|
||||
|
@ -1472,7 +1486,11 @@ get_comp_string(void)
|
|||
zsfree(varname);
|
||||
varname = ztrdup((char *) line + i + 1);
|
||||
line[wb - 1] = sav;
|
||||
insubscr = 1;
|
||||
if ((keypm = (Param) paramtab->getnode(paramtab, varname)) &&
|
||||
(keypm->flags & PM_HASHED))
|
||||
insubscr = 2;
|
||||
else
|
||||
insubscr = 1;
|
||||
}
|
||||
}
|
||||
/* This variable will hold the current word in quoted form. */
|
||||
|
@ -3524,7 +3542,7 @@ int
|
|||
addmatches(Cadata dat, char **argv)
|
||||
{
|
||||
char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL;
|
||||
char **aign = NULL, **dparr;
|
||||
char **aign = NULL, **dparr = NULL;
|
||||
int lpl, lsl, pl, sl, bpl, bsl, llpl = 0, llsl = 0, nm = mnum;
|
||||
int oisalt = 0, isalt, isexact, doadd;
|
||||
Cline lc = NULL;
|
||||
|
@ -4360,7 +4378,7 @@ callcompfunc(char *s, char *fn)
|
|||
|
||||
PERMALLOC {
|
||||
q = compwords = (char **)
|
||||
zalloc((clwnum - aadd + 1) * sizeof(char *));
|
||||
zalloc((clwnum + 1) * sizeof(char *));
|
||||
for (p = clwords + aadd; *p; p++, q++) {
|
||||
tmp = dupstring(*p);
|
||||
untokenize(tmp);
|
||||
|
@ -4829,13 +4847,22 @@ makecomplistglobal(char *os, int incmd, int lst, int flags)
|
|||
char *s;
|
||||
|
||||
ccont = CC_CCCONT;
|
||||
cc_dummy.suffix = NULL;
|
||||
|
||||
if (linwhat == IN_ENV) {
|
||||
/* Default completion for parameter values. */
|
||||
cc = &cc_default;
|
||||
keypm = NULL;
|
||||
} else if (linwhat == IN_MATH) {
|
||||
/* Parameter names inside mathematical expression. */
|
||||
cc_dummy.mask = CC_PARAMS;
|
||||
if (insubscr == 2) {
|
||||
/* Inside subscript of assoc array, complete keys. */
|
||||
cc_dummy.mask = 0;
|
||||
cc_dummy.suffix = "]";
|
||||
} else {
|
||||
/* Other math environment, complete paramete names. */
|
||||
keypm = NULL;
|
||||
cc_dummy.mask = CC_PARAMS;
|
||||
}
|
||||
cc = &cc_dummy;
|
||||
cc_dummy.refc = 10000;
|
||||
} else if (linwhat == IN_COND) {
|
||||
|
@ -4851,13 +4878,16 @@ makecomplistglobal(char *os, int incmd, int lst, int flags)
|
|||
(CC_FILES | CC_PARAMS);
|
||||
cc = &cc_dummy;
|
||||
cc_dummy.refc = 10000;
|
||||
} else if (linredir)
|
||||
keypm = NULL;
|
||||
} else if (linredir) {
|
||||
/* In redirections use default completion. */
|
||||
cc = &cc_default;
|
||||
else
|
||||
keypm = NULL;
|
||||
} else {
|
||||
/* Otherwise get the matches for the command. */
|
||||
keypm = NULL;
|
||||
return makecomplistcmd(os, incmd, flags);
|
||||
|
||||
}
|
||||
if (cc) {
|
||||
/* First, use the -T compctl. */
|
||||
if (!(flags & CFN_FIRST)) {
|
||||
|
@ -5917,7 +5947,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
Comp compc = NULL;
|
||||
char *e, *h, hpatsav;
|
||||
Histent he;
|
||||
int i = curhist - 1, n = cc->hnum;
|
||||
int i = addhistnum(curhist,-1,HIST_FOREIGN), n = cc->hnum;
|
||||
|
||||
/* Parse the pattern, if it isn't the null string. */
|
||||
if (*(cc->hpat)) {
|
||||
|
@ -5971,7 +6001,12 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|||
if ((t = cc->mask & (CC_ALREG | CC_ALGLOB)))
|
||||
/* Add the two types of aliases. */
|
||||
dumphashtable(aliastab, t | (cc->mask & (CC_DISCMDS|CC_EXCMDS)));
|
||||
|
||||
if (keypm && cc == &cc_dummy) {
|
||||
/* Add the keys of the parameter in keypm. */
|
||||
scanhashtable(keypm->gets.hfn(keypm), 0, 0, PM_UNSET, addhnmatch, 0);
|
||||
keypm = NULL;
|
||||
cc_dummy.suffix = NULL;
|
||||
}
|
||||
if (!errflag && cc->ylist) {
|
||||
/* generate the user-defined display list: if anything fails, *
|
||||
* we silently allow the normal completion list to be used. */
|
||||
|
|
|
@ -572,10 +572,8 @@ undo(void)
|
|||
static void
|
||||
unapplychange(struct change *ch)
|
||||
{
|
||||
if(ch->hist != histline) {
|
||||
remember_edits();
|
||||
setline(zle_get_event(histline = ch->hist));
|
||||
}
|
||||
if(ch->hist != histline)
|
||||
zle_setline(quietgethist(ch->hist));
|
||||
cs = ch->off;
|
||||
if(ch->ins)
|
||||
foredel(ztrlen(ch->ins));
|
||||
|
@ -613,10 +611,8 @@ redo(void)
|
|||
static void
|
||||
applychange(struct change *ch)
|
||||
{
|
||||
if(ch->hist != histline) {
|
||||
remember_edits();
|
||||
setline(zle_get_event(histline = ch->hist));
|
||||
}
|
||||
if(ch->hist != histline)
|
||||
zle_setline(quietgethist(ch->hist));
|
||||
cs = ch->off;
|
||||
if(ch->del)
|
||||
foredel(ztrlen(ch->del));
|
||||
|
|
|
@ -120,7 +120,7 @@ static struct builtin builtins[] =
|
|||
BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"),
|
||||
|
||||
#ifdef DYNAMIC
|
||||
BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "LaudicIp", NULL),
|
||||
BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "ILabcdipu", NULL),
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -142,6 +142,7 @@ createbuiltintable(void)
|
|||
builtintab->hash = hasher;
|
||||
builtintab->emptytable = NULL;
|
||||
builtintab->filltable = NULL;
|
||||
builtintab->cmpnodes = strcmp;
|
||||
builtintab->addnode = addhashnode;
|
||||
builtintab->getnode = gethashnode;
|
||||
builtintab->getnode2 = gethashnode2;
|
||||
|
@ -1146,19 +1147,17 @@ bin_fc(char *nam, char **argv, char *ops, int func)
|
|||
}
|
||||
if (ops['R']) {
|
||||
/* read history from a file */
|
||||
readhistfile(*argv ? *argv : getsparam("HISTFILE"), 1);
|
||||
readhistfile(*argv, 1, ops['I'] ? HFILE_SKIPOLD : 0);
|
||||
return 0;
|
||||
}
|
||||
if (ops['W']) {
|
||||
/* write history to a file */
|
||||
savehistfile(*argv ? *argv : getsparam("HISTFILE"), 1,
|
||||
(ops['I'] ? 2 : 0));
|
||||
savehistfile(*argv, 1, ops['I'] ? HFILE_SKIPOLD : 0);
|
||||
return 0;
|
||||
}
|
||||
if (ops['A']) {
|
||||
/* append history to a file */
|
||||
savehistfile(*argv ? *argv : getsparam("HISTFILE"), 1,
|
||||
(ops['I'] ? 3 : 1));
|
||||
savehistfile(*argv, 1, HFILE_APPEND | (ops['I'] ? HFILE_SKIPOLD : 0));
|
||||
return 0;
|
||||
}
|
||||
if (!(ops['l'] && unset(HISTNOSTORE)))
|
||||
|
@ -1200,9 +1199,9 @@ bin_fc(char *nam, char **argv, char *ops, int func)
|
|||
}
|
||||
/* default values of first and last, and range checking */
|
||||
if (first == -1)
|
||||
first = (ops['l']) ? curhist - 16 : curhist - 1;
|
||||
first = ops['l']? addhistnum(curhist,-16,0) : addhistnum(curhist,-1,0);
|
||||
if (last == -1)
|
||||
last = (ops['l']) ? curhist - 1 : first;
|
||||
last = ops['l']? addhistnum(curhist,-1,0) : first;
|
||||
if (first < firsthist())
|
||||
first = firsthist();
|
||||
if (last == -1)
|
||||
|
@ -1267,7 +1266,7 @@ fcgetcomm(char *s)
|
|||
* numbers indicate reversed numbering. */
|
||||
if ((cmd = atoi(s))) {
|
||||
if (cmd < 0)
|
||||
cmd = curhist + cmd;
|
||||
cmd = addhistnum(curhist,cmd,HIST_FOREIGN);
|
||||
if (cmd >= curhist) {
|
||||
zwarnnam("fc", "bad history number: %d", 0, cmd);
|
||||
return -1;
|
||||
|
@ -1331,7 +1330,7 @@ static int
|
|||
fclist(FILE *f, int n, int r, int D, int d, int first, int last, struct asgment *subs, Comp com)
|
||||
{
|
||||
int fclistdone = 0;
|
||||
char *s, *hs;
|
||||
char *s;
|
||||
Histent ent;
|
||||
|
||||
/* reverse range if required */
|
||||
|
@ -1344,28 +1343,31 @@ fclist(FILE *f, int n, int r, int D, int d, int first, int last, struct asgment
|
|||
if (!subs)
|
||||
fclistdone = 1;
|
||||
|
||||
for (;;) {
|
||||
hs = quietgetevent(first);
|
||||
if (!hs) {
|
||||
ent = gethistent(first, first < last? GETHIST_DOWNWARD : GETHIST_UPWARD);
|
||||
if (!ent || ent->histnum < first || ent->histnum > last) {
|
||||
if (first == last)
|
||||
zwarnnam("fc", "no such event: %d", NULL, first);
|
||||
return 1;
|
||||
}
|
||||
s = dupstring(hs);
|
||||
else
|
||||
zwarnnam("fc", "no events in that range", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
s = dupstring(ent->text);
|
||||
/* this if does the pattern matching, if required */
|
||||
if (!com || domatch(s, com, 0)) {
|
||||
/* perform substitution */
|
||||
fclistdone |= fcsubs(&s, subs);
|
||||
|
||||
/* do numbering */
|
||||
if (n)
|
||||
fprintf(f, "%5d ", first);
|
||||
ent = NULL;
|
||||
if (n) {
|
||||
fprintf(f, "%5d%c ", ent->histnum,
|
||||
ent->flags & HIST_FOREIGN? '*' : ' ');
|
||||
}
|
||||
/* output actual time (and possibly date) of execution of the
|
||||
command, if required */
|
||||
if (d) {
|
||||
struct tm *ltm;
|
||||
if (!ent)
|
||||
ent = gethistent(first);
|
||||
ltm = localtime(&ent->stim);
|
||||
if (d >= 2) {
|
||||
if (d >= 8) {
|
||||
|
@ -1387,8 +1389,6 @@ fclist(FILE *f, int n, int r, int D, int d, int first, int last, struct asgment
|
|||
/* display the time taken by the command, if required */
|
||||
if (D) {
|
||||
long diff;
|
||||
if (!ent)
|
||||
ent = gethistent(first);
|
||||
diff = (ent->ftim) ? ent->ftim - ent->stim : 0;
|
||||
fprintf(f, "%ld:%02ld ", diff / 60, diff % 60);
|
||||
}
|
||||
|
@ -1401,12 +1401,14 @@ fclist(FILE *f, int n, int r, int D, int d, int first, int last, struct asgment
|
|||
fprintf(f, "%s\n", s);
|
||||
}
|
||||
/* move on to the next history line, or quit the loop */
|
||||
if (first == last)
|
||||
break;
|
||||
else if (first > last)
|
||||
first--;
|
||||
else
|
||||
first++;
|
||||
if (first < last) {
|
||||
if (!(ent = down_histent(ent)) || ent->histnum > last)
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (!(ent = up_histent(ent)) || ent->histnum < last)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* final processing */
|
||||
|
@ -1768,7 +1770,8 @@ bin_typeset(char *name, char **argv, char *ops, int func)
|
|||
for (i = 0; i < paramtab->hsize; i++) {
|
||||
for (pm = (Param) paramtab->nodes[i]; pm;
|
||||
pm = (Param) pm->next) {
|
||||
if ((pm->flags & PM_RESTRICTED) && isset(RESTRICTED))
|
||||
if (((pm->flags & PM_RESTRICTED) && isset(RESTRICTED)) ||
|
||||
(pm->flags & PM_UNSET))
|
||||
continue;
|
||||
if (domatch(pm->nam, com, 0))
|
||||
addlinknode(pmlist, pm);
|
||||
|
@ -2523,10 +2526,7 @@ bin_print(char *name, char **args, char *ops, int func)
|
|||
char **pargs = args;
|
||||
|
||||
PERMALLOC {
|
||||
ent = gethistent(++curhist);
|
||||
zsfree(ent->text);
|
||||
if (ent->nwords)
|
||||
zfree(ent->words, ent->nwords*2*sizeof(short));
|
||||
ent = prepnexthistent(++curhist);
|
||||
while (*pargs++)
|
||||
nwords++;
|
||||
if ((ent->nwords = nwords)) {
|
||||
|
@ -2543,6 +2543,7 @@ bin_print(char *name, char **args, char *ops, int func)
|
|||
ent->text = zjoin(args, ' ');
|
||||
ent->stim = ent->ftim = time(NULL);
|
||||
ent->flags = 0;
|
||||
addhistnode(histtab, ent->text, ent);
|
||||
} LASTALLOC;
|
||||
return 0;
|
||||
}
|
||||
|
@ -2952,7 +2953,7 @@ zexit(int val, int from_signal)
|
|||
killrunjobs(from_signal);
|
||||
if (isset(RCS) && interact) {
|
||||
if (!nohistsave)
|
||||
savehistfile(getsparam("HISTFILE"), 1, isset(APPENDHISTORY) ? 3 : 0);
|
||||
savehistfile(NULL, 1, HFILE_USE_OPTIONS);
|
||||
if (islogin && !subsh) {
|
||||
sourcehome(".zlogout");
|
||||
#ifdef GLOBAL_ZLOGOUT
|
||||
|
|
|
@ -1862,7 +1862,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
|
|||
/* If we are exec'ing a command, and we are not in a subshell, *
|
||||
* then check if we should save the history file. */
|
||||
if (isset(RCS) && interact && !nohistsave)
|
||||
savehistfile(getsparam("HISTFILE"), 1, isset(APPENDHISTORY) ? 3 : 0);
|
||||
savehistfile(NULL, 1, HFILE_USE_OPTIONS);
|
||||
exit(lastval);
|
||||
}
|
||||
|
||||
|
@ -1874,7 +1874,7 @@ execcmd(Cmd cmd, int input, int output, int how, int last1)
|
|||
/* If we are exec'ing a command, and we are not *
|
||||
* in a subshell, then save the history file. */
|
||||
if (!subsh && isset(RCS) && interact && !nohistsave)
|
||||
savehistfile(getsparam("HISTFILE"), 1, isset(APPENDHISTORY) ? 3 : 0);
|
||||
savehistfile(NULL, 1, HFILE_USE_OPTIONS);
|
||||
}
|
||||
if (type == SIMPLE) {
|
||||
if (cmd->vars) {
|
||||
|
@ -2232,7 +2232,7 @@ getoutput(char *cmd, int qt)
|
|||
zclose(pipes[1]);
|
||||
retval = readoutput(pipes[0], qt);
|
||||
fdtable[pipes[0]] = 0;
|
||||
child_suspend(0); /* unblocks */
|
||||
waitforpid(pid); /* unblocks */
|
||||
lastval = cmdoutval;
|
||||
return retval;
|
||||
}
|
||||
|
|
176
Src/hashtable.c
176
Src/hashtable.c
|
@ -83,7 +83,7 @@ hasher(char *str)
|
|||
unsigned hashval = 0;
|
||||
|
||||
while (*str)
|
||||
hashval += (hashval << 5) + ((unsigned) *str++);
|
||||
hashval += (hashval << 5) + *(unsigned char *)str++;
|
||||
|
||||
return hashval;
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ deletehashtable(HashTable ht)
|
|||
}
|
||||
|
||||
/* Add a node to a hash table. *
|
||||
* nam is the key to use in hashing. dat is a pointer *
|
||||
* nam is the key to use in hashing. nodeptr points *
|
||||
* to the node to add. If there is already a node in *
|
||||
* the table with the same key, it is first freed, and *
|
||||
* then the new node is added. If the number of nodes *
|
||||
|
@ -148,6 +148,17 @@ deletehashtable(HashTable ht)
|
|||
/**/
|
||||
void
|
||||
addhashnode(HashTable ht, char *nam, void *nodeptr)
|
||||
{
|
||||
HashNode oldnode = addhashnode2(ht, nam, nodeptr);
|
||||
if (oldnode)
|
||||
ht->freenode(oldnode);
|
||||
}
|
||||
|
||||
/* Add a node to a hash table, returning the old node on replacment. */
|
||||
|
||||
/**/
|
||||
HashNode
|
||||
addhashnode2(HashTable ht, char *nam, void *nodeptr)
|
||||
{
|
||||
unsigned hashval;
|
||||
HashNode hn, hp, hq;
|
||||
|
@ -164,11 +175,11 @@ addhashnode(HashTable ht, char *nam, void *nodeptr)
|
|||
ht->nodes[hashval] = hn;
|
||||
if (++ht->ct >= ht->hsize * 2 && !ht->scan)
|
||||
expandhashtable(ht);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* else check if the first node contains the same key */
|
||||
if (!strcmp(hp->nam, hn->nam)) {
|
||||
if (ht->cmpnodes(hp->nam, hn->nam) == 0) {
|
||||
ht->nodes[hashval] = hn;
|
||||
replacing:
|
||||
hn->next = hp->next;
|
||||
|
@ -182,15 +193,14 @@ addhashnode(HashTable ht, char *nam, void *nodeptr)
|
|||
} else if(ht->scan->u.u == hp)
|
||||
ht->scan->u.u = hn;
|
||||
}
|
||||
ht->freenode(hp);
|
||||
return;
|
||||
return hp;
|
||||
}
|
||||
|
||||
/* else run through the list and check all the keys */
|
||||
hq = hp;
|
||||
hp = hp->next;
|
||||
for (; hp; hq = hp, hp = hp->next) {
|
||||
if (!strcmp(hp->nam, hn->nam)) {
|
||||
if (ht->cmpnodes(hp->nam, hn->nam) == 0) {
|
||||
hq->next = hn;
|
||||
goto replacing;
|
||||
}
|
||||
|
@ -201,6 +211,7 @@ addhashnode(HashTable ht, char *nam, void *nodeptr)
|
|||
ht->nodes[hashval] = hn;
|
||||
if (++ht->ct >= ht->hsize * 2 && !ht->scan)
|
||||
expandhashtable(ht);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get an enabled entry in a hash table. *
|
||||
|
@ -217,7 +228,7 @@ gethashnode(HashTable ht, char *nam)
|
|||
|
||||
hashval = ht->hash(nam) % ht->hsize;
|
||||
for (hp = ht->nodes[hashval]; hp; hp = hp->next) {
|
||||
if (!strcmp(hp->nam, nam)) {
|
||||
if (ht->cmpnodes(hp->nam, nam) == 0) {
|
||||
if (hp->flags & DISABLED)
|
||||
return NULL;
|
||||
else
|
||||
|
@ -241,7 +252,7 @@ gethashnode2(HashTable ht, char *nam)
|
|||
|
||||
hashval = ht->hash(nam) % ht->hsize;
|
||||
for (hp = ht->nodes[hashval]; hp; hp = hp->next) {
|
||||
if (!strcmp(hp->nam, nam))
|
||||
if (ht->cmpnodes(hp->nam, nam) == 0)
|
||||
return hp;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -267,7 +278,7 @@ removehashnode(HashTable ht, char *nam)
|
|||
return NULL;
|
||||
|
||||
/* else check if the key in the first one matches */
|
||||
if (!strcmp(hp->nam, nam)) {
|
||||
if (ht->cmpnodes(hp->nam, nam) == 0) {
|
||||
ht->nodes[hashval] = hp->next;
|
||||
gotit:
|
||||
ht->ct--;
|
||||
|
@ -288,7 +299,7 @@ removehashnode(HashTable ht, char *nam)
|
|||
hq = hp;
|
||||
hp = hp->next;
|
||||
for (; hp; hq = hp, hp = hp->next) {
|
||||
if (!strcmp(hp->nam, nam)) {
|
||||
if (ht->cmpnodes(hp->nam, nam) == 0) {
|
||||
hq->next = hp->next;
|
||||
goto gotit;
|
||||
}
|
||||
|
@ -316,7 +327,7 @@ enablehashnode(HashNode hn, int flags)
|
|||
hn->flags &= ~DISABLED;
|
||||
}
|
||||
|
||||
/* Compare two hash table entries */
|
||||
/* Compare two hash table entries by name */
|
||||
|
||||
/**/
|
||||
static int
|
||||
|
@ -498,6 +509,7 @@ emptyhashtable(HashTable ht)
|
|||
resizehashtable(ht, ht->hsize);
|
||||
}
|
||||
|
||||
/**/
|
||||
#ifdef ZSH_HASH_DEBUG
|
||||
|
||||
/* Print info about hash table */
|
||||
|
@ -550,6 +562,7 @@ bin_hashinfo(char *nam, char **args, char *ops, int func)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif /* ZSH_HASH_DEBUG */
|
||||
|
||||
/********************************/
|
||||
|
@ -577,6 +590,7 @@ createcmdnamtable(void)
|
|||
cmdnamtab->hash = hasher;
|
||||
cmdnamtab->emptytable = emptycmdnamtable;
|
||||
cmdnamtab->filltable = fillcmdnamtable;
|
||||
cmdnamtab->cmpnodes = strcmp;
|
||||
cmdnamtab->addnode = addhashnode;
|
||||
cmdnamtab->getnode = gethashnode2;
|
||||
cmdnamtab->getnode2 = gethashnode2;
|
||||
|
@ -747,6 +761,7 @@ createshfunctable(void)
|
|||
shfunctab->hash = hasher;
|
||||
shfunctab->emptytable = NULL;
|
||||
shfunctab->filltable = NULL;
|
||||
shfunctab->cmpnodes = strcmp;
|
||||
shfunctab->addnode = addhashnode;
|
||||
shfunctab->getnode = gethashnode;
|
||||
shfunctab->getnode2 = gethashnode2;
|
||||
|
@ -920,6 +935,7 @@ createreswdtable(void)
|
|||
reswdtab->hash = hasher;
|
||||
reswdtab->emptytable = NULL;
|
||||
reswdtab->filltable = NULL;
|
||||
reswdtab->cmpnodes = strcmp;
|
||||
reswdtab->addnode = addhashnode;
|
||||
reswdtab->getnode = gethashnode;
|
||||
reswdtab->getnode2 = gethashnode2;
|
||||
|
@ -980,6 +996,7 @@ createaliastable(void)
|
|||
aliastab->hash = hasher;
|
||||
aliastab->emptytable = NULL;
|
||||
aliastab->filltable = NULL;
|
||||
aliastab->cmpnodes = strcmp;
|
||||
aliastab->addnode = addhashnode;
|
||||
aliastab->getnode = gethashnode;
|
||||
aliastab->getnode2 = gethashnode2;
|
||||
|
@ -1109,6 +1126,7 @@ createnameddirtable(void)
|
|||
nameddirtab->hash = hasher;
|
||||
nameddirtab->emptytable = emptynameddirtable;
|
||||
nameddirtab->filltable = fillnameddirtable;
|
||||
nameddirtab->cmpnodes = strcmp;
|
||||
nameddirtab->addnode = addnameddirnode;
|
||||
nameddirtab->getnode = gethashnode;
|
||||
nameddirtab->getnode2 = gethashnode2;
|
||||
|
@ -1219,3 +1237,137 @@ printnameddirnode(HashNode hn, int printflags)
|
|||
quotedzputs(nd->dir, stdout);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/*************************************/
|
||||
/* History Line Hash Table Functions */
|
||||
/*************************************/
|
||||
|
||||
/**/
|
||||
void
|
||||
createhisttable(void)
|
||||
{
|
||||
histtab = newhashtable(599, "histtab", NULL);
|
||||
|
||||
histtab->hash = histhasher;
|
||||
histtab->emptytable = emptyhisttable;
|
||||
histtab->filltable = NULL;
|
||||
histtab->cmpnodes = histstrcmp;
|
||||
histtab->addnode = addhistnode;
|
||||
histtab->getnode = gethashnode2;
|
||||
histtab->getnode2 = gethashnode2;
|
||||
histtab->removenode = removehashnode;
|
||||
histtab->disablenode = NULL;
|
||||
histtab->enablenode = NULL;
|
||||
histtab->freenode = freehistnode;
|
||||
histtab->printnode = NULL;
|
||||
}
|
||||
|
||||
/**/
|
||||
unsigned
|
||||
histhasher(char *str)
|
||||
{
|
||||
unsigned hashval = 0;
|
||||
|
||||
while (inblank(*str)) str++;
|
||||
|
||||
while (*str) {
|
||||
if (inblank(*str)) {
|
||||
do str++; while (inblank(*str));
|
||||
if (*str)
|
||||
hashval += (hashval << 5) + ' ';
|
||||
}
|
||||
else
|
||||
hashval += (hashval << 5) + *(unsigned char *)str++;
|
||||
}
|
||||
return hashval;
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
emptyhisttable(HashTable ht)
|
||||
{
|
||||
emptyhashtable(ht);
|
||||
if (hist_ring)
|
||||
histremovedups();
|
||||
}
|
||||
|
||||
/* Compare two strings with normalized white-space */
|
||||
|
||||
/**/
|
||||
int
|
||||
histstrcmp(const char *str1, const char *str2)
|
||||
{
|
||||
while (inblank(*str1)) str1++;
|
||||
while (inblank(*str2)) str2++;
|
||||
while (*str1 && *str2) {
|
||||
if (inblank(*str1)) {
|
||||
if (!inblank(*str2))
|
||||
break;
|
||||
do str1++; while (inblank(*str1));
|
||||
do str2++; while (inblank(*str2));
|
||||
}
|
||||
else {
|
||||
if (*str1 != *str2)
|
||||
break;
|
||||
str1++;
|
||||
str2++;
|
||||
}
|
||||
}
|
||||
return *str1 - *str2;
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
addhistnode(HashTable ht, char *nam, void *nodeptr)
|
||||
{
|
||||
HashNode oldnode = addhashnode2(ht, nam, nodeptr);
|
||||
Histent he = (Histent)nodeptr;
|
||||
if (oldnode && oldnode != nodeptr) {
|
||||
if (he->flags & HIST_MAKEUNIQUE
|
||||
|| (he->flags & HIST_FOREIGN && (Histent)oldnode == he->up)) {
|
||||
he->flags |= HIST_DUP;
|
||||
addhashnode(ht, oldnode->nam, oldnode); /* Remove the new dup */
|
||||
}
|
||||
else {
|
||||
oldnode->flags |= HIST_DUP;
|
||||
if (hist_ignore_all_dups)
|
||||
freehistnode(oldnode); /* Remove the old dup */
|
||||
}
|
||||
}
|
||||
else
|
||||
he->flags &= ~HIST_MAKEUNIQUE;
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
freehistnode(HashNode nodeptr)
|
||||
{
|
||||
freehistdata((Histent)nodeptr, 1);
|
||||
zfree(nodeptr, sizeof (struct histent));
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
freehistdata(Histent he, int unlink)
|
||||
{
|
||||
if (!he)
|
||||
return;
|
||||
|
||||
if (!(he->flags & HIST_DUP))
|
||||
removehashnode(histtab, he->text);
|
||||
|
||||
zsfree(he->text);
|
||||
if (he->nwords)
|
||||
zfree(he->words, he->nwords*2*sizeof(short));
|
||||
|
||||
if (unlink) {
|
||||
if (!--histlinect)
|
||||
hist_ring = NULL;
|
||||
else {
|
||||
if (he == hist_ring)
|
||||
hist_ring = hist_ring->up;
|
||||
he->up->down = he->down;
|
||||
he->down->up = he->up;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
743
Src/hist.c
743
Src/hist.c
|
@ -56,23 +56,29 @@ int excs, exlast;
|
|||
* Note on curhist: with history inactive, this points to the
|
||||
* last line actually added to the history list. With history active,
|
||||
* the line does not get added to the list until hend(), if at all.
|
||||
* However, curhist is incremented to reflect the current line anyway.
|
||||
* Thus if the line is not added to the list, curhist must be
|
||||
* However, curhist is incremented to reflect the current line anyway
|
||||
* and a temporary history entry is inserted while the user is editing.
|
||||
* If the resulting line was not added to the list, curhist is
|
||||
* decremented in hend().
|
||||
*/
|
||||
|
||||
/**/
|
||||
int curhist;
|
||||
|
||||
/* number of history entries */
|
||||
|
||||
/**/
|
||||
int histentct;
|
||||
|
||||
/* array of history entries */
|
||||
|
||||
struct histent curline;
|
||||
|
||||
/* current line count of allocated history entries */
|
||||
|
||||
/**/
|
||||
Histent histentarr;
|
||||
int histlinect;
|
||||
|
||||
/* The history lines are kept in a hash, and also doubly-linked in a ring */
|
||||
|
||||
/**/
|
||||
HashTable histtab;
|
||||
/**/
|
||||
Histent hist_ring;
|
||||
|
||||
/* capacity of history lists */
|
||||
|
||||
|
@ -90,6 +96,17 @@ int histdone;
|
|||
/**/
|
||||
int histactive;
|
||||
|
||||
/* Current setting of the associated option, but sometimes also includes
|
||||
* the setting of the HIST_SAVE_NO_DUPS option. */
|
||||
|
||||
/**/
|
||||
int hist_ignore_all_dups;
|
||||
|
||||
/* What flags (if any) we should skip when moving through the history */
|
||||
|
||||
/**/
|
||||
int hist_skip_flags;
|
||||
|
||||
/* Bits of histactive variable */
|
||||
#define HA_ACTIVE (1<<0) /* History mechanism is active */
|
||||
#define HA_NOSTORE (1<<1) /* Don't store the line when finished */
|
||||
|
@ -395,7 +412,7 @@ histsubchar(int c)
|
|||
if (!*buf) {
|
||||
if (c != '%') {
|
||||
if (isset(CSHJUNKIEHISTORY))
|
||||
ev = curhist - 1;
|
||||
ev = addhistnum(curhist,-1,HIST_FOREIGN);
|
||||
else
|
||||
ev = defev;
|
||||
if (c == ':' && evset == -1)
|
||||
|
@ -410,10 +427,10 @@ histsubchar(int c)
|
|||
evset = 0;
|
||||
}
|
||||
} else if ((t0 = atoi(buf))) {
|
||||
ev = (t0 < 0) ? curhist + t0 : t0;
|
||||
ev = (t0 < 0) ? addhistnum(curhist,t0,HIST_FOREIGN) : t0;
|
||||
evset = 1;
|
||||
} else if ((unsigned)*buf == bangchar) {
|
||||
ev = curhist - 1;
|
||||
ev = addhistnum(curhist,-1,HIST_FOREIGN);
|
||||
evset = 1;
|
||||
} else if (*buf == '#') {
|
||||
ev = curhist;
|
||||
|
@ -650,8 +667,6 @@ strinend(void)
|
|||
void
|
||||
hbegin(void)
|
||||
{
|
||||
Histent curhistent;
|
||||
|
||||
isfirstln = isfirstch = 1;
|
||||
errflag = histdone = spaceflag = 0;
|
||||
stophist = (!interact || unset(BANGHIST) || unset(SHINSTDIN)) << 1;
|
||||
|
@ -661,43 +676,23 @@ hbegin(void)
|
|||
|
||||
if (histactive & HA_JUNKED)
|
||||
curhist--;
|
||||
curhistent = gethistent(curhist);
|
||||
if (!curhistent->ftim)
|
||||
curhistent->ftim = time(NULL);
|
||||
histactive = HA_ACTIVE;
|
||||
if (hist_ring && !hist_ring->ftim)
|
||||
hist_ring->ftim = time(NULL);
|
||||
if (interact && isset(SHINSTDIN) && !strin) {
|
||||
histactive = HA_ACTIVE;
|
||||
attachtty(mypgrp);
|
||||
defev = curhist;
|
||||
curhist++;
|
||||
if (!hist_ring)
|
||||
hist_ring = curline.up = curline.down = &curline;
|
||||
else {
|
||||
curline.up = hist_ring;
|
||||
curline.down = hist_ring->down;
|
||||
hist_ring->down = hist_ring->down->up = &curline;
|
||||
hist_ring = &curline;
|
||||
}
|
||||
curline.histnum = ++curhist;
|
||||
defev = addhistnum(curhist, -1, HIST_FOREIGN);
|
||||
} else
|
||||
histactive |= HA_NOINC;
|
||||
}
|
||||
|
||||
/* compare current line with history entry using only text in words */
|
||||
|
||||
/**/
|
||||
static int
|
||||
histcmp(Histent he)
|
||||
{
|
||||
int kword, lword;
|
||||
int nwords = chwordpos/2;
|
||||
|
||||
/* If the history entry came from a file, the words were not
|
||||
* divided by the lexer so we have to resort to strcmp.
|
||||
*/
|
||||
if (he->flags & HIST_READ)
|
||||
return strcmp(he->text, chline);
|
||||
|
||||
if (nwords != he->nwords)
|
||||
return 1;
|
||||
|
||||
for (kword = 0; kword < 2*nwords; kword += 2)
|
||||
if ((lword = chwords[kword+1]-chwords[kword])
|
||||
!= he->words[kword+1]-he->words[kword] ||
|
||||
memcmp(he->text+he->words[kword], chline+chwords[kword], lword))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
histactive = HA_ACTIVE | HA_NOINC;
|
||||
}
|
||||
|
||||
/**/
|
||||
|
@ -726,6 +721,140 @@ histreduceblanks(void)
|
|||
chline[pos] = '\0';
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
histremovedups(void)
|
||||
{
|
||||
Histent he, next;
|
||||
for (he = hist_ring; he; he = next) {
|
||||
next = up_histent(he);
|
||||
if (he->flags & HIST_DUP)
|
||||
freehistnode((HashNode)he);
|
||||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
int
|
||||
addhistnum(int hl, int n, int xflags)
|
||||
{
|
||||
int dir = n < 0? -1 : n > 0? 1 : 0;
|
||||
Histent he = gethistent(hl, dir);
|
||||
|
||||
if (!he)
|
||||
return 0;
|
||||
if (he->histnum != hl)
|
||||
n -= dir;
|
||||
if (n)
|
||||
he = movehistent(he, n, xflags);
|
||||
if (!he)
|
||||
return dir < 0? firsthist() : curhist;
|
||||
return he->histnum;
|
||||
}
|
||||
|
||||
/**/
|
||||
Histent
|
||||
movehistent(Histent he, int n, int xflags)
|
||||
{
|
||||
while (n < 0) {
|
||||
if (!(he = up_histent(he)))
|
||||
return NULL;
|
||||
if (!(he->flags & xflags))
|
||||
n++;
|
||||
}
|
||||
while (n > 0) {
|
||||
if (!(he = down_histent(he)))
|
||||
return NULL;
|
||||
if (!(he->flags & xflags))
|
||||
n--;
|
||||
}
|
||||
return he;
|
||||
}
|
||||
|
||||
/**/
|
||||
Histent
|
||||
up_histent(Histent he)
|
||||
{
|
||||
return he->up == hist_ring? NULL : he->up;
|
||||
}
|
||||
|
||||
/**/
|
||||
Histent
|
||||
down_histent(Histent he)
|
||||
{
|
||||
return he == hist_ring? NULL : he->down;
|
||||
}
|
||||
|
||||
/**/
|
||||
Histent
|
||||
gethistent(int ev, int nearmatch)
|
||||
{
|
||||
Histent he;
|
||||
|
||||
if (!hist_ring)
|
||||
return NULL;
|
||||
|
||||
if (ev - hist_ring->down->histnum < hist_ring->histnum - ev) {
|
||||
for (he = hist_ring->down; he->histnum <= ev; he = he->down) {
|
||||
if (he->histnum == ev)
|
||||
return he;
|
||||
}
|
||||
if (nearmatch < 0)
|
||||
return up_histent(he);
|
||||
if (nearmatch > 0)
|
||||
return he;
|
||||
}
|
||||
else {
|
||||
for (he = hist_ring; he->histnum >= ev; he = he->up) {
|
||||
if (he->histnum == ev)
|
||||
return he;
|
||||
}
|
||||
if (nearmatch < 0)
|
||||
return he;
|
||||
if (nearmatch > 0)
|
||||
return down_histent(he);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**/
|
||||
Histent
|
||||
prepnexthistent(int histnum)
|
||||
{
|
||||
Histent he;
|
||||
|
||||
if (histlinect < histsiz) {
|
||||
he = (Histent)zcalloc(sizeof *he);
|
||||
if (!hist_ring)
|
||||
hist_ring = he->up = he->down = he;
|
||||
else {
|
||||
he->up = hist_ring;
|
||||
he->down = hist_ring->down;
|
||||
hist_ring->down = he->down->up = he;
|
||||
hist_ring = he;
|
||||
}
|
||||
histlinect++;
|
||||
}
|
||||
else {
|
||||
he = hist_ring->down;
|
||||
if (isset(HISTEXPIREDUPSFIRST) && !(he->flags & HIST_DUP)) {
|
||||
do {
|
||||
he = he->down;
|
||||
} while (he != hist_ring->down && !(he->flags & HIST_DUP)) ;
|
||||
if (he != hist_ring->down) {
|
||||
he->up->down = he->down;
|
||||
he->down->up = he->up;
|
||||
he->up = hist_ring;
|
||||
he->down = hist_ring->down;
|
||||
hist_ring->down = he->down->up = he;
|
||||
}
|
||||
}
|
||||
freehistdata(hist_ring = he, 0);
|
||||
}
|
||||
hist_ring->histnum = histnum;
|
||||
return hist_ring;
|
||||
}
|
||||
|
||||
/* say we're done using the history mechanism */
|
||||
|
||||
/**/
|
||||
|
@ -733,19 +862,35 @@ int
|
|||
hend(void)
|
||||
{
|
||||
int flag, save = 1;
|
||||
char *hf = getsparam("HISTFILE");
|
||||
|
||||
DPUTS(!chline, "BUG: chline is NULL in hend()");
|
||||
if (histdone & HISTFLAG_SETTY)
|
||||
settyinfo(&shttyinfo);
|
||||
if (!(histactive & HA_NOINC)) {
|
||||
curline.up->down = curline.down;
|
||||
curline.down->up = curline.up;
|
||||
if (hist_ring == &curline) {
|
||||
if (!histlinect)
|
||||
hist_ring = NULL;
|
||||
else
|
||||
hist_ring = curline.up;
|
||||
}
|
||||
curhist--;
|
||||
}
|
||||
if (histactive & (HA_NOSTORE|HA_NOINC)) {
|
||||
zfree(chline, hlinesz);
|
||||
zfree(chwords, chwordlen*sizeof(short));
|
||||
chline = NULL;
|
||||
if (!(histactive & HA_NOINC))
|
||||
curhist--;
|
||||
histactive = 0;
|
||||
return 1;
|
||||
}
|
||||
if (hist_ignore_all_dups != isset(HISTIGNOREALLDUPS)
|
||||
&& (hist_ignore_all_dups = isset(HISTIGNOREALLDUPS)) != 0)
|
||||
histremovedups();
|
||||
/* For history sharing, lock history file once for both read and write */
|
||||
if (isset(SHAREHISTORY) && lockhistfile(hf, 0))
|
||||
readhistfile(hf, 0, HFILE_USE_OPTIONS | HFILE_FAST);
|
||||
flag = histdone;
|
||||
histdone = 0;
|
||||
if (hptr < chline + 1)
|
||||
|
@ -781,8 +926,10 @@ hend(void)
|
|||
}
|
||||
if (save) {
|
||||
Histent he;
|
||||
int keepflags = 0;
|
||||
int keepflags;
|
||||
|
||||
for (he = hist_ring; he && he->flags & hist_skip_flags;
|
||||
he = up_histent(he)) ;
|
||||
#ifdef DEBUG
|
||||
/* debugging only */
|
||||
if (chwordpos%2) {
|
||||
|
@ -796,23 +943,21 @@ hend(void)
|
|||
/* strip superfluous blanks, if desired */
|
||||
if (isset(HISTREDUCEBLANKS))
|
||||
histreduceblanks();
|
||||
|
||||
if (isset(HISTIGNOREDUPS) && (he = gethistent(curhist - 1))
|
||||
&& he->text && !histcmp(he)) {
|
||||
if ((isset(HISTIGNOREDUPS) || isset(HISTIGNOREALLDUPS)) && he
|
||||
&& histstrcmp(chline, he->text) == 0) {
|
||||
/* This history entry compares the same as the previous.
|
||||
* In case minor changes were made, we overwrite the
|
||||
* previous one with the current one. This also gets
|
||||
* the timestamp right. However, keep the old flags.
|
||||
* previous one with the current one. This also gets the
|
||||
* timestamp right. Perhaps, preserve the HIST_OLD flag.
|
||||
*/
|
||||
keepflags = he->flags;
|
||||
curhist--;
|
||||
keepflags = he->flags & HIST_OLD; /* Avoid re-saving */
|
||||
freehistdata(he, 0);
|
||||
} else {
|
||||
keepflags = 0;
|
||||
he = prepnexthistent(++curhist);
|
||||
}
|
||||
|
||||
he = gethistent(curhist);
|
||||
zsfree(he->text);
|
||||
he->text = ztrdup(chline);
|
||||
if (he->nwords)
|
||||
zfree(he->words, he->nwords*2*sizeof(short));
|
||||
he->stim = time(NULL);
|
||||
he->ftim = 0L;
|
||||
he->flags = keepflags;
|
||||
|
@ -821,12 +966,15 @@ hend(void)
|
|||
he->words = (short *)zalloc(chwordpos * sizeof(short));
|
||||
memcpy(he->words, chwords, chwordpos * sizeof(short));
|
||||
}
|
||||
} else
|
||||
curhist--;
|
||||
addhistnode(histtab, he->text, he);
|
||||
}
|
||||
zfree(chline, hlinesz);
|
||||
zfree(chwords, chwordlen*sizeof(short));
|
||||
chline = NULL;
|
||||
histactive = 0;
|
||||
if (isset(SHAREHISTORY) || isset(INCREMENTALAPPENDHISTORY))
|
||||
savehistfile(hf, 1, HFILE_USE_OPTIONS | HFILE_FAST);
|
||||
unlockhistfile(hf); /* It's OK to call this even if we aren't locked */
|
||||
return !(flag & HISTFLAG_NOEXEC || errflag);
|
||||
}
|
||||
|
||||
|
@ -838,10 +986,7 @@ remhist(void)
|
|||
{
|
||||
if (!(histactive & HA_ACTIVE)) {
|
||||
if (!(histactive & HA_JUNKED)) {
|
||||
/* make sure this doesn't show up when we do firsthist() */
|
||||
Histent he = gethistent(curhist);
|
||||
zsfree(he->text);
|
||||
he->text = NULL;
|
||||
freehistnode((HashNode)hist_ring);
|
||||
histactive |= HA_JUNKED;
|
||||
/* curhist-- is delayed until the next hbegin() */
|
||||
}
|
||||
|
@ -1026,18 +1171,21 @@ getargspec(int argc, int marg, int evset)
|
|||
static int
|
||||
hconsearch(char *str, int *marg)
|
||||
{
|
||||
int t0, t1 = 0;
|
||||
int t1 = 0;
|
||||
char *s;
|
||||
Histent he;
|
||||
|
||||
for (t0 = curhist - 1; (he = quietgethist(t0)); t0--)
|
||||
for (he = up_histent(hist_ring); he; he = up_histent(he)) {
|
||||
if (he->flags & HIST_FOREIGN)
|
||||
continue;
|
||||
if ((s = strstr(he->text, str))) {
|
||||
int pos = s - he->text;
|
||||
while (t1 < he->nwords && he->words[2*t1] <= pos)
|
||||
t1++;
|
||||
*marg = t1 - 1;
|
||||
return t0;
|
||||
return he->histnum;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1047,12 +1195,15 @@ hconsearch(char *str, int *marg)
|
|||
int
|
||||
hcomsearch(char *str)
|
||||
{
|
||||
int t0;
|
||||
char *hs;
|
||||
Histent he;
|
||||
int len = strlen(str);
|
||||
|
||||
for (t0 = curhist - 1; (hs = quietgetevent(t0)); t0--)
|
||||
if (!strncmp(hs, str, strlen(str)))
|
||||
return t0;
|
||||
for (he = up_histent(hist_ring); he; he = up_histent(he)) {
|
||||
if (he->flags & HIST_FOREIGN)
|
||||
continue;
|
||||
if (strncmp(he->text, str, len) == 0)
|
||||
return he->histnum;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1206,33 +1357,15 @@ convamps(char *out, char *in, int inlen)
|
|||
}
|
||||
|
||||
/**/
|
||||
struct histent *
|
||||
Histent
|
||||
quietgethist(int ev)
|
||||
{
|
||||
static struct histent storehist;
|
||||
|
||||
if (ev < firsthist() || ev > curhist)
|
||||
return NULL;
|
||||
if (ev == curhist && (histactive & HA_ACTIVE)) {
|
||||
/* The current history line has not been stored. Build it up
|
||||
* from other variables.
|
||||
*/
|
||||
storehist.text = chline;
|
||||
storehist.nwords = chwordpos/2;
|
||||
storehist.words = chwords;
|
||||
|
||||
return &storehist;
|
||||
} else
|
||||
return gethistent(ev);
|
||||
}
|
||||
|
||||
/**/
|
||||
char *
|
||||
quietgetevent(int ev)
|
||||
{
|
||||
Histent ent = quietgethist(ev);
|
||||
|
||||
return ent ? ent->text : NULL;
|
||||
curline.text = chline;
|
||||
curline.nwords = chwordpos/2;
|
||||
curline.words = chwords;
|
||||
}
|
||||
return gethistent(ev, GETHIST_EXACT);
|
||||
}
|
||||
|
||||
/**/
|
||||
|
@ -1362,10 +1495,9 @@ quotebreak(char **tr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* read an arbitrary amount of data into a buffer until stop is found */
|
||||
|
||||
/**/
|
||||
#if 0 /**/
|
||||
char *
|
||||
hdynread(int stop)
|
||||
{
|
||||
|
@ -1424,61 +1556,80 @@ hdynread2(int stop)
|
|||
void
|
||||
inithist(void)
|
||||
{
|
||||
histentct = histsiz;
|
||||
histentarr = (Histent) zcalloc(histentct * sizeof *histentarr);
|
||||
createhisttable();
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
resizehistents(void)
|
||||
{
|
||||
int newentct, t0, t1, firstlex;
|
||||
Histent newarr;
|
||||
|
||||
newentct = histsiz;
|
||||
newarr = (Histent) zcalloc(newentct * sizeof *newarr);
|
||||
firstlex = curhist - histsiz + 1;
|
||||
t0 = firsthist();
|
||||
if (t0 < curhist - newentct)
|
||||
t0 = curhist - newentct;
|
||||
t1 = t0 % newentct;
|
||||
for (; t0 <= curhist; t0++) {
|
||||
newarr[t1] = *gethistent(t0);
|
||||
if (t0 < firstlex) {
|
||||
zsfree(newarr[t1].text);
|
||||
newarr[t1].text = NULL;
|
||||
}
|
||||
t1++;
|
||||
if (t1 == newentct)
|
||||
t1 = 0;
|
||||
}
|
||||
free(histentarr);
|
||||
histentarr = newarr;
|
||||
histentct = newentct;
|
||||
while (histlinect > histsiz)
|
||||
freehistnode((HashNode)hist_ring->down);
|
||||
}
|
||||
|
||||
/* Remember the last line in the history file so we can find it again. */
|
||||
static struct {
|
||||
char *text;
|
||||
time_t stim, mtim;
|
||||
off_t fpos, fsiz;
|
||||
int next_write_ev;
|
||||
} lasthist;
|
||||
|
||||
static int histfile_linect;
|
||||
|
||||
/**/
|
||||
void
|
||||
readhistfile(char *s, int err)
|
||||
readhistfile(char *fn, int err, int readflags)
|
||||
{
|
||||
char *buf;
|
||||
char *buf, *start = NULL;
|
||||
FILE *in;
|
||||
Histent ent;
|
||||
time_t tim = time(NULL);
|
||||
Histent he;
|
||||
time_t stim, ftim, tim = time(NULL);
|
||||
off_t fpos;
|
||||
short *wordlist;
|
||||
struct stat sb;
|
||||
int nwordpos, nwordlist, bufsiz;
|
||||
int searching, newflags;
|
||||
|
||||
if (!s)
|
||||
if (!fn && !(fn = getsparam("HISTFILE")))
|
||||
return;
|
||||
if ((in = fopen(unmeta(s), "r"))) {
|
||||
if (readflags & HFILE_FAST) {
|
||||
if (stat(fn, &sb) < 0
|
||||
|| (lasthist.fsiz == sb.st_size && lasthist.mtim == sb.st_mtime)
|
||||
|| !lockhistfile(fn, 0))
|
||||
return;
|
||||
lasthist.fsiz = sb.st_size;
|
||||
lasthist.mtim = sb.st_mtime;
|
||||
}
|
||||
else if (!lockhistfile(fn, 1))
|
||||
return;
|
||||
if ((in = fopen(unmeta(fn), "r"))) {
|
||||
nwordlist = 16;
|
||||
wordlist = (short *)zalloc(nwordlist*sizeof(short));
|
||||
bufsiz = 1024;
|
||||
buf = zalloc(bufsiz);
|
||||
|
||||
while (fgets(buf, bufsiz, in)) {
|
||||
if (readflags & HFILE_FAST && lasthist.text) {
|
||||
if (lasthist.fpos < lasthist.fsiz) {
|
||||
fseek(in, lasthist.fpos, 0);
|
||||
searching = 1;
|
||||
}
|
||||
else {
|
||||
histfile_linect = 0;
|
||||
searching = -1;
|
||||
}
|
||||
} else
|
||||
searching = 0;
|
||||
|
||||
newflags = HIST_OLD | HIST_READ;
|
||||
if (readflags & HFILE_FAST)
|
||||
newflags |= HIST_FOREIGN;
|
||||
if (readflags & HFILE_SKIPOLD
|
||||
|| (hist_ignore_all_dups && newflags & hist_skip_flags))
|
||||
newflags |= HIST_MAKEUNIQUE;
|
||||
while (fpos = ftell(in), fgets(buf, bufsiz, in)) {
|
||||
int l = strlen(buf);
|
||||
char *pt, *start;
|
||||
char *pt;
|
||||
|
||||
while (l) {
|
||||
while (buf[l - 1] != '\n') {
|
||||
|
@ -1488,114 +1639,184 @@ readhistfile(char *s, int err)
|
|||
l++;
|
||||
break;
|
||||
}
|
||||
l = strlen(buf);
|
||||
l += strlen(buf+l);
|
||||
}
|
||||
buf[l - 1] = '\0';
|
||||
if (l > 1 && buf[l - 2] == '\\') {
|
||||
buf[l - 2] = '\n';
|
||||
fgets(buf + l - 1, bufsiz - (l - 1), in);
|
||||
l = strlen(buf);
|
||||
buf[--l - 1] = '\n';
|
||||
fgets(buf + l, bufsiz - l, in);
|
||||
l += strlen(buf+l);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
ent = gethistent(++curhist);
|
||||
pt = buf;
|
||||
if (*pt == ':') {
|
||||
pt++;
|
||||
ent->stim = zstrtol(pt, NULL, 0);
|
||||
stim = zstrtol(pt, NULL, 0);
|
||||
for (; *pt != ':' && *pt; pt++);
|
||||
if (*pt) {
|
||||
pt++;
|
||||
ent->ftim = zstrtol(pt, NULL, 0);
|
||||
ftim = zstrtol(pt, NULL, 0);
|
||||
for (; *pt != ';' && *pt; pt++);
|
||||
if (*pt)
|
||||
pt++;
|
||||
} else {
|
||||
ent->ftim = tim;
|
||||
}
|
||||
if (ent->stim == 0)
|
||||
ent->stim = tim;
|
||||
if (ent->ftim == 0)
|
||||
ent->ftim = tim;
|
||||
} else
|
||||
ftim = stim;
|
||||
} else {
|
||||
ent->ftim = ent->stim = tim;
|
||||
if (*pt == '\\' && pt[1] == ':')
|
||||
pt++;
|
||||
stim = ftim = 0;
|
||||
}
|
||||
|
||||
zsfree(ent->text);
|
||||
ent->text = ztrdup(pt);
|
||||
ent->flags = HIST_OLD|HIST_READ;
|
||||
if (ent->nwords)
|
||||
zfree(ent->words, ent->nwords*2*sizeof(short));
|
||||
if (searching) {
|
||||
if (searching > 0) {
|
||||
if (stim == lasthist.stim
|
||||
&& histstrcmp(pt, lasthist.text) == 0)
|
||||
searching = 0;
|
||||
else {
|
||||
fseek(in, 0, 0);
|
||||
histfile_linect = 0;
|
||||
searching = -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (stim < lasthist.stim) {
|
||||
histfile_linect++;
|
||||
continue;
|
||||
}
|
||||
searching = 0;
|
||||
}
|
||||
|
||||
if (readflags & HFILE_USE_OPTIONS) {
|
||||
histfile_linect++;
|
||||
lasthist.fpos = fpos;
|
||||
lasthist.stim = stim;
|
||||
}
|
||||
|
||||
he = prepnexthistent(++curhist);
|
||||
he->text = ztrdup(pt);
|
||||
he->flags = newflags;
|
||||
if ((he->stim = stim) == 0)
|
||||
he->stim = he->ftim = tim;
|
||||
else if (ftim < stim)
|
||||
he->ftim = stim + ftim;
|
||||
else
|
||||
he->ftim = ftim;
|
||||
|
||||
/* Divide up the words. We don't know how it lexes,
|
||||
so just look for spaces.
|
||||
so just look for white-space.
|
||||
*/
|
||||
nwordpos = 0;
|
||||
start = pt;
|
||||
do {
|
||||
while (*pt == ' ')
|
||||
while (inblank(*pt))
|
||||
pt++;
|
||||
if (*pt) {
|
||||
if (nwordpos >= nwordlist)
|
||||
wordlist = (short *) realloc(wordlist,
|
||||
(nwordlist += 16)*sizeof(short));
|
||||
wordlist[nwordpos++] = pt - start;
|
||||
while (*pt && *pt != ' ')
|
||||
while (*pt && !inblank(*pt))
|
||||
pt++;
|
||||
wordlist[nwordpos++] = pt - start;
|
||||
}
|
||||
} while (*pt);
|
||||
|
||||
ent->nwords = nwordpos/2;
|
||||
if (ent->nwords) {
|
||||
ent->words = (short *)zalloc(nwordpos*sizeof(short));
|
||||
memcpy(ent->words, wordlist, nwordpos*sizeof(short));
|
||||
he->nwords = nwordpos/2;
|
||||
if (he->nwords) {
|
||||
he->words = (short *)zalloc(nwordpos*sizeof(short));
|
||||
memcpy(he->words, wordlist, nwordpos*sizeof(short));
|
||||
} else
|
||||
ent->words = (short *)NULL;
|
||||
he->words = (short *)NULL;
|
||||
addhistnode(histtab, he->text, he);
|
||||
if (hist_ring != he)
|
||||
curhist--; /* We discarded a foreign duplicate */
|
||||
}
|
||||
if (start && readflags & HFILE_USE_OPTIONS) {
|
||||
zsfree(lasthist.text);
|
||||
lasthist.text = ztrdup(start);
|
||||
}
|
||||
fclose(in);
|
||||
|
||||
zfree(wordlist, nwordlist*sizeof(short));
|
||||
zfree(buf, bufsiz);
|
||||
|
||||
fclose(in);
|
||||
} else if (err)
|
||||
zerr("can't read history file", s, 0);
|
||||
zerr("can't read history file", fn, 0);
|
||||
|
||||
unlockhistfile(fn);
|
||||
}
|
||||
|
||||
/**/
|
||||
void
|
||||
savehistfile(char *s, int err, int app)
|
||||
savehistfile(char *fn, int err, int writeflags)
|
||||
{
|
||||
char *t;
|
||||
char *t, *start = NULL;
|
||||
FILE *out;
|
||||
int ev;
|
||||
Histent ent;
|
||||
Histent he;
|
||||
int xcurhist = curhist - !!(histactive & HA_ACTIVE);
|
||||
int savehist = getiparam("SAVEHIST");
|
||||
int extended_history = isset(EXTENDEDHISTORY);
|
||||
|
||||
if (!s || !interact || savehist <= 0)
|
||||
if (!interact || savehist <= 0 || !hist_ring
|
||||
|| (!fn && !(fn = getsparam("HISTFILE"))))
|
||||
return;
|
||||
ev = curhist - savehist + 1;
|
||||
if (ev < firsthist())
|
||||
ev = firsthist();
|
||||
if (app & 1)
|
||||
out = fdopen(open(unmeta(s),
|
||||
O_CREAT | O_WRONLY | O_APPEND | O_NOCTTY, 0600), "a");
|
||||
else
|
||||
out = fdopen(open(unmeta(s),
|
||||
O_CREAT | O_WRONLY | O_TRUNC | O_NOCTTY, 0600), "w");
|
||||
if (writeflags & HFILE_FAST) {
|
||||
he = gethistent(lasthist.next_write_ev, GETHIST_DOWNWARD);
|
||||
while (he && he->flags & HIST_OLD) {
|
||||
lasthist.next_write_ev = he->histnum + 1;
|
||||
he = down_histent(he);
|
||||
}
|
||||
if (!he || !lockhistfile(fn, 0))
|
||||
return;
|
||||
if (histfile_linect > savehist + savehist / 5)
|
||||
writeflags &= ~HFILE_FAST;
|
||||
}
|
||||
else {
|
||||
if (!lockhistfile(fn, 1))
|
||||
return;
|
||||
he = hist_ring->down;
|
||||
}
|
||||
if (writeflags & HFILE_USE_OPTIONS) {
|
||||
if (isset(APPENDHISTORY) || isset(INCREMENTALAPPENDHISTORY)
|
||||
|| isset(SHAREHISTORY))
|
||||
writeflags |= HFILE_APPEND | HFILE_SKIPOLD;
|
||||
else
|
||||
histfile_linect = 0;
|
||||
if (isset(HISTSAVENODUPS))
|
||||
writeflags |= HFILE_SKIPDUPS;
|
||||
if (isset(SHAREHISTORY))
|
||||
extended_history = 1;
|
||||
}
|
||||
if (writeflags & HFILE_APPEND) {
|
||||
out = fdopen(open(unmeta(fn),
|
||||
O_CREAT | O_WRONLY | O_APPEND | O_NOCTTY, 0600), "a");
|
||||
}
|
||||
else {
|
||||
out = fdopen(open(unmeta(fn),
|
||||
O_CREAT | O_WRONLY | O_TRUNC | O_NOCTTY, 0600), "w");
|
||||
}
|
||||
if (out) {
|
||||
for (; ev <= curhist - !!(histactive & HA_ACTIVE); ev++) {
|
||||
ent = gethistent(ev);
|
||||
if (app & 2) {
|
||||
if (ent->flags & HIST_OLD)
|
||||
for (; he && he->histnum <= xcurhist; he = down_histent(he)) {
|
||||
if ((writeflags & HFILE_SKIPDUPS && he->flags & HIST_DUP)
|
||||
|| (writeflags & HFILE_SKIPFOREIGN && he->flags & HIST_FOREIGN))
|
||||
continue;
|
||||
if (writeflags & HFILE_SKIPOLD) {
|
||||
if (he->flags & HIST_OLD)
|
||||
continue;
|
||||
ent->flags |= HIST_OLD;
|
||||
he->flags |= HIST_OLD;
|
||||
if (writeflags & HFILE_USE_OPTIONS)
|
||||
lasthist.next_write_ev = he->histnum + 1;
|
||||
}
|
||||
t = ent->text;
|
||||
if (isset(EXTENDEDHISTORY)) {
|
||||
fprintf(out, ": %ld:%ld;",
|
||||
(long)ent->stim,
|
||||
(long)ent->ftim);
|
||||
if (writeflags & HFILE_USE_OPTIONS) {
|
||||
lasthist.fpos = ftell(out);
|
||||
lasthist.stim = he->stim;
|
||||
histfile_linect++;
|
||||
}
|
||||
t = start = he->text;
|
||||
if (extended_history) {
|
||||
fprintf(out, ": %ld:%ld;", (long)he->stim,
|
||||
he->ftim? (long)(he->ftim - he->stim) : 0L);
|
||||
} else if (*t == ':')
|
||||
fputc('\\', out);
|
||||
|
||||
|
@ -1606,69 +1827,109 @@ savehistfile(char *s, int err, int app)
|
|||
}
|
||||
fputc('\n', out);
|
||||
}
|
||||
if (start && writeflags & HFILE_USE_OPTIONS) {
|
||||
struct stat sb;
|
||||
fflush(out);
|
||||
if (fstat(fileno(out), &sb) == 0) {
|
||||
lasthist.fsiz = sb.st_size;
|
||||
lasthist.mtim = sb.st_mtime;
|
||||
}
|
||||
zsfree(lasthist.text);
|
||||
lasthist.text = ztrdup(start);
|
||||
}
|
||||
fclose(out);
|
||||
|
||||
if (app & 2 && (out = fopen(unmeta(s), "r"))) {
|
||||
char **store, buf[1024], **ptr;
|
||||
int i, l, histnum = 0;
|
||||
if ((writeflags & (HFILE_SKIPOLD | HFILE_FAST)) == HFILE_SKIPOLD) {
|
||||
HashTable remember_histtab = histtab;
|
||||
Histent remember_hist_ring = hist_ring;
|
||||
int remember_histlinect = histlinect;
|
||||
int remember_curhist = curhist;
|
||||
|
||||
store = (char **)zcalloc((savehist + 1) * sizeof *store);
|
||||
while (fgets(buf, sizeof(buf), out)) {
|
||||
char *t;
|
||||
hist_ring = NULL;
|
||||
curhist = histlinect = 0;
|
||||
histsiz = savehist;
|
||||
createhisttable(); /* sets histtab */
|
||||
|
||||
if (store[i = histnum % savehist])
|
||||
free(store[i]);
|
||||
store[i] = ztrdup(buf);
|
||||
l = strlen(buf);
|
||||
if (l > 1) {
|
||||
t = store[i] + l;
|
||||
while ((t[-1] != '\n' ||
|
||||
(t[-1] == '\n' && t[-2] == '\\')) &&
|
||||
fgets(buf, sizeof(buf), out)) {
|
||||
l += strlen(buf);
|
||||
store[i] = zrealloc(store[i], l + 1);
|
||||
t = store[i] + l;
|
||||
strcat(store[i], buf);
|
||||
}
|
||||
}
|
||||
histnum++;
|
||||
}
|
||||
fclose(out);
|
||||
if ((out = fdopen(open(unmeta(s),
|
||||
O_WRONLY | O_TRUNC | O_NOCTTY, 0600), "w"))) {
|
||||
if (histnum < savehist)
|
||||
for (i = 0; i < histnum; i++)
|
||||
fprintf(out, "%s", store[i]);
|
||||
else
|
||||
for (i = histnum; i < histnum + savehist; i++)
|
||||
fprintf(out, "%s", store[i % savehist]);
|
||||
fclose(out);
|
||||
}
|
||||
for (ptr = store; *ptr; ptr++)
|
||||
zsfree(*ptr);
|
||||
free(store);
|
||||
hist_ignore_all_dups |= isset(HISTSAVENODUPS);
|
||||
readhistfile(fn, err, 0);
|
||||
hist_ignore_all_dups = isset(HISTIGNOREALLDUPS);
|
||||
savehistfile(fn, err, 0);
|
||||
deletehashtable(histtab);
|
||||
|
||||
curhist = remember_curhist;
|
||||
histlinect = remember_histlinect;
|
||||
hist_ring = remember_hist_ring;
|
||||
histtab = remember_histtab;
|
||||
}
|
||||
} else if (err)
|
||||
zerr("can't write history file %s", s, 0);
|
||||
zerr("can't write history file %s", fn, 0);
|
||||
|
||||
unlockhistfile(fn);
|
||||
}
|
||||
|
||||
static int lockhistct;
|
||||
|
||||
/**/
|
||||
int
|
||||
firsthist(void)
|
||||
lockhistfile(char *fn, int keep_trying)
|
||||
{
|
||||
int ev;
|
||||
Histent ent;
|
||||
int ct = lockhistct;
|
||||
|
||||
ev = curhist - histentct + 1;
|
||||
if (ev < 1)
|
||||
ev = 1;
|
||||
do {
|
||||
ent = gethistent(ev);
|
||||
if (ent->text)
|
||||
break;
|
||||
ev++;
|
||||
if (!fn && !(fn = getsparam("HISTFILE")))
|
||||
return 0;
|
||||
if (!lockhistct++) {
|
||||
struct stat sb;
|
||||
int fd, len = strlen(fn);
|
||||
char *tmpfile, *lockfile;
|
||||
|
||||
tmpfile = zalloc(len + 10 + 1);
|
||||
sprintf(tmpfile, "%s.%ld", fn, mypid);
|
||||
if ((fd = open(tmpfile, O_RDWR|O_CREAT|O_EXCL, 0644)) >= 0) {
|
||||
write(fd, "0\n", 2);
|
||||
close(fd);
|
||||
lockfile = zalloc(len + 5 + 1);
|
||||
sprintf(lockfile, "%s.LOCK", fn);
|
||||
while (link(tmpfile, lockfile) < 0) {
|
||||
if (stat(lockfile, &sb) < 0) {
|
||||
if (errno == ENOENT)
|
||||
continue;
|
||||
}
|
||||
else if (keep_trying) {
|
||||
if (time(NULL) - sb.st_mtime < 10)
|
||||
sleep(1);
|
||||
else
|
||||
unlink(lockfile);
|
||||
continue;
|
||||
}
|
||||
lockhistct--;
|
||||
break;
|
||||
}
|
||||
free(lockfile);
|
||||
}
|
||||
unlink(tmpfile);
|
||||
free(tmpfile);
|
||||
}
|
||||
while (ev < curhist);
|
||||
return ev;
|
||||
return ct != lockhistct;
|
||||
}
|
||||
|
||||
/* Unlock the history file if this corresponds to the last nested lock
|
||||
* request. If we don't have the file locked, just return.
|
||||
*/
|
||||
|
||||
/**/
|
||||
void
|
||||
unlockhistfile(char *fn)
|
||||
{
|
||||
if (!fn && !(fn = getsparam("HISTFILE")))
|
||||
return;
|
||||
if (--lockhistct) {
|
||||
if (lockhistct < 0)
|
||||
lockhistct = 0;
|
||||
}
|
||||
else {
|
||||
char *lockfile = zalloc(strlen(fn) + 5 + 1);
|
||||
sprintf(lockfile, "%s.LOCK", fn);
|
||||
unlink(lockfile);
|
||||
free(lockfile);
|
||||
}
|
||||
}
|
||||
|
|
17
Src/init.c
17
Src/init.c
|
@ -110,15 +110,14 @@ loop(int toplevel, int justonce)
|
|||
List prelist;
|
||||
|
||||
if (toplevel && (prelist = getshfunc("preexec")) != &dummy_list) {
|
||||
Histent he = gethistent(curhist);
|
||||
LinkList args;
|
||||
int osc = sfcontext;
|
||||
|
||||
PERMALLOC {
|
||||
args = newlinklist();
|
||||
addlinknode(args, "preexec");
|
||||
if (he && he->text)
|
||||
addlinknode(args, he->text);
|
||||
if (hist_ring)
|
||||
addlinknode(args, hist_ring->text);
|
||||
} LASTALLOC;
|
||||
sfcontext = SFC_HOOK;
|
||||
doshfunc("preexec", prelist, args, 0, 1);
|
||||
|
@ -642,11 +641,13 @@ setupvals(void)
|
|||
wrappers = NULL;
|
||||
|
||||
#ifdef TIOCGWINSZ
|
||||
adjustwinsize();
|
||||
adjustwinsize(0);
|
||||
#else
|
||||
/* Using zero below sets the defaults from termcap */
|
||||
setiparam("COLUMNS", 0);
|
||||
setiparam("LINES", 0);
|
||||
/* columns and lines are normally zero, unless something different *
|
||||
* was inhereted from the environment. If either of them are zero *
|
||||
* the setiparam calls below set them to the defaults from termcap */
|
||||
setiparam("COLUMNS", columns);
|
||||
setiparam("LINES", lines);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETRLIMIT
|
||||
|
@ -828,7 +829,7 @@ init_misc(void)
|
|||
}
|
||||
|
||||
if (interact && isset(RCS))
|
||||
readhistfile(getsparam("HISTFILE"), 0);
|
||||
readhistfile(NULL, 0, HFILE_USE_OPTIONS);
|
||||
}
|
||||
|
||||
/* source a file */
|
||||
|
|
34
Src/jobs.c
34
Src/jobs.c
|
@ -180,11 +180,14 @@ update_job(Job jn)
|
|||
} else { /* job is done, so remember return value */
|
||||
lastval2 = val;
|
||||
/* If last process was run in the current shell, keep old status
|
||||
* and let it handle its own traps
|
||||
* and let it handle its own traps, but always allow the test
|
||||
* for the pgrp.
|
||||
*/
|
||||
if (job == thisjob && !(jn->stat & STAT_CURSH)) {
|
||||
lastval = val;
|
||||
inforeground = 1;
|
||||
if (jn->stat & STAT_CURSH)
|
||||
inforeground = 1;
|
||||
else if (job == thisjob) {
|
||||
lastval = val;
|
||||
inforeground = 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,8 +201,20 @@ update_job(Job jn)
|
|||
/* is this job in the foreground of an interactive shell? */
|
||||
if (mypgrp != pgrp && inforeground &&
|
||||
(jn->gleader == pgrp || (pgrp > 1 && kill(-pgrp, 0) == -1))) {
|
||||
attachtty(mypgrp);
|
||||
adjustwinsize(); /* check window size and adjust if necessary */
|
||||
if (list_pipe) {
|
||||
/*
|
||||
* Oh, dear, we're right in the middle of some confusion
|
||||
* of shell jobs on the righthand side of a pipeline, so
|
||||
* it's death to call attachtty() just yet. Mark the
|
||||
* fact in the job, so that the attachtty() will be called
|
||||
* when the job is finally deleted.
|
||||
*/
|
||||
jn->stat |= STAT_ATTACH;
|
||||
} else {
|
||||
attachtty(mypgrp);
|
||||
/* check window size and adjust if necessary */
|
||||
adjustwinsize(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,7 +238,7 @@ update_job(Job jn)
|
|||
* process group from the shell, so the shell will not receive *
|
||||
* terminal signals, therefore we we pretend that the shell got *
|
||||
* the signal too. */
|
||||
if (inforeground && isset(MONITOR) && WIFSIGNALED(status)) {
|
||||
if (inforeground == 2 && isset(MONITOR) && WIFSIGNALED(status)) {
|
||||
int sig = WTERMSIG(status);
|
||||
|
||||
if (sig == SIGINT || sig == SIGQUIT) {
|
||||
|
@ -609,6 +624,11 @@ deletejob(Job jn)
|
|||
{
|
||||
struct process *pn, *nx;
|
||||
|
||||
if (jn->stat & STAT_ATTACH) {
|
||||
attachtty(mypgrp);
|
||||
adjustwinsize(0);
|
||||
}
|
||||
|
||||
pn = jn->procs;
|
||||
jn->procs = NULL;
|
||||
for (; pn; pn = nx) {
|
||||
|
|
39
Src/module.c
39
Src/module.c
|
@ -142,6 +142,7 @@ addwrapper(Module m, FuncWrap w)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**/
|
||||
#ifdef DYNAMIC
|
||||
|
||||
/* $module_path ($MODULE_PATH) */
|
||||
|
@ -238,6 +239,7 @@ deletewrapper(Module m, FuncWrap w)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**/
|
||||
#ifdef AIXDYNAMIC
|
||||
|
||||
#include <sys/ldr.h>
|
||||
|
@ -273,6 +275,7 @@ load_and_bind(const char *fn)
|
|||
#define dlclose(X) unload(X)
|
||||
#define dlerror() (dlerrstr[0])
|
||||
|
||||
/**/
|
||||
#else
|
||||
|
||||
#ifdef HAVE_DLFCN_H
|
||||
|
@ -289,6 +292,7 @@ load_and_bind(const char *fn)
|
|||
# endif
|
||||
#endif
|
||||
|
||||
/**/
|
||||
#ifdef HPUXDYNAMIC
|
||||
# define dlopen(file,mode) (void *)shl_load((file), (mode), (long) 0)
|
||||
# define dlclose(handle) shl_unload((shl_t)(handle))
|
||||
|
@ -309,6 +313,7 @@ hpux_dlsym(void *handle, char *name)
|
|||
# ifndef HAVE_DLCLOSE
|
||||
# define dlclose(X) ((X), 0)
|
||||
# endif
|
||||
/**/
|
||||
#endif
|
||||
|
||||
#ifdef DLSYM_NEEDS_UNDERSCORE
|
||||
|
@ -331,6 +336,7 @@ hpux_dlsym(void *handle, char *name)
|
|||
# define STR_FINISH_S "finish_%s"
|
||||
#endif /* !DLSYM_NEEDS_UNDERSCORE */
|
||||
|
||||
/**/
|
||||
#endif /* !AIXDYNAMIC */
|
||||
|
||||
#ifndef RTLD_LAZY
|
||||
|
@ -408,6 +414,7 @@ find_module(const char *name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**/
|
||||
#ifdef AIXDYNAMIC
|
||||
|
||||
/**/
|
||||
|
@ -438,6 +445,7 @@ finish_module(Module m)
|
|||
return ((int (*)_((int,Module))) m->handle)(3, m);
|
||||
}
|
||||
|
||||
/**/
|
||||
#else
|
||||
|
||||
static Module_func
|
||||
|
@ -523,6 +531,7 @@ finish_module(Module m)
|
|||
return r;
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif /* !AIXDYNAMIC */
|
||||
|
||||
/**/
|
||||
|
@ -664,7 +673,7 @@ autoloadscan(HashNode hn, int printflags)
|
|||
if(bn->flags & BINF_ADDED)
|
||||
return;
|
||||
if(printflags & PRINT_LIST) {
|
||||
fputs("zmodload -a ", stdout);
|
||||
fputs("zmodload -ab ", stdout);
|
||||
if(bn->optstr[0] == '-')
|
||||
fputs("-- ", stdout);
|
||||
quotedzputs(bn->optstr, stdout);
|
||||
|
@ -687,7 +696,12 @@ autoloadscan(HashNode hn, int printflags)
|
|||
int
|
||||
bin_zmodload(char *nam, char **args, char *ops, int func)
|
||||
{
|
||||
if(ops['d'] && ops['a']) {
|
||||
if ((ops['b'] || ops['c'] || ops['p']) && !(ops['a'] || ops['u'])) {
|
||||
zwarnnam(nam, "-b, -c, and -p must be combined with -a or -u",
|
||||
NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (ops['d'] && ops['a']) {
|
||||
zwarnnam(nam, "-d cannot be combined with -a", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
|
@ -695,16 +709,20 @@ bin_zmodload(char *nam, char **args, char *ops, int func)
|
|||
zwarnnam(nam, "what do you want to unload?", NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
if(ops['d'])
|
||||
if (ops['d'])
|
||||
return bin_zmodload_dep(nam, args, ops);
|
||||
else if(ops['a'])
|
||||
else if ((ops['a'] || ops['b']) && !(ops['c'] || ops['p']))
|
||||
return bin_zmodload_auto(nam, args, ops);
|
||||
else if (ops['c'] || ops['C'])
|
||||
else if (ops['c'] && !(ops['b'] || ops['p']))
|
||||
return bin_zmodload_cond(nam, args, ops);
|
||||
else if (ops['p'])
|
||||
else if (ops['p'] && !(ops['b'] || ops['c']))
|
||||
return bin_zmodload_param(nam, args, ops);
|
||||
else
|
||||
else if (!(ops['a'] || ops['b'] || ops['c'] || ops['p']))
|
||||
return bin_zmodload_load(nam, args, ops);
|
||||
else
|
||||
zwarnnam(nam, "use only one of -b, -c, or -p", NULL, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**/
|
||||
|
@ -865,7 +883,7 @@ bin_zmodload_cond(char *nam, char **args, char *ops)
|
|||
for (p = condtab; p; p = p->next) {
|
||||
if (p->module) {
|
||||
if (ops['L']) {
|
||||
fputs("zmodload -c", stdout);
|
||||
fputs("zmodload -ac", stdout);
|
||||
if (p->flags & CONDF_INFIX)
|
||||
putchar('I');
|
||||
printf(" %s %s\n", p->module, p->name);
|
||||
|
@ -908,7 +926,7 @@ printautoparams(HashNode hn, int lon)
|
|||
|
||||
if (pm->flags & PM_AUTOLOAD) {
|
||||
if (lon)
|
||||
printf("zmodload -p %s %s\n", pm->u.str, pm->nam);
|
||||
printf("zmodload -ap %s %s\n", pm->u.str, pm->nam);
|
||||
else
|
||||
printf("%s (%s)\n", pm->nam, pm->u.str);
|
||||
}
|
||||
|
@ -1097,6 +1115,7 @@ bin_zmodload_load(char *nam, char **args, char *ops)
|
|||
}
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif /* DYNAMIC */
|
||||
|
||||
/* The list of module-defined conditions. */
|
||||
|
@ -1252,6 +1271,7 @@ deleteparamdefs(char const *nam, Paramdef d, int size)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**/
|
||||
#ifdef DYNAMIC
|
||||
|
||||
/* This adds a definition for autoloading a module for a condition. */
|
||||
|
@ -1342,4 +1362,5 @@ add_autoparam(char *nam, char *module)
|
|||
pm->flags |= PM_AUTOLOAD;
|
||||
}
|
||||
|
||||
/**/
|
||||
#endif
|
||||
|
|
|
@ -124,15 +124,20 @@ static struct optname optns[] = {
|
|||
{NULL, "hashlistall", OPT_ALL, HASHLISTALL},
|
||||
{NULL, "histallowclobber", 0, HISTALLOWCLOBBER},
|
||||
{NULL, "histbeep", OPT_ALL, HISTBEEP},
|
||||
{NULL, "histexpiredupsfirst", 0, HISTEXPIREDUPSFIRST},
|
||||
{NULL, "histfindnodups", 0, HISTFINDNODUPS},
|
||||
{NULL, "histignorealldups", 0, HISTIGNOREALLDUPS},
|
||||
{NULL, "histignoredups", 0, HISTIGNOREDUPS},
|
||||
{NULL, "histignorespace", 0, HISTIGNORESPACE},
|
||||
{NULL, "histnofunctions", 0, HISTNOFUNCTIONS},
|
||||
{NULL, "histnostore", 0, HISTNOSTORE},
|
||||
{NULL, "histreduceblanks", 0, HISTREDUCEBLANKS},
|
||||
{NULL, "histsavenodups", 0, HISTSAVENODUPS},
|
||||
{NULL, "histverify", 0, HISTVERIFY},
|
||||
{NULL, "hup", OPT_EMULATE|OPT_ZSH, HUP},
|
||||
{NULL, "ignorebraces", OPT_EMULATE|OPT_SH, IGNOREBRACES},
|
||||
{NULL, "ignoreeof", 0, IGNOREEOF},
|
||||
{NULL, "incrementalappendhistory",0, INCREMENTALAPPENDHISTORY},
|
||||
{NULL, "interactive", OPT_SPECIAL, INTERACTIVE},
|
||||
{NULL, "interactivecomments", OPT_EMULATE|OPT_BOURNE, INTERACTIVECOMMENTS},
|
||||
{NULL, "ksharrays", OPT_EMULATE|OPT_BOURNE, KSHARRAYS},
|
||||
|
@ -176,6 +181,7 @@ static struct optname optns[] = {
|
|||
{NULL, "restricted", OPT_SPECIAL, RESTRICTED},
|
||||
{NULL, "rmstarsilent", OPT_BOURNE, RMSTARSILENT},
|
||||
{NULL, "rmstarwait", 0, RMSTARWAIT},
|
||||
{NULL, "sharehistory", OPT_KSH, SHAREHISTORY},
|
||||
{NULL, "shfileexpansion", OPT_EMULATE|OPT_BOURNE, SHFILEEXPANSION},
|
||||
{NULL, "shglob", OPT_EMULATE|OPT_BOURNE, SHGLOB},
|
||||
{NULL, "shinstdin", OPT_SPECIAL, SHINSTDIN},
|
||||
|
@ -378,9 +384,9 @@ printoptionnode(HashNode hn, int set)
|
|||
optno = -optno;
|
||||
if (isset(KSHOPTIONPRINT)) {
|
||||
if (defset(on))
|
||||
printf("no%-20s%s\n", on->nam, isset(optno) ? "off" : "on");
|
||||
printf("no%-19s %s\n", on->nam, isset(optno) ? "off" : "on");
|
||||
else
|
||||
printf("%-22s%s\n", on->nam, isset(optno) ? "on" : "off");
|
||||
printf("%-21s %s\n", on->nam, isset(optno) ? "on" : "off");
|
||||
} else if (set == (isset(optno) ^ defset(on))) {
|
||||
if (set ^ isset(optno))
|
||||
fputs("no", stdout);
|
||||
|
@ -399,6 +405,7 @@ createoptiontable(void)
|
|||
optiontab->hash = hasher;
|
||||
optiontab->emptytable = NULL;
|
||||
optiontab->filltable = NULL;
|
||||
optiontab->cmpnodes = strcmp;
|
||||
optiontab->addnode = addhashnode;
|
||||
optiontab->getnode = gethashnode;
|
||||
optiontab->getnode2 = gethashnode2;
|
||||
|
@ -635,6 +642,8 @@ dosetopt(int optno, int value, int force)
|
|||
}
|
||||
} else if(!force && (optno == INTERACTIVE || optno == SHINSTDIN ||
|
||||
optno == SINGLECOMMAND)) {
|
||||
if (opts[optno] == value)
|
||||
return 0;
|
||||
/* it is not permitted to change the value of these options */
|
||||
return -1;
|
||||
} else if(!force && optno == USEZLE && value) {
|
||||
|
|
25
Src/params.c
25
Src/params.c
|
@ -270,6 +270,7 @@ newparamtable(int size, char const *name)
|
|||
ht->hash = hasher;
|
||||
ht->emptytable = emptyhashtable;
|
||||
ht->filltable = NULL;
|
||||
ht->cmpnodes = strcmp;
|
||||
ht->addnode = addhashnode;
|
||||
ht->getnode = getparamnode;
|
||||
ht->getnode2 = getparamnode;
|
||||
|
@ -282,6 +283,7 @@ newparamtable(int size, char const *name)
|
|||
return ht;
|
||||
}
|
||||
|
||||
/**/
|
||||
#ifdef DYNAMIC
|
||||
/**/
|
||||
static HashNode
|
||||
|
@ -299,6 +301,7 @@ getparamnode(HashTable ht, char *nam)
|
|||
}
|
||||
return hn;
|
||||
}
|
||||
/**/
|
||||
#endif /* DYNAMIC */
|
||||
|
||||
/* Copy a parameter hash table */
|
||||
|
@ -1753,7 +1756,7 @@ unsetparam_pm(Param pm, int altflag, int exp)
|
|||
* Some specials, such as those used in zle, still need removing
|
||||
* from the parameter table; they have the PM_REMOVABLE flag.
|
||||
*/
|
||||
if ((locallevel && locallevel >= pm->level) ||
|
||||
if ((pm->level && locallevel >= pm->level) ||
|
||||
(pm->flags & (PM_SPECIAL|PM_REMOVABLE)) == PM_SPECIAL)
|
||||
return;
|
||||
|
||||
|
@ -1963,23 +1966,11 @@ intvarsetfn(Param pm, long x)
|
|||
void
|
||||
zlevarsetfn(Param pm, long x)
|
||||
{
|
||||
if ((long *)pm->u.data == & columns) {
|
||||
if(x <= 0)
|
||||
x = tccolumns > 0 ? tccolumns : 80;
|
||||
if (x > 2)
|
||||
termflags &= ~TERM_NARROW;
|
||||
else
|
||||
termflags |= TERM_NARROW;
|
||||
} else if ((long *)pm->u.data == & lines) {
|
||||
if(x <= 0)
|
||||
x = tclines > 0 ? tclines : 24;
|
||||
if (x > 2)
|
||||
termflags &= ~TERM_SHORT;
|
||||
else
|
||||
termflags |= TERM_SHORT;
|
||||
}
|
||||
long *p = (long *)pm->u.data;
|
||||
|
||||
*((long *)pm->u.data) = x;
|
||||
*p = x;
|
||||
if (p == &lines || p == &columns)
|
||||
adjustwinsize(2 + (p == &columns));
|
||||
}
|
||||
|
||||
/* Function to set value of generic special scalar *
|
||||
|
|
|
@ -129,10 +129,9 @@ intr(void)
|
|||
install_handler(SIGINT);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* disable ^C interrupts */
|
||||
|
||||
/**/
|
||||
#if 0 /**/
|
||||
void
|
||||
nointr(void)
|
||||
{
|
||||
|
@ -505,7 +504,7 @@ handler(int sig)
|
|||
|
||||
#ifdef SIGWINCH
|
||||
case SIGWINCH:
|
||||
adjustwinsize(); /* check window size and adjust */
|
||||
adjustwinsize(1); /* check window size and adjust */
|
||||
if (sigtrapped[SIGWINCH])
|
||||
dotrap(SIGWINCH);
|
||||
break;
|
||||
|
|
25
Src/subst.c
25
Src/subst.c
|
@ -245,35 +245,43 @@ singsub(char **s)
|
|||
* the result is stored in *a. If `a' is zero a multiple word result is *
|
||||
* joined using sep or the IFS parameter if sep is zero and the result *
|
||||
* is returned in *s. The return value is true iff the expansion *
|
||||
* resulted in an empty list */
|
||||
* resulted in an empty list. *
|
||||
* The mult_isarr variable is used by paramsubst() to tell if it yields *
|
||||
* an array. */
|
||||
|
||||
static int mult_isarr;
|
||||
|
||||
/**/
|
||||
static int
|
||||
multsub(char **s, char ***a, int *isarr, char *sep)
|
||||
{
|
||||
LinkList foo;
|
||||
int l;
|
||||
int l, omi = mult_isarr;
|
||||
char **r, **p;
|
||||
|
||||
mult_isarr = 0;
|
||||
foo = newlinklist();
|
||||
addlinknode(foo, *s);
|
||||
prefork(foo, 0);
|
||||
if (errflag) {
|
||||
if (isarr)
|
||||
*isarr = 0;
|
||||
mult_isarr = omi;
|
||||
return 0;
|
||||
}
|
||||
if ((l = countlinknodes(foo)) > 1 || a) {
|
||||
if ((l = countlinknodes(foo))) {
|
||||
p = r = ncalloc((l + 1) * sizeof(char*));
|
||||
while (nonempty(foo))
|
||||
*p++ = (char *)ugetnode(foo);
|
||||
*p = NULL;
|
||||
if (a) {
|
||||
if (a && mult_isarr) {
|
||||
*a = r;
|
||||
*isarr = 1;
|
||||
mult_isarr = omi;
|
||||
return 0;
|
||||
}
|
||||
*s = sepjoin(r, NULL);
|
||||
mult_isarr = omi;
|
||||
return 0;
|
||||
}
|
||||
if (l)
|
||||
|
@ -282,6 +290,7 @@ multsub(char **s, char ***a, int *isarr, char *sep)
|
|||
*s = dupstring("");
|
||||
if (isarr)
|
||||
*isarr = 0;
|
||||
mult_isarr = omi;
|
||||
return !l;
|
||||
}
|
||||
|
||||
|
@ -977,16 +986,12 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
skipparens(*s, *s == Inpar ? Outpar : Outbrace, &s);
|
||||
sav = *s;
|
||||
*s = 0;
|
||||
if (multsub(&val, ((!aspar && (!quoted || nojoin)) ? &aval : NULL),
|
||||
&isarr, NULL) &&
|
||||
quoted) {
|
||||
if (multsub(&val, (aspar ? NULL : &aval), &isarr, NULL) && quoted) {
|
||||
isarr = -1;
|
||||
aval = alloc(sizeof(char *));
|
||||
aspar = 0;
|
||||
} else if (aspar)
|
||||
idbeg = val;
|
||||
if (isarr)
|
||||
isarr = -1;
|
||||
copied = 1;
|
||||
*s = sav;
|
||||
v = (Value) NULL;
|
||||
|
@ -1465,6 +1470,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
val = dupstring(buf);
|
||||
isarr = 0;
|
||||
}
|
||||
mult_isarr = isarr;
|
||||
if (isarr > 0 && !plan9 && (!aval || !aval[0])) {
|
||||
val = dupstring("");
|
||||
isarr = 0;
|
||||
|
@ -1485,6 +1491,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int ssub)
|
|||
val = aval[0];
|
||||
else
|
||||
isarr = 2;
|
||||
mult_isarr = isarr;
|
||||
}
|
||||
}
|
||||
if (casmod) {
|
||||
|
|
|
@ -72,10 +72,9 @@ taddstr(char *s)
|
|||
tptr += sl;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* add an integer to the text buffer */
|
||||
|
||||
/**/
|
||||
#if 0 /**/
|
||||
void
|
||||
taddint(int x)
|
||||
{
|
||||
|
|
61
Src/utils.c
61
Src/utils.c
|
@ -209,10 +209,9 @@ nicechar(int c)
|
|||
return buf;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Output a string's visible representation. */
|
||||
|
||||
/**/
|
||||
#if 0 /**/
|
||||
void
|
||||
nicefputs(char *s, FILE *f)
|
||||
{
|
||||
|
@ -853,27 +852,64 @@ int resetneeded;
|
|||
/**/
|
||||
int winchanged;
|
||||
#endif
|
||||
|
||||
/* check the size of the window and adjust if necessary */
|
||||
|
||||
/* check the size of the window and adjust if necessary. *
|
||||
* The value of from: *
|
||||
* 0: called from update_job or setupvals *
|
||||
* 1: called from the SIGWINCH handler *
|
||||
* 2: the user have just changed LINES manually *
|
||||
* 3: the user have just changed COLUMNS manually */
|
||||
|
||||
/**/
|
||||
void
|
||||
adjustwinsize(void)
|
||||
adjustwinsize(int from)
|
||||
{
|
||||
#ifdef TIOCGWINSZ
|
||||
int oldcols = columns, oldrows = lines;
|
||||
|
||||
#ifdef TIOCGWINSZ
|
||||
static int userlines, usercols;
|
||||
|
||||
if (SHTTY == -1)
|
||||
return;
|
||||
|
||||
ioctl(SHTTY, TIOCGWINSZ, (char *)&shttyinfo.winsize);
|
||||
setiparam("COLUMNS", shttyinfo.winsize.ws_col);
|
||||
setiparam("LINES", shttyinfo.winsize.ws_row);
|
||||
if (zleactive && (oldcols != columns || oldrows != lines)) {
|
||||
if (from == 2)
|
||||
userlines = lines > 0;
|
||||
if (from == 3)
|
||||
usercols = columns > 0;
|
||||
|
||||
if (!ioctl(SHTTY, TIOCGWINSZ, (char *)&shttyinfo.winsize)) {
|
||||
if (!userlines || from == 1)
|
||||
lines = shttyinfo.winsize.ws_row;
|
||||
if (!usercols || from == 1)
|
||||
columns = shttyinfo.winsize.ws_col;
|
||||
}
|
||||
#endif /* TIOCGWINSZ */
|
||||
|
||||
if (lines <= 0)
|
||||
lines = tclines > 0 ? tclines : 24;
|
||||
if (columns <= 0)
|
||||
columns = tccolumns > 0 ? tccolumns : 80;
|
||||
if (lines > 2)
|
||||
termflags &= ~TERM_SHORT;
|
||||
else
|
||||
termflags |= TERM_SHORT;
|
||||
if (columns > 2)
|
||||
termflags &= ~TERM_NARROW;
|
||||
else
|
||||
termflags |= TERM_NARROW;
|
||||
|
||||
#ifdef TIOCGWINSZ
|
||||
if (interact && from >= 2) {
|
||||
shttyinfo.winsize.ws_row = lines;
|
||||
shttyinfo.winsize.ws_col = columns;
|
||||
ioctl(SHTTY, TIOCSWINSZ, (char *)&shttyinfo.winsize);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (zleactive && (from >= 2 || oldcols != columns || oldrows != lines)) {
|
||||
resetneeded = winchanged = 1;
|
||||
zrefresh();
|
||||
}
|
||||
#endif /* TIOCGWINSZ */
|
||||
}
|
||||
|
||||
/* Move a fd to a place >= 10 and mark the new fd in fdtable. If the fd *
|
||||
|
@ -3343,10 +3379,9 @@ dquotedztrdup(char const *s)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Unmetafy and output a string, double quoting it in its entirety. */
|
||||
|
||||
/**/
|
||||
#if 0 /**/
|
||||
int
|
||||
dquotedzputs(char const *s, FILE *stream)
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@ addbuiltins
|
|||
addconddefs
|
||||
addedx
|
||||
addhashnode
|
||||
addhistnum
|
||||
addparamdefs
|
||||
addwrapper
|
||||
arrvargetfn
|
||||
|
@ -45,6 +46,7 @@ deleteparamdefs
|
|||
deletewrapper
|
||||
domatch
|
||||
doshfunc
|
||||
down_histent
|
||||
dputs
|
||||
dquotedztrdup
|
||||
dummy_list
|
||||
|
@ -97,6 +99,8 @@ hgetc
|
|||
hgetline
|
||||
histentarr
|
||||
histentct
|
||||
hist_ring
|
||||
hist_skip_flags
|
||||
holdintr
|
||||
hptr
|
||||
hrealloc
|
||||
|
@ -132,6 +136,7 @@ metadiffer
|
|||
metafy
|
||||
metalen
|
||||
mode_to_octal
|
||||
movehistent
|
||||
mypgrp
|
||||
mypid
|
||||
nameddirtab
|
||||
|
@ -240,6 +245,7 @@ unmetafy
|
|||
unsetparam
|
||||
unsetparam_pm
|
||||
untokenize
|
||||
up_histent
|
||||
uremnode
|
||||
useheap
|
||||
winchanged
|
||||
|
|
36
Src/zsh.h
36
Src/zsh.h
|
@ -294,7 +294,7 @@ struct linklist {
|
|||
#define peekfirst(X) ((X)->first->dat)
|
||||
#define pushnode(X,Y) insertlinknode(X,(LinkNode) X,Y)
|
||||
#define incnode(X) (X = nextnode(X))
|
||||
#define gethistent(X) (histentarr+((X)%histentct))
|
||||
#define firsthist() (hist_ring? hist_ring->down->histnum : curhist)
|
||||
|
||||
|
||||
/********************************/
|
||||
|
@ -611,6 +611,7 @@ struct job {
|
|||
#define STAT_CURSH (1<<9) /* last command is in current shell */
|
||||
#define STAT_NOSTTY (1<<10) /* the tty settings are not inherited */
|
||||
/* from this job when it exits. */
|
||||
#define STAT_ATTACH (1<<11) /* delay reattaching shell to tty */
|
||||
|
||||
#define SP_RUNNING -1 /* fake status for jobs currently running */
|
||||
|
||||
|
@ -679,6 +680,7 @@ typedef void (*AddNodeFunc) _((HashTable, char *, void *));
|
|||
typedef HashNode (*GetNodeFunc) _((HashTable, char *));
|
||||
typedef HashNode (*RemoveNodeFunc) _((HashTable, char *));
|
||||
typedef void (*FreeNodeFunc) _((HashNode));
|
||||
typedef int (*CompareFunc) _((const char *, const char *));
|
||||
|
||||
/* type of function that is passed to *
|
||||
* scanhashtable or scanmatchtable */
|
||||
|
@ -698,6 +700,7 @@ struct hashtable {
|
|||
HashFunc hash; /* pointer to hash function for this table */
|
||||
TableFunc emptytable; /* pointer to function to empty table */
|
||||
TableFunc filltable; /* pointer to function to fill table */
|
||||
CompareFunc cmpnodes; /* pointer to function to compare two nodes */
|
||||
AddNodeFunc addnode; /* pointer to function to add new node */
|
||||
GetNodeFunc getnode; /* pointer to function to get an enabled node */
|
||||
GetNodeFunc getnode2; /* pointer to function to get node */
|
||||
|
@ -1015,18 +1018,30 @@ struct nameddir {
|
|||
/* history entry */
|
||||
|
||||
struct histent {
|
||||
HashNode hash_next; /* next in hash chain */
|
||||
char *text; /* the history line itself */
|
||||
int flags; /* Misc flags */
|
||||
|
||||
Histent up; /* previous line (moving upward) */
|
||||
Histent down; /* next line (moving downward) */
|
||||
char *zle_text; /* the edited history line */
|
||||
time_t stim; /* command started time (datestamp) */
|
||||
time_t ftim; /* command finished time */
|
||||
short *words; /* Position of words in history */
|
||||
/* line: as pairs of start, end */
|
||||
int nwords; /* Number of words in history line */
|
||||
int flags; /* Misc flags */
|
||||
int histnum; /* A sequential history number */
|
||||
};
|
||||
|
||||
#define HIST_OLD 0x00000001 /* Command is already written to disk*/
|
||||
#define HIST_READ 0x00000002 /* Command was read back from disk*/
|
||||
#define HIST_MAKEUNIQUE 0x00000001 /* Kill this new entry if not unique */
|
||||
#define HIST_OLD 0x00000002 /* Command is already written to disk*/
|
||||
#define HIST_READ 0x00000004 /* Command was read back from disk*/
|
||||
#define HIST_DUP 0x00000008 /* Command duplicates a later line */
|
||||
#define HIST_FOREIGN 0x00000010 /* Command came from another shell */
|
||||
|
||||
#define GETHIST_UPWARD (-1)
|
||||
#define GETHIST_DOWNWARD 1
|
||||
#define GETHIST_EXACT 0
|
||||
|
||||
/* Parts of the code where history expansion is disabled *
|
||||
* should be within a pair of STOPHIST ... ALLOWHIST */
|
||||
|
@ -1039,6 +1054,13 @@ struct histent {
|
|||
#define HISTFLAG_RECALL 4
|
||||
#define HISTFLAG_SETTY 8
|
||||
|
||||
#define HFILE_APPEND 0x0001
|
||||
#define HFILE_SKIPOLD 0x0002
|
||||
#define HFILE_SKIPDUPS 0x0004
|
||||
#define HFILE_SKIPFOREIGN 0x0008
|
||||
#define HFILE_FAST 0x0010
|
||||
#define HFILE_USE_OPTIONS 0x8000
|
||||
|
||||
/******************************************/
|
||||
/* Definitions for programable completion */
|
||||
/******************************************/
|
||||
|
@ -1120,15 +1142,20 @@ enum {
|
|||
HASHLISTALL,
|
||||
HISTALLOWCLOBBER,
|
||||
HISTBEEP,
|
||||
HISTEXPIREDUPSFIRST,
|
||||
HISTFINDNODUPS,
|
||||
HISTIGNOREALLDUPS,
|
||||
HISTIGNOREDUPS,
|
||||
HISTIGNORESPACE,
|
||||
HISTNOFUNCTIONS,
|
||||
HISTNOSTORE,
|
||||
HISTREDUCEBLANKS,
|
||||
HISTSAVENODUPS,
|
||||
HISTVERIFY,
|
||||
HUP,
|
||||
IGNOREBRACES,
|
||||
IGNOREEOF,
|
||||
INCREMENTALAPPENDHISTORY,
|
||||
INTERACTIVE,
|
||||
INTERACTIVECOMMENTS,
|
||||
KSHARRAYS,
|
||||
|
@ -1172,6 +1199,7 @@ enum {
|
|||
RESTRICTED,
|
||||
RMSTARSILENT,
|
||||
RMSTARWAIT,
|
||||
SHAREHISTORY,
|
||||
SHFILEEXPANSION,
|
||||
SHGLOB,
|
||||
SHINSTDIN,
|
||||
|
|
|
@ -302,7 +302,11 @@ then
|
|||
echo
|
||||
zmodload -d -L
|
||||
echo
|
||||
zmodload -a -L
|
||||
zmodload -ab -L
|
||||
echo
|
||||
zmodload -ac -L
|
||||
echo
|
||||
zmodload -ap -L
|
||||
echo
|
||||
zmodload -L
|
||||
else
|
||||
|
|
|
@ -189,9 +189,6 @@
|
|||
/* Define to 1 if struct timezone is defined by a system header */
|
||||
#undef HAVE_STRUCT_TIMEZONE
|
||||
|
||||
/* Define if your system's typeahead disappears from the shell editor. */
|
||||
#undef CLOBBERS_TYPEAHEAD
|
||||
|
||||
/* Define to 1 if there is a prototype defined for brk() on your system */
|
||||
#undef HAVE_BRK_PROTO
|
||||
|
||||
|
|
41
aczsh.m4
41
aczsh.m4
|
@ -24,6 +24,47 @@ dnl Zsh Development Group have no obligation to provide maintenance,
|
|||
dnl support, updates, enhancements, or modifications.
|
||||
dnl
|
||||
|
||||
dnl
|
||||
dnl Code from the configure system for bash 2.03 (not zsh copyright).
|
||||
dnl If available, use support for large files unless the user specified
|
||||
dnl one of the CPPFLAGS, LDFLAGS, or LIBS variables (<eggert@twinsun.com>
|
||||
dnl via GNU patch 2.5)
|
||||
dnl
|
||||
AC_DEFUN(zsh_LARGE_FILE_SUPPORT,
|
||||
[AC_MSG_CHECKING(whether large file support needs explicit enabling)
|
||||
ac_getconfs=''
|
||||
ac_result=yes
|
||||
ac_set=''
|
||||
ac_shellvars='CPPFLAGS LDFLAGS LIBS'
|
||||
for ac_shellvar in $ac_shellvars; do
|
||||
case $ac_shellvar in
|
||||
CPPFLAGS) ac_lfsvar=LFS_CFLAGS ac_lfs64var=LFS64_CFLAGS ;;
|
||||
*) ac_lfsvar=LFS_$ac_shellvar ac_lfs64var=LFS64_$ac_shellvar ;;
|
||||
esac
|
||||
eval test '"${'$ac_shellvar'+set}"' = set && ac_set=$ac_shellvar
|
||||
(getconf $ac_lfsvar) >/dev/null 2>&1 || { ac_result=no; break; }
|
||||
ac_getconf=`getconf $ac_lfsvar`
|
||||
ac_getconf64=`getconf $ac_lfs64var`
|
||||
ac_getconfs=$ac_getconfs$ac_getconf\ $ac_getconf64
|
||||
eval ac_test_$ac_shellvar="\$ac_getconf\ \$ac_getconf64"
|
||||
done
|
||||
case "$ac_result$ac_getconfs" in
|
||||
yes) ac_result=no ;;
|
||||
esac
|
||||
case "$ac_result$ac_set" in
|
||||
yes?*) test "x$ac_set" != "xLDFLAGS" -o "x$auto_ldflags" = x && {
|
||||
ac_result="yes, but $ac_set is already set, so use its settings"
|
||||
}
|
||||
esac
|
||||
AC_MSG_RESULT($ac_result)
|
||||
case $ac_result in
|
||||
yes)
|
||||
for ac_shellvar in $ac_shellvars; do
|
||||
eval $ac_shellvar=\$ac_test_$ac_shellvar
|
||||
done ;;
|
||||
esac
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl zsh_SYS_DYNAMIC_BROKEN
|
||||
dnl Check whether static/shared library linking is broken.
|
||||
|
|
23
configure.in
23
configure.in
|
@ -204,6 +204,10 @@ test -z "${LDFLAGS+set}" && LDFLAGS= auto_ldflags=1
|
|||
|
||||
AC_PROG_CC
|
||||
|
||||
dnl Check for large file support (Solaris).
|
||||
dnl This needs to be done early to get the stuff into the flags.
|
||||
zsh_LARGE_FILE_SUPPORT
|
||||
|
||||
dnl if the user hasn't specified CFLAGS, then
|
||||
dnl if compiler is gcc, then use -O2 and some warning flags
|
||||
dnl else use -O
|
||||
|
@ -883,25 +887,6 @@ zsh_PATH_UTMP(wtmp)
|
|||
zsh_PATH_UTMP(utmpx)
|
||||
zsh_PATH_UTMP(wtmpx)
|
||||
|
||||
dnl ----------------
|
||||
dnl TYPEAHEAD KLUDGE
|
||||
dnl ----------------
|
||||
dnl Some systems clobber typeahead when you go from canonical input
|
||||
dnl processing to non-canonical, so we need a FIONREAD ioctl.
|
||||
dnl I don't know how to check this with configure, so I am using the
|
||||
dnl system names directly.
|
||||
dnl The doubled square brackets are necessary because autoconf uses m4.
|
||||
AC_CACHE_CHECK(if typeahead needs FIONREAD, zsh_cv_sys_clobbers_typeahead,
|
||||
[case x-$host_vendor-$host_os in
|
||||
x-*-ultrix* | x-*-dgux* | x-sni-sysv4* | x-*-irix*)
|
||||
zsh_cv_sys_clobbers_typeahead=yes;;
|
||||
*)
|
||||
zsh_cv_sys_clobbers_typeahead=no;;
|
||||
esac])
|
||||
if test $zsh_cv_sys_clobbers_typeahead = yes; then
|
||||
AC_DEFINE(CLOBBERS_TYPEAHEAD)
|
||||
fi
|
||||
|
||||
dnl -------------------
|
||||
dnl brk/sbrk PROTOTYPES
|
||||
dnl -------------------
|
||||
|
|
|
@ -1012,7 +1012,71 @@ pws: 6165: globsubst'd foo='~/bin' depended on extendedglob being set
|
|||
|
||||
Sven: 6167: show unloaded parameters as undefined
|
||||
|
||||
Bart: 6171 as rewritten in 6174: old RedHat Linux doesn't have normall
|
||||
Bart: 6171 as rewritten in 6174: old RedHat Linux doesn't have normal
|
||||
definitions for poll.
|
||||
|
||||
pws: 6180: Completion/Core/compinstall
|
||||
|
||||
pws-18
|
||||
|
||||
Bart: 6188: compinit speedup
|
||||
|
||||
pws: 6193: [un]setopt shouldn't complain when setting an unsettable option
|
||||
to the value it already has
|
||||
|
||||
Sven: 6194: complete assoc array arguments by default where necessary
|
||||
|
||||
Sven: 6195: _expand_word and _correct_word change.
|
||||
|
||||
Sven: 6197: off by one error parsing assignment in completion
|
||||
|
||||
pws: 6202: trivial _correct_filename change, ^Xc -> ^XC
|
||||
|
||||
pws: 6205: use FIONREAD wherever defined, read chars immediately into
|
||||
buffer
|
||||
|
||||
Bart: 6213: race condition in $(...), use waitforpid() instead of
|
||||
unblocking child (which shouldn't happen until later).
|
||||
|
||||
Tanaka Akira: 6219: initialize a variable in zle_tricky.c
|
||||
|
||||
Wayne: 6220: various compilation warnings
|
||||
|
||||
pws: 6224: alter 6205 to read chars only when necessary, but ensure
|
||||
terminal is set appropriately.
|
||||
|
||||
pws: 6227: configuration for large file support (from bash aclocal.m4).
|
||||
|
||||
pws: 6235: unset -m shouldn't restore unset parameters; unsetting a global
|
||||
should remove it from paramtab even inside a function.
|
||||
|
||||
Wayne: 6236: history changes to improve management of duplicate lines,
|
||||
incremental history read/write, and sharing history
|
||||
|
||||
pws: 6237: window size code upgraded from 3.0.6-pre2, plus Bart's patch
|
||||
4447.
|
||||
|
||||
pws: 6238: Wayne's share_history option set in ksh emulation
|
||||
|
||||
pws: 6239: need space after incrementalappendhistory for kshoptionprint
|
||||
|
||||
pws: 6240: a pipeline ending in a builtin didn't attach to the tty pgrp.
|
||||
|
||||
Wayne: 6241: history editing can use foreign history commands; history
|
||||
appended in hend() instead of hbegin()
|
||||
|
||||
Sven: 6046: nested parameter expansions can return either arrays or
|
||||
scalars.
|
||||
|
||||
pws: 6246: doc changes for 6046, plus subscripts done properly
|
||||
|
||||
Sven: 6249: fix for 6046 (problem showed up with $(...))
|
||||
|
||||
Wayne: 6255: more history: zle toggle between local/global history; `zle
|
||||
widget' can now take a direct numeric argument; small tweaks
|
||||
|
||||
pws: 6257: rewrite 6240 for any old builtin structure after the pipeline
|
||||
|
||||
pws: 6258: yet another attempt at the same problem
|
||||
|
||||
pws: 6259: second version of compinstall
|
||||
|
|
Loading…
Reference in a new issue