zsh-workers
 help / color / mirror / code / Atom feed
From: Peter Stephenson <pws@csr.com>
To: zsh-workers@sunsite.dk
Subject: PATCH: cd -q (was Re: _canonical_path ...)
Date: Thu, 27 Mar 2008 12:15:25 +0000	[thread overview]
Message-ID: <20080327121525.5b4059f9@news01> (raw)
In-Reply-To: <20080327112506.7298e9ef@news01>

On Thu, 27 Mar 2008 11:25:06 +0000
Peter Stephenson <pws@csr.com> wrote:
> I thought unfunction was silent if a function didn't exist, as is now
> true of (and required for) unset, but apparently not.
> +_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
> +}

The more I think about this (and I'd really like to stop now), the more
wrong it seems to me that it's so hard to get the shell to cd without
side effects.  Indeed, the patch above is incomplete since it omits
the new chpwd_functions array, and I haven't work out a foolproof
way of suppressing the effect of chpwd without forking the shell.
chpwd will typically print a bogus directory to the terminal title
bar, which is to be avoided; but it can in principle do anything
and if we're not sticking around in the directory the interactive
environment really doesn't need to care about the cd.

Any comments about the following proposal, which adds the -q option
to all relevant functions?  If it looks OK, I'll change the function
above to unsetopt PUSHD_NO_DUPS and use pushd -q/popd -q to sanitize
the directory with REPLY=$PWD and remove the fork.

Index: Doc/Zsh/builtins.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/builtins.yo,v
retrieving revision 1.103
diff -u -r1.103 builtins.yo
--- Doc/Zsh/builtins.yo	1 Feb 2008 19:59:45 -0000	1.103
+++ Doc/Zsh/builtins.yo	27 Mar 2008 11:49:30 -0000
@@ -152,9 +152,9 @@
 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
@@ -189,6 +189,11 @@
 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
@@ -795,7 +800,7 @@
 )
 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 +809,11 @@
 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 +945,9 @@
 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 +966,14 @@
 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.
Index: Src/builtin.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/builtin.c,v
retrieving revision 1.188
diff -u -r1.188 builtin.c
--- Src/builtin.c	2 Mar 2008 21:21:53 -0000	1.188
+++ Src/builtin.c	27 Mar 2008 11:49:31 -0000
@@ -50,8 +50,8 @@
     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 @@
     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 @@
 	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 @@
 
 /**/
 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 @@
 
     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 @@
     /* 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 */

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


  reply	other threads:[~2008-03-27 12:16 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-26 10:44 _canonical_path not working on *BSD Baptiste Daroussin
2008-03-26 15:01 ` Debian bugs (Re: _canonical_path not working on *BSD) Bart Schaefer
2008-03-26 15:25   ` Clint Adams
2008-03-26 15:05 ` _canonical_path not working on *BSD Peter Stephenson
2008-03-26 15:27   ` Baptiste Daroussin
2008-03-26 15:34     ` Peter Stephenson
2008-03-26 15:51       ` Pea
2008-03-26 15:59       ` Clint Adams
2008-03-26 15:21 ` Pea
2008-03-26 15:36 ` Bart Schaefer
2008-03-26 15:40   ` Peter Stephenson
2008-03-26 16:04     ` Peter Stephenson
2008-03-26 16:18       ` Bart Schaefer
2008-03-26 16:21       ` Peter Stephenson
2008-03-26 16:38         ` Pea
2008-03-26 16:46           ` Peter Stephenson
2008-03-26 17:08             ` Pea
2008-03-26 17:17             ` Baptiste Daroussin
2008-03-27 10:23             ` Peter Stephenson
2008-03-27 11:08               ` Pea
2008-03-27 11:25                 ` Peter Stephenson
2008-03-27 12:15                   ` Peter Stephenson [this message]
2008-03-27 12:25                     ` PATCH: cd -q (was Re: _canonical_path ...) Stephane Chazelas
2008-03-27 12:35                     ` Mikael Magnusson
2008-03-27 12:48                       ` Peter Stephenson
2008-03-27 12:56                         ` Mikael Magnusson
2008-03-27 18:45                     ` Peter Stephenson
2008-03-28  8:16                       ` Pea
2008-03-28 11:01                       ` Mikael Magnusson
2008-03-28 14:35                         ` Peter Stephenson
2008-03-27 12:31                   ` _canonical_path not working on *BSD Pea
2008-03-27 15:39               ` Bart Schaefer
2008-03-27 18:06                 ` Peter Stephenson
2008-03-28  1:01                   ` Bart Schaefer
2008-03-28  7:51                     ` Mikael Magnusson
2008-03-28 10:01                     ` Peter Stephenson
2008-03-26 16:25       ` Pea

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080327121525.5b4059f9@news01 \
    --to=pws@csr.com \
    --cc=zsh-workers@sunsite.dk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).