diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | Completion/Unix/Type/_canonical_paths | 57 | ||||
-rw-r--r-- | Doc/Zsh/builtins.yo | 39 | ||||
-rw-r--r-- | Etc/relnotes_4.3.6.txt | 19 | ||||
-rw-r--r-- | Src/builtin.c | 17 |
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 */ |