emacs-devel
[Top][All Lists]
Advanced

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

Functional argument for `directory-files' and `directory-files-and-attri


From: Dmitry Antipov
Subject: Functional argument for `directory-files' and `directory-files-and-attributes'
Date: Mon, 03 Aug 2009 18:42:54 +0400
User-agent: Thunderbird 2.0.0.21 (X11/20090320)

Hello all,

this patch illustrates an idea to provide functional argument for
both `directory-files' and `directory-files-and-attributes'.

The goal is to implement more advanced matching techniques than it's
may be done with plain regular expressions. For example:

1) (directory-files "." nil "\\.c$") is equal to
   (directory-files "." nil '(lambda (name) (if (string-match "\\.c$" name) t 
nil));

2) (directory-files "." nil '(lambda (name) (if (string-match "\\.c$" name) nil 
t))
   inverts the matching, i.e. matches everything except those names ends with 
.c;

3) Match those ends with .c or .h and it's > 300K in size:
   (directory-files
    "."
    nil
    '(lambda (name) (if (and (< 307200 (nth 7 (file-attributes name)))
                             (string-match "\\.[ch]$" name)) t nil)))

Dmitry
Index: dired.c
===================================================================
RCS file: /sources/emacs/emacs/src/dired.c,v
retrieving revision 1.166
diff -u -r1.166 dired.c
--- dired.c     13 Jul 2009 20:22:45 -0000      1.166
+++ dired.c     3 Aug 2009 14:17:21 -0000
@@ -152,7 +152,7 @@
   Lisp_Object list, dirfilename, encoded_directory;
   struct re_pattern_buffer *bufp = NULL;
   int needsep = 0;
-  int count = SPECPDL_INDEX ();
+  int matchtype, count = SPECPDL_INDEX ();
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
   DIRENTRY *dp;
 #ifdef WINDOWSNT
@@ -165,10 +165,10 @@
   GCPRO5 (match, directory, list, dirfilename, encoded_directory);
   dirfilename = Fdirectory_file_name (directory);
 
-  if (!NILP (match))
+  if (NILP (match))
+    matchtype = 0;
+  else if (STRINGP (match))
     {
-      CHECK_STRING (match);
-
       /* MATCH might be a flawed regular expression.  Rather than
         catching and signaling our own errors, we just call
         compile_pattern to do the work for us.  */
@@ -181,7 +181,12 @@
 # else /* !WINDOWSNT */
       bufp = compile_pattern (match, 0, Qnil, 0, 1);
 # endif         /* !WINDOWSNT */
+      matchtype = 1;
     }
+  else if (FUNCTIONP (match))
+    matchtype = 2;
+  else
+    wrong_type_argument (intern ("string-or-function-p"), match);
 
   /* Note: ENCODE_FILE and DECODE_FILE can GC because they can run
      run_pre_post_conversion_on_str which calls Lisp directly and
@@ -191,7 +196,7 @@
   encoded_directory = (STRING_MULTIBYTE (directory)
                       ? ENCODE_FILE (directory) : directory);
 
-  /* Now *bufp is the compiled form of MATCH; don't call anything
+  /* Now *bufp may be a compiled form of MATCH; if so, don't call anything
      which might compile a new regexp until we're done with the loop!  */
 
   BLOCK_INPUT;
@@ -277,9 +282,20 @@
          immediate_quit = 1;
          QUIT;
 
-         if (NILP (match)
-             || (0 <= re_search (bufp, SDATA (name), len, 0, len, 0)))
-           wanted = 1;
+         switch (matchtype)
+           {
+           case 0:
+             wanted = 1;
+             break;
+           case 1:
+             wanted = (0 <= re_search (bufp, SDATA (name), len, 0, len, 0));
+             break;
+           case 2:
+             wanted = EQ (call1 (match, name), Qt);
+             break;
+           default:
+             abort ();
+           }
 
          immediate_quit = 0;
 
@@ -366,7 +382,10 @@
 There are three optional arguments:
 If FULL is non-nil, return absolute file names.  Otherwise return names
  that are relative to the specified directory.
-If MATCH is non-nil, mention only file names that match the regexp MATCH.
+If MATCH is nil, all file names are matched.
+If MATCH is a string, mention only file names that match the regexp MATCH.
+If MATCH is a function, it should accept file name as the only string
+argument and return t whether the name matches, or nil otherwise.
 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
   Otherwise, the list returned is sorted with `stringp-lessp'.
   NOSORT is useful if you plan to sort the result yourself.  */)
@@ -392,7 +411,10 @@
 There are four optional arguments:
 If FULL is non-nil, return absolute file names.  Otherwise return names
  that are relative to the specified directory.
-If MATCH is non-nil, mention only file names that match the regexp MATCH.
+If MATCH is nil, all file names are matched.
+If MATCH is a string, mention only file names that match the regexp MATCH.
+If MATCH is a function, it should accept file name as the only string
+argument and return t whether the name matches, or nil otherwise.
 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
  NOSORT is useful if you plan to sort the result yourself.
 ID-FORMAT specifies the preferred format of attributes uid and gid, see

reply via email to

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