summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Completion/Unix/Type/_canonical_paths57
-rw-r--r--Doc/Zsh/builtins.yo39
-rw-r--r--Etc/relnotes_4.3.6.txt19
-rw-r--r--Src/builtin.c17
5 files changed, 93 insertions, 46 deletions
diff --git a/ChangeLog b/ChangeLog
index 40ab94286..3ae57347c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2008-03-28 Peter Stephenson <pws@csr.com>
+
+ * 24768: Completion/Unix/Type/_canonical_paths,
+ Doc/Zsh/builtins.yo, Etc/relnotes_4.3.6.txt, Src/builtin.c:
+ add -q option to cd, chdir, pushd, popd; use in _canonical_paths;
+ document in release note.
+
2008-03-27 Peter Stephenson <pws@csr.com>
* 24759: Completion/Unix/Type/_canonical_paths: unfunction
diff --git a/Completion/Unix/Type/_canonical_paths b/Completion/Unix/Type/_canonical_paths
index 3274145a8..d23b913ef 100644
--- a/Completion/Unix/Type/_canonical_paths
+++ b/Completion/Unix/Type/_canonical_paths
@@ -15,42 +15,45 @@
_canonical_paths_pwd() {
# Get the canonical directory name by changing to it.
- # To be run in a subshell.
- (( ${+functions[chpwd]} )) && unfunction chpwd
- setopt CHASE_LINKS
- cd $1 2>/dev/null && pwd
+ integer chaselinks
+ [[ -o chaselinks ]] && (( chaselinks = 1 ))
+ setopt localoptions nopushdignoredups chaselinks
+ if builtin pushd -q -- $1 2>/dev/null; then
+ REPLY=$PWD
+ (( chaselinks )) || unsetopt chaselinks
+ builtin popd -q
+ else
+ REPLY=$1
+ fi
}
_canonical_paths_get_canonical_path() {
- typeset newfile dir
+ typeset newfile nondir
typeset -A seen
REPLY=$1
- # Resolve any trailing symbolic links, guarding against loops.
- while [[ -z ${seen[$REPLY]} ]]; do
- seen[$REPLY]=1
- newfile=()
- zstat -A newfile +link $REPLY 2>/dev/null
- if [[ -n $newfile[1] ]]; then
- REPLY=$newfile[1]
- else
- break
- fi
- done
-
# Canonicalise the directory path. We may not be able to
# do this if we can't read all components.
if [[ -d $REPLY ]]; then
- dir="$(_canonical_paths_pwd $REPLY)"
- if [[ -n $dir ]]; then
- REPLY=$dir
- fi
- elif [[ $REPLY = */*[^/] && $REPLY != /[^/]# ]]; then
- # Don't try this if there's a trailing slash or we're in
- # the root directory.
- dir="$(_canonical_paths_pwd ${REPLY%/*})"
- if [[ -n $dir ]]; then
- REPLY=$dir/${REPLY##*/}
+ _canonical_paths_pwd $REPLY
+ else
+ # Resolve any trailing symbolic links, guarding against loops.
+ while [[ -z ${seen[$REPLY]} ]]; do
+ seen[$REPLY]=1
+ newfile=()
+ zstat -A newfile +link $REPLY 2>/dev/null
+ if [[ -n $newfile[1] ]]; then
+ REPLY=$newfile[1]
+ else
+ break
+ fi
+ done
+ if [[ $REPLY = */*[^/] && $REPLY != /[^/]# ]]; then
+ # Don't try this if there's a trailing slash or we're in
+ # the root directory.
+ nondir=${REPLY##*/#}
+ _canonical_paths_pwd ${REPLY%/#*}
+ REPLY+="/$nondir"
fi
fi
}
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 516489886..574692078 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -152,16 +152,16 @@ alias(bye)(exit)
module(cap)(zsh/cap)
findex(cd)
cindex(directories, changing)
-xitem(tt(cd) [ tt(-sLP) ] [ var(arg) ])
-xitem(tt(cd) [ tt(-sLP) ] var(old) var(new))
-item(tt(cd) [ tt(-sLP) ] {tt(PLUS())|tt(-)}var(n))(
+xitem(tt(cd) [ tt(-qsLP) ] [ var(arg) ])
+xitem(tt(cd) [ tt(-qsLP) ] var(old) var(new))
+item(tt(cd) [ tt(-qsLP) ] {tt(PLUS())|tt(-)}var(n))(
Change the current directory. In the first form, change the
current directory to var(arg), or to the value of tt($HOME) if
var(arg) is not specified. If var(arg) is `tt(-)', change to the
value of tt($OLDPWD), the previous directory.
Otherwise, if var(arg) begins with a slash, attempt to change to the
-director given by var(arg).
+directory given by var(arg).
If var(arg) does not begin with a slash, the behaviour depends on whether
the current directory `tt(.)' occurs in the list of directories contained
@@ -189,11 +189,17 @@ An argument of the form `tt(-)var(n)' counts from the right.
If the tt(PUSHD_MINUS) option is set, the meanings of `tt(PLUS())'
and `tt(-)' in this context are swapped.
+If the tt(-q) (quiet) option is specified, the hook function tt(chpwd)
+and the functions in the array tt(chpwd_functions) are not called.
+This is useful for calls to tt(cd) that do not change the environment
+seen by an interactive user.
+
If the tt(-s) option is specified, tt(cd) refuses to change the current
directory if the given pathname contains symlinks. If the tt(-P) option
is given or the tt(CHASE_LINKS) option is set, symbolic links are resolved
to their true values. If the tt(-L) option is given symbolic links are
-followed regardless of the state of the tt(CHASE_LINKS) option.
+retained in the directory (and not resolved) regardless of the state of
+the tt(CHASE_LINKS) option.
)
alias(chdir)(cd)
module(clone)(zsh/clone)
@@ -795,7 +801,7 @@ Same as tt(exit), except that it only works in a login shell.
)
prefix(noglob)
findex(popd)
-item(tt(popd) [ {tt(PLUS())|tt(-)}var(n) ])(
+item(tt(popd) [ [-q] {tt(PLUS())|tt(-)}var(n) ])(
Remove an entry from the directory stack, and perform a tt(cd) to
the new top directory. With no argument, the current top entry is
removed. An argument of the form `tt(PLUS())var(n)' identifies a stack
@@ -804,6 +810,11 @@ starting with zero. An argument of the form tt(-n) counts from the right.
pindex(PUSHD_MINUS, use of)
If the tt(PUSHD_MINUS) option is set, the meanings of `tt(PLUS())' and
`tt(-)' in this context are swapped.
+
+If the tt(-q) (quiet) option is specified, the hook function tt(chpwd)
+and the functions in the array tt($chpwd_functions) are not called,
+and the new directory stack is not printed. This is useful for calls to
+tt(popd) that do not change the environment seen by an interactive user.
)
findex(print)
xitem(tt(print) [ tt(-abcDilmnNoOpPrsz) ] [ tt(-u) var(n) ] [ tt(-f) var(format) ] [ tt(-C) var(cols) ])
@@ -935,9 +946,9 @@ pindex(PUSHD_TO_HOME, use of)
pindex(PUSHD_MINUS, use of)
pindex(CDABLE_VARS, use of)
pindex(PUSHD_SILENT, use of)
-xitem(tt(pushd) [ tt(-sLP) ] [ var(arg) ])
-xitem(tt(pushd) [ tt(-sLP) ] var(old) var(new))
-item(tt(pushd) [ tt(-sLP) ] {tt(PLUS())|tt(-)}var(n))(
+xitem(tt(pushd) [ tt(-qsLP) ] [ var(arg) ])
+xitem(tt(pushd) [ tt(-qsLP) ] var(old) var(new))
+item(tt(pushd) [ tt(-qsLP) ] {tt(PLUS())|tt(-)}var(n))(
Change the current directory, and push the old current directory
onto the directory stack. In the first form, change the
current directory to var(arg).
@@ -956,8 +967,14 @@ command, starting with zero. An argument of the form `tt(-)var(n)' counts
from the right. If the tt(PUSHD_MINUS) option is set, the meanings
of `tt(PLUS())' and `tt(-)' in this context are swapped.
-If the option tt(PUSHD_SILENT) is not set, the directory
-stack will be printed after a tt(pushd) is performed.
+If the tt(-q) (quiet) option is specified, the hook function tt(chpwd)
+and the functions in the array tt($chpwd_functions) are not called,
+and the new directory stack is not printed. This is useful for calls to
+tt(pushd) that do not change the environment seen by an interactive user.
+
+If the option tt(-q) is not specified and the shell option tt(PUSHD_SILENT)
+is not set, the directory stack will be printed after a tt(pushd) is
+performed.
The options tt(-s), tt(-L) and tt(-P) have the same meanings as for the
tt(cd) builtin.
diff --git a/Etc/relnotes_4.3.6.txt b/Etc/relnotes_4.3.6.txt
new file mode 100644
index 000000000..32ac311b9
--- /dev/null
+++ b/Etc/relnotes_4.3.6.txt
@@ -0,0 +1,19 @@
+Version 4.3.6 contains mostly bugfixes, but there are some small
+improvements. No incompatibilities with previous versions are known.
+
+Visible changes in the shell and its modules since 4.3.5 include the
+following:
+
+The parameter subscripting flag "e", which existed but had limited
+usefulness, has been extended to allow reverse matching of strings instead
+of patterns. For example, "${array[(ie)*]}" substitutes the index of the
+array element that contains the exact string "*". In previous versions of
+the shell a fairly hairy process was necessary to ensure pattern characters
+were quoted.
+
+The cd, chdir, pushd and popd builtins now take the option -q (quiet) which
+avoids side effects when changing directories, suppressing the effect of
+the chpwd function, the chpwd_functions array and printing of the directory
+stack. The last was already possible with the option PUSHD_SILENT, but in
+previous versions of the shell there was no easy way of suppressing the
+other side effects.
diff --git a/Src/builtin.c b/Src/builtin.c
index 14252efc5..c70d4de69 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -50,8 +50,8 @@ static struct builtin builtins[] =
BUILTIN("bg", 0, bin_fg, 0, -1, BIN_BG, NULL, NULL),
BUILTIN("break", BINF_PSPECIAL, bin_break, 0, 1, BIN_BREAK, NULL, NULL),
BUILTIN("bye", 0, bin_break, 0, 1, BIN_EXIT, NULL, NULL),
- BUILTIN("cd", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 2, BIN_CD, "sPL", NULL),
- BUILTIN("chdir", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 2, BIN_CD, "sPL", NULL),
+ BUILTIN("cd", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 2, BIN_CD, "qsPL", NULL),
+ BUILTIN("chdir", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 2, BIN_CD, "qsPL", NULL),
BUILTIN("continue", BINF_PSPECIAL, bin_break, 0, 1, BIN_CONTINUE, NULL, NULL),
BUILTIN("declare", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klmprtuxz", NULL),
BUILTIN("dirs", 0, bin_dirs, 0, -1, 0, "clpv", NULL),
@@ -98,10 +98,10 @@ static struct builtin builtins[] =
BUILTIN("patdebug", 0, bin_patdebug, 1, -1, 0, "p", NULL),
#endif
- BUILTIN("popd", 0, bin_cd, 0, 1, BIN_POPD, NULL, NULL),
+ BUILTIN("popd", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 1, BIN_POPD, "q", NULL),
BUILTIN("print", BINF_PRINTOPTS, bin_print, 0, -1, BIN_PRINT, "abcC:Df:ilmnNoOpPrRsu:z-", NULL),
BUILTIN("printf", 0, bin_print, 1, -1, BIN_PRINTF, NULL, NULL),
- BUILTIN("pushd", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 2, BIN_PUSHD, "sPL", NULL),
+ BUILTIN("pushd", BINF_SKIPINVALID | BINF_SKIPDASH | BINF_DASHDASHVALID, bin_cd, 0, 2, BIN_PUSHD, "qsPL", NULL),
BUILTIN("pushln", 0, bin_print, 0, -1, BIN_PRINT, NULL, "-nz"),
BUILTIN("pwd", 0, bin_pwd, 0, 0, 0, "rLP", NULL),
BUILTIN("r", 0, bin_fc, 0, -1, BIN_R, "nrl", NULL),
@@ -788,7 +788,7 @@ bin_cd(char *nam, char **argv, Options ops, int func)
unqueue_signals();
return 1;
}
- cd_new_pwd(func, dir);
+ cd_new_pwd(func, dir, OPT_ISSET(ops, 'q'));
if (stat(unmeta(pwd), &st1) < 0) {
setjobpwd();
@@ -1087,7 +1087,7 @@ cd_try_chdir(char *pfix, char *dest, int hard)
/**/
static void
-cd_new_pwd(int func, LinkNode dir)
+cd_new_pwd(int func, LinkNode dir, int quiet)
{
char *new_pwd, *s;
int dirstacksize;
@@ -1127,7 +1127,7 @@ cd_new_pwd(int func, LinkNode dir)
if (isset(INTERACTIVE)) {
if (func != BIN_CD) {
- if (unset(PUSHDSILENT))
+ if (unset(PUSHDSILENT) && !quiet)
printdirstack();
} else if (doprintdir) {
fprintdir(pwd, stdout);
@@ -1138,7 +1138,8 @@ cd_new_pwd(int func, LinkNode dir)
/* execute the chpwd function */
fflush(stdout);
fflush(stderr);
- callhookfunc("chpwd", NULL, 1);
+ if (!quiet)
+ callhookfunc("chpwd", NULL, 1);
dirstacksize = getiparam("DIRSTACKSIZE");
/* handle directory stack sizes out of range */