emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 4529057: Make directory-files-recursively take a PR


From: Lars Ingebrigtsen
Subject: [Emacs-diffs] master 4529057: Make directory-files-recursively take a PREDICATE parameter
Date: Mon, 15 Jul 2019 05:54:16 -0400 (EDT)

branch: master
commit 4529057c97322893fb415512a2a51bc4616754f7
Author: Lars Ingebrigtsen <address@hidden>
Commit: Lars Ingebrigtsen <address@hidden>

    Make directory-files-recursively take a PREDICATE parameter
    
    * lisp/files.el (directory-files-recursively): Take an optional
    PREDICATE parameter (bug#28567).
    
    * doc/lispref/files.texi (Contents of Directories): Document it.
---
 doc/lispref/files.texi |  9 ++++++++-
 etc/NEWS               |  4 ++++
 lisp/files.el          | 39 +++++++++++++++++++++++++++++----------
 3 files changed, 41 insertions(+), 11 deletions(-)

diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 66678d3..0519f78 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -2911,7 +2911,7 @@ An error is signaled if @var{directory} is not the name 
of a directory
 that can be read.
 @end defun
 
-@defun directory-files-recursively directory regexp &optional 
include-directories
+@defun directory-files-recursively directory regexp &optional 
include-directories predicate
 Return all files under @var{directory} whose names match @var{regexp}.
 This function searches the specified @var{directory} and its
 sub-directories, recursively, for files whose basenames (i.e., without
@@ -2925,6 +2925,13 @@ alphabetically by their basenames.  By default, 
directories whose
 names match @var{regexp} are omitted from the list, but if the
 optional argument @var{include-directories} is non-@code{nil}, they
 are included.
+
+By default, all subdirectories are descended into.  If @var{predicate}
+is @code{t}, errors when trying to descend into a subdirectory (for
+instance, if it's not readable by this user) are ignored.  If it's
+neither @code{nil} nor @code{t}, it should be a function that takes
+one parameter (the subdirectory name) and should return non-@code{nil}
+if the directory is to be descended into.
 @end defun
 
 @defun directory-files-and-attributes directory &optional full-name 
match-regexp nosort id-format
diff --git a/etc/NEWS b/etc/NEWS
index 97143d2..edba159 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2326,6 +2326,10 @@ zero-padding, upper- and lower-casing, and limiting the 
length of the
 interpolated strings.  The function has now also been documented in
 the Emacs Lisp manual.
 
++++
+** `directory-files-recursively' can now take an optional PREDICATE
+parameter to control descending into subdirectories.
+
 
 * Changes in Emacs 27.1 on Non-Free Operating Systems
 
diff --git a/lisp/files.el b/lisp/files.el
index b2249bf..f76b08f 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -812,13 +812,22 @@ The path separator is colon in GNU and GNU-like systems."
                  (lambda (f) (and (file-directory-p f) 'dir-ok)))
     (error "No such directory found via CDPATH environment variable"))))
 
-(defun directory-files-recursively (dir regexp &optional include-directories)
+(defun directory-files-recursively (dir regexp
+                                        &optional include-directories 
predicate)
   "Return list of all files under DIR that have file names matching REGEXP.
-This function works recursively.  Files are returned in \"depth first\"
-order, and files from each directory are sorted in alphabetical order.
-Each file name appears in the returned list in its absolute form.
-Optional argument INCLUDE-DIRECTORIES non-nil means also include in the
-output directories whose names match REGEXP."
+This function works recursively.  Files are returned in \"depth
+first\" order, and files from each directory are sorted in
+alphabetical order.  Each file name appears in the returned list
+in its absolute form.
+
+Optional argument INCLUDE-DIRECTORIES non-nil means also include
+in the output directories whose names match REGEXP.
+
+PREDICATE can be either nil (which means that all subdirectories
+are descended into), t (which means that subdirectories that
+can't be read are ignored), or a function (which is called with
+name name of the subdirectory and should return non-nil if the
+subdirectory is to be descended into)."
   (let* ((result nil)
         (files nil)
          (dir (directory-file-name dir))
@@ -832,10 +841,20 @@ output directories whose names match REGEXP."
            (let* ((leaf (substring file 0 (1- (length file))))
                   (full-file (concat dir "/" leaf)))
              ;; Don't follow symlinks to other directories.
-             (unless (file-symlink-p full-file)
-               (setq result
-                     (nconc result (directory-files-recursively
-                                    full-file regexp include-directories))))
+             (when (and (not (file-symlink-p full-file))
+                         ;; Allow filtering subdirectories.
+                         (or (eq predicate nil)
+                             (eq predicate t)
+                             (funcall predicate full-file)))
+                (let ((sub-files
+                       (if (eq predicate t)
+                           (condition-case _
+                               (directory-files-recursively
+                               full-file regexp include-directories)
+                             (file-error nil))
+                         (directory-files-recursively
+                         full-file regexp include-directories))))
+                 (setq result (nconc result sub-files))))
              (when (and include-directories
                         (string-match regexp leaf))
                (setq result (nconc result (list full-file)))))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]