unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Stefan Monnier <monnier@IRO.UMontreal.CA>
To: Chong Yidong <cyd@stupidchicken.com>
Cc: 7924@debbugs.gnu.org, Reuben Thomas <rrt@sc3d.org>
Subject: bug#7924: 23.2.91; Documentation about CDPATH is a little misleading
Date: Tue, 01 Feb 2011 17:11:52 -0500	[thread overview]
Message-ID: <jwv62t3h0eb.fsf-monnier+emacs@gnu.org> (raw)
In-Reply-To: <87k4hnp9ui.fsf@stupidchicken.com> (Chong Yidong's message of "Sat, 29 Jan 2011 18:29:41 -0500")

>> Both in the manual and in the docstring for `cd', one might reasonably
>> infer (as I did!) that CDPATH will be searched when completing relative
>> directory names, but this is not the case.
>> 
>> Is there in fact any way to get this to work? It’s something that one
>> can do nicely in bash in a terminal, for example, but not in shell-mode.

> I think this needs new code in `read-file-name-internal' (the completion
> function for read-file-name).

The patch below seems to work in my brief testing.


        Stefan


=== modified file 'lisp/files.el'
--- lisp/files.el	2011-02-01 20:53:09 +0000
+++ lisp/files.el	2011-02-01 22:06:43 +0000
@@ -700,25 +700,36 @@
 `path-separator') when resolving a relative directory name.
 The path separator is colon in GNU and GNU-like systems."
   (interactive
-   (list (read-directory-name "Change default directory: "
+   (list
+    ;; FIXME: There's a subtle bug in the completion below.  Seems linked
+    ;; to a fundamental difficulty of implementing `predicate' correctly.
+    ;; The manifestation is that TAB may list non-directories in the case where
+    ;; those files also correspond to valid directories (if your cd-path is (A/
+    ;; B/) and you have A/a a file and B/a a directory, then both `a' and `a/'
+    ;; will be listed as valid completions).
+    ;; This is because `a' (listed because of A/a) is indeed a valid choice
+    ;; (which will lead to the use of B/a).
+    (minibuffer-with-setup-hook
+        (lambda ()
+          (setq minibuffer-completion-table
+                (apply-partially #'locate-file-completion-table
+                                 cd-path nil))
+          (setq minibuffer-completion-predicate
+                (lambda (dir)
+                  (locate-file dir cd-path nil
+                               (lambda (f) (and (file-directory-p f) 'dir-ok))))))
+      (unless cd-path
+        (setq cd-path (or (parse-colon-path (getenv "CDPATH"))
+                          (list "./"))))
+      (read-directory-name "Change default directory: "
 			 default-directory default-directory
-			 (and (member cd-path '(nil ("./")))
-			      (null (getenv "CDPATH"))))))
-  (if (file-name-absolute-p dir)
-      (cd-absolute (expand-file-name dir))
-    (if (null cd-path)
-	(let ((trypath (parse-colon-path (getenv "CDPATH"))))
-	  (setq cd-path (or trypath (list "./")))))
-    (if (not (catch 'found
-	       (mapc
-		(function (lambda (x)
-			    (let ((f (expand-file-name (concat x dir))))
-			      (if (file-directory-p f)
-				  (progn
-				    (cd-absolute f)
-				    (throw 'found t))))))
-		cd-path)
-	       nil))
+                           t))))
+  (unless cd-path
+    (setq cd-path (or (parse-colon-path (getenv "CDPATH"))
+                      (list "./"))))
+  (cd-absolute
+   (or (locate-file dir cd-path nil
+                    (lambda (f) (and (file-directory-p f) 'dir-ok)))
 	(error "No such directory found via CDPATH environment variable"))))
 
 (defun load-file (file)

=== modified file 'src/lread.c'
--- src/lread.c	2011-01-31 18:47:03 +0000
+++ src/lread.c	2011-02-01 21:57:03 +0000
@@ -1223,7 +1223,9 @@
 file name when searching.
 If non-nil, PREDICATE is used instead of `file-readable-p'.
 PREDICATE can also be an integer to pass to the access(2) function,
-in which case file-name-handlers are ignored.  */)
+in which case file-name-handlers are ignored.
+This function will normally skip directories, so if you want it to find
+directories, make sure the PREDICATE function return `dir-ok' for them.  */)
   (Lisp_Object filename, Lisp_Object path, Lisp_Object suffixes, Lisp_Object predicate)
 {
   Lisp_Object file;
@@ -1233,6 +1235,7 @@
   return file;
 }
 
+static Lisp_Object Qdir_ok;
 
 /* Search for a file whose name is STR, looking in directories
    in the Lisp list PATH, and trying suffixes from SUFFIX.
@@ -1350,9 +1353,12 @@
 	      if (NILP (predicate))
 		exists = !NILP (Ffile_readable_p (string));
 	      else
-		exists = !NILP (call1 (predicate, string));
-	      if (exists && !NILP (Ffile_directory_p (string)))
-		exists = 0;
+		{
+		  Lisp_Object tmp = call1 (predicate, string);
+		  exists = !NILP (tmp)
+		    && (EQ (tmp, Qdir_ok)
+			|| !NILP (Ffile_directory_p (string)));
+		}
 
 	      if (exists)
 		{
@@ -4369,6 +4375,9 @@
   Qfile_truename = intern_c_string ("file-truename");
   staticpro (&Qfile_truename) ;
 
+  Qdir_ok = intern_c_string ("dir-ok");
+  staticpro (&Qdir_ok);
+  
   Qdo_after_load_evaluation = intern_c_string ("do-after-load-evaluation");
   staticpro (&Qdo_after_load_evaluation) ;
 






  parent reply	other threads:[~2011-02-01 22:11 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-01-26 21:48 bug#7924: 23.2.91; Documentation about CDPATH is a little misleading Reuben Thomas
2011-01-29 23:29 ` Chong Yidong
2011-01-30 13:34   ` Reuben Thomas
2011-01-31  4:09   ` Stefan Monnier
2011-02-01 22:11   ` Stefan Monnier [this message]
2011-02-03 11:41     ` Reuben Thomas
2011-02-18 17:27       ` Stefan Monnier
2011-02-22 11:25     ` Andrew W. Nosenko

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

  List information: https://www.gnu.org/software/emacs/

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

  git send-email \
    --in-reply-to=jwv62t3h0eb.fsf-monnier+emacs@gnu.org \
    --to=monnier@iro.umontreal.ca \
    --cc=7924@debbugs.gnu.org \
    --cc=cyd@stupidchicken.com \
    --cc=rrt@sc3d.org \
    /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.savannah.gnu.org/cgit/emacs.git

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 read-only IMAP folder(s) and NNTP newsgroup(s).