unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* empty-directory predicate, native implementation
@ 2020-10-13  2:22 Arthur Miller
  2020-10-13  8:01 ` Michael Albinus
  2020-10-13 14:48 ` Eli Zaretskii
  0 siblings, 2 replies; 71+ messages in thread
From: Arthur Miller @ 2020-10-13  2:22 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1704 bytes --]

It is easy to check for an empty dir in elisp; we can just list files
and check if there is a list or not:

  (null (directory-files directory-name nil nodots t)))

where nodots is just regex to omit dot files (from dired+).

But then this is quite inneficient. We are listing all files in each
dir since directory-files will return entire content of directory. Also
we are matching every filename to a regex just to eliminate first two.
Alternative would be to take length and see if it is > 2; but then we
would iterate whole list twice. So I can't see anything avialable in
dired/elisp and I think a predicate implemented in low-level is better solution.
We are really interested just to see if there is some file; so we can
just open dir, and read first few entries, if there is more then 2 files
(. and .. on *nix) we can just abort and return true.

I have tested an idea with getdents (Linux syscall) and I can see
difference. Attached is a patch for dired.c and a test file to play with
some benchmark.

In somewhat synthetic test where I just looped a "lisp" and "native"
predicate over a several hundred directories, I can see quite drammatic
difference in performance. On a directory with something about ~800
subdirs, native prediate takes ~0.002s while lisp predicate goes in ~0.01s.

I have made also a small test to mark empty dirs in dired, and there I
see some difference. On same directory, I get consistently
~2.4s for lisp version and ~2s for native version.

This isn't any kind of drammatic difference for most use; file I/O
is dominated by disk access anyway, but i still don't like to spend cpu
on unnecessary evaluations, so I wonder if we could get native predicate
in elisp? 


[-- Attachment #2: dired-mark-empty.el --]
[-- Type: text/plain, Size: 2175 bytes --]

(require 'dired)

(defvar nodots "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")

(defun dired-go-to-first ()
    (interactive)
    (goto-char (point-min))
    (dired-next-line 1)
    (skip-chars-forward " \n\t"))

(defun dired-go-to-last ()
    (interactive)
    (goto-char (point-max))
    (dired-next-line -1)
    (skip-chars-forward " \n\t"))

(defun dired-is-empty-p (directory-name)
  (null (directory-files directory-name nil nodots t)))

(defun directory-number-files (directory-name &optional omit-filter)
  (length (directory-files directory-name nil omit-filter t)))

(defun dired-mark-empty-dirs ()
  (interactive)
  (when (equal major-mode 'dired-mode)
    (let ((curr-dir))
      (save-excursion
        (dired-go-to-first)
        
        (while (not (eobp))
          (setq curr-dir (dired-file-name-at-point))
          (cond ((or (null curr-dir)
                     (string= curr-dir ".")
                     (string= curr-dir ".."))
                     ;; do nothing here
                 )
                ((file-directory-p curr-dir)
                 (when (dired-is-empty-p curr-dir)
                   (dired-mark 1)
                   (dired-previous-line 1))))
          (dired-next-line 1))))))

(defun dired-mark-empty-dirs-native ()
  (interactive)
  (when (equal major-mode 'dired-mode)
    (let ((curr-dir))
      (save-excursion
        (dired-go-to-first)
        
        (while (not (eobp))
          (setq curr-dir (dired-file-name-at-point))
          (cond ((or (null curr-dir)
                     (string= curr-dir ".")
                     (string= curr-dir ".."))
                     ;; do nothing here
                 )
                ((file-directory-p curr-dir)
                 (when (directory-empty-p curr-dir)
                   (dired-mark 1)
                   (dired-previous-line 1))))
          (dired-next-line 1))))))

;;(benchmark-run-compiled 10 (directory-empty-p "/some/directory/here"))
;;(benchmark-run-compiled 10 (dired-is-empty-p "/some/directory/here"))

;; must be in some dired buffer for this
;;(benchmark-run-compiled 10 (dired-mark-empty-dirs))
;;(benchmark-run-compiled 10 (dired-mark-empty-dirs-native))

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: dired.patch --]
[-- Type: text/x-patch, Size: 2749 bytes --]

--- src/dired.c	2020-10-13 04:08:36.028838472 +0200
+++ ../dired.c	2020-10-13 04:07:48.374572510 +0200
@@ -21,6 +21,7 @@
 #include <config.h>
 
 #include <sys/stat.h>
+#include <sys/syscall.h>
 
 #ifdef HAVE_PWD_H
 #include <pwd.h>
@@ -39,6 +40,7 @@
 #include "systime.h"
 #include "buffer.h"
 #include "coding.h"
+#include "blockinput.h"
 
 #ifdef MSDOS
 #include "msdos.h"	/* for fstatat */
@@ -929,7 +931,7 @@
   struct stat s;
 
   /* An array to hold the mode string generated by filemodestring,
-     including its terminating space and null byte.  */
+     including its terminating space and NUL byte.  */
   char modes[sizeof "-rwxr-xr-x "];
 
   char *uname = NULL, *gname = NULL;
@@ -1078,6 +1080,50 @@
   return groups;
 }
 
+typedef struct dirent* pdirent;
+DEFUN ("directory-empty-p", Fdirectory_empty_p,
+       Sdirectory_empty_p, 1, 1, 0,
+       doc: /* Returns t if directory DIRNAME does not contain any
+       user files (special files . and .. are excluded
+       automatically), nil otherwise. */)
+(Lisp_Object dirname)
+{
+        #define BSIZE 1024
+        char buf[BSIZE];
+        const char* name;
+        int fd, n = 0, p = 0, c = 0;
+        pdirent d;
+
+        if(!STRINGP(dirname))
+                error("Directory name not a string object.");
+        
+        dirname = Fexpand_file_name(dirname, Qnil);
+        name = SSDATA(dirname);
+
+        fd = open (name, O_RDONLY | O_DIRECTORY);
+
+        if( fd == -1 )
+                error("Can't open directory.");
+
+        //block_input();
+        /* 32-bit version of getdents should be good enough;
+           we are just looking at first 3 files*/
+        n = syscall(SYS_getdents,fd,buf, BSIZE);
+        if(n == -1)
+                error("Can't read directory data.");
+
+        while(p < n && c < 3) {
+                d = (pdirent) (buf + p);
+                p += d->d_reclen;
+                c++;
+        }
+        //unblock_input();
+        
+        close(fd);
+        return (c > 2) ? Qnil : Qt;
+}
+
+
 void
 syms_of_dired (void)
 {
@@ -1089,7 +1135,8 @@
   DEFSYM (Qfile_attributes_lessp, "file-attributes-lessp");
   DEFSYM (Qdefault_directory, "default-directory");
   DEFSYM (Qdecomposed_characters, "decomposed-characters");
-
+  DEFSYM (Qdirectory_empty_p, "directory-empty-p")
+          
   defsubr (&Sdirectory_files);
   defsubr (&Sdirectory_files_and_attributes);
   defsubr (&Sfile_name_completion);
@@ -1098,6 +1145,7 @@
   defsubr (&Sfile_attributes_lessp);
   defsubr (&Ssystem_users);
   defsubr (&Ssystem_groups);
+  defsubr (&Sdirectory_empty_p);
 
   DEFVAR_LISP ("completion-ignored-extensions", Vcompletion_ignored_extensions,
 	       doc: /* Completion ignores file names ending in any string in this list.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13  2:22 Arthur Miller
@ 2020-10-13  8:01 ` Michael Albinus
  2020-10-13 11:42   ` Arthur Miller
  2020-10-13 14:48 ` Eli Zaretskii
  1 sibling, 1 reply; 71+ messages in thread
From: Michael Albinus @ 2020-10-13  8:01 UTC (permalink / raw)
  To: Arthur Miller; +Cc: emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi Arthur,

> This isn't any kind of drammatic difference for most use; file I/O
> is dominated by disk access anyway, but i still don't like to spend cpu
> on unnecessary evaluations, so I wonder if we could get native predicate
> in elisp?

I don't know whether we will add this function, but in case of: you
shall call a file name handler first. See for example Fdirectory_files.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13  8:01 ` Michael Albinus
@ 2020-10-13 11:42   ` Arthur Miller
  2020-10-13 13:16     ` Michael Albinus
  0 siblings, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-13 11:42 UTC (permalink / raw)
  To: Michael Albinus; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 948 bytes --]

Michael Albinus <michael.albinus@gmx.de> writes:

> Arthur Miller <arthur.miller@live.com> writes:
>
> Hi Arthur,
>
>> This isn't any kind of drammatic difference for most use; file I/O
>> is dominated by disk access anyway, but i still don't like to spend cpu
>> on unnecessary evaluations, so I wonder if we could get native predicate
>> in elisp?
>
> I don't know whether we will add this function, but in case of: you
> shall call a file name handler first. See for example Fdirectory_files.
>
> Best regards, Michael.
Thanks for looking at this.

I have seen in the source code calls to Ffind_file_handler, and have
been looking at the function in fileio.c, but I didn't figured out what
it really does, so I didn't use it. I tested without and it worked fine
:-). Anyway, I have added it now, but I am not sure if I using it
correctly, since I am not sure what it does.

By the way, what are "special constructs" referred to in the comment?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: dired.c patch --]
[-- Type: text/x-patch, Size: 3082 bytes --]

--- src/dired.c	2020-10-13 13:36:27.069967986 +0200
+++ ../dired.c	2020-10-13 13:35:47.695916558 +0200
@@ -21,6 +21,7 @@
 #include <config.h>
 
 #include <sys/stat.h>
+#include <sys/syscall.h>
 
 #ifdef HAVE_PWD_H
 #include <pwd.h>
@@ -39,6 +40,7 @@
 #include "systime.h"
 #include "buffer.h"
 #include "coding.h"
+#include "blockinput.h"
 
 #ifdef MSDOS
 #include "msdos.h"	/* for fstatat */
@@ -929,7 +931,7 @@
   struct stat s;
 
   /* An array to hold the mode string generated by filemodestring,
-     including its terminating space and null byte.  */
+     including its terminating space and NUL byte.  */
   char modes[sizeof "-rwxr-xr-x "];
 
   char *uname = NULL, *gname = NULL;
@@ -1078,6 +1080,58 @@
   return groups;
 }
 
+typedef struct dirent* pdirent;
+DEFUN ("directory-empty-p", Fdirectory_empty_p,
+       Sdirectory_empty_p, 1, 1, 0,
+       doc: /* Returns t if directory DIRNAME does not contain any
+       user files (special files . and .. are excluded
+       automatically), nil otherwise. */)
+(Lisp_Object dirname)
+{
+        #define BSIZE 1024
+        char buf[BSIZE];
+        const char* name;
+        int fd, n = 0, p = 0, c = 0;
+        pdirent d;
+        Lisp_Object handler;
+
+        if(!STRINGP(dirname))
+                error("Directory name not a string object.");
+        
+        dirname = Fexpand_file_name(dirname, Qnil);
+
+        /* If the file name has special constructs in it,
+           call the corresponding file name handler.  */
+        handler = Ffind_file_name_handler (dirname, Qdirectory_empty_p);
+        if (!NILP (handler))
+                return call2 (handler, Qdirectory_empty_p, dirname);
+        
+        name = SSDATA(dirname);
+
+        fd = open (name, O_RDONLY | O_DIRECTORY);
+
+        if( fd == -1 )
+                error("Can't open directory.");
+
+        //block_input();
+        /* 32-bit version of getdents should be good enough;
+           we are just looking at first 3 files*/
+        n = syscall(SYS_getdents,fd,buf, BSIZE);
+        if(n == -1)
+                error("Can't read directory data.");
+
+        while(p < n && c < 3) {
+                d = (pdirent) (buf + p);
+                p += d->d_reclen;
+                c++;
+        }
+        //unblock_input();
+        
+        close(fd);
+        return (c > 2) ? Qnil : Qt;
+}
+
+
 void
 syms_of_dired (void)
 {
@@ -1089,7 +1143,8 @@
   DEFSYM (Qfile_attributes_lessp, "file-attributes-lessp");
   DEFSYM (Qdefault_directory, "default-directory");
   DEFSYM (Qdecomposed_characters, "decomposed-characters");
-
+  DEFSYM (Qdirectory_empty_p, "directory-empty-p")
+          
   defsubr (&Sdirectory_files);
   defsubr (&Sdirectory_files_and_attributes);
   defsubr (&Sfile_name_completion);
@@ -1098,6 +1153,7 @@
   defsubr (&Sfile_attributes_lessp);
   defsubr (&Ssystem_users);
   defsubr (&Ssystem_groups);
+  defsubr (&Sdirectory_empty_p);
 
   DEFVAR_LISP ("completion-ignored-extensions", Vcompletion_ignored_extensions,
 	       doc: /* Completion ignores file names ending in any string in this list.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13 11:42   ` Arthur Miller
@ 2020-10-13 13:16     ` Michael Albinus
  2020-10-13 18:32       ` Arthur Miller
  0 siblings, 1 reply; 71+ messages in thread
From: Michael Albinus @ 2020-10-13 13:16 UTC (permalink / raw)
  To: Arthur Miller; +Cc: emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi Arthur,

> I have seen in the source code calls to Ffind_file_handler, and have
> been looking at the function in fileio.c, but I didn't figured out what
> it really does, so I didn't use it. I tested without and it worked fine
> :-). Anyway, I have added it now, but I am not sure if I using it
> correctly, since I am not sure what it does.

Looks good.

Simplified spoken, this code makes Tramp work. If you call for example
(directory-empty-p "/sudo::/") , find-file-name-handler (the ELisp
equivalent to Ffind_file_name_handler) checks, whether Tramp feels
responsible for this directory name, and it calls Tramp's function in
case.

You know, that your function cannot handle "/sudo::/".

> By the way, what are "special constructs" referred to in the comment?

Tramp file name syntax here. See (info "(elisp) Magic File Names")

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13  2:22 Arthur Miller
  2020-10-13  8:01 ` Michael Albinus
@ 2020-10-13 14:48 ` Eli Zaretskii
  2020-10-13 18:43   ` Arthur Miller
  2020-10-13 18:44   ` Michael Albinus
  1 sibling, 2 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-10-13 14:48 UTC (permalink / raw)
  To: Arthur Miller; +Cc: emacs-devel

> From: Arthur Miller <arthur.miller@live.com>
> Date: Tue, 13 Oct 2020 04:22:36 +0200
> 
> It is easy to check for an empty dir in elisp; we can just list files
> and check if there is a list or not:
> 
>   (null (directory-files directory-name nil nodots t)))
> 
> where nodots is just regex to omit dot files (from dired+).
> 
> But then this is quite inneficient. We are listing all files in each
> dir since directory-files will return entire content of directory. Also
> we are matching every filename to a regex just to eliminate first two.
> Alternative would be to take length and see if it is > 2; but then we
> would iterate whole list twice. So I can't see anything avialable in
> dired/elisp and I think a predicate implemented in low-level is better solution.
> We are really interested just to see if there is some file; so we can
> just open dir, and read first few entries, if there is more then 2 files
> (. and .. on *nix) we can just abort and return true.
> 
> I have tested an idea with getdents (Linux syscall) and I can see
> difference. Attached is a patch for dired.c and a test file to play with
> some benchmark.

If all we want is to stop reading a directory after N entries, why not
simply extend directory-files to accept one more argument: the maximum
number of file entries to read?  That should be easy to implement, and
will not require us to repeat all the code that is already there in
directory-files (and which you missed).  For example, file names need
to be encoded before they are passed to libc functions (or any
external APIs that expect file names).  As a bonus, we will be able to
return the file names we read, not just ignore them.  And the code
will be much more portable; if someone wants a more efficient
Linux-only version, that could be added as an additional feature
(assuming the speed difference justifies that).

WDYT?



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13 13:16     ` Michael Albinus
@ 2020-10-13 18:32       ` Arthur Miller
  2020-10-13 18:39         ` Michael Albinus
  0 siblings, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-13 18:32 UTC (permalink / raw)
  To: Michael Albinus; +Cc: emacs-devel

Michael Albinus <michael.albinus@gmx.de> writes:

> Arthur Miller <arthur.miller@live.com> writes:
>
> Hi Arthur,
>
>> I have seen in the source code calls to Ffind_file_handler, and have
>> been looking at the function in fileio.c, but I didn't figured out what
>> it really does, so I didn't use it. I tested without and it worked fine
>> :-). Anyway, I have added it now, but I am not sure if I using it
>> correctly, since I am not sure what it does.
>
> Looks good.
>
> Simplified spoken, this code makes Tramp work. If you call for example
> (directory-empty-p "/sudo::/") , find-file-name-handler (the ELisp
> equivalent to Ffind_file_name_handler) checks, whether Tramp feels
> responsible for this directory name, and it calls Tramp's function in
> case.
>
> You know, that your function cannot handle "/sudo::/".
:-) Actually I forgott that part completely.

>> By the way, what are "special constructs" referred to in the comment?
>
> Tramp file name syntax here. See (info "(elisp) Magic File Names")
>
Thank you very much for kind explanation; I have read the info now, and
I understand it now. Not sure that I know how to implement it though,
but it does not matter; Eli's suggestion seems even better; I think.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13 18:32       ` Arthur Miller
@ 2020-10-13 18:39         ` Michael Albinus
  2020-10-13 23:20           ` Arthur Miller
  0 siblings, 1 reply; 71+ messages in thread
From: Michael Albinus @ 2020-10-13 18:39 UTC (permalink / raw)
  To: Arthur Miller; +Cc: emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi Arthur,

>> Tramp file name syntax here. See (info "(elisp) Magic File Names")
>>
> Thank you very much for kind explanation; I have read the info now, and
> I understand it now. Not sure that I know how to implement it though,
> but it does not matter; Eli's suggestion seems even better; I think.

Agreed, we shall follow Eli's suggestion. But if we would take your
proposal, the Tramp implementation would happen in tramp.el.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13 14:48 ` Eli Zaretskii
@ 2020-10-13 18:43   ` Arthur Miller
  2020-10-13 19:12     ` Eli Zaretskii
  2020-10-13 18:44   ` Michael Albinus
  1 sibling, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-13 18:43 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Arthur Miller <arthur.miller@live.com>
>> Date: Tue, 13 Oct 2020 04:22:36 +0200
>> 
>> It is easy to check for an empty dir in elisp; we can just list files
>> and check if there is a list or not:
>> 
>>   (null (directory-files directory-name nil nodots t)))
>> 
>> where nodots is just regex to omit dot files (from dired+).
>> 
>> But then this is quite inneficient. We are listing all files in each
>> dir since directory-files will return entire content of directory. Also
>> we are matching every filename to a regex just to eliminate first two.
>> Alternative would be to take length and see if it is > 2; but then we
>> would iterate whole list twice. So I can't see anything avialable in
>> dired/elisp and I think a predicate implemented in low-level is better solution.
>> We are really interested just to see if there is some file; so we can
>> just open dir, and read first few entries, if there is more then 2 files
>> (. and .. on *nix) we can just abort and return true.
>> 
>> I have tested an idea with getdents (Linux syscall) and I can see
>> difference. Attached is a patch for dired.c and a test file to play with
>> some benchmark.
>
> If all we want is to stop reading a directory after N entries, why not
> simply extend directory-files to accept one more argument: the maximum
> number of file entries to read?  That should be easy to implement, and
> will not require us to repeat all the code that is already there in
> directory-files (and which you missed).  For example, file names need
> to be encoded before they are passed to libc functions (or any
> external APIs that expect file names).  As a bonus, we will be able to
> return the file names we read, not just ignore them.  And the code
> will be much more portable; if someone wants a more efficient
> Linux-only version, that could be added as an additional feature
> (assuming the speed difference justifies that).
Oh; and you say that now when I have just implemented a Windows
version :-).

> WDYT?
I think that sounds like a very good idea; or rather a splended one!
Much better then a predicate. If directory-files is asked just for 1
file, with regex to ignore, it would read max 3 files at most, and on
some filysystems maybe only one file.

> directory-files (and which you missed).  For example, file names need
> to be encoded before they are passed to libc functions (or any
> external APIs that expect file names).
Actually I didn't; I first tested with ENCODE_FILE but I didn't know
what it does, and it appeared like it is working without, so I ditched
it. I totally forgott about tramp & co, as Michael points out :-).

I didn't count on it to be correct; I am not so very familiar with
Emascs source, there are so many details to take care of, I was rather
just presenting an idea.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13 14:48 ` Eli Zaretskii
  2020-10-13 18:43   ` Arthur Miller
@ 2020-10-13 18:44   ` Michael Albinus
  2020-10-13 19:14     ` Eli Zaretskii
  1 sibling, 1 reply; 71+ messages in thread
From: Michael Albinus @ 2020-10-13 18:44 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Arthur Miller, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

Hi Eli,

> As a bonus, we will be able to return the file names we read, not just
> ignore them.

I agree with your proposal. However, I don't see why it is a bonus to
know which file names have read already, because they are taken in
random order. I fail to see how does it help, whether a file name is
returned under the first N matches, or not.

> WDYT?

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13 18:43   ` Arthur Miller
@ 2020-10-13 19:12     ` Eli Zaretskii
  2020-10-13 19:59       ` Arthur Miller
  0 siblings, 1 reply; 71+ messages in thread
From: Eli Zaretskii @ 2020-10-13 19:12 UTC (permalink / raw)
  To: Arthur Miller; +Cc: emacs-devel

> From: Arthur Miller <arthur.miller@live.com>
> Cc: emacs-devel@gnu.org
> Date: Tue, 13 Oct 2020 20:43:41 +0200
> 
> > directory-files (and which you missed).  For example, file names need
> > to be encoded before they are passed to libc functions (or any
> > external APIs that expect file names).
> Actually I didn't; I first tested with ENCODE_FILE but I didn't know
> what it does, and it appeared like it is working without, so I ditched
> it.

It worked without ENCODE_FILE by sheer luck: you must have tried that
on a system where file names are encoded in UTF-8, and so most file
names can be used without any conversion (but ENCODE_FILE already
knows that).



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13 18:44   ` Michael Albinus
@ 2020-10-13 19:14     ` Eli Zaretskii
  2020-10-13 20:08       ` Arthur Miller
  2020-10-14  1:52       ` Arthur Miller
  0 siblings, 2 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-10-13 19:14 UTC (permalink / raw)
  To: Michael Albinus; +Cc: arthur.miller, emacs-devel

> From: Michael Albinus <michael.albinus@gmx.de>
> Cc: Arthur Miller <arthur.miller@live.com>,  emacs-devel@gnu.org
> Date: Tue, 13 Oct 2020 20:44:18 +0200
> 
> > As a bonus, we will be able to return the file names we read, not just
> > ignore them.
> 
> I agree with your proposal. However, I don't see why it is a bonus to
> know which file names have read already, because they are taken in
> random order.

The order depends on the filesystem.  For example, MS-Windows
filesystems always report in alphabetic order.

> I fail to see how does it help, whether a file name is returned
> under the first N matches, or not.

Well, it is easy to disregard the names if they aren't needed.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13 19:12     ` Eli Zaretskii
@ 2020-10-13 19:59       ` Arthur Miller
  2020-10-14 14:08         ` Eli Zaretskii
  0 siblings, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-13 19:59 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1706 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Arthur Miller <arthur.miller@live.com>
>> Cc: emacs-devel@gnu.org
>> Date: Tue, 13 Oct 2020 20:43:41 +0200
>> 
>> > directory-files (and which you missed).  For example, file names need
>> > to be encoded before they are passed to libc functions (or any
>> > external APIs that expect file names).
>> Actually I didn't; I first tested with ENCODE_FILE but I didn't know
>> what it does, and it appeared like it is working without, so I ditched
>> it.
>
> It worked without ENCODE_FILE by sheer luck: you must have tried that
> on a system where file names are encoded in UTF-8, and so most file
> names can be used without any conversion (but ENCODE_FILE already
> knows that).
I see :-). I spent quite a lot time earlier today to get it to work on
windows, mostly for the conversion between utf8 and unicode; tried first
to manually convert between utf/wide, and after several tries discovered
some functions in w32.c I could reuse: filename_to_utf16 and 
filename_to_ansi, which worked for me (minus tramp of course).

Can I ask two questions, just for my learning; you seem to handle
ascii/unicode "manually"; in w32.c I have seen quite a few places where
switch is done on if(w32_unicode_filenames); is it possible to somehow
pass to configure script if Emacs should be compiled with wide or asci
version of win api? 

Second question: block_input; is there some general rule(s) what calls you
enclose with block/unblock_input? I guess OS will anyway block the
process after call to SYS_getdents so I didn't enclosed it; but I am not
sure if that would be needed at all or not.

I have attached my patch with win code as illustration to those
questions.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: dired.c --]
[-- Type: text/x-patch, Size: 5635 bytes --]

--- src/dired.c	2020-10-13 20:09:48.235962328 +0200
+++ ../dired.c	2020-10-13 20:09:10.865527164 +0200
@@ -22,6 +22,12 @@
 
 #include <sys/stat.h>
 
+#if __linux__
+#include <sys/syscall.h>
+#elif _WIN32
+#include <windows.h>
+#endif
+
 #ifdef HAVE_PWD_H
 #include <pwd.h>
 #endif
@@ -39,6 +45,7 @@
 #include "systime.h"
 #include "buffer.h"
 #include "coding.h"
+#include "blockinput.h"
 
 #ifdef MSDOS
 #include "msdos.h"	/* for fstatat */
@@ -929,7 +936,7 @@
   struct stat s;
 
   /* An array to hold the mode string generated by filemodestring,
-     including its terminating space and null byte.  */
+     including its terminating space and NUL byte.  */
   char modes[sizeof "-rwxr-xr-x "];
 
   char *uname = NULL, *gname = NULL;
@@ -1078,6 +1085,119 @@
   return groups;
 }
 
+DEFUN ("directory-empty-p", Fdirectory_empty_p,
+       Sdirectory_empty_p, 1, 1, 0,
+       doc: /* Returns t if directory DIRNAME does not contain any
+       user files (special files . and .. are excluded
+       automatically), nil otherwise. */)
+(Lisp_Object dirname)
+{
+        const char* name;
+        Lisp_Object handler;
+
+        if(!STRINGP(dirname))
+                error("Directory name not a string object.");
+        
+        dirname = Fexpand_file_name(dirname, Qnil);
+
+        /* If the file name has special constructs in it,
+           call the corresponding file name handler.  */
+        handler = Ffind_file_name_handler (dirname, Qdirectory_empty_p);
+        if (!NILP (handler))
+                return call2 (handler, Qdirectory_empty_p, dirname);
+        
+        name = SSDATA(dirname);
+        
+#ifdef __linux__
+        {
+                typedef struct dirent* pdirent;
+#define BSIZE 1024
+                pdirent d;
+                char buf[BSIZE];
+                int fd, n = 0, p = 0, c = 0;
+                
+                fd = open (name, O_RDONLY | O_DIRECTORY);
+
+                if( fd == -1 )
+                        error("Can't open directory.");
+
+                //block_input();
+                /* 32-bit version of getdents should be good enough;
+                   we are just looking at first 3 files*/
+                n = syscall(SYS_getdents,fd,buf, BSIZE);
+                if(n == -1)
+                        error("Can't read directory data.");
+
+                while(p < n && c < 3) {
+                        d = (pdirent) (buf + p);
+                        p += d->d_reclen;
+                        c++;
+                }
+                //unblock_input();
+        
+                close(fd);
+                return (c > 2) ? Qnil : Qt;
+        }
+#elif _WIN32
+        {
+                int len, c = 0;
+                HANDLE h = INVALID_HANDLE_VALUE;
+
+                if(w32_unicode_filenames){
+                        WIN32_FIND_DATAW ffd;
+                        wchar_t wname[MAX_PATH];
+                        filename_to_utf16(name, wname);
+                        len = wcslen(wname);
+
+                        if (!len)
+                                error(TEXT("Can't read directory name."));
+
+                        if(len > MAX_PATH - 3)
+                                error(TEXT("Directory path too long."));
+
+                        wcscat(wname, L"\\*");
+                
+                        h = FindFirstFileW(wname, &ffd);
+                        if (h == INVALID_HANDLE_VALUE)
+                                error(TEXT("Can't open directory."));
+
+                        while (FindNextFileW(h, &ffd) && c < 1){
+                                if(wcscmp(ffd.cFileName, L".") &&
+                                   wcscmp(ffd.cFileName, L".."))
+                                        c++;
+                        }
+                }else {
+                        WIN32_FIND_DATAA ffd;
+                        char aname[MAX_UTF8_PATH];
+                        filename_to_ansi(name, aname);
+                        len = strlen(aname);
+
+                        if (!len)
+                                error(TEXT("Can't read directory name."));
+
+                        if(len > MAX_PATH - 3)
+                                error(TEXT("Directory path too long."));
+
+                        strcat(aname, "\\*");
+                        
+                        h = FindFirstFileA(aname, &ffd);
+                        if (h == INVALID_HANDLE_VALUE)
+                                error(TEXT("Can't open directory."));
+                        
+                        while (FindNextFileA(h, &ffd) && c < 1){
+                                if(strcmp(ffd.cFileName, ".") &&
+                                   strcmp(ffd.cFileName, ".."))
+                                        c++;
+                        }
+                }
+                
+                FindClose(h);
+                return (c > 0) ? Qnil : Qt;
+        }
+#endif
+}
+
+
 void
 syms_of_dired (void)
 {
@@ -1089,7 +1209,8 @@
   DEFSYM (Qfile_attributes_lessp, "file-attributes-lessp");
   DEFSYM (Qdefault_directory, "default-directory");
   DEFSYM (Qdecomposed_characters, "decomposed-characters");
-
+  DEFSYM (Qdirectory_empty_p, "directory-empty-p")
+          
   defsubr (&Sdirectory_files);
   defsubr (&Sdirectory_files_and_attributes);
   defsubr (&Sfile_name_completion);
@@ -1098,6 +1219,7 @@
   defsubr (&Sfile_attributes_lessp);
   defsubr (&Ssystem_users);
   defsubr (&Ssystem_groups);
+  defsubr (&Sdirectory_empty_p);
 
   DEFVAR_LISP ("completion-ignored-extensions", Vcompletion_ignored_extensions,
 	       doc: /* Completion ignores file names ending in any string in this list.

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13 19:14     ` Eli Zaretskii
@ 2020-10-13 20:08       ` Arthur Miller
  2020-10-14  1:52       ` Arthur Miller
  1 sibling, 0 replies; 71+ messages in thread
From: Arthur Miller @ 2020-10-13 20:08 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Michael Albinus, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Michael Albinus <michael.albinus@gmx.de>
>> Cc: Arthur Miller <arthur.miller@live.com>,  emacs-devel@gnu.org
>> Date: Tue, 13 Oct 2020 20:44:18 +0200
>> 
>> > As a bonus, we will be able to return the file names we read, not just
>> > ignore them.
>> 
>> I agree with your proposal. However, I don't see why it is a bonus to
>> know which file names have read already, because they are taken in
>> random order.
>
> The order depends on the filesystem.  For example, MS-Windows
> filesystems always report in alphabetic order.
>
Not that it is important, just as a note:

I looked up today msdn while I was playing with this, they mention that
order is not guarantueed at all; FAT systems will returned file in order
they are written on disk, while on NTFS & CDFS they are usually returned
in alphabetical order. I don't know why they say "usually" :-), but they
do remark that any application should sort results if sorted order is
important.

https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-findnextfilea

>> I fail to see how does it help, whether a file name is returned
>> under the first N matches, or not.
>
> Well, it is easy to disregard the names if they aren't needed.
I am not sure of use-case, but it can be a bonus to get N number of
files instead of all. If Elisp was used for scripting in some very large
filesystems maybe? I don't know.




^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13 18:39         ` Michael Albinus
@ 2020-10-13 23:20           ` Arthur Miller
  2020-10-14  9:19             ` Michael Albinus
  0 siblings, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-13 23:20 UTC (permalink / raw)
  To: Michael Albinus; +Cc: emacs-devel

Michael Albinus <michael.albinus@gmx.de> writes:

> Arthur Miller <arthur.miller@live.com> writes:
>
> Hi Arthur,
>
>>> Tramp file name syntax here. See (info "(elisp) Magic File Names")
>>>
>> Thank you very much for kind explanation; I have read the info now, and
>> I understand it now. Not sure that I know how to implement it though,
>> but it does not matter; Eli's suggestion seems even better; I think.
>
> Agreed, we shall follow Eli's suggestion. But if we would take your
> proposal, the Tramp implementation would happen in tramp.el.
>
> Best regards, Michael.
Thanks for the pointer. I was looking at tramp.el, but I it is ~6k loc
:-). I am not sure I understand what I would need to do to implement
for this; would like to learn though. Can you maybe point me to some
function which I can take a look that would be similar to what I tried
here use-case.

Anyway, Eli's idea is much simpler; I just implemented and tested and it
seems to work nice. I have a problem with helm-find-files but I'll post
in the answer to Eli together with the patch.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13 19:14     ` Eli Zaretskii
  2020-10-13 20:08       ` Arthur Miller
@ 2020-10-14  1:52       ` Arthur Miller
  2020-10-14  9:21         ` Michael Albinus
  1 sibling, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-14  1:52 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Michael Albinus, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1833 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Michael Albinus <michael.albinus@gmx.de>
>> Cc: Arthur Miller <arthur.miller@live.com>,  emacs-devel@gnu.org
>> Date: Tue, 13 Oct 2020 20:44:18 +0200
>> 
>> > As a bonus, we will be able to return the file names we read, not just
>> > ignore them.
>> 
>> I agree with your proposal. However, I don't see why it is a bonus to
>> know which file names have read already, because they are taken in
>> random order.
>
> The order depends on the filesystem.  For example, MS-Windows
> filesystems always report in alphabetic order.
>
>> I fail to see how does it help, whether a file name is returned
>> under the first N matches, or not.
>
> Well, it is easy to disregard the names if they aren't needed.

Your idea was definitely much simpler to implement, rather trivial :-).
I just tested for myself, and it seems to work well.

The only thing I am not sure about is how to deal with 0 count; I
mean if user explicitly ask for 0 count; the case when count is not
NILP. I have chosen not to deal with it all, I check for zer set
explicit limit for count to be [1,COUNT]. I am not sure if that is best
thing to do; maybe just to return Qnil? I am probably doing something
else wrong, advice apprecaiated. 

I had some problems until I realized i used wrong number converter; I
used fixnum, seems like I need fixnat. I am still not sure if I am
correct but it seems to work now. 

I tested this compared to my old "native" predicate, on GNU/Linux only
and just to run naked predicate on a big number of dirs, and it seems to
be just very slight difference; ~0.002 vs ~0.004 definitely not dramatic
as entire decimal place.

I needed to "touch" 2 other files due to chagned signature of
directory_files: lisp.h and sysdep.c.

In attached .el file are two small tests (I run them with M-:).


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: dired.c.patch --]
[-- Type: text/x-patch, Size: 5123 bytes --]

--- src/dired.c	2020-10-14 03:35:16.781786426 +0200
+++ ../dired2.c	2020-10-14 03:35:05.271568190 +0200
@@ -20,6 +20,7 @@
 
 #include <config.h>
 
+#include <stddef.h>
 #include <sys/stat.h>
 
 #ifdef HAVE_PWD_H
@@ -165,7 +166,7 @@
 Lisp_Object
 directory_files_internal (Lisp_Object directory, Lisp_Object full,
 			  Lisp_Object match, Lisp_Object nosort, bool attrs,
-			  Lisp_Object id_format)
+			  Lisp_Object id_format, Lisp_Object count_to_return)
 {
   if (!NILP (match))
     CHECK_STRING (match);
@@ -223,7 +224,14 @@
 #ifdef WINDOWSNT
   case_table = BVAR (&buffer_defaults, case_canon_table);
 #endif
-
+  
+  ptrdiff_t ind = 0, last = 0;
+  if(!NILP(count_to_return) && FIXNATP(count_to_return))
+      last = XFIXNAT(count_to_return);
+  
+  if(!last)
+    last = 1;
+  
   /* Read directory entries and accumulate them into LIST.  */
   Lisp_Object list = Qnil;
   for (struct dirent *dp; (dp = read_dirent (d, directory)); )
@@ -267,6 +275,13 @@
       else
 	finalname = name;
 
+      if(!NILP(count_to_return) && FIXNATP(count_to_return))
+        {
+          if(ind == last)
+            break;
+          ind ++;
+        }
+      
       list = Fcons (attrs ? Fcons (finalname, fileattrs) : finalname, list);
     }
 
@@ -282,13 +297,13 @@
   if (NILP (nosort))
     list = Fsort (Fnreverse (list),
 		  attrs ? Qfile_attributes_lessp : Qstring_lessp);
-
+  
   (void) directory_volatile;
   return list;
 }
 
 
-DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
+DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 5, 0,
        doc: /* Return a list of names of files in DIRECTORY.
 There are three optional arguments:
 If FULL is non-nil, return absolute file names.  Otherwise return names
@@ -296,9 +311,14 @@
 If MATCH is non-nil, mention only file names that match the regexp MATCH.
 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
  Otherwise, the list returned is sorted with `string-lessp'.
- NOSORT is useful if you plan to sort the result yourself.  */)
+ NOSORT is useful if you plan to sort the result yourself. 
+If COUNT is  non-nil, the function will return max (COUNT,length)
+ files, where length means number of files in directory. Order
+ in which files are returned is not guaranteed and is file system and
+ OS dependent. COUNT has to be an integral number in interval
+ [1,COUNT]. */) 
   (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
-   Lisp_Object nosort)
+   Lisp_Object nosort, Lisp_Object count)
 {
   directory = Fexpand_file_name (directory, Qnil);
 
@@ -306,14 +326,15 @@
      call the corresponding file name handler.  */
   Lisp_Object handler = Ffind_file_name_handler (directory, Qdirectory_files);
   if (!NILP (handler))
-    return call5 (handler, Qdirectory_files, directory,
-                  full, match, nosort);
+    return call6 (handler, Qdirectory_files, directory,
+                  full, match, nosort, count);
 
-  return directory_files_internal (directory, full, match, nosort, false, Qnil);
+  return directory_files_internal (directory, full, match, nosort,
+                                   false, Qnil, count);
 }
 
 DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes,
-       Sdirectory_files_and_attributes, 1, 5, 0,
+       Sdirectory_files_and_attributes, 1, 6, 0,
        doc: /* Return a list of names of files and their attributes in DIRECTORY.
 Value is a list of the form:
 
@@ -331,9 +352,14 @@
 ID-FORMAT specifies the preferred format of attributes uid and gid, see
 `file-attributes' for further documentation.
 On MS-Windows, performance depends on `w32-get-true-file-attributes',
-which see.  */)
-  (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
-   Lisp_Object nosort, Lisp_Object id_format)
+which see. 
+If COUNT is  non-nil, the function will return max (COUNT,length)
+ files, where length means number of files in directory. Order
+ in which files are returned is not guaranteed and is file system and
+ OS dependent. COUNT has to be an integral number in interval
+ [1,COUNT]. */)
+(Lisp_Object directory, Lisp_Object full, Lisp_Object match,
+   Lisp_Object nosort, Lisp_Object id_format, Lisp_Object count)
 {
   directory = Fexpand_file_name (directory, Qnil);
 
@@ -342,11 +368,11 @@
   Lisp_Object handler
     = Ffind_file_name_handler (directory, Qdirectory_files_and_attributes);
   if (!NILP (handler))
-    return call6 (handler, Qdirectory_files_and_attributes,
-                  directory, full, match, nosort, id_format);
+    return call7 (handler, Qdirectory_files_and_attributes,
+                  directory, full, match, nosort, id_format, count);
 
   return directory_files_internal (directory, full, match, nosort,
-				   true, id_format);
+				   true, id_format, count);
 }
 
 \f
@@ -929,7 +955,7 @@
   struct stat s;
 
   /* An array to hold the mode string generated by filemodestring,
-     including its terminating space and null byte.  */
+     including its terminating space and NUL byte.  */
   char modes[sizeof "-rwxr-xr-x "];
 
   char *uname = NULL, *gname = NULL;

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: sysdep.c.patch --]
[-- Type: text/x-patch, Size: 534 bytes --]

--- src/sysdep.c	2020-10-13 23:22:37.521367461 +0200
+++ ../sysdep.c	2020-10-13 22:53:04.272682143 +0200
@@ -2892,7 +2892,8 @@
      process.  */
   procdir = build_string ("/proc");
   match = build_string ("[0-9]+");
-  proclist = directory_files_internal (procdir, Qnil, match, Qt, false, Qnil);
+  proclist = directory_files_internal (procdir, Qnil, match, Qt,
+                                       false, Qnil, Qnil);
 
   /* `proclist' gives process IDs as strings.  Destructively convert
      each string into a number.  */

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: lisp.h.patch --]
[-- Type: text/x-patch, Size: 510 bytes --]

--- src/lisp.h	2020-10-13 23:20:23.555386699 +0200
+++ ../lisp.h	2020-10-13 22:47:04.192203245 +0200
@@ -4633,7 +4633,7 @@
 extern void syms_of_dired (void);
 extern Lisp_Object directory_files_internal (Lisp_Object, Lisp_Object,
                                              Lisp_Object, Lisp_Object,
-                                             bool, Lisp_Object);
+                                             bool, Lisp_Object, Lisp_Object);
 
 /* Defined in term.c.  */
 extern int *char_ins_del_vector;

[-- Attachment #5: dired-mark-empty.el --]
[-- Type: text/plain, Size: 2395 bytes --]

(require 'dired)

(defvar nodots "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")

(defun dired-go-to-first ()
    (interactive)
    (goto-char (point-min))
    (dired-next-line 1)
    (skip-chars-forward " \n\t"))

(defun dired-is-empty-p (directory-name)
  (null (directory-files directory-name nil nodots t 1)))

(defun directory-number-files (directory-name &optional omit-filter)
  (length (directory-files directory-name nil omit-filter t)))

(defun dired-mark-empty-dirs ()
  (interactive)
  (when (equal major-mode 'dired-mode)
    (let ((curr-dir))
      (save-excursion
        (dired-go-to-first)
        
        (while (not (eobp))
          (setq curr-dir (dired-file-name-at-point))
          (cond ((or (null curr-dir)
                     (string= curr-dir ".")
                     (string= curr-dir ".."))
                     ;; do nothing here
                 )
                ((file-directory-p curr-dir)
                 (when (dired-is-empty-p curr-dir)
                   (dired-mark 1)
                   (dired-previous-line 1))))
          (dired-next-line 1))))))

(defun test-1 (dir-name count)
  "Ask for COUNT number of files from directory DIR-NAME."
  (let ((max (length (directory-files dir-name nil nil t)))
        (res (length (directory-files dir-name nil nil t count))))
    (cond ((>= max count)
           (if (= res count)
               (message "passed: asked: %d get: %d number files in dir: %d" count
                        res max)
             (message "not-passed: asked: %s get: %s number files in dir: %s" count
                      res max)))
          ((< max count)
           (if (< res count)
              (message "passed: asked: %d get: %d number files in dir: %d" count
                       res max)
            (message "not-passed: asked: %s get: %s number files in dir: %s" count
                     res max)))
          (t
           (message "Invalid case!")))))

(defun test-2 (dir-name count)
  "Ask for random number of files in interval [1,COUNT] files from every subdir
of directory DIR-NAME."
  (let ((dirs (directory-files dir-name t nodots t)))
    (dolist (curr-dir dirs)
      (when (file-directory-p curr-dir)
        (test-1 curr-dir (+ 1 (random count)))))))

;;(benchmark-run-compiled 10 (dired-is-empty-p "/some/path"))

;; must be in some dired buffer for this
;;(benchmark-run-compiled 10 (dired-mark-empty-dirs))

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13 23:20           ` Arthur Miller
@ 2020-10-14  9:19             ` Michael Albinus
  2020-10-14 13:53               ` Arthur Miller
  0 siblings, 1 reply; 71+ messages in thread
From: Michael Albinus @ 2020-10-14  9:19 UTC (permalink / raw)
  To: Arthur Miller; +Cc: emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi Arthur,

> Thanks for the pointer. I was looking at tramp.el, but I it is ~6k loc
> :-). I am not sure I understand what I would need to do to implement
> for this; would like to learn though. Can you maybe point me to some
> function which I can take a look that would be similar to what I tried
> here use-case.

Follow directory-files. tramp-handle-directory-files is the Tramp
implementation of that function.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-14  1:52       ` Arthur Miller
@ 2020-10-14  9:21         ` Michael Albinus
  2020-10-14 13:56           ` Arthur Miller
  0 siblings, 1 reply; 71+ messages in thread
From: Michael Albinus @ 2020-10-14  9:21 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Eli Zaretskii, emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi Arthur,

> The only thing I am not sure about is how to deal with 0 count; I
> mean if user explicitly ask for 0 count; the case when count is not
> NILP.

>I have chosen not to deal with it all, I check for zer set
> explicit limit for count to be [1,COUNT]. I am not sure if that is best
> thing to do; maybe just to return Qnil? I am probably doing something
> else wrong, advice apprecaiated.

Returning Qnil seems to be OK, when count is 0.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-14  9:19             ` Michael Albinus
@ 2020-10-14 13:53               ` Arthur Miller
  0 siblings, 0 replies; 71+ messages in thread
From: Arthur Miller @ 2020-10-14 13:53 UTC (permalink / raw)
  To: Michael Albinus; +Cc: emacs-devel

Michael Albinus <michael.albinus@gmx.de> writes:

> Arthur Miller <arthur.miller@live.com> writes:
>
> Hi Arthur,
>
>> Thanks for the pointer. I was looking at tramp.el, but I it is ~6k loc
>> :-). I am not sure I understand what I would need to do to implement
>> for this; would like to learn though. Can you maybe point me to some
>> function which I can take a look that would be similar to what I tried
>> here use-case.
>
> Follow directory-files. tramp-handle-directory-files is the Tramp
> implementation of that function.
>
> Best regards, Michael.
Of course; I am so stupid sometimes :-) I was too fast, wasn't thinking, thanks!



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-14  9:21         ` Michael Albinus
@ 2020-10-14 13:56           ` Arthur Miller
  2020-10-14 14:41             ` Michael Albinus
  2020-10-14 14:49             ` Arthur Miller
  0 siblings, 2 replies; 71+ messages in thread
From: Arthur Miller @ 2020-10-14 13:56 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Eli Zaretskii, emacs-devel

Michael Albinus <michael.albinus@gmx.de> writes:

> Arthur Miller <arthur.miller@live.com> writes:
>
> Hi Arthur,
>
>> The only thing I am not sure about is how to deal with 0 count; I
>> mean if user explicitly ask for 0 count; the case when count is not
>> NILP.
>
>>I have chosen not to deal with it all, I check for zer set
>> explicit limit for count to be [1,COUNT]. I am not sure if that is best
>> thing to do; maybe just to return Qnil? I am probably doing something
>> else wrong, advice apprecaiated.
>
> Returning Qnil seems to be OK, when count is 0.
>
> Best regards, Michael.
What about return the length, number of the files in that case?

In order to get number of the files currently we would get list of files
and get length of the list afterwards; if we asked to get 0 files, it
could return the length; I thought of it afterwards.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-13 19:59       ` Arthur Miller
@ 2020-10-14 14:08         ` Eli Zaretskii
  2020-10-14 14:43           ` Arthur Miller
  0 siblings, 1 reply; 71+ messages in thread
From: Eli Zaretskii @ 2020-10-14 14:08 UTC (permalink / raw)
  To: Arthur Miller; +Cc: emacs-devel

> From: Arthur Miller <arthur.miller@live.com>
> Cc: emacs-devel@gnu.org
> Date: Tue, 13 Oct 2020 21:59:47 +0200
> 
> Can I ask two questions, just for my learning; you seem to handle
> ascii/unicode "manually"; in w32.c I have seen quite a few places where
> switch is done on if(w32_unicode_filenames); is it possible to somehow
> pass to configure script if Emacs should be compiled with wide or asci
> version of win api? 

The idea is not to decide this at configure and compile time, but at
runtime.  That way, the same Emacs binary can run both on systems that
support "wide" (a.k.a. "Unicode") APIs and on systems that don't.
Think about users who download the "official" binaries from the GNU
FTP site.

Besides, the compile-time "switch" to Unicode makes all TCHAR
variables be wchar_t under the hood, which means one cannot use
strlen, strcat, etc.  So this "feature" is a mixed blessing,
especially when the internal encoding is UTF-8.

> Second question: block_input; is there some general rule(s) what calls you
> enclose with block/unblock_input? I guess OS will anyway block the
> process after call to SYS_getdents so I didn't enclosed it; but I am not
> sure if that would be needed at all or not.

See the commentary in src/blockinput.h, I hope it answers the
question.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-14 13:56           ` Arthur Miller
@ 2020-10-14 14:41             ` Michael Albinus
  2020-10-14 15:07               ` Arthur Miller
  2020-10-14 14:49             ` Arthur Miller
  1 sibling, 1 reply; 71+ messages in thread
From: Michael Albinus @ 2020-10-14 14:41 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Eli Zaretskii, emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi Arthur,

>>>I have chosen not to deal with it all, I check for zer set
>>> explicit limit for count to be [1,COUNT]. I am not sure if that is best
>>> thing to do; maybe just to return Qnil? I am probably doing something
>>> else wrong, advice apprecaiated.
>>
>> Returning Qnil seems to be OK, when count is 0.
>>
> What about return the length, number of the files in that case?

No, this would be another signature of the response (number instead of
list of strings).

> In order to get number of the files currently we would get list of files
> and get length of the list afterwards; if we asked to get 0 files, it
> could return the length; I thought of it afterwards.

I cannot imagine that this information is needed somewhere. Why do you
need to know, how many files are in a directory?

Berst regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-14 14:08         ` Eli Zaretskii
@ 2020-10-14 14:43           ` Arthur Miller
  0 siblings, 0 replies; 71+ messages in thread
From: Arthur Miller @ 2020-10-14 14:43 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Arthur Miller <arthur.miller@live.com>
>> Cc: emacs-devel@gnu.org
>> Date: Tue, 13 Oct 2020 21:59:47 +0200
>> 
>> Can I ask two questions, just for my learning; you seem to handle
>> ascii/unicode "manually"; in w32.c I have seen quite a few places where
>> switch is done on if(w32_unicode_filenames); is it possible to somehow
>> pass to configure script if Emacs should be compiled with wide or asci
>> version of win api? 
>
> The idea is not to decide this at configure and compile time, but at
> runtime.  That way, the same Emacs binary can run both on systems that
> support "wide" (a.k.a. "Unicode") APIs and on systems that don't.
> Think about users who download the "official" binaries from the GNU
> FTP site.
Ok, I understand the reason now.

> Besides, the compile-time "switch" to Unicode makes all TCHAR
> variables be wchar_t under the hood, which means one cannot use
> strlen, strcat, etc.  So this "feature" is a mixed blessing,
> especially when the internal encoding is UTF-8.
Yes; that is what they do in VS (they have option on general tab to use
unicode/multibyte/not-defined == ascii), so I was thinking about
something like that with configure, but now I understand why you don't
have it.

>> Second question: block_input; is there some general rule(s) what calls you
>> enclose with block/unblock_input? I guess OS will anyway block the
>> process after call to SYS_getdents so I didn't enclosed it; but I am not
>> sure if that would be needed at all or not.
>
> See the commentary in src/blockinput.h, I hope it answers the
> question.
Yes, will do. Thanks.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-14 13:56           ` Arthur Miller
  2020-10-14 14:41             ` Michael Albinus
@ 2020-10-14 14:49             ` Arthur Miller
  1 sibling, 0 replies; 71+ messages in thread
From: Arthur Miller @ 2020-10-14 14:49 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Eli Zaretskii, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1511 bytes --]

Arthur Miller <arthur.miller@live.com> writes:

> Michael Albinus <michael.albinus@gmx.de> writes:
>
>> Arthur Miller <arthur.miller@live.com> writes:
>>
>> Hi Arthur,
>>
>>> The only thing I am not sure about is how to deal with 0 count; I
>>> mean if user explicitly ask for 0 count; the case when count is not
>>> NILP.
>>
>>>I have chosen not to deal with it all, I check for zer set
>>> explicit limit for count to be [1,COUNT]. I am not sure if that is best
>>> thing to do; maybe just to return Qnil? I am probably doing something
>>> else wrong, advice apprecaiated.
>>
>> Returning Qnil seems to be OK, when count is 0.
>>
>> Best regards, Michael.
> What about return the length, number of the files in that case?
>
> In order to get number of the files currently we would get list of files
> and get length of the list afterwards; if we asked to get 0 files, it
> could return the length; I thought of it afterwards.

Ok; just a very-very fast hack; I am in very rush today, so this was my
coffee pause :-)

I have tested with those previous tests, seems to work, but I don't have
time to test on windows. I am also not sure if I can circut that early,
please see just as an idea.

If cunt 0 is asked, then directory-files will return number of files in
directory. If also "match" is provided it *should* give only number of
files that match the given regex and sort will have no effect (no
sorting). I don't have time to test with match or to write docs; but can
do probably tomorrow or on friday.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: dired.c.patch --]
[-- Type: text/x-patch, Size: 5572 bytes --]

--- /home/arthur/dired.c	2020-10-13 13:06:07.517648492 +0200
+++ src/dired.c	2020-10-14 16:18:03.750214680 +0200
@@ -20,6 +20,7 @@
 
 #include <config.h>
 
+#include <stddef.h>
 #include <sys/stat.h>
 
 #ifdef HAVE_PWD_H
@@ -165,7 +166,7 @@
 Lisp_Object
 directory_files_internal (Lisp_Object directory, Lisp_Object full,
 			  Lisp_Object match, Lisp_Object nosort, bool attrs,
-			  Lisp_Object id_format)
+			  Lisp_Object id_format, Lisp_Object count_to_return)
 {
   if (!NILP (match))
     CHECK_STRING (match);
@@ -224,6 +225,18 @@
   case_table = BVAR (&buffer_defaults, case_canon_table);
 #endif
 
+  bool only_length = false;
+  ptrdiff_t ind = 0, last = 0;
+  if(!NILP(count_to_return) && FIXNATP(count_to_return))
+    {
+      last = XFIXNAT(count_to_return);
+  
+      if(!last){
+        last = 1;
+        only_length = true;
+      }
+    }
+
   /* Read directory entries and accumulate them into LIST.  */
   Lisp_Object list = Qnil;
   for (struct dirent *dp; (dp = read_dirent (d, directory)); )
@@ -267,7 +280,22 @@
       else
 	finalname = name;
 
-      list = Fcons (attrs ? Fcons (finalname, fileattrs) : finalname, list);
+      if (only_length)
+        {
+          ind++;
+        }
+      else
+        {
+          if (!NILP(count_to_return) && FIXNATP(count_to_return))
+            {
+              if (ind == last)
+                break;
+              ind ++;
+            }
+      
+          list = Fcons (attrs ? Fcons (finalname, fileattrs) :
+                        finalname, list);
+        }
     }
 
   closedir (d);
@@ -279,16 +307,19 @@
   /* Discard the unwind protect.  */
   specpdl_ptr = specpdl + count;
 
+  if (only_length)
+    return make_fixnum(ind);
+
   if (NILP (nosort))
     list = Fsort (Fnreverse (list),
 		  attrs ? Qfile_attributes_lessp : Qstring_lessp);
-
+  
   (void) directory_volatile;
   return list;
 }
 
 
-DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
+DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 5, 0,
        doc: /* Return a list of names of files in DIRECTORY.
 There are three optional arguments:
 If FULL is non-nil, return absolute file names.  Otherwise return names
@@ -296,9 +327,14 @@
 If MATCH is non-nil, mention only file names that match the regexp MATCH.
 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
  Otherwise, the list returned is sorted with `string-lessp'.
- NOSORT is useful if you plan to sort the result yourself.  */)
+ NOSORT is useful if you plan to sort the result yourself. 
+If COUNT is  non-nil, the function will return max (COUNT,length)
+ files, where length means number of files in directory. Order
+ in which files are returned is not guaranteed and is file system and
+ OS dependent. COUNT has to be an integral number in interval
+ [1,COUNT]. */) 
   (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
-   Lisp_Object nosort)
+   Lisp_Object nosort, Lisp_Object count)
 {
   directory = Fexpand_file_name (directory, Qnil);
 
@@ -306,14 +342,15 @@
      call the corresponding file name handler.  */
   Lisp_Object handler = Ffind_file_name_handler (directory, Qdirectory_files);
   if (!NILP (handler))
-    return call5 (handler, Qdirectory_files, directory,
-                  full, match, nosort);
+    return call6 (handler, Qdirectory_files, directory,
+                  full, match, nosort, count);
 
-  return directory_files_internal (directory, full, match, nosort, false, Qnil);
+  return directory_files_internal (directory, full, match, nosort,
+                                   false, Qnil, count);
 }
 
 DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes,
-       Sdirectory_files_and_attributes, 1, 5, 0,
+       Sdirectory_files_and_attributes, 1, 6, 0,
        doc: /* Return a list of names of files and their attributes in DIRECTORY.
 Value is a list of the form:
 
@@ -331,9 +368,14 @@
 ID-FORMAT specifies the preferred format of attributes uid and gid, see
 `file-attributes' for further documentation.
 On MS-Windows, performance depends on `w32-get-true-file-attributes',
-which see.  */)
-  (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
-   Lisp_Object nosort, Lisp_Object id_format)
+which see. 
+If COUNT is  non-nil, the function will return max (COUNT,length)
+ files, where length means number of files in directory. Order
+ in which files are returned is not guaranteed and is file system and
+ OS dependent. COUNT has to be an integral number in interval
+ [1,COUNT]. */)
+(Lisp_Object directory, Lisp_Object full, Lisp_Object match,
+   Lisp_Object nosort, Lisp_Object id_format, Lisp_Object count)
 {
   directory = Fexpand_file_name (directory, Qnil);
 
@@ -342,11 +384,11 @@
   Lisp_Object handler
     = Ffind_file_name_handler (directory, Qdirectory_files_and_attributes);
   if (!NILP (handler))
-    return call6 (handler, Qdirectory_files_and_attributes,
-                  directory, full, match, nosort, id_format);
+    return call7 (handler, Qdirectory_files_and_attributes,
+                  directory, full, match, nosort, id_format, count);
 
   return directory_files_internal (directory, full, match, nosort,
-				   true, id_format);
+				   true, id_format, count);
 }
 
 \f
@@ -929,7 +971,7 @@
   struct stat s;
 
   /* An array to hold the mode string generated by filemodestring,
-     including its terminating space and null byte.  */
+     including its terminating space and NUL byte.  */
   char modes[sizeof "-rwxr-xr-x "];
 
   char *uname = NULL, *gname = NULL;

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-14 14:41             ` Michael Albinus
@ 2020-10-14 15:07               ` Arthur Miller
  2020-10-14 15:53                 ` Michael Albinus
  0 siblings, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-14 15:07 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Eli Zaretskii, emacs-devel

Michael Albinus <michael.albinus@gmx.de> writes:

> Arthur Miller <arthur.miller@live.com> writes:
>
> Hi Arthur,
>
>>>>I have chosen not to deal with it all, I check for zer set
>>>> explicit limit for count to be [1,COUNT]. I am not sure if that is best
>>>> thing to do; maybe just to return Qnil? I am probably doing something
>>>> else wrong, advice apprecaiated.
>>>
>>> Returning Qnil seems to be OK, when count is 0.
>>>
>> What about return the length, number of the files in that case?
>
> No, this would be another signature of the response (number instead of
> list of strings).
>
>> In order to get number of the files currently we would get list of files
>> and get length of the list afterwards; if we asked to get 0 files, it
>> could return the length; I thought of it afterwards.
>
> I cannot imagine that this information is needed somewhere. Why do you
> need to know, how many files are in a directory?
>
> Berst regards, Michael.
No idea :-).

It was just to test if empty; but now empty is better served with asking
just for one file and testing for null; and I was also thinking what to
do with 0 count if asked for after I sent patch yesterday; it seemed
like a bit more useful then just return nil early.

I can send tomorrow one that just returns nil and exits.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-14 15:07               ` Arthur Miller
@ 2020-10-14 15:53                 ` Michael Albinus
  2020-10-14 16:12                   ` Eli Zaretskii
  0 siblings, 1 reply; 71+ messages in thread
From: Michael Albinus @ 2020-10-14 15:53 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Eli Zaretskii, emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi Arthur,

> It was just to test if empty; but now empty is better served with asking
> just for one file and testing for null; and I was also thinking what to
> do with 0 count if asked for after I sent patch yesterday; it seemed
> like a bit more useful then just return nil early.
>
> I can send tomorrow one that just returns nil and exits.

Let's wait what Eli prefers.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-14 15:53                 ` Michael Albinus
@ 2020-10-14 16:12                   ` Eli Zaretskii
  2020-10-14 16:21                     ` Michael Albinus
  0 siblings, 1 reply; 71+ messages in thread
From: Eli Zaretskii @ 2020-10-14 16:12 UTC (permalink / raw)
  To: Michael Albinus; +Cc: arthur.miller, emacs-devel

> From: Michael Albinus <michael.albinus@gmx.de>
> Cc: Eli Zaretskii <eliz@gnu.org>,  emacs-devel@gnu.org
> Date: Wed, 14 Oct 2020 17:53:38 +0200
> 
> > It was just to test if empty; but now empty is better served with asking
> > just for one file and testing for null; and I was also thinking what to
> > do with 0 count if asked for after I sent patch yesterday; it seemed
> > like a bit more useful then just return nil early.
> >
> > I can send tomorrow one that just returns nil and exits.
> 
> Let's wait what Eli prefers.

I think 0 doesn't make much sense, so we might as well not support
that at all.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-14 16:12                   ` Eli Zaretskii
@ 2020-10-14 16:21                     ` Michael Albinus
  2020-10-14 16:29                       ` Eli Zaretskii
  0 siblings, 1 reply; 71+ messages in thread
From: Michael Albinus @ 2020-10-14 16:21 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: arthur.miller, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> I think 0 doesn't make much sense, so we might as well not support
> that at all.

In general, I agree. Calling directory-files with COUNT being 0,
literally, doesn't make sense. But COUNT could be the result of some
arithmetics, and instead urging the caller to test it, we could simply
return nil. Which is correct, reading nil as the empty list.

And it doesn't cost us anything.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-14 16:21                     ` Michael Albinus
@ 2020-10-14 16:29                       ` Eli Zaretskii
  2020-10-15  5:53                         ` Arthur Miller
  0 siblings, 1 reply; 71+ messages in thread
From: Eli Zaretskii @ 2020-10-14 16:29 UTC (permalink / raw)
  To: Michael Albinus; +Cc: arthur.miller, emacs-devel

> From: Michael Albinus <michael.albinus@gmx.de>
> Cc: arthur.miller@live.com,  emacs-devel@gnu.org
> Date: Wed, 14 Oct 2020 18:21:21 +0200
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> > I think 0 doesn't make much sense, so we might as well not support
> > that at all.
> 
> In general, I agree. Calling directory-files with COUNT being 0,
> literally, doesn't make sense. But COUNT could be the result of some
> arithmetics, and instead urging the caller to test it, we could simply
> return nil. Which is correct, reading nil as the empty list.
> 
> And it doesn't cost us anything.

I'm okay with interpreting "don't support" as "return nil".



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-14 16:29                       ` Eli Zaretskii
@ 2020-10-15  5:53                         ` Arthur Miller
  2020-10-15  9:12                           ` Michael Albinus
  0 siblings, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-15  5:53 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Michael Albinus, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1222 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Michael Albinus <michael.albinus@gmx.de>
>> Cc: arthur.miller@live.com,  emacs-devel@gnu.org
>> Date: Wed, 14 Oct 2020 18:21:21 +0200
>> 
>> Eli Zaretskii <eliz@gnu.org> writes:
>> 
>> > I think 0 doesn't make much sense, so we might as well not support
>> > that at all.
>> 
>> In general, I agree. Calling directory-files with COUNT being 0,
>> literally, doesn't make sense. But COUNT could be the result of some
>> arithmetics, and instead urging the caller to test it, we could simply
>> return nil. Which is correct, reading nil as the empty list.
>> 
>> And it doesn't cost us anything.
>
> I'm okay with interpreting "don't support" as "return nil".

Attached is patch which return nil early.

I was thinking a bit when it would be useful to return length; the only
thing I come up is to maybe allocate some structure, a vector or
something based on how many files there are without really carying about
files. In case there are many such objects, there would be lots of list
the lisp system does not care about, and GC will have to work a lot
unnecessary, but i think it is probably very rare case if not very
artifical, so nil is just fine for the most use-cases.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: dired.c.patch --]
[-- Type: text/x-patch, Size: 5369 bytes --]

--- src/dired.c	2020-10-15 07:43:02.633804624 +0200
+++ ../dired4.c	2020-10-15 07:42:01.358574645 +0200
@@ -17,7 +17,6 @@
 You should have received a copy of the GNU General Public License
 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 
-
 #include <config.h>
 
 #include <sys/stat.h>
@@ -165,8 +164,19 @@
 Lisp_Object
 directory_files_internal (Lisp_Object directory, Lisp_Object full,
 			  Lisp_Object match, Lisp_Object nosort, bool attrs,
-			  Lisp_Object id_format)
+			  Lisp_Object id_format, Lisp_Object return_count)
 {
+  ptrdiff_t ind = 0, last = 0;
+
+  /* check count first for early exit */
+  if (FIXNATP(return_count))
+    {
+      last = XFIXNAT(return_count);
+  
+      if (!last)
+        return Qnil;
+    }
+
   if (!NILP (match))
     CHECK_STRING (match);
 
@@ -267,6 +277,13 @@
       else
 	finalname = name;
 
+      if (FIXNATP(return_count))
+        {
+          if (ind == last)
+            break;
+          ind ++;
+        }
+
       list = Fcons (attrs ? Fcons (finalname, fileattrs) : finalname, list);
     }
 
@@ -287,8 +304,7 @@
   return list;
 }
 
-
-DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
+DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 5, 0,
        doc: /* Return a list of names of files in DIRECTORY.
 There are three optional arguments:
 If FULL is non-nil, return absolute file names.  Otherwise return names
@@ -296,9 +312,14 @@
 If MATCH is non-nil, mention only file names that match the regexp MATCH.
 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
  Otherwise, the list returned is sorted with `string-lessp'.
- NOSORT is useful if you plan to sort the result yourself.  */)
+ NOSORT is useful if you plan to sort the result yourself.
+If COUNT is  non-nil, the function will return max of COUNT and length
+ files, where length is number of files in the directory. Order
+ in which files are returned is not guaranteed and is file system and
+ OS dependent. COUNT has to be an integral number in interval
+ [1,COUNT]. If 0 files are requested the function will return nil. */)
   (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
-   Lisp_Object nosort)
+   Lisp_Object nosort, Lisp_Object count)
 {
   directory = Fexpand_file_name (directory, Qnil);
 
@@ -306,34 +327,40 @@
      call the corresponding file name handler.  */
   Lisp_Object handler = Ffind_file_name_handler (directory, Qdirectory_files);
   if (!NILP (handler))
-    return call5 (handler, Qdirectory_files, directory,
-                  full, match, nosort);
+    return call6 (handler, Qdirectory_files, directory,
+                  full, match, nosort, count);
 
-  return directory_files_internal (directory, full, match, nosort, false, Qnil);
+  return directory_files_internal (directory, full, match, nosort,
+                                   false, Qnil, count);
 }
 
 DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes,
-       Sdirectory_files_and_attributes, 1, 5, 0,
-       doc: /* Return a list of names of files and their attributes in DIRECTORY.
+       Sdirectory_files_and_attributes, 1, 6, 0, doc
+       : /* Return a list of names of files and their attributes in DIRECTORY.
 Value is a list of the form:
 
-  ((FILE1 . FILE1-ATTRS) (FILE2 . FILE2-ATTRS) ...)
+((FILE1 . FILE1-ATTRS) (FILE2 . FILE2-ATTRS) ...)
 
 where each FILEn-ATTRS is the attributes of FILEn as returned
 by `file-attributes'.
 
 This function accepts four optional arguments:
 If FULL is non-nil, return absolute file names.  Otherwise return names
- that are relative to the specified directory.
+that are relative to the specified directory.
 If MATCH is non-nil, mention only file names that match the regexp MATCH.
 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.
+NOSORT is useful if you plan to sort the result yourself.
 ID-FORMAT specifies the preferred format of attributes uid and gid, see
 `file-attributes' for further documentation.
 On MS-Windows, performance depends on `w32-get-true-file-attributes',
-which see.  */)
-  (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
-   Lisp_Object nosort, Lisp_Object id_format)
+which see.
+If COUNT is  non-nil, the function will return max of COUNT and length
+ files, where length is number of files in the directory. Order
+ in which files are returned is not guaranteed and is file system and
+ OS dependent. COUNT has to be an integral number in interval
+ [1,COUNT]. If 0 files are requested the function will return nil. */)
+(Lisp_Object directory, Lisp_Object full, Lisp_Object match,
+ Lisp_Object nosort, Lisp_Object id_format, Lisp_Object count)
 {
   directory = Fexpand_file_name (directory, Qnil);
 
@@ -342,11 +369,11 @@
   Lisp_Object handler
     = Ffind_file_name_handler (directory, Qdirectory_files_and_attributes);
   if (!NILP (handler))
-    return call6 (handler, Qdirectory_files_and_attributes,
-                  directory, full, match, nosort, id_format);
+    return call7 (handler, Qdirectory_files_and_attributes,
+                  directory, full, match, nosort, id_format, count);
 
   return directory_files_internal (directory, full, match, nosort,
-				   true, id_format);
+				   true, id_format, count);
 }
 
 \f

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-15  5:53                         ` Arthur Miller
@ 2020-10-15  9:12                           ` Michael Albinus
  2020-10-15 11:33                             ` Arthur Miller
  0 siblings, 1 reply; 71+ messages in thread
From: Michael Albinus @ 2020-10-15  9:12 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Eli Zaretskii, emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi Arthur,

> Attached is patch which return nil early.

Thanks for this. I haven't seen your name on the FSF file; I guess your
legal papers are on the way?

In the meantime, we could prepare the other changes. These are

- Adapt the description of directory-files and
  directory-files-and-attributes in doc/lispref/files.texi.

- Add an entry to etc/NEWS.

- Adapt the file name handlers. These are ange-ftp-directory-files,
  ange-ftp-directory-files-and-attributes, tramp-handle-directory-files,
  tramp-handle-directory-files-and-attributes,
  tramp-adb-handle-directory-files-and-attributes,
  tramp-crypt-handle-directory-files,
  tramp-rclone-handle-directory-files,
  tramp-sh-handle-directory-files-and-attributes,
  tramp-smb-handle-directory-files.

- Adapt resp extend ERT tests. These are tramp-test16-directory-files,
  tramp-test19-directory-files-and-attributes,
  tramp-archive-test16-directory-files and
  tramp-archive-test19-directory-files-and-attributes.

- Optionally (but much appreciated), write new ERT tests for
  directory-files and directory-files-and-attributes.

And here are some minor comments about your patch:

> +      if (FIXNATP(return_count))
> +        {
> +          if (ind == last)
> +            break;
> +          ind ++;
> +        }
> +

Wouldn't it be more efficient to test

      if (!last && ind == last)
	break;
      ind ++;

> +DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 5, 0,
>         doc: /* Return a list of names of files in DIRECTORY.
>  There are three optional arguments:
>  If FULL is non-nil, return absolute file names.  Otherwise return names
> @@ -296,9 +312,14 @@
>  If MATCH is non-nil, mention only file names that match the regexp MATCH.
>  If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
>   Otherwise, the list returned is sorted with `string-lessp'.
> - NOSORT is useful if you plan to sort the result yourself.  */)
> + NOSORT is useful if you plan to sort the result yourself.
> +If COUNT is  non-nil, the function will return max of COUNT and length
> + files, where length is number of files in the directory. Order
> + in which files are returned is not guaranteed and is file system and
> + OS dependent. COUNT has to be an integral number in interval
> + [1,COUNT]. If 0 files are requested the function will return nil. */)

I know what you mean, but I had to read it twice in order to
understand. Why not simply

If COUNT is a natural number, the function will return up to COUNT files.

>  DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes,
> -       Sdirectory_files_and_attributes, 1, 5, 0,
> -       doc: /* Return a list of names of files and their attributes in DIRECTORY.
> +       Sdirectory_files_and_attributes, 1, 6, 0, doc
> +       : /* Return a list of names of files and their attributes in DIRECTORY.
>  Value is a list of the form:
>
> -  ((FILE1 . FILE1-ATTRS) (FILE2 . FILE2-ATTRS) ...)
> +((FILE1 . FILE1-ATTRS) (FILE2 . FILE2-ATTRS) ...)

Why do you remove the indentation? It is intentional, I believe.

>  This function accepts four optional arguments:
>  If FULL is non-nil, return absolute file names.  Otherwise return names
> - that are relative to the specified directory.
> +that are relative to the specified directory.
>  If MATCH is non-nil, mention only file names that match the regexp MATCH.
>  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.
> +NOSORT is useful if you plan to sort the result yourself.

Same here.

> +If COUNT is  non-nil, the function will return max of COUNT and length
> + files, where length is number of files in the directory. Order
> + in which files are returned is not guaranteed and is file system and
> + OS dependent. COUNT has to be an integral number in interval
> + [1,COUNT]. If 0 files are requested the function will return nil. */)

See above.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-15  9:12                           ` Michael Albinus
@ 2020-10-15 11:33                             ` Arthur Miller
  2020-10-15 12:21                               ` Michael Albinus
  2020-10-15 13:38                               ` Stefan Monnier
  0 siblings, 2 replies; 71+ messages in thread
From: Arthur Miller @ 2020-10-15 11:33 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Eli Zaretskii, emacs-devel

Michael Albinus <michael.albinus@gmx.de> writes:

> Arthur Miller <arthur.miller@live.com> writes:
>
> Hi Arthur,
>
>> Attached is patch which return nil early.
>
> Thanks for this. I haven't seen your name on the FSF file; I guess your
> legal papers are on the way?
They are not, but they can be if someone send me link. I've been looking
at this page:

https://www.gnu.org/prep/maintain/html_node/Copyright-Papers.html#Copyright-Papers

but I am not really sure where do I send request.

> In the meantime, we could prepare the other changes. These are
>
> - Adapt the description of directory-files and
>   directory-files-and-attributes in doc/lispref/files.texi.
>
> - Add an entry to etc/NEWS.
>
> - Adapt the file name handlers. These are ange-ftp-directory-files,
>   ange-ftp-directory-files-and-attributes, tramp-handle-directory-files,
>   tramp-handle-directory-files-and-attributes,
>   tramp-adb-handle-directory-files-and-attributes,
>   tramp-crypt-handle-directory-files,
>   tramp-rclone-handle-directory-files,
>   tramp-sh-handle-directory-files-and-attributes,
>   tramp-smb-handle-directory-files.

Aha, so it is how it works; didn't have time to look into tramp yet.
Ok, I'll do; I'll sent in patch(es) when I am done. Probably not today
though but during the weekend of beginning of the next week.

So many changes just for one signature :-).
> - Adapt resp extend ERT tests. These are tramp-test16-directory-files,
>   tramp-test19-directory-files-and-attributes,
>   tramp-archive-test16-directory-files and
>   tramp-archive-test19-directory-files-and-attributes.
>
> - Optionally (but much appreciated), write new ERT tests for
>   directory-files and directory-files-and-attributes.

Will have to look at ERT, I suppose it is not too complicated,
opportunity to learn it.

> And here are some minor comments about your patch:
>
>> +      if (FIXNATP(return_count))
>> +        {
>> +          if (ind == last)
>> +            break;
>> +          ind ++;
>> +        }
>> +
>
> Wouldn't it be more efficient to test
>
>       if (!last && ind == last)
> 	break;
>       ind ++;
It will :-)

I mainly try to be clear "what I intent" for some future reader; since
previous code uses lisp.h macros, I used same. I thought that one extra
'if' is not that much of a penalty, I'll gladly shortcircut with !last.

>> +DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 5, 0,
>>         doc: /* Return a list of names of files in DIRECTORY.
>>  There are three optional arguments:
>>  If FULL is non-nil, return absolute file names.  Otherwise return names
>> @@ -296,9 +312,14 @@
>>  If MATCH is non-nil, mention only file names that match the regexp MATCH.
>>  If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
>>   Otherwise, the list returned is sorted with `string-lessp'.
>> - NOSORT is useful if you plan to sort the result yourself.  */)
>> + NOSORT is useful if you plan to sort the result yourself.
>> +If COUNT is  non-nil, the function will return max of COUNT and length
>> + files, where length is number of files in the directory. Order
>> + in which files are returned is not guaranteed and is file system and
>> + OS dependent. COUNT has to be an integral number in interval
>> + [1,COUNT]. If 0 files are requested the function will return nil. */)
>
> I know what you mean, but I had to read it twice in order to
> understand. Why not simply
>
> If COUNT is a natural number, the function will return up to COUNT files.
I was thinking myself that the last argument took as much doc-space as
comment for the rest of entire function :-). I tried to be as
no-doubt-clear as well as not-so-mathematical, but I definitely think
your version is much nicer. We go with that.

>>  DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes,
>> -       Sdirectory_files_and_attributes, 1, 5, 0,
>> -       doc: /* Return a list of names of files and their attributes in DIRECTORY.
>> +       Sdirectory_files_and_attributes, 1, 6, 0, doc
>> +       : /* Return a list of names of files and their attributes in DIRECTORY.
>>  Value is a list of the form:
>>
>> -  ((FILE1 . FILE1-ATTRS) (FILE2 . FILE2-ATTRS) ...)
>> +((FILE1 . FILE1-ATTRS) (FILE2 . FILE2-ATTRS) ...)
>
> Why do you remove the indentation? It is intentional, I believe.
I don't. It is my Emacs. I have by defualt "linux" as identation
style; and changed to "gnu" and even setq default, but Emacs arsed
about identing "linux" style anyway; so I "manually" idented everything
I sent in that changed, and I have just missed those since I didn't
edited those at all.




^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-15 11:33                             ` Arthur Miller
@ 2020-10-15 12:21                               ` Michael Albinus
  2020-10-15 13:29                                 ` Arthur Miller
                                                   ` (2 more replies)
  2020-10-15 13:38                               ` Stefan Monnier
  1 sibling, 3 replies; 71+ messages in thread
From: Michael Albinus @ 2020-10-15 12:21 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Eli Zaretskii, emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi Arthur,

>> Thanks for this. I haven't seen your name on the FSF file; I guess your
>> legal papers are on the way?
> They are not, but they can be if someone send me link. I've been looking
> at this page:
>
> https://www.gnu.org/prep/maintain/html_node/Copyright-Papers.html#Copyright-Papers
>
> but I am not really sure where do I send request.

Sorry, I should have asked. I'll send you the template off-list.

>> - Adapt the file name handlers. These are ange-ftp-directory-files,
>>   ange-ftp-directory-files-and-attributes, tramp-handle-directory-files,
>>   tramp-handle-directory-files-and-attributes,
>>   tramp-adb-handle-directory-files-and-attributes,
>>   tramp-crypt-handle-directory-files,
>>   tramp-rclone-handle-directory-files,
>>   tramp-sh-handle-directory-files-and-attributes,
>>   tramp-smb-handle-directory-files.
>
> Aha, so it is how it works; didn't have time to look into tramp yet.
> Ok, I'll do; I'll sent in patch(es) when I am done. Probably not today
> though but during the weekend of beginning of the next week.

There's no rush. Doing the legal work will take a week or so.

> So many changes just for one signature :-).

In order to enjoy you: Tramp is backward compatible back to Emacs
25. This must also be taken into account :-)

But don't worry, I'll make the needed changes after your commit.

>> - Adapt resp extend ERT tests. These are tramp-test16-directory-files,
>>   tramp-test19-directory-files-and-attributes,
>>   tramp-archive-test16-directory-files and
>>   tramp-archive-test19-directory-files-and-attributes.
>>
>> - Optionally (but much appreciated), write new ERT tests for
>>   directory-files and directory-files-and-attributes.
>
> Will have to look at ERT, I suppose it is not too complicated,
> opportunity to learn it.

A look at the ert manual might help. (info "(ert)")

> I mainly try to be clear "what I intent" for some future reader; since
> previous code uses lisp.h macros, I used same. I thought that one extra
> 'if' is not that much of a penalty, I'll gladly shortcircut with !last.

In case you feel the need, you could also provide a comment.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-15 12:21                               ` Michael Albinus
@ 2020-10-15 13:29                                 ` Arthur Miller
  2020-10-15 14:01                                 ` Arthur Miller
  2020-10-16 23:31                                 ` Arthur Miller
  2 siblings, 0 replies; 71+ messages in thread
From: Arthur Miller @ 2020-10-15 13:29 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Eli Zaretskii, emacs-devel

Michael Albinus <michael.albinus@gmx.de> writes:

> Arthur Miller <arthur.miller@live.com> writes:
>
> Hi Arthur,
>
>>> Thanks for this. I haven't seen your name on the FSF file; I guess your
>>> legal papers are on the way?
>> They are not, but they can be if someone send me link. I've been looking
>> at this page:
>>
>> https://www.gnu.org/prep/maintain/html_node/Copyright-Papers.html#Copyright-Papers
>>
>> but I am not really sure where do I send request.
>
> Sorry, I should have asked. I'll send you the template off-list.
>
>>> - Adapt the file name handlers. These are ange-ftp-directory-files,
>>>   ange-ftp-directory-files-and-attributes, tramp-handle-directory-files,
>>>   tramp-handle-directory-files-and-attributes,
>>>   tramp-adb-handle-directory-files-and-attributes,
>>>   tramp-crypt-handle-directory-files,
>>>   tramp-rclone-handle-directory-files,
>>>   tramp-sh-handle-directory-files-and-attributes,
>>>   tramp-smb-handle-directory-files.
>>
>> Aha, so it is how it works; didn't have time to look into tramp yet.
>> Ok, I'll do; I'll sent in patch(es) when I am done. Probably not today
>> though but during the weekend of beginning of the next week.
>
> There's no rush. Doing the legal work will take a week or so.
>
>> So many changes just for one signature :-).
>
> In order to enjoy you: Tramp is backward compatible back to Emacs
> 25. This must also be taken into account :-)
:-) You definitely understand my humour!

> But don't worry, I'll make the needed changes after your commit.
>
>>> - Adapt resp extend ERT tests. These are tramp-test16-directory-files,
>>>   tramp-test19-directory-files-and-attributes,
>>>   tramp-archive-test16-directory-files and
>>>   tramp-archive-test19-directory-files-and-attributes.
>>>
>>> - Optionally (but much appreciated), write new ERT tests for
>>>   directory-files and directory-files-and-attributes.
>>
>> Will have to look at ERT, I suppose it is not too complicated,
>> opportunity to learn it.
>
> A look at the ert manual might help. (info "(ert)")
>
>> I mainly try to be clear "what I intent" for some future reader; since
>> previous code uses lisp.h macros, I used same. I thought that one extra
>> 'if' is not that much of a penalty, I'll gladly shortcircut with !last.
>
> In case you feel the need, you could also provide a comment.
>
> Best regards, Michael.

Ok, I have sent a request for papers; and will deep dive into tramp soon.

Thank you a lot for guiding me, it is indispensible.

Best regards
/a



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-15 11:33                             ` Arthur Miller
  2020-10-15 12:21                               ` Michael Albinus
@ 2020-10-15 13:38                               ` Stefan Monnier
  2020-10-16 23:33                                 ` Arthur Miller
  1 sibling, 1 reply; 71+ messages in thread
From: Stefan Monnier @ 2020-10-15 13:38 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Eli Zaretskii, Michael Albinus, emacs-devel

> They are not, but they can be if someone send me link. I've been looking
> at this page:

Here it is.  Please fill the form below and then send it as instructed
to the FSF so they can send you the relevant paperwork to sign.
Thank you for your contribution,


        Stefan


Please email the following information to assign@gnu.org, and we
will send you the assignment form for your past and future changes.

Please use your full legal name (in ASCII characters) as the subject
line of the message.
----------------------------------------------------------------------
REQUEST: SEND FORM FOR PAST AND FUTURE CHANGES

[What is the name of the program or package you're contributing to?]
Emacs

[Did you copy any files or text written by someone else in these changes?
Even if that material is free software, we need to know about it.]


[Do you have an employer who might have a basis to claim to own
your changes?  Do you attend a school which might make such a claim?]


[For the copyright registration, what country are you a citizen of?]


[What year were you born?]


[Please write your email address here.]


[Please write your postal address here.]





[Which files have you changed so far, and which new files have you written
so far?]




^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-15 12:21                               ` Michael Albinus
  2020-10-15 13:29                                 ` Arthur Miller
@ 2020-10-15 14:01                                 ` Arthur Miller
  2020-10-15 14:41                                   ` Michael Albinus
  2020-10-16 23:31                                 ` Arthur Miller
  2 siblings, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-15 14:01 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Eli Zaretskii, emacs-devel

Michael Albinus <michael.albinus@gmx.de> writes:

>>> - Adapt the file name handlers. These are ange-ftp-directory-files,
>>>   ange-ftp-directory-files-and-attributes, tramp-handle-directory-files,
>>>   tramp-handle-directory-files-and-attributes,
>>>   tramp-adb-handle-directory-files-and-attributes,
>>>   tramp-crypt-handle-directory-files,
>>>   tramp-rclone-handle-directory-files,
>>>   tramp-sh-handle-directory-files-and-attributes,
>>>   tramp-smb-handle-directory-files.

Sorry to bother, just one question: I am looking at ange-ftp, and see no
'nosort' and 'id-format' arguments passed in ange-ftp-directory-files:

(defun ange-ftp-directory-files (directory &optional full match &rest v19-args)

Are those (and count) taken care of as "rest" together with &rest
v19-args or should I specify them as it is done in ange-ftp-directory-and-attributes:

(defun ange-ftp-directory-files-and-attributes
  (directory &optional full match nosort id-format)


Would this work:

(defun ange-ftp-directory-files (directory &optional full match
                                           nosort id-format count
					   &rest v19-args)
  (setq directory (expand-file-name directory))
  (if (ange-ftp-ftp-name directory)
      (progn
	(ange-ftp-barf-if-not-directory directory)
	(let ((tail (ange-ftp-hash-table-keys
		     (ange-ftp-get-files directory)))
	      files f)
	  (setq directory (file-name-as-directory directory))
	  (while tail
	    (setq f (car tail)
		  tail (cdr tail))
	    (if (or (not match) (string-match-p match f))
		(setq files
		      (cons (if full (concat directory f) f) files))))
	  (nreverse files)))
    (apply 'ange-ftp-real-directory-files directory full match nosort
                                           id-format count v19-args))) 

(defun ange-ftp-directory-files-and-attributes
  (directory &optional full match nosort id-format count)
  (setq directory (expand-file-name directory))
  (if (ange-ftp-ftp-name directory)
      (mapcar
       (lambda (file)
	 (cons file (file-attributes (expand-file-name file directory))))
       (ange-ftp-directory-files directory full match nosort))
    (ange-ftp-real-directory-files-and-attributes
     directory full match nosort id-format count)))

Can I remove either &rest v19-version, or nosort through count?



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-15 14:01                                 ` Arthur Miller
@ 2020-10-15 14:41                                   ` Michael Albinus
  2020-10-15 15:22                                     ` Arthur Miller
  0 siblings, 1 reply; 71+ messages in thread
From: Michael Albinus @ 2020-10-15 14:41 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Eli Zaretskii, emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi Arthur,

> Sorry to bother, just one question: I am looking at ange-ftp, and see no
> 'nosort' and 'id-format' arguments passed in ange-ftp-directory-files:
>
> (defun ange-ftp-directory-files (directory &optional full match &rest v19-args)
>
> Are those (and count) taken care of as "rest" together with &rest
> v19-args or should I specify them as it is done in ange-ftp-directory-and-attributes:
>
> (defun ange-ftp-directory-files-and-attributes
>   (directory &optional full match nosort id-format)

ange-ftp.el hasn't been touched for years, so it would be great if we
could synchronize the signatures. v19-args aren't needed any longer.

> Can I remove either &rest v19-version, or nosort through count?

The former. And yes, nosort, id-format and count shall be implemented.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-15 14:41                                   ` Michael Albinus
@ 2020-10-15 15:22                                     ` Arthur Miller
  0 siblings, 0 replies; 71+ messages in thread
From: Arthur Miller @ 2020-10-15 15:22 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Eli Zaretskii, emacs-devel

Michael Albinus <michael.albinus@gmx.de> writes:

> Arthur Miller <arthur.miller@live.com> writes:
>
> Hi Arthur,
>
>> Sorry to bother, just one question: I am looking at ange-ftp, and see no
>> 'nosort' and 'id-format' arguments passed in ange-ftp-directory-files:
>>
>> (defun ange-ftp-directory-files (directory &optional full match &rest v19-args)
>>
>> Are those (and count) taken care of as "rest" together with &rest
>> v19-args or should I specify them as it is done in ange-ftp-directory-and-attributes:
>>
>> (defun ange-ftp-directory-files-and-attributes
>>   (directory &optional full match nosort id-format)
>
> ange-ftp.el hasn't been touched for years, so it would be great if we
> could synchronize the signatures. v19-args aren't needed any longer.
>
>> Can I remove either &rest v19-version, or nosort through count?
>
> The former. And yes, nosort, id-format and count shall be implemented.
>
> Best regards, Michael.
Yes;

Thanks for the help! 



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-15 12:21                               ` Michael Albinus
  2020-10-15 13:29                                 ` Arthur Miller
  2020-10-15 14:01                                 ` Arthur Miller
@ 2020-10-16 23:31                                 ` Arthur Miller
  2020-10-17  8:13                                   ` Michael Albinus
  2 siblings, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-16 23:31 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Eli Zaretskii, emacs-devel

Michael Albinus <michael.albinus@gmx.de> writes:

> Arthur Miller <arthur.miller@live.com> writes:
>
> Hi Arthur,
>
>>> Thanks for this. I haven't seen your name on the FSF file; I guess your
>>> legal papers are on the way?
>> They are not, but they can be if someone send me link. I've been looking
>> at this page:
>>
>> https://www.gnu.org/prep/maintain/html_node/Copyright-Papers.html#Copyright-Papers
>>
>> but I am not really sure where do I send request.
>
> Sorry, I should have asked. I'll send you the template off-list.
>
>>> - Adapt the file name handlers. These are ange-ftp-directory-files,
>>>   ange-ftp-directory-files-and-attributes, tramp-handle-directory-files,
>>>   tramp-handle-directory-files-and-attributes,
>>>   tramp-adb-handle-directory-files-and-attributes,
>>>   tramp-crypt-handle-directory-files,
>>>   tramp-rclone-handle-directory-files,
>>>   tramp-sh-handle-directory-files-and-attributes,
>>>   tramp-smb-handle-directory-files.
>>
>> Aha, so it is how it works; didn't have time to look into tramp yet.
>> Ok, I'll do; I'll sent in patch(es) when I am done. Probably not today
>> though but during the weekend of beginning of the next week.
>
> There's no rush. Doing the legal work will take a week or so.
>
>> So many changes just for one signature :-).
>
> In order to enjoy you: Tramp is backward compatible back to Emacs
> 25. This must also be taken into account :-)
>
> But don't worry, I'll make the needed changes after your commit.
>
>>> - Adapt resp extend ERT tests. These are tramp-test16-directory-files,
>>>   tramp-test19-directory-files-and-attributes,
>>>   tramp-archive-test16-directory-files and
>>>   tramp-archive-test19-directory-files-and-attributes.
>>>
>>> - Optionally (but much appreciated), write new ERT tests for
>>>   directory-files and directory-files-and-attributes.
>>
>> Will have to look at ERT, I suppose it is not too complicated,
>> opportunity to learn it.
>
> A look at the ert manual might help. (info "(ert)")
>
>> I mainly try to be clear "what I intent" for some future reader; since
>> previous code uses lisp.h macros, I used same. I thought that one extra
>> 'if' is not that much of a penalty, I'll gladly shortcircut with !last.
>
> In case you feel the need, you could also provide a comment.
>
> Best regards, Michael.
I have patched handlers; which version should I make patches against:
current master or latest stable? How would you like patches; each in own
file?

I will look at ert tests too.




^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-15 13:38                               ` Stefan Monnier
@ 2020-10-16 23:33                                 ` Arthur Miller
  0 siblings, 0 replies; 71+ messages in thread
From: Arthur Miller @ 2020-10-16 23:33 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Eli Zaretskii, Michael Albinus, emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> They are not, but they can be if someone send me link. I've been looking
>> at this page:
>
> Here it is.  Please fill the form below and then send it as instructed
> to the FSF so they can send you the relevant paperwork to sign.
> Thank you for your contribution,
>
>
>         Stefan
>
>
> Please email the following information to assign@gnu.org, and we
> will send you the assignment form for your past and future changes.
>
> Please use your full legal name (in ASCII characters) as the subject
> line of the message.
> ----------------------------------------------------------------------
> REQUEST: SEND FORM FOR PAST AND FUTURE CHANGES
>
> [What is the name of the program or package you're contributing to?]
> Emacs
>
> [Did you copy any files or text written by someone else in these changes?
> Even if that material is free software, we need to know about it.]
>
>
> [Do you have an employer who might have a basis to claim to own
> your changes?  Do you attend a school which might make such a claim?]
>
>
> [For the copyright registration, what country are you a citizen of?]
>
>
> [What year were you born?]
>
>
> [Please write your email address here.]
>
>
> [Please write your postal address here.]
>
>
>
>
>
> [Which files have you changed so far, and which new files have you written
> so far?]
Michael sent me one, so I already sent it; thx anyway.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-16 23:31                                 ` Arthur Miller
@ 2020-10-17  8:13                                   ` Michael Albinus
  2020-10-17 19:03                                     ` Arthur Miller
  0 siblings, 1 reply; 71+ messages in thread
From: Michael Albinus @ 2020-10-17  8:13 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Eli Zaretskii, emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi Arthur,

> I have patched handlers; which version should I make patches against:
> current master or latest stable? How would you like patches; each in own
> file?

The patches shall be towards master. And I don't care, whether they are
just one file, or several ones :-)

> I will look at ert tests too.

Thanks. Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-17  8:13                                   ` Michael Albinus
@ 2020-10-17 19:03                                     ` Arthur Miller
  2020-10-17 20:03                                       ` Drew Adams
  2020-10-18 11:52                                       ` Michael Albinus
  0 siblings, 2 replies; 71+ messages in thread
From: Arthur Miller @ 2020-10-17 19:03 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Eli Zaretskii, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 458 bytes --]

Michael Albinus <michael.albinus@gmx.de> writes:

> Arthur Miller <arthur.miller@live.com> writes:
>
> Hi Arthur,
>
>> I have patched handlers; which version should I make patches against:
>> current master or latest stable? How would you like patches; each in own
>> file?
>
> The patches shall be towards master. And I don't care, whether they are
> just one file, or several ones :-)
>
>> I will look at ert tests too.
>
> Thanks. Best regards, Michael.


[-- Attachment #2: directory-files.patch --]
[-- Type: text/x-patch, Size: 22847 bytes --]

diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 3b8b4fb3a9..2f15176e79 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -2917,7 +2917,7 @@ Contents of Directories
 the latter case, it can optionally display information about each file,
 depending on the options passed to the @code{ls} command.
 
-@defun directory-files directory &optional full-name match-regexp nosort
+@defun directory-files directory &optional full-name match-regexp nosort count
 This function returns a list of the names of the files in the directory
 @var{directory}.  By default, the list is in alphabetical order.
 
@@ -2937,6 +2937,13 @@ Contents of Directories
 are processed in.  If the order of processing is visible to the user,
 then the user will probably be happier if you do sort the names.
 
+If @var{count} is non-@code{nil}, the function will return first
+@var{count} number of files, or all files, whichever occurs
+first. @var{count} has to be a natural number (> 0). You can use this
+function to short circuit evaluation in case you are just interested to
+find if a directory is empty or not (request one file and tell it to
+ignore dot-files).
+
 @example
 @group
 (directory-files "~lewis")
@@ -2946,6 +2953,14 @@ Contents of Directories
 @end group
 @end example
 
+@example
+@group
+  (null (directory-files directory-name nil
+  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*" t 1))
+     @result{} nil
+@end group
+@end example
+
 An error is signaled if @var{directory} is not the name of a directory
 that can be read.
 @end defun
@@ -2996,7 +3011,7 @@ Contents of Directories
 non-@code{nil} if that directory is the one it is looking for.
 @end defun
 
-@defun directory-files-and-attributes directory &optional full-name match-regexp nosort id-format
+@defun directory-files-and-attributes directory &optional full-name match-regexp nosort id-format count
 This is similar to @code{directory-files} in deciding which files
 to report on and how to report their names.  However, instead
 of returning a list of file names, it returns for each file a
diff --git a/etc/NEWS b/etc/NEWS
index 1838b6b38a..25c54d3dfe 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1550,6 +1550,13 @@ ledit.el, lmenu.el, lucid.el and old-whitespace.el.
 \f
 * Lisp Changes in Emacs 28.1
 
++++
+** 'diirectory-files' function can now take an additional count parameter
+This option makes directory-files return COUNT first files in
+directory. If match is given, the function vill return first COUNT files
+that match the expression. The option is useful for checking if
+directory is empty since it will check at most 3 files when COUNT = 1.
+
 +++
 ** 'truncate-string-ellipsis' now uses '…' by default.
 Modes that use 'truncate-string-to-width' with non-nil, non-string
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
index 0cb8d7cb83..335a07914c 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -3427,8 +3427,8 @@ ange-ftp-file-accessible-directory-p
   (and (file-directory-p name)
        (file-readable-p name)))
 
-(defun ange-ftp-directory-files (directory &optional full match
-					   &rest v19-args)
+(defun ange-ftp-directory-files (directory &optional full match nosort
+					   count)
   (setq directory (expand-file-name directory))
   (if (ange-ftp-ftp-name directory)
       (progn
@@ -3444,18 +3444,19 @@ ange-ftp-directory-files
 		(setq files
 		      (cons (if full (concat directory f) f) files))))
 	  (nreverse files)))
-    (apply 'ange-ftp-real-directory-files directory full match v19-args)))
+    (apply 'ange-ftp-real-directory-files directory full match nosort count)))
 
 (defun ange-ftp-directory-files-and-attributes
-  (directory &optional full match nosort id-format)
+  (directory &optional full match nosort attrs id-format count)
   (setq directory (expand-file-name directory))
   (if (ange-ftp-ftp-name directory)
       (mapcar
        (lambda (file)
 	 (cons file (file-attributes (expand-file-name file directory))))
-       (ange-ftp-directory-files directory full match nosort))
+       (ange-ftp-directory-files directory full match nosort attrs
+                                 id_format count))
     (ange-ftp-real-directory-files-and-attributes
-     directory full match nosort id-format)))
+     directory full match nosort attrs id-format count)))
 
 (defun ange-ftp-file-attributes (file &optional id-format)
   (setq file (expand-file-name file))
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 49ecaa58ee..26ec24a075 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -301,7 +301,7 @@ tramp-do-parse-file-attributes-with-ls
       file-properties)))
 
 (defun tramp-adb-handle-directory-files-and-attributes
-  (directory &optional full match nosort id-format)
+  (directory &optional full match nosort id-format count)
   "Like `directory-files-and-attributes' for Tramp files."
   (unless (file-exists-p directory)
     (tramp-error
@@ -312,7 +312,7 @@ tramp-adb-handle-directory-files-and-attributes
       (copy-tree
        (with-tramp-file-property
 	   v localname (format "directory-files-and-attributes-%s-%s-%s-%s"
-			       full match id-format nosort)
+			       full match id-format nosort count)
 	 (with-current-buffer (tramp-get-buffer v)
 	   (when (tramp-adb-send-command-and-check
 		  v (format "%s -a -l %s"
diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el
index 3e96daa7b1..bda3735db4 100644
--- a/lisp/net/tramp-crypt.el
+++ b/lisp/net/tramp-crypt.el
@@ -667,7 +667,10 @@ tramp-crypt-handle-delete-file
     (let (tramp-crypt-enabled)
       (delete-file (tramp-crypt-encrypt-file-name filename) trash))))
 
-(defun tramp-crypt-handle-directory-files (directory &optional full match nosort)
+;; This function does not seem to pass match and nosort into
+;; directory-files at all; is that intentional or bug?
+(defun tramp-crypt-handle-directory-files (directory &optional full
+                                                     match nosort count)
   "Like `directory-files' for Tramp files."
   (unless (file-exists-p directory)
     (tramp-error
diff --git a/lisp/net/tramp-rclone.el b/lisp/net/tramp-rclone.el
index 3701bfc22c..787eead807 100644
--- a/lisp/net/tramp-rclone.el
+++ b/lisp/net/tramp-rclone.el
@@ -300,8 +300,10 @@ tramp-rclone-handle-delete-file
     (tramp-flush-file-properties v localname)
     (tramp-rclone-flush-directory-cache v)))
 
+;; This function did not pass nosort arguemnt into directory-files
+;; not sure if intentional or bug
 (defun tramp-rclone-handle-directory-files
-    (directory &optional full match nosort)
+    (directory &optional full match nosort count)
   "Like `directory-files' for Tramp files."
   (unless (file-exists-p directory)
     (tramp-error
@@ -312,7 +314,8 @@ tramp-rclone-handle-directory-files
     (with-parsed-tramp-file-name directory nil
       (let ((result
 	     (directory-files
-	      (tramp-rclone-local-file-name directory) full match)))
+	      (tramp-rclone-local-file-name directory) full match
+              nosort count)))
 	;; Massage the result.
 	(when full
 	  (let ((local (concat "^" (regexp-quote (tramp-rclone-mount-point v))))
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 15eab0a4de..7a969979ac 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -1701,9 +1701,9 @@ tramp-sh-handle-file-ownership-preserved-p
 		    (tramp-get-remote-gid v 'integer)))))))))
 
 ;; Directory listings.
-
+;; what about perl & sta -> need to fix list to count?
 (defun tramp-sh-handle-directory-files-and-attributes
-  (directory &optional full match nosort id-format)
+  (directory &optional full match nosort id-format count)
   "Like `directory-files-and-attributes' for Tramp files."
   (unless id-format (setq id-format 'integer))
   (unless (file-exists-p directory)
@@ -1743,7 +1743,7 @@ tramp-sh-handle-directory-files-and-attributes
 	    (sort result (lambda (x y) (string< (car x) (car y)))))
 	  ;; The scripts could fail, for example with huge file size.
 	  (tramp-handle-directory-files-and-attributes
-	   directory full match nosort id-format)))))
+	   directory full match nosort id-format count)))))
 
 (defun tramp-do-directory-files-and-attributes-with-perl
   (vec localname &optional id-format)
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index 1b6af2a2e3..62135f514d 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -690,29 +690,36 @@ tramp-smb-handle-delete-file
 	   v 'file-error "%s `%s'" (match-string 0) filename))))))
 
 (defun tramp-smb-handle-directory-files
-  (directory &optional full match nosort)
+  (directory &optional full match nosort count)
   "Like `directory-files' for Tramp files."
   (unless (file-exists-p directory)
     (tramp-error
      (tramp-dissect-file-name directory) tramp-file-missing
      "No such file or directory" directory))
-  (let ((result (mapcar #'directory-file-name
-			(file-name-all-completions "" directory))))
-    ;; Discriminate with regexp.
-    (when match
-      (setq result
-	    (delete nil
-		    (mapcar (lambda (x) (when (string-match-p match x) x))
-			    result))))
-    ;; Prepend directory.
-    (when full
-      (setq result
-	    (mapcar
-	     (lambda (x) (format "%s/%s" (directory-file-name directory) x))
-	     result)))
-    ;; Sort them if necessary.
-    (unless nosort (setq result (sort result #'string-lessp)))
-    result))
+  (let ((result nil)
+        (numres 0))
+    (when (or (not count) (> count 0))
+        (setq result (mapcar #'directory-file-name
+			     (file-name-all-completions "" directory)))
+      ;; Discriminate with regexp.
+      (when match
+        (setq result
+	      (delete nil
+		      (mapcar (lambda (x) (when (string-match-p match x) x))
+			      result))))
+
+      ;; return [0,count) number of results
+      (setq result (cl-subseq result 0 count))
+
+      ;; Prepend directory.
+      (when full
+        (setq result
+	      (mapcar
+	       (lambda (x) (format "%s/%s" (directory-file-name directory) x))
+	       result)))
+      ;; Sort them if necessary.
+      (unless nosort (setq result (sort result #'string-lessp)))
+      result)))
 
 (defun tramp-smb-handle-expand-file-name (name &optional dir)
   "Like `expand-file-name' for Tramp files."
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 6d44ad23ad..a99af70196 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -3114,7 +3114,8 @@ tramp-handle-directory-file-name
     (setq directory (substring directory 0 -1)))
   directory)
 
-(defun tramp-handle-directory-files (directory &optional full match nosort)
+(defun tramp-handle-directory-files (directory &optional full match
+                                               nosort count)
   "Like `directory-files' for Tramp files."
   (unless (file-exists-p directory)
     (tramp-error
@@ -3133,13 +3134,13 @@ tramp-handle-directory-files
       (if nosort result (sort result #'string<)))))
 
 (defun tramp-handle-directory-files-and-attributes
-  (directory &optional full match nosort id-format)
+  (directory &optional full match nosort id-format count)
   "Like `directory-files-and-attributes' for Tramp files."
   (mapcar
    (lambda (x)
      (cons x (file-attributes
 	      (if full x (expand-file-name x directory)) id-format)))
-   (directory-files directory full match nosort)))
+   (directory-files directory full match nosort count)))
 
 (defun tramp-handle-dired-uncache (dir)
   "Like `dired-uncache' for Tramp files."
diff --git a/src/dired.c b/src/dired.c
index 1584b6acf0..1fc8dd27fa 100644
--- a/src/dired.c
+++ b/src/dired.c
@@ -17,7 +17,6 @@
 You should have received a copy of the GNU General Public License
 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 
-
 #include <config.h>
 
 #include <sys/stat.h>
@@ -165,8 +164,26 @@ read_dirent (DIR *dir, Lisp_Object dirname)
 Lisp_Object
 directory_files_internal (Lisp_Object directory, Lisp_Object full,
 			  Lisp_Object match, Lisp_Object nosort, bool attrs,
-			  Lisp_Object id_format)
+			  Lisp_Object id_format, Lisp_Object return_count)
 {
+  ptrdiff_t ind = 0, last = 0;
+
+  /* check count first for early exit */
+  if (FIXNUMP(return_count))
+    {
+      last = XFIXNUM (return_count);
+      if (last <= 0)
+        return Qnil;
+    }
+
+  if (FIXNATP(return_count))
+    {
+      last = XFIXNAT(return_count);
+
+      if (!last)
+        return Qnil;
+    }
+
   if (!NILP (match))
     CHECK_STRING (match);
 
@@ -267,6 +284,10 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
       else
 	finalname = name;
 
+      if (last && ind == last)
+          break;
+      ind ++;
+
       list = Fcons (attrs ? Fcons (finalname, fileattrs) : finalname, list);
     }
 
@@ -287,8 +308,7 @@ directory_files_internal (Lisp_Object directory, Lisp_Object full,
   return list;
 }
 
-
-DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
+DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 5, 0,
        doc: /* Return a list of names of files in DIRECTORY.
 There are three optional arguments:
 If FULL is non-nil, return absolute file names.  Otherwise return names
@@ -296,9 +316,12 @@ DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
 If MATCH is non-nil, mention only file names that match the regexp MATCH.
 If NOSORT is non-nil, the list is not sorted--its order is unpredictable.
  Otherwise, the list returned is sorted with `string-lessp'.
- NOSORT is useful if you plan to sort the result yourself.  */)
+ NOSORT is useful if you plan to sort the result yourself.
+If COUNT is  non-nil, the function will return max of COUNT and length
+ files, where length is number of files in the directory. COUNT has to
+ be a natural number > 0. */)
   (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
-   Lisp_Object nosort)
+   Lisp_Object nosort, Lisp_Object count)
 {
   directory = Fexpand_file_name (directory, Qnil);
 
@@ -306,34 +329,38 @@ DEFUN ("directory-files", Fdirectory_files, Sdirectory_files, 1, 4, 0,
      call the corresponding file name handler.  */
   Lisp_Object handler = Ffind_file_name_handler (directory, Qdirectory_files);
   if (!NILP (handler))
-    return call5 (handler, Qdirectory_files, directory,
-                  full, match, nosort);
+    return call6 (handler, Qdirectory_files, directory,
+                  full, match, nosort, count);
 
-  return directory_files_internal (directory, full, match, nosort, false, Qnil);
+  return directory_files_internal (directory, full, match, nosort,
+                                   false, Qnil, count);
 }
 
 DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes,
-       Sdirectory_files_and_attributes, 1, 5, 0,
-       doc: /* Return a list of names of files and their attributes in DIRECTORY.
+       Sdirectory_files_and_attributes, 1, 6, 0, doc
+       : /* Return a list of names of files and their attributes in DIRECTORY.
 Value is a list of the form:
 
-  ((FILE1 . FILE1-ATTRS) (FILE2 . FILE2-ATTRS) ...)
+((FILE1 . FILE1-ATTRS) (FILE2 . FILE2-ATTRS) ...)
 
 where each FILEn-ATTRS is the attributes of FILEn as returned
 by `file-attributes'.
 
 This function accepts four optional arguments:
 If FULL is non-nil, return absolute file names.  Otherwise return names
- that are relative to the specified directory.
+that are relative to the specified directory.
 If MATCH is non-nil, mention only file names that match the regexp MATCH.
 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.
+NOSORT is useful if you plan to sort the result yourself.
 ID-FORMAT specifies the preferred format of attributes uid and gid, see
 `file-attributes' for further documentation.
 On MS-Windows, performance depends on `w32-get-true-file-attributes',
-which see.  */)
-  (Lisp_Object directory, Lisp_Object full, Lisp_Object match,
-   Lisp_Object nosort, Lisp_Object id_format)
+which see.
+If COUNT is  non-nil, the function will return max of COUNT and length
+ files, where length is number of files in the directory. COUNT has to
+ be a natural number > 0. */)
+(Lisp_Object directory, Lisp_Object full, Lisp_Object match,
+ Lisp_Object nosort, Lisp_Object id_format, Lisp_Object count)
 {
   directory = Fexpand_file_name (directory, Qnil);
 
@@ -342,11 +369,11 @@ DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes,
   Lisp_Object handler
     = Ffind_file_name_handler (directory, Qdirectory_files_and_attributes);
   if (!NILP (handler))
-    return call6 (handler, Qdirectory_files_and_attributes,
-                  directory, full, match, nosort, id_format);
+    return call7 (handler, Qdirectory_files_and_attributes,
+                  directory, full, match, nosort, id_format, count);
 
   return directory_files_internal (directory, full, match, nosort,
-				   true, id_format);
+				   true, id_format, count);
 }
 
 \f
diff --git a/src/lisp.h b/src/lisp.h
index 45353fbef3..a3cfb5044d 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4612,7 +4612,7 @@ maybe_disable_address_randomization (int argc, char **argv)
 extern void syms_of_dired (void);
 extern Lisp_Object directory_files_internal (Lisp_Object, Lisp_Object,
                                              Lisp_Object, Lisp_Object,
-                                             bool, Lisp_Object);
+                                             bool, Lisp_Object, Lisp_Object);
 
 /* Defined in term.c.  */
 extern int *char_ins_del_vector;
diff --git a/src/sysdep.c b/src/sysdep.c
index f6c0ddee01..9111f1863e 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -2892,7 +2892,7 @@ list_system_processes (void)
      process.  */
   procdir = build_string ("/proc");
   match = build_string ("[0-9]+");
-  proclist = directory_files_internal (procdir, Qnil, match, Qt, false, Qnil);
+  proclist = directory_files_internal (procdir, Qnil, match, Qt, false, Qnil, Qnil);
 
   /* `proclist' gives process IDs as strings.  Destructively convert
      each string into a number.  */
diff --git a/test/src/dired-tests.el b/test/src/dired-tests.el
new file mode 100644
index 0000000000..3b739e59cc
--- /dev/null
+++ b/test/src/dired-tests.el
@@ -0,0 +1,92 @@
+;;; dired-tests.el --- Tests for directory-files in dired.c  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2015-2020 Free Software Foundation, Inc.
+
+;; Author: Arthur Miller <arthur.miller@live.com>
+;; Keywords:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+(require 'ert)
+
+(ert-deftest directory-files-tests ()
+  (let ((name (expand-file-name "directory-files-test"
+                                (temporary-file-directory)))
+        ;; nodots expression from dired+ by Drew A.
+        (nodots "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"))
+
+    (message name)
+    (when (file-directory-p name)
+      (delete-directory name t))
+    (make-directory name)
+    (when (file-directory-p name)
+      (should (= 2 (length (directory-files name))))
+      (should-not (directory-files name nil nodots t 1))
+      (dolist (file '(a b c d))
+        (make-empty-file (expand-file-name (symbol-name file) name)))
+      (should (= 6 (length (directory-files name))))
+      (should (equal "abcd" (string-join (directory-files name nil
+                                                          nodots) "")))
+      (should (= 2 (length (directory-files name nil "[bc]"))))
+      (should (= 3 (length (directory-files name nil nodots nil 3))))
+      (dolist (file '(5 4 3 2 1))
+        (make-empty-file (expand-file-name (number-to-string file) name)))
+      (should (= 0 (length (directory-files name nil "[0-9]" t -1))))
+      (should (= 5 (length (directory-files name nil "[0-9]" t))))
+      (should (= 5 (length (directory-files name nil "[0-9]" t 50))))
+  )))
+
+(ert-deftest directory-files-and-attributes-tests ()
+  (let ((name (expand-file-name "directory-files-test"
+                                (temporary-file-directory)))
+        ;; nodots expression from dired+ by Drew A.
+        (nodots "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"))
+
+    (message name)
+    (when (file-directory-p name)
+      (delete-directory name t))
+    (make-directory name)
+    (when (file-directory-p name)
+      (should (= 2 (length (directory-files name))))
+      (should-not (directory-files-and-attributes name t nodots t 1))
+      (dolist (file '(a b c d))
+        (make-directory (expand-file-name (symbol-name file) name)))
+      (should (= 6 (length (directory-files-and-attributes name))))
+      (dolist (dir (directory-files-and-attributes name t nodots))
+        (should (file-directory-p (car dir)))
+        (should-not (file-regular-p (car dir))))
+      (should (= 2 (length
+                    (directory-files-and-attributes name nil "[bc]"))))
+      (should (= 3 (length
+                    (directory-files-and-attributes name nil nodots
+                                                    nil nil 3))))
+      (dolist (file '(5 4 3 2 1))
+        (make-empty-file (expand-file-name (number-to-string file) name)))
+      (should (= 0 (length
+                    (directory-files-and-attributes name nil
+                                                    "[0-9]" t 1 -1))))
+      (should (= 5 (length
+                    (directory-files-and-attributes name nil "[0-9]" t))))
+      (should (= 5 (length
+                    (directory-files-and-attributes name nil
+                                                    "[0-9]" t nil 50))))
+      )))
+
+(provide 'dired-tests)
+;;; dired-tests.el ends here

[-- Attachment #3: Type: text/plain, Size: 877 bytes --]


See how this works.I have done patch between two branches.

Please check that handlers stuff. I am not sure how to test it, and am
not sure I get those correct; especially tramp-crypt.

I am using a regular expression from Dired+ by Drew in two places. I
have mention it the comment in ert tests, but don't know how to mention
it in the example in manual. Maybe remove example, or maybe it can stay
without creds?

I also discovered that I wasn't covered with FIXNUM all the way; thought
it was unsigned int so -1 would be converted into ffffffff, which
would just yeild all results. Seems like fixnum is not what I thought so I
have added test for <=0 which return nil.

Ert test are mostly foxused on new argument. I haven't found something
related to dired in test/src so I have created dired-tests.el. If it
shoudl be in some other place I can rename it.

Best regards
/a

^ permalink raw reply related	[flat|nested] 71+ messages in thread

* RE: empty-directory predicate, native implementation
  2020-10-17 19:03                                     ` Arthur Miller
@ 2020-10-17 20:03                                       ` Drew Adams
  2020-10-17 20:27                                         ` Arthur Miller
                                                           ` (2 more replies)
  2020-10-18 11:52                                       ` Michael Albinus
  1 sibling, 3 replies; 71+ messages in thread
From: Drew Adams @ 2020-10-17 20:03 UTC (permalink / raw)
  To: Arthur Miller, Michael Albinus; +Cc: Eli Zaretskii, emacs-devel

Sorry I'm coming to this late.  It's a long thread,
and I've only checked your patch, not the messages.

I don't understand why we would do this.  Is the
real aim to be able to have an empty-directory
predicate, i.e., to be able to see if there are
no files in a directory?

If so, then why not do just that, witout
bothering (changing the signature of)
`directory-files'?

Is there really some use case for getting only
the first N files in a directory?  I can
understand wanting to test whether a dir is
empty.  I can't see why someone would want the
first N files (however "first" might be defined).

The doc string itself seems to suggest that the
(only?) use case is to test for emptiness:

 You can use this function to short circuit evaluation
 in case you are just interested to find if a directory
 is empty or not (request one file and tell it to
 ignore dot-files).

That need is clear enough.  But what else is
COUNT useful for?  How about having the doc
string also tell us what we can use a COUNT
value > 1 for?  That's the case that really
needs pointing out, not the empty-dir-p case.

And what is the order that defines which file
is first, second, etc.?  Without knowing that,
what use is getting the "first" N?

If this has already been raised, discussed,
and dismissed, fine - apologies for the noise.
If not, what's the raison d'etre for adding
optional parameter COUNT?

Why not just add a predicate `directory-empty-p'?



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-17 20:03                                       ` Drew Adams
@ 2020-10-17 20:27                                         ` Arthur Miller
  2020-10-17 21:18                                           ` Drew Adams
  2020-10-17 21:02                                         ` Arthur Miller
  2020-10-18  2:47                                         ` Eli Zaretskii
  2 siblings, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-17 20:27 UTC (permalink / raw)
  To: Drew Adams; +Cc: Eli Zaretskii, Michael Albinus, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 3228 bytes --]

Drew Adams <drew.adams@oracle.com> writes:

> Sorry I'm coming to this late.  It's a long thread,
> and I've only checked your patch, not the messages.
>
> I don't understand why we would do this.  Is the
> real aim to be able to have an empty-directory
> predicate, i.e., to be able to see if there are
> no files in a directory?
Yes.
> If so, then why not do just that, witout
> bothering (changing the signature of)
> `directory-files'?
Because it is not possible to that efficiently with current elisp; how
would you do that directly? OS does not have such call, one have to
iterate through directories. At least I am not aware of such call. If
you know, please tell me, I would be happy to use it, at least for myself.

Fastest I am aware of is to get a buffered list with SYS_getdents and then
check for first non-dot file. That changes complexity from linear in
number of files in directory to constant (3 files at max). It works only
on Linux kernel, and I don't know if there is nt version of such call,
or what there is on macs.

I suggested such predicate, but to not re-iterate entire discussion, pls
check my first mail and followed 2 or 3 I think.

> Is there really some use case for getting only
> the first N files in a directory?  I can
> understand wanting to test whether a dir is
> empty.  I can't see why someone would want the
> first N files (however "first" might be defined).
Probably not; it is just a result of having count parameter. 

> The doc string itself seems to suggest that the
> (only?) use case is to test for emptiness:
>
>  You can use this function to short circuit evaluation
>  in case you are just interested to find if a directory
>  is empty or not (request one file and tell it to
>  ignore dot-files).
It does not say only, but it suggests it can be usd in that way. But
yes, that was the driver behind.

Check the attachment; maybe something you would like to have in Dired+?

I don't know if it could become a part of Dired itself, I believe it is
probably too niche and subjective.

> That need is clear enough.  But what else is
> COUNT useful for?  How about having the doc
> string also tell us what we can use a COUNT
> value > 1 for?  That's the case that really
> needs pointing out, not the empty-dir-p case.
>
> And what is the order that defines which file
> is first, second, etc.?  Without knowing that,
> what use is getting the "first" N?
OS.

There is no hard guarantee by OS:s that you will get files in
particular order. I had that sentence in docs, but it was a bit too
verse. I am not very literal of me, if you can phrase it better and more
concise, please go ahead, I would appreciate. Check all docs if you have
time and feel for it, I always need help with the language.

> If this has already been raised, discussed,
> and dismissed, fine - apologies for the noise.
> If not, what's the raison d'etre for adding
> optional parameter COUNT?
I hope you don't mind me snitching your regex for nodots. I was trying
to get one fast myself, and gave up after half hour, would never thought
it was so picky to get that one right.

> Why not just add a predicate `directory-empty-p'?
:-) Check my first mail. I implemented one with that name.

Best regards
/a


[-- Attachment #2: dired-mark-empty-dirs.el --]
[-- Type: text/plain, Size: 961 bytes --]

(require 'dired)

(defvar nodots "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*")

(defun dired-go-to-first ()
    (interactive)
    (goto-char (point-min))
    (dired-next-line 1)
    (skip-chars-forward " \n\t"))

(defun directory-is-empty-p (directory-name)
  (null (directory-files directory-name nil nodots t 1)))

(defun dired-mark-empty-dirs ()
  (interactive)
  (when (equal major-mode 'dired-mode)
    (let ((curr-dir))
      (save-excursion
        (dired-go-to-first)
        
        (while (not (eobp))
          (setq curr-dir (dired-file-name-at-point))
          (cond ((or (null curr-dir)
                     (string= curr-dir ".")
                     (string= curr-dir ".."))
                     ;; do nothing here
                 )
                ((file-directory-p curr-dir)
                 (when (directory-is-empty-p curr-dir)
                   (dired-mark 1)
                   (dired-previous-line 1))))
          (dired-next-line 1))))))

^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-17 20:03                                       ` Drew Adams
  2020-10-17 20:27                                         ` Arthur Miller
@ 2020-10-17 21:02                                         ` Arthur Miller
  2020-10-17 21:27                                           ` Drew Adams
  2020-10-18  2:47                                         ` Eli Zaretskii
  2 siblings, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-17 21:02 UTC (permalink / raw)
  To: Drew Adams; +Cc: Eli Zaretskii, Michael Albinus, emacs-devel

Drew Adams <drew.adams@oracle.com> writes:

> Sorry I'm coming to this late.  It's a long thread,
> and I've only checked your patch, not the messages.
>
> I don't understand why we would do this.  Is the
> real aim to be able to have an empty-directory
> predicate, i.e., to be able to see if there are
> no files in a directory?
I would just like to add to the previous mail; that this optimisation
really does not matter on very first call.

Since read_files calls readdir, which reads in 32k batch (I think),
system will still fetch quite many inodes. The first call is probably
one that matters most for most application, or in most cases, in Emacs
for Dired's purposes, so there is not much savings to directly to SYS_getdents
directly so I agree with Eli that we don't need to go to Linux specific calls.

The most effect we get on subsequent calls comes probably from
Lisp itsel, by cutting of unnecessary lists traversals and list elements
creation as well as comparing entire directory contents with regex to
eliminate dots with such text. At least what I think currently, maybe I
am wrong about, I am not really expert in systems programming, so I am
not super on all the details.




^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: empty-directory predicate, native implementation
  2020-10-17 20:27                                         ` Arthur Miller
@ 2020-10-17 21:18                                           ` Drew Adams
  2020-10-17 22:06                                             ` Arthur Miller
  0 siblings, 1 reply; 71+ messages in thread
From: Drew Adams @ 2020-10-17 21:18 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Eli Zaretskii, Michael Albinus, emacs-devel

> > Sorry I'm coming to this late.  It's a long thread,
> > and I've only checked your patch, not the messages.
> >
> > I don't understand why we would do this.  Is the
> > real aim to be able to have an empty-directory
> > predicate, i.e., to be able to see if there are
> > no files in a directory?
>
> Yes.
>
> > If so, then why not do just that, without
> > bothering (changing the signature of)
> > `directory-files'?
>
> Because it is not possible to that efficiently with current elisp; how
> would you do that directly? OS does not have such call, one have to
> iterate through directories. At least I am not aware of such call. If
> you know, please tell me, I would be happy to use it, at least for myself.
> 
> Fastest I am aware of is to get a buffered list with SYS_getdents and then
> check for first non-dot file. That changes complexity from linear in
> number of files in directory to constant (3 files at max). It works only
> on Linux kernel, and I don't know if there is nt version of such call,
> or what there is on macs.
> 
> I suggested such predicate, but to not re-iterate entire discussion, pls
> check my first mail and followed 2 or 3 I think.

I took a quick look at the first few messages etc.

I see that Eli suggested not implementing an
empty-directory predicate directly but instead
adding a COUNT parameter to `directory-files' (Lisp).

That's just what I questioned.  If the aim is an
empty-directory pred then why not code it in C, like
we do `directory-files'?  And instead of duplicating
code, if that would be the case, extend the C code
underlying `directory-files' to be usable also for
such a predicate, stopping as soon as it finds one
file.

IOW, what you've done, but not expose the COUNT
parameter to Lisp.  If its real purpose is just to
check for emptiness, then from Lisp I'd think we'd
have a separate predicate for that, and we wouldn't
change the signature of `directory-files'.

UNLESS there really IS some use for a COUNT value > 1.

That was my question.  If there's some use case, in
Lisp, for COUNT, i.e., for returning the "first" N
files, then fine.  But if not, I don't see why we
would add COUNT to `directory-files' (Lisp), as
opposed to just getting the emptiness check from C
(perhaps by adding a COUNT there, but not changing
the Lisp interface for `directory-files').

Not a big deal.  Just a question; just something
that occurred to me when I saw this.  I think a
Lisp user is likely to ask herself the same thing:
apart from passing 1 for COUNT, why would I ever
use COUNT?

And if it were agreed that there's no use case for
COUNT > 1, but for some reason a separate predicate,
`directory-empty-p' isn't wanted, then change COUNT
to a Boolean parameter that just says you want an
emptiness check.

If COUNT > 1 has no utility then, if you have to add
a parameter for Lisp, its name, doc, and behavior
should at least be more indicative of its purpose, no?

Don't get me wrong.  I'm generally in favor of Lisp
Boolean functions and such that return useful non-nil
truth values.  I _really_ like that.  But here I don't
see the usefulness of the non-nil return value, which
means the thing will confuse and mislead sometimes.

> > Is there really some use case for getting only
> > the first N files in a directory?  I can
> > understand wanting to test whether a dir is
> > empty.  I can't see why someone would want the
> > first N files (however "first" might be defined).
>
> Probably not; it is just a result of having count parameter.

Should be the other way round, no?  We should have
a COUNT parameter only if it's useful.  If we're
adding it just for implementation purposes, then why
not just do that under the covers in the C code?

Anyway, I don't mean to belabor this.  I've asked
my question and clarified why I asked.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: empty-directory predicate, native implementation
  2020-10-17 21:02                                         ` Arthur Miller
@ 2020-10-17 21:27                                           ` Drew Adams
  2020-10-17 21:58                                             ` Arthur Miller
  0 siblings, 1 reply; 71+ messages in thread
From: Drew Adams @ 2020-10-17 21:27 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Eli Zaretskii, Michael Albinus, emacs-devel

> > Sorry I'm coming to this late.  It's a long thread,
> > and I've only checked your patch, not the messages.
> >
> > I don't understand why we would do this.  Is the
> > real aim to be able to have an empty-directory
> > predicate, i.e., to be able to see if there are
> > no files in a directory?
>
> I would just like to add to the previous mail; that this optimisation
> really does not matter on very first call...

Believe me, I'm not trying to second-guess any
implementation.  I haven't (and won't) look at the
C code, and I'm not very qualified to do so anyway.

I was guessing that COUNT = 1 would be quicker for an
emptiness check than COUNT > 1 (e.g. COUNT = 80000).

But my argument wasn't about implementation or
efficiency.  Even if, for some reason, C had to "get"
(info about) all of the files in the directory, just
to determine whether the dir is empty, my argument
would be the same wrt Lisp: have a separate predicate,
or have a Boolean new parameter, instead of having a
COUNT new parameter.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-17 21:27                                           ` Drew Adams
@ 2020-10-17 21:58                                             ` Arthur Miller
  2020-10-18 12:06                                               ` Michael Albinus
  0 siblings, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-17 21:58 UTC (permalink / raw)
  To: Drew Adams; +Cc: Eli Zaretskii, Michael Albinus, emacs-devel

Drew Adams <drew.adams@oracle.com> writes:

>> > Sorry I'm coming to this late.  It's a long thread,
>> > and I've only checked your patch, not the messages.
>> >
>> > I don't understand why we would do this.  Is the
>> > real aim to be able to have an empty-directory
>> > predicate, i.e., to be able to see if there are
>> > no files in a directory?
>>
>> I would just like to add to the previous mail; that this optimisation
>> really does not matter on very first call...
>
> Believe me, I'm not trying to second-guess any
> implementation.  I haven't (and won't) look at the
> C code, and I'm not very qualified to do so anyway.
>
> I was guessing that COUNT = 1 would be quicker for an
> emptiness check than COUNT > 1 (e.g. COUNT = 80000).
>
> But my argument wasn't about implementation or
> efficiency.  Even if, for some reason, C had to "get"
> (info about) all of the files in the directory, just
> to determine whether the dir is empty, my argument
> would be the same wrt Lisp: have a separate predicate,
> or have a Boolean new parameter, instead of having a
> COUNT new parameter.
I am not sure I follow; but it is a building block to build that
predicate. I agree with you that it is much nice to have such predicate
built-in than if anyone is building their own if it is just one liner.

I have no problems to build that predicate on directory_files_internal
either, it is trivial; and it would remove need to change the function
signature and count confusion, but than instead of changing one
parameter in a signature it would be a new predicate in Lisp
implementation. Wold be nice exercise to me to learn how to write
a tramp handler :-), but I am not sure it is desired.

Don't know, what Michael and Eli have to say about?



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-17 21:18                                           ` Drew Adams
@ 2020-10-17 22:06                                             ` Arthur Miller
  0 siblings, 0 replies; 71+ messages in thread
From: Arthur Miller @ 2020-10-17 22:06 UTC (permalink / raw)
  To: Drew Adams; +Cc: Eli Zaretskii, Michael Albinus, emacs-devel

Drew Adams <drew.adams@oracle.com> writes:

>> > Sorry I'm coming to this late.  It's a long thread,
>> > and I've only checked your patch, not the messages.
>> >
>> > I don't understand why we would do this.  Is the
>> > real aim to be able to have an empty-directory
>> > predicate, i.e., to be able to see if there are
>> > no files in a directory?
>>
>> Yes.
>>
>> > If so, then why not do just that, without
>> > bothering (changing the signature of)
>> > `directory-files'?
>>
>> Because it is not possible to that efficiently with current elisp; how
>> would you do that directly? OS does not have such call, one have to
>> iterate through directories. At least I am not aware of such call. If
>> you know, please tell me, I would be happy to use it, at least for myself.
>> 
>> Fastest I am aware of is to get a buffered list with SYS_getdents and then
>> check for first non-dot file. That changes complexity from linear in
>> number of files in directory to constant (3 files at max). It works only
>> on Linux kernel, and I don't know if there is nt version of such call,
>> or what there is on macs.
>> 
>> I suggested such predicate, but to not re-iterate entire discussion, pls
>> check my first mail and followed 2 or 3 I think.
>
> I took a quick look at the first few messages etc.
>
> I see that Eli suggested not implementing an
> empty-directory predicate directly but instead
> adding a COUNT parameter to `directory-files' (Lisp).
>
> That's just what I questioned.  If the aim is an
> empty-directory pred then why not code it in C, like
> we do `directory-files'?  And instead of duplicating
> code, if that would be the case, extend the C code
> underlying `directory-files' to be usable also for
> such a predicate, stopping as soon as it finds one
> file.
>
> IOW, what you've done, but not expose the COUNT
> parameter to Lisp.  If its real purpose is just to
> check for emptiness, then from Lisp I'd think we'd
> have a separate predicate for that, and we wouldn't
> change the signature of `directory-files'.
>
> UNLESS there really IS some use for a COUNT value > 1.
>
> That was my question.  If there's some use case, in
> Lisp, for COUNT, i.e., for returning the "first" N
> files, then fine.  But if not, I don't see why we
> would add COUNT to `directory-files' (Lisp), as
> opposed to just getting the emptiness check from C
> (perhaps by adding a COUNT there, but not changing
> the Lisp interface for `directory-files').
>
> Not a big deal.  Just a question; just something
> that occurred to me when I saw this.  I think a
> Lisp user is likely to ask herself the same thing:
> apart from passing 1 for COUNT, why would I ever
> use COUNT?
>
> And if it were agreed that there's no use case for
> COUNT > 1, but for some reason a separate predicate,
> `directory-empty-p' isn't wanted, then change COUNT
> to a Boolean parameter that just says you want an
> emptiness check.
>
> If COUNT > 1 has no utility then, if you have to add
> a parameter for Lisp, its name, doc, and behavior
> should at least be more indicative of its purpose, no?
>
> Don't get me wrong.  I'm generally in favor of Lisp
> Boolean functions and such that return useful non-nil
> truth values.  I _really_ like that.  But here I don't
> see the usefulness of the non-nil return value, which
> means the thing will confuse and mislead sometimes.
>
>> > Is there really some use case for getting only
>> > the first N files in a directory?  I can
>> > understand wanting to test whether a dir is
>> > empty.  I can't see why someone would want the
>> > first N files (however "first" might be defined).
>>
>> Probably not; it is just a result of having count parameter.
>
> Should be the other way round, no?  We should have
> a COUNT parameter only if it's useful.  If we're
> adding it just for implementation purposes, then why
> not just do that under the covers in the C code?
>
> Anyway, I don't mean to belabor this.  I've asked
> my question and clarified why I asked.

Yeah, sure; I completely buy your reasoning. When I think of, one user
case for COUNT is maybe if a user have some kind of limited structure to
fill and just wish to taken N number of files. I don't know if that is
very common in Elisp, it's not directly a system programming lang, so I
think it is an artifical example.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-17 20:03                                       ` Drew Adams
  2020-10-17 20:27                                         ` Arthur Miller
  2020-10-17 21:02                                         ` Arthur Miller
@ 2020-10-18  2:47                                         ` Eli Zaretskii
  2 siblings, 0 replies; 71+ messages in thread
From: Eli Zaretskii @ 2020-10-18  2:47 UTC (permalink / raw)
  To: Drew Adams; +Cc: michael.albinus, arthur.miller, emacs-devel

> Date: Sat, 17 Oct 2020 13:03:35 -0700 (PDT)
> From: Drew Adams <drew.adams@oracle.com>
> Cc: Eli Zaretskii <eliz@gnu.org>, emacs-devel@gnu.org
> 
> I don't understand why we would do this.  Is the
> real aim to be able to have an empty-directory
> predicate, i.e., to be able to see if there are
> no files in a directory?

It could be useful to know that a directory has at least N files in
it, and the complexity of stopping a loop after N iterations is the
same as stopping after 1 iteration.

> If so, then why not do just that, witout
> bothering (changing the signature of)
> `directory-files'?

The signature got an additional optional argument, which is backward
compatible.  And it is now trivial to implement the predicate for an
empty directory based on the modified directory-files.

> And what is the order that defines which file
> is first, second, etc.?  Without knowing that,
> what use is getting the "first" N?

As discussed: on some filesystems the order is known in advance.  Not
sure how important that is.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: empty-directory predicate, native implementation
       [not found]                                         ` <<83ft6cs10u.fsf@gnu.org>
@ 2020-10-18  4:05                                           ` Drew Adams
  0 siblings, 0 replies; 71+ messages in thread
From: Drew Adams @ 2020-10-18  4:05 UTC (permalink / raw)
  To: Eli Zaretskii, Drew Adams; +Cc: michael.albinus, arthur.miller, emacs-devel

> > I don't understand why we would do this.
> 
> It could be useful to know that a directory has at least N files in it

OK, if you say so.  That was my question, though:
why/when would that be useful?  No doubt I lack
imagination.

It's not important - to me, anyway.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-17 19:03                                     ` Arthur Miller
  2020-10-17 20:03                                       ` Drew Adams
@ 2020-10-18 11:52                                       ` Michael Albinus
  2020-10-18 16:15                                         ` Drew Adams
                                                           ` (2 more replies)
  1 sibling, 3 replies; 71+ messages in thread
From: Michael Albinus @ 2020-10-18 11:52 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Eli Zaretskii, emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi Arthur,

> Please check that handlers stuff. I am not sure how to test it, and am
> not sure I get those correct; especially tramp-crypt.

See comments below.

> I am using a regular expression from Dired+ by Drew in two places. I
> have mention it the comment in ert tests, but don't know how to mention
> it in the example in manual. Maybe remove example, or maybe it can stay
> without creds?

You don't need that regexp from Drew. We have the constant
directory-files-no-dot-files-regexp for that purpose.

> I also discovered that I wasn't covered with FIXNUM all the way; thought
> it was unsigned int so -1 would be converted into ffffffff, which
> would just yeild all results. Seems like fixnum is not what I thought so I
> have added test for <=0 which return nil.

What's wrong using FIXNATP and XFIXNAT everywhere?

> Ert test are mostly foxused on new argument. I haven't found something
> related to dired in test/src so I have created dired-tests.el. If it
> shoudl be in some other place I can rename it.

test/src/dired-tests.el is perfect. Maybe you add a comment, that just
the tests for COUNT are added.

> diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
> index 3b8b4fb3a9..2f15176e79 100644
> --- a/doc/lispref/files.texi
> +++ b/doc/lispref/files.texi
>
> +If @var{count} is non-@code{nil}, the function will return first
> +@var{count} number of files, or all files, whichever occurs
> +first. @var{count} has to be a natural number (> 0). You can use this
> +function to short circuit evaluation in case you are just interested to
> +find if a directory is empty or not (request one file and tell it to
> +ignore dot-files).

In Emacs documentation, we use two spaces after an end-of-sentence
period. Furthermore, pls say "file name" instead of "file"; this is what
we return.

> +@example
> +@group
> +  (null (directory-files directory-name nil
> +  "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*" t 1))

Please format properly. It shall be

(null
 (directory-files directory-name
   nil directory-files-no-dot-files-regexp t 1))

> diff --git a/etc/NEWS b/etc/NEWS
> index 1838b6b38a..25c54d3dfe 100644
> --- a/etc/NEWS
> +++ b/etc/NEWS
> +** 'diirectory-files' function can now take an additional count parameter

Pls fix the spelling error. Finish the header line with a period. Use
capital letters COUNT.

> +This option makes directory-files return COUNT first files in

It is not an option, but rather an optional parameter. Quote
directory-files. Use two spaces. Use "file names". Fix "vill".

> The option is useful for checking if
> +directory is empty since it will check at most 3 files when COUNT = 1.

As it stands it is not understandable, without mentioning the respective
regexp. Better, you keep this sentence out.

> diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
> index 0cb8d7cb83..335a07914c 100644
> --- a/lisp/net/ange-ftp.el
> +++ b/lisp/net/ange-ftp.el
> +(defun ange-ftp-directory-files (directory &optional full match nosort
> +					   count)

Could be in  the same line.

> @@ -3444,18 +3444,19 @@ ange-ftp-directory-files
>  		(setq files
>  		      (cons (if full (concat directory f) f) files))))
>  	  (nreverse files)))
> -    (apply 'ange-ftp-real-directory-files directory full match v19-args)))
> +    (apply 'ange-ftp-real-directory-files directory full match nosort count)))

That is the fallback. But I don't see an implementation of
COUNT. (Should be in the "while tail" loop).

>  (defun ange-ftp-directory-files-and-attributes
> -  (directory &optional full match nosort id-format)
> +  (directory &optional full match nosort attrs id-format count)

What it attrs good for?

> -       (ange-ftp-directory-files directory full match nosort))
> +       (ange-ftp-directory-files directory full match nosort attrs
> +                                 id_format count))

Remove attrs. Use id-format.

>      (ange-ftp-real-directory-files-and-attributes
> -     directory full match nosort id-format)))
> +     directory full match nosort attrs id-format count)))

Remove attrs.

> --- a/lisp/net/tramp-adb.el
> +++ b/lisp/net/tramp-adb.el
> @@ -312,7 +312,7 @@ tramp-adb-handle-directory-files-and-attributes
>        (copy-tree
>         (with-tramp-file-property
>  	   v localname (format "directory-files-and-attributes-%s-%s-%s-%s"
> -			       full match id-format nosort)
> +			       full match id-format nosort count)

If you want to add count to the property name, you must adapt the format
string.

I miss the implementation of count.

> diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el
> index 3e96daa7b1..bda3735db4 100644
> --- a/lisp/net/tramp-crypt.el
> +++ b/lisp/net/tramp-crypt.el
> +;; This function does not seem to pass match and nosort into
> +;; directory-files at all; is that intentional or bug?

ATM: yes. Leave it as it is, we could change later on. Add FIXME in the comment.

> diff --git a/lisp/net/tramp-rclone.el b/lisp/net/tramp-rclone.el
> index 3701bfc22c..787eead807 100644
> --- a/lisp/net/tramp-rclone.el
> +++ b/lisp/net/tramp-rclone.el
> +;; This function did not pass nosort arguemnt into directory-files
> +;; not sure if intentional or bug

You can remove the comment, because you did it right.

> diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
> index 15eab0a4de..7a969979ac 100644
> +;; what about perl & sta -> need to fix list to count?

That's correct. Mark the comment as FIXME.

> diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
> index 1b6af2a2e3..62135f514d 100644
> --- a/lisp/net/tramp-smb.el
> +++ b/lisp/net/tramp-smb.el
> +  (let ((result nil)
> +        (numres 0))

numres is not used. The rest I need to test later; I'm currently just
dry reading.

> diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
> index 6d44ad23ad..a99af70196 100644
> --- a/lisp/net/tramp.el
> +++ b/lisp/net/tramp.el
> +(defun tramp-handle-directory-files (directory &optional full match
> +                                               nosort count)

This fits into one line (80 chars). I'm missiong an implementation for count.

> diff --git a/src/dired.c b/src/dired.c
> index 1584b6acf0..1fc8dd27fa 100644
> --- a/src/dired.c
> +++ b/src/dired.c
> @@ -17,7 +17,6 @@
> +  if (FIXNUMP(return_count))
> +    {
> +      last = XFIXNUM (return_count);
> +      if (last <= 0)
> +        return Qnil;
> +    }

This is superfluous. Remove it.

> +If COUNT is  non-nil, the function will return max of COUNT and length
> + files, where length is number of files in the directory. COUNT has to
> + be a natural number > 0. */)

So you haven't changed the docstring?

>  DEFUN ("directory-files-and-attributes", Fdirectory_files_and_attributes,
> -       Sdirectory_files_and_attributes, 1, 5, 0,
> -       doc: /* Return a list of names of files and their attributes in DIRECTORY.
> +       Sdirectory_files_and_attributes, 1, 6, 0, doc
> +       : /* Return a list of names of files and their attributes in DIRECTORY.
>  Value is a list of the form:
>
> -  ((FILE1 . FILE1-ATTRS) (FILE2 . FILE2-ATTRS) ...)
> +((FILE1 . FILE1-ATTRS) (FILE2 . FILE2-ATTRS) ...)

...

Still the indentation doesn't fit with the original.

> diff --git a/test/src/dired-tests.el b/test/src/dired-tests.el
> new file mode 100644
> index 0000000000..3b739e59cc
> --- /dev/null
> +++ b/test/src/dired-tests.el
> +;; Copyright (C) 2015-2020 Free Software Foundation, Inc.

This shall be just 2020.

> +        ;; nodots expression from dired+ by Drew A.
> +        (nodots "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"))

Not needed. Use directory-files-no-dot-files-regexp.

> +    (message name)

That's OK for debugging purposes. Finally, the tests shall be silent.

> +    (make-directory name)

Tests shall not kepp garbage. Please delete the directory at the end of
the test, preferred as unwindorm of unwind-protect.

> +(ert-deftest directory-files-and-attributes-tests ()

Same comments apply.

> Best regards

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-17 21:58                                             ` Arthur Miller
@ 2020-10-18 12:06                                               ` Michael Albinus
  0 siblings, 0 replies; 71+ messages in thread
From: Michael Albinus @ 2020-10-18 12:06 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Eli Zaretskii, Drew Adams, emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi,

>> But my argument wasn't about implementation or
>> efficiency.  Even if, for some reason, C had to "get"
>> (info about) all of the files in the directory, just
>> to determine whether the dir is empty, my argument
>> would be the same wrt Lisp: have a separate predicate,
>> or have a Boolean new parameter, instead of having a
>> COUNT new parameter.
>
> I am not sure I follow; but it is a building block to build that
> predicate. I agree with you that it is much nice to have such predicate
> built-in than if anyone is building their own if it is just one liner.
>
> I have no problems to build that predicate on directory_files_internal
> either, it is trivial; and it would remove need to change the function
> signature and count confusion, but than instead of changing one
> parameter in a signature it would be a new predicate in Lisp
> implementation. Wold be nice exercise to me to learn how to write
> a tramp handler :-), but I am not sure it is desired.
>
> Don't know, what Michael and Eli have to say about?

I'm in line with Eli here. I have no glaring example that we need COUNT
greater than one. Just a vague idea, that it could help to implement a
more performant file name completion, especially in the remote
case. That is, if you have a very large directory, you let complete file
names on-the-fly (while typing in the minibuffer) with just the first 50
hits from directory-files, which could be retrieved much faster than,
say, more than 2000 file names (this is what I have in /usr/bin). The
complete file names for completion are retrieved, when the user hits TAB.

Just a vague idea; I haven't checked how to implement.

So I propose we still use the COUNT optional argument. This isn't worse
than an argument NOT-EMPTY, which would let directory-files return
immediately after the first hit has found.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: empty-directory predicate, native implementation
  2020-10-18 11:52                                       ` Michael Albinus
@ 2020-10-18 16:15                                         ` Drew Adams
  2020-10-18 16:43                                           ` Michael Albinus
                                                             ` (2 more replies)
  2020-10-18 22:21                                         ` Arthur Miller
       [not found]                                         ` <VI1PR06MB45266BE5DFC72AEB27567A6C961E0@VI1PR06MB4526.eurprd06.prod.outlook.com>
  2 siblings, 3 replies; 71+ messages in thread
From: Drew Adams @ 2020-10-18 16:15 UTC (permalink / raw)
  To: Michael Albinus, Arthur Miller; +Cc: Eli Zaretskii, emacs-devel

> > I am using a regular expression from Dired+ by Drew in two places. I
> > have mention it the comment in ert tests, but don't know how to mention
> > it in the example in manual. Maybe remove example, or maybe it can stay
> > without creds?
> 
> You don't need that regexp from Drew. We have the constant
> directory-files-no-dot-files-regexp for that purpose.

FWIW -

`directory-files-no-dot-files-regexp' was added to Emacs 23.
Its value then was the same as that of `diredp-re-no-dot':
"^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*".  The value was
changed in Emacs 27, to "[^.]\\|\\.\\.\\.".

For my purposes (Dired) I want the former, not the latter,
so `diredp-re-no-dot' remains the former.  The two behave
quite differently.  

See https://lists.gnu.org/archive/html/emacs-devel/2020-04/msg00764.html



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-18 16:15                                         ` Drew Adams
@ 2020-10-18 16:43                                           ` Michael Albinus
  2020-10-18 20:15                                           ` Stefan Monnier
  2020-10-19  0:03                                           ` Arthur Miller
  2 siblings, 0 replies; 71+ messages in thread
From: Michael Albinus @ 2020-10-18 16:43 UTC (permalink / raw)
  To: Drew Adams; +Cc: Eli Zaretskii, Arthur Miller, emacs-devel

Drew Adams <drew.adams@oracle.com> writes:

Hi Drew,

> `directory-files-no-dot-files-regexp' was added to Emacs 23.
> Its value then was the same as that of `diredp-re-no-dot':
> "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*".  The value was
> changed in Emacs 27, to "[^.]\\|\\.\\.\\.".
>
> For my purposes (Dired) I want the former, not the latter,
> so `diredp-re-no-dot' remains the former.  The two behave
> quite differently.
>
> See https://lists.gnu.org/archive/html/emacs-devel/2020-04/msg00764.html

FTR, I have also problems to understand how the current value of
directory-files-no-dot-files-regexp works. But I fail to find a case
where it is wrong.

(string-match directory-files-no-dot-files-regexp ".") => nil
(string-match directory-files-no-dot-files-regexp "..") => nil
(string-match directory-files-no-dot-files-regexp ".a") => 1
(string-match directory-files-no-dot-files-regexp "..a") => 2

Could you pls give me an example which shows the problem with that
constant? In case there is, I'll lobby for your request in the given
message :-)

Thanks, and best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-18 16:15                                         ` Drew Adams
  2020-10-18 16:43                                           ` Michael Albinus
@ 2020-10-18 20:15                                           ` Stefan Monnier
  2020-10-18 21:25                                             ` Drew Adams
  2020-10-19  0:03                                           ` Arthur Miller
  2 siblings, 1 reply; 71+ messages in thread
From: Stefan Monnier @ 2020-10-18 20:15 UTC (permalink / raw)
  To: Drew Adams; +Cc: Eli Zaretskii, Michael Albinus, Arthur Miller, emacs-devel

> For my purposes (Dired) I want the former, not the latter,

Why?

> The two behave quite differently.

Can you give an example?

> See https://lists.gnu.org/archive/html/emacs-devel/2020-04/msg00764.html

I don't see any answer to those two questions in that message either.


        Stefan




^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: empty-directory predicate, native implementation
@ 2020-10-18 21:13 Drew Adams
  2020-10-18 22:15 ` Stefan Monnier
                   ` (2 more replies)
  0 siblings, 3 replies; 71+ messages in thread
From: Drew Adams @ 2020-10-18 21:13 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Eli Zaretskii, Arthur Miller, emacs-devel

> > `directory-files-no-dot-files-regexp' was added to Emacs 23.
> > Its value then was the same as that of `diredp-re-no-dot':
> > "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*".  The value was
> > changed in Emacs 27, to "[^.]\\|\\.\\.\\.".
> >
> > For my purposes (Dired) I want the former, not the latter,
> > so `diredp-re-no-dot' remains the former.  The two behave
> > quite differently.
> >
> > See https://urldefense.com/v3/__https://lists.gnu.org/archive/html/emacs-
> devel/2020-
> 04/msg00764.html__;!!GqivPVa7Brio!PWSpyl3EDfFC2LKEXIP7mdNKcGl6HzDDLwE2SFOWdxS
> ZaQ3phv5AVvVuUb-CN6kG$
> 
> FTR, I have also problems to understand how the current value of
> directory-files-no-dot-files-regexp works. But I fail to find a case
> where it is wrong.
> 
> (string-match directory-files-no-dot-files-regexp ".") => nil
> (string-match directory-files-no-dot-files-regexp "..") => nil
> (string-match directory-files-no-dot-files-regexp ".a") => 1
> (string-match directory-files-no-dot-files-regexp "..a") => 2
> 
> Could you pls give me an example which shows the problem with that
> constant? In case there is, I'll lobby for your request in the given
> message :-)

Dunno.  And perhaps I misspoke in saying they behave quite
differently.  They _can_ behave quite differently, depending
on how they're used.

And frankly I think that the only current Dired+ uses of the
regexp don't depend on the difference, as they all just pass
it to `directory-files' as the MATCH arg.  And in that case
the new regexp is just as usable.

In general, the difference between the two is this, AFAICT:
the old one (which is the one still used by Dired+) matches
the complete file name (the nondirectory part), whereas the
new one matches only enough of it to distinguish the . and
.. cases.

IOW, what's different, AFAICS, is the match data: the match.

So if you use the regexp only with `string-match-p' (which
doesn't care about the match data), or if you use it only
with `directory-files', then there's no real difference in
the effect.  But if you use it for some context where the
matched parts are important, that is, where the match-data
matters, then there's a big difference.

Perhaps in the past I used the regexp also for purposes of
grabbing the matched part(s).  I don't recall.

I didn't complain about Emacs changing the value of the
variable - no lobbying is needed.  What I said was that
"it's not clear to me" why people were claiming that the
new regexp is "more correct" than the old one.  (No one
ever responded to that, explaining in what way the old
one was somehow incorrect.)

Paul's mail responding to my mail in that emacs-devel
thread says, BTW:

  As Drew's comments make evident, the doc string is
  unclear. It should be something like 'Regexp that
  matches part of a nonempty string if the string is
  ^^^^^^^^^^^^
  neither "." nor "..".'

But I couldn't find where in that thread I said that.

Anyway, I've said it now.  The old regexp matches all
chars in the nondir part of the file name.  The new
regexp doesn't.  The match data for the old regexp
gives you the matched name.  But no, that's not
needed for `directory-file-names'.
___

[BTW, neither manual nor doc string for `directory-files'
says what MATCH is matched against, other than "file names".
But apparently it's matched only against the nondirectory
part of file names, even if FULL is non-nil.]



^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: empty-directory predicate, native implementation
  2020-10-18 20:15                                           ` Stefan Monnier
@ 2020-10-18 21:25                                             ` Drew Adams
  0 siblings, 0 replies; 71+ messages in thread
From: Drew Adams @ 2020-10-18 21:25 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Eli Zaretskii, Michael Albinus, Arthur Miller, emacs-devel

> > For my purposes (Dired) I want the former, not the latter,
> 
> Why?
> 
> > The two behave quite differently.
> 
> Can you give an example?

See my reply to Michael.  What they match (match-data)
is different.

But for the Dired use I make of it, it turns out that I
don't care: it in fact makes no difference which I use.

(My use of it is as old as the original `dired-re-no-dot'.)



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-18 21:13 Drew Adams
@ 2020-10-18 22:15 ` Stefan Monnier
  2020-10-19  7:54   ` Michael Albinus
  2020-10-19  0:24 ` Arthur Miller
  2020-10-19  7:51 ` Michael Albinus
  2 siblings, 1 reply; 71+ messages in thread
From: Stefan Monnier @ 2020-10-18 22:15 UTC (permalink / raw)
  To: Drew Adams; +Cc: Eli Zaretskii, Michael Albinus, Arthur Miller, emacs-devel

> ever responded to that, explaining in what way the old
> one was somehow incorrect.)

One case that's mishandled by the old regexp is the case where
the file name includes an LF char (not matched by `.`).


        Stefan




^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-18 11:52                                       ` Michael Albinus
  2020-10-18 16:15                                         ` Drew Adams
@ 2020-10-18 22:21                                         ` Arthur Miller
  2020-10-19  8:04                                           ` Michael Albinus
       [not found]                                         ` <VI1PR06MB45266BE5DFC72AEB27567A6C961E0@VI1PR06MB4526.eurprd06.prod.outlook.com>
  2 siblings, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-18 22:21 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Eli Zaretskii, emacs-devel

Michael Albinus <michael.albinus@gmx.de> writes:

> What's wrong using FIXNATP and XFIXNAT everywhere?
If we return nil for 0 count, then it make sense to return nil for
negative count too?

XFIXNAT will turn it negative num into some big int.
I thought first it is fine, but after second thought I don't think it is
best thing to do.

if (FIXNUMP(return_count))
    {
      last = XFIXNUM(return_count);

      if (last < 1)
        return Qnil;
    }

This works better.

Negative bignums end up also as big unsigneds which results with all
file namess returned, but I don't know if it matters. Correct me if I am wrong.

>> --- a/lisp/net/tramp-adb.el
>> +++ b/lisp/net/tramp-adb.el
>> @@ -312,7 +312,7 @@ tramp-adb-handle-directory-files-and-attributes
>>        (copy-tree
>>         (with-tramp-file-property
>>  	   v localname (format "directory-files-and-attributes-%s-%s-%s-%s"
>> -			       full match id-format nosort)
>> +			       full match id-format nosort count)
I did that first, but then decided to skip count in format and forgot
to delete the count from the argument list. I didn't know how format was
used so I didn't want to mess with it; but if it is only for the name,
then it is maybe useful?

>> diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
>> index 6d44ad23ad..a99af70196 100644
>> --- a/lisp/net/tramp.el
>> +++ b/lisp/net/tramp.el
>> +(defun tramp-handle-directory-files (directory &optional full match
>> +                                               nosort count)
>
> This fits into one line (80 chars).
It is 81 chars so Emacs breaks the line. I can call it num, saves 2 chars.

I have fixed identation and docs; as well as other stuff you pointed
out. I can send patch when I get answers to questions above.

Best regards; sorry for giving you so much work!

/a



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-18 16:15                                         ` Drew Adams
  2020-10-18 16:43                                           ` Michael Albinus
  2020-10-18 20:15                                           ` Stefan Monnier
@ 2020-10-19  0:03                                           ` Arthur Miller
  2 siblings, 0 replies; 71+ messages in thread
From: Arthur Miller @ 2020-10-19  0:03 UTC (permalink / raw)
  To: Drew Adams; +Cc: Eli Zaretskii, Michael Albinus, emacs-devel

Drew Adams <drew.adams@oracle.com> writes:

> FWIW -
>
> `directory-files-no-dot-files-regexp' was added to Emacs 23.
> Its value then was the same as that of `diredp-re-no-dot':
> "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*".  The value was
> changed in Emacs 27, to "[^.]\\|\\.\\.\\.".
>
> For my purposes (Dired) I want the former, not the latter,
> so `diredp-re-no-dot' remains the former.  The two behave
> quite differently.  
Do you mind if I ask what is the difference? I have tried now both and I
am seemingly getting same results from both. Is there some special case
where `directory-files-no-dot-files-regexp' does not work correct?



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-18 21:13 Drew Adams
  2020-10-18 22:15 ` Stefan Monnier
@ 2020-10-19  0:24 ` Arthur Miller
  2020-10-19  0:37   ` Drew Adams
  2020-10-19  7:51 ` Michael Albinus
  2 siblings, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-19  0:24 UTC (permalink / raw)
  To: Drew Adams; +Cc: Eli Zaretskii, Michael Albinus, emacs-devel

Drew Adams <drew.adams@oracle.com> writes:

>> > `directory-files-no-dot-files-regexp' was added to Emacs 23.
>> > Its value then was the same as that of `diredp-re-no-dot':
>> > "^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*".  The value was
>> > changed in Emacs 27, to "[^.]\\|\\.\\.\\.".
>> >
>> > For my purposes (Dired) I want the former, not the latter,
>> > so `diredp-re-no-dot' remains the former.  The two behave
>> > quite differently.
>> >
>> > See https://urldefense.com/v3/__https://lists.gnu.org/archive/html/emacs-
>> devel/2020-
>> 04/msg00764.html__;!!GqivPVa7Brio!PWSpyl3EDfFC2LKEXIP7mdNKcGl6HzDDLwE2SFOWdxS
>> ZaQ3phv5AVvVuUb-CN6kG$
>> 
>> FTR, I have also problems to understand how the current value of
>> directory-files-no-dot-files-regexp works. But I fail to find a case
>> where it is wrong.
>> 
>> (string-match directory-files-no-dot-files-regexp ".") => nil
>> (string-match directory-files-no-dot-files-regexp "..") => nil
>> (string-match directory-files-no-dot-files-regexp ".a") => 1
>> (string-match directory-files-no-dot-files-regexp "..a") => 2
>> 
>> Could you pls give me an example which shows the problem with that
>> constant? In case there is, I'll lobby for your request in the given
>> message :-)
>
> Dunno.  And perhaps I misspoke in saying they behave quite
> differently.  They _can_ behave quite differently, depending
> on how they're used.
>
> And frankly I think that the only current Dired+ uses of the
> regexp don't depend on the difference, as they all just pass
> it to `directory-files' as the MATCH arg.  And in that case
> the new regexp is just as usable.
>
> In general, the difference between the two is this, AFAICT:
> the old one (which is the one still used by Dired+) matches
> the complete file name (the nondirectory part), whereas the
> new one matches only enough of it to distinguish the . and
> .. cases.
>
> IOW, what's different, AFAICS, is the match data: the match.
>
> So if you use the regexp only with `string-match-p' (which
> doesn't care about the match data), or if you use it only
> with `directory-files', then there's no real difference in
> the effect.  But if you use it for some context where the
> matched parts are important, that is, where the match-data
> matters, then there's a big difference.
>
> Perhaps in the past I used the regexp also for purposes of
> grabbing the matched part(s).  I don't recall.
>
> I didn't complain about Emacs changing the value of the
> variable - no lobbying is needed.  What I said was that
> "it's not clear to me" why people were claiming that the
> new regexp is "more correct" than the old one.  (No one
> ever responded to that, explaining in what way the old
> one was somehow incorrect.)
>
> Paul's mail responding to my mail in that emacs-devel
> thread says, BTW:
>
>   As Drew's comments make evident, the doc string is
>   unclear. It should be something like 'Regexp that
>   matches part of a nonempty string if the string is
>   ^^^^^^^^^^^^
>   neither "." nor "..".'
>
> But I couldn't find where in that thread I said that.
>
> Anyway, I've said it now.  The old regexp matches all
> chars in the nondir part of the file name.  The new
> regexp doesn't.  The match data for the old regexp
> gives you the matched name.  But no, that's not
> needed for `directory-file-names'.
> ___
>
> [BTW, neither manual nor doc string for `directory-files'
> says what MATCH is matched against, other than "file names".
> But apparently it's matched only against the nondirectory
> part of file names, even if FULL is non-nil.]

Thanks, that was really informative! Thank you for writing and
explaining all that. I guess for purpose of tests and manual where I
have used your regex, we can live with built-in one.

Please ignore my other mail; I sent it before I red the rest of resonses.

I am obviously to new here, so before I suggest something again :-), can
I ask if you have already considered having a predicate as a filter
function instead of regex? Is it considered as too much work to
implement? 



^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: empty-directory predicate, native implementation
  2020-10-19  0:24 ` Arthur Miller
@ 2020-10-19  0:37   ` Drew Adams
  2020-10-19  2:15     ` Arthur Miller
  0 siblings, 1 reply; 71+ messages in thread
From: Drew Adams @ 2020-10-19  0:37 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Eli Zaretskii, Michael Albinus, emacs-devel

> I guess for purpose of tests and manual where I
> have used your regex, we can live with built-in one.

Yes, most likely.

> Please ignore my other mail; I sent it before I red the rest of resonses.

No problem.

> I am obviously to new here, so before I suggest something again :-), can
> I ask if you have already considered having a predicate as a filter
> function instead of regex? Is it considered as too much work to
> implement?

Is that a question for me?  If so, a predicate where,
in what context?

As I mentioned, the current uses of the regexp, in
Dired+ as in vanilla Dired, are just to pass to
`directory-files' as the MATCH argument.

There are also Dired+ and Dired functions that accept
a predicate as argument.  `diredp-get-files'
`diredp-get-subdirs', and `diredp-files-within', for
example.

What is it that you'd like to do/suggest?  Or are you
asking something about the predicate of this thread?



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-19  0:37   ` Drew Adams
@ 2020-10-19  2:15     ` Arthur Miller
  0 siblings, 0 replies; 71+ messages in thread
From: Arthur Miller @ 2020-10-19  2:15 UTC (permalink / raw)
  To: Drew Adams; +Cc: Eli Zaretskii, Michael Albinus, emacs-devel

Drew Adams <drew.adams@oracle.com> writes:

>> I guess for purpose of tests and manual where I
>> have used your regex, we can live with built-in one.
>
> Yes, most likely.
>
>> Please ignore my other mail; I sent it before I red the rest of resonses.
>
> No problem.
>
>> I am obviously to new here, so before I suggest something again :-), can
>> I ask if you have already considered having a predicate as a filter
>> function instead of regex? Is it considered as too much work to
>> implement?
>
> Is that a question for me?
In general; for you and anyone who has been developing this
functionality and have time and will to answer.

>  If so, a predicate where, in what context?
> There are also Dired+ and Dired functions that accept
> a predicate as argument.  `diredp-get-files'
> `diredp-get-subdirs', and `diredp-files-within', for
> example.
>
> What is it that you'd like to do/suggest?
I don't know for sure; so I guess I'll play with it when I have time and
sent in suggestion if I make something. :-). Sorry for the noise.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-18 21:13 Drew Adams
  2020-10-18 22:15 ` Stefan Monnier
  2020-10-19  0:24 ` Arthur Miller
@ 2020-10-19  7:51 ` Michael Albinus
  2020-10-19 15:25   ` Drew Adams
  2 siblings, 1 reply; 71+ messages in thread
From: Michael Albinus @ 2020-10-19  7:51 UTC (permalink / raw)
  To: Drew Adams; +Cc: Eli Zaretskii, Arthur Miller, emacs-devel

Drew Adams <drew.adams@oracle.com> writes:

Hi Drew,

> IOW, what's different, AFAICS, is the match data: the match.
>
> So if you use the regexp only with `string-match-p' (which
> doesn't care about the match data), or if you use it only
> with `directory-files', then there's no real difference in
> the effect.  But if you use it for some context where the
> matched parts are important, that is, where the match-data
> matters, then there's a big difference.

Yes. But to be fair, the docstring of directory-files-no-dot-files-regexp
didn't promise to return any kind of match data. Using it was just using
an undocumented side effect.

> I didn't complain about Emacs changing the value of the
> variable - no lobbying is needed.  What I said was that
> "it's not clear to me" why people were claiming that the
> new regexp is "more correct" than the old one.  (No one
> ever responded to that, explaining in what way the old
> one was somehow incorrect.)

I believe this statement was rather for the different instances of
regexps over the code, all of them claiming to match just "." and
"..". And some of them might have been wrong.

> [BTW, neither manual nor doc string for `directory-files'
> says what MATCH is matched against, other than "file names".
> But apparently it's matched only against the nondirectory
> part of file names, even if FULL is non-nil.]

I've fixed the docstrings of directory-files-no-dot-files-regexp,
directory-files and directory-files-and-attributes.

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-18 22:15 ` Stefan Monnier
@ 2020-10-19  7:54   ` Michael Albinus
  0 siblings, 0 replies; 71+ messages in thread
From: Michael Albinus @ 2020-10-19  7:54 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Eli Zaretskii, Arthur Miller, Drew Adams, emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

Hi Stefan,

> One case that's mishandled by the old regexp is the case where
> the file name includes an LF char (not matched by `.`).

Well, I regard this rather as a regression. Do we want to handle file
names containing a line break?

>         Stefan

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-18 22:21                                         ` Arthur Miller
@ 2020-10-19  8:04                                           ` Michael Albinus
  2020-10-19 14:01                                             ` Arthur Miller
  0 siblings, 1 reply; 71+ messages in thread
From: Michael Albinus @ 2020-10-19  8:04 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Eli Zaretskii, emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi Arthur,

>> What's wrong using FIXNATP and XFIXNAT everywhere?
>
> If we return nil for 0 count, then it make sense to return nil for
> negative count too?

*Any* non-nil COUNT, which is not a natural number, is handled as it
were nil. That's what my proposal for the docstring tries to say ("If
COUNT is a natural number ...").

> XFIXNAT will turn it negative num into some big int.
> I thought first it is fine, but after second thought I don't think it is
> best thing to do.
>
> if (FIXNUMP(return_count))
>     {
>       last = XFIXNUM(return_count);
>
>       if (last < 1)
>         return Qnil;
>     }
>
> This works better.

But if you use FIXNATP instead of FIXNUMP, there's no problem at all.

>>> --- a/lisp/net/tramp-adb.el
>>> +++ b/lisp/net/tramp-adb.el
>>> @@ -312,7 +312,7 @@ tramp-adb-handle-directory-files-and-attributes
>>>        (copy-tree
>>>         (with-tramp-file-property
>>>  	   v localname (format "directory-files-and-attributes-%s-%s-%s-%s"
>>> -			       full match id-format nosort)
>>> +			       full match id-format nosort count)
> I did that first, but then decided to skip count in format and forgot
> to delete the count from the argument list. I didn't know how format was
> used so I didn't want to mess with it; but if it is only for the name,
> then it is maybe useful?

Well, the name is used for caches. If we want to use the cache also for
a non-nil COUNT, we must use it also for the cache entry.

>>> diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
>>> index 6d44ad23ad..a99af70196 100644
>>> --- a/lisp/net/tramp.el
>>> +++ b/lisp/net/tramp.el
>>> +(defun tramp-handle-directory-files (directory &optional full match
>>> +                                               nosort count)
>>
>> This fits into one line (80 chars).
> It is 81 chars so Emacs breaks the line. I can call it num, saves 2 chars.

It's not important. But in my Emacs, the closing parenthesis is at
position 80, IIRC :-)

> Best regards; sorry for giving you so much work!

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-19  8:04                                           ` Michael Albinus
@ 2020-10-19 14:01                                             ` Arthur Miller
  2020-10-19 14:50                                               ` Michael Albinus
  0 siblings, 1 reply; 71+ messages in thread
From: Arthur Miller @ 2020-10-19 14:01 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Eli Zaretskii, emacs-devel

Michael Albinus <michael.albinus@gmx.de> writes:

> Arthur Miller <arthur.miller@live.com> writes:
>
> Hi Arthur,
>
>>> What's wrong using FIXNATP and XFIXNAT everywhere?
>>
>> If we return nil for 0 count, then it make sense to return nil for
>> negative count too?
>
> *Any* non-nil COUNT, which is not a natural number, is handled as it
> were nil. That's what my proposal for the docstring tries to say ("If
> COUNT is a natural number ...").
Yes, that is how I interpreted it; just wanted to confirm.

>> XFIXNAT will turn it negative num into some big int.
>> I thought first it is fine, but after second thought I don't think it is
>> best thing to do.
>>
>> if (FIXNUMP(return_count))
>>     {
>>       last = XFIXNUM(return_count);
>>
>>       if (last < 1)
>>         return Qnil;
>>     }
>>
>> This works better.
>
> But if you use FIXNATP instead of FIXNUMP, there's no problem at all.
I tryed, but it discards negative numbers - from lisp.h:

INLINE bool
FIXNATP (Lisp_Object x)
{
  return FIXNUMP (x) && 0 <= XFIXNUM (x);
}

This discards negative numbers, which then leaves last = 0, which
results later in all files returned. Either I have to add another test
or use FIXNUM. Or do I missinterpret the code?

With fixnum negative numbers are catched unless they are bignumbers.

FIXNATP uses under the hood FIXNUMP, so check for FIXNUMP is cheaper too.

>>>> --- a/lisp/net/tramp-adb.el
>>>> +++ b/lisp/net/tramp-adb.el
>>>> @@ -312,7 +312,7 @@ tramp-adb-handle-directory-files-and-attributes
>>>>        (copy-tree
>>>>         (with-tramp-file-property
>>>>  	   v localname (format "directory-files-and-attributes-%s-%s-%s-%s"
>>>> -			       full match id-format nosort)
>>>> +			       full match id-format nosort count)
>> I did that first, but then decided to skip count in format and forgot
>> to delete the count from the argument list. I didn't know how format was
>> used so I didn't want to mess with it; but if it is only for the name,
>> then it is maybe useful?
>
> Well, the name is used for caches. If we want to use the cache also for
> a non-nil COUNT, we must use it also for the cache entry.
Yes, I will add the count to format.

>>>> diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
>>>> index 6d44ad23ad..a99af70196 100644
>>>> --- a/lisp/net/tramp.el
>>>> +++ b/lisp/net/tramp.el
>>>> +(defun tramp-handle-directory-files (directory &optional full match
>>>> +                                               nosort count)
>>>
>>> This fits into one line (80 chars).
>> It is 81 chars so Emacs breaks the line. I can call it num, saves 2 chars.
>
> It's not important. But in my Emacs, the closing parenthesis is at
> position 80, IIRC :-)
Ha :-) Mine was 81. Emacs ways are strange sometimes. Anyway, I changed
to 'num' - 2 chars off! :D



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-10-19 14:01                                             ` Arthur Miller
@ 2020-10-19 14:50                                               ` Michael Albinus
  0 siblings, 0 replies; 71+ messages in thread
From: Michael Albinus @ 2020-10-19 14:50 UTC (permalink / raw)
  To: Arthur Miller; +Cc: Eli Zaretskii, emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi Arthur,

>> *Any* non-nil COUNT, which is not a natural number, is handled as it
>> were nil. That's what my proposal for the docstring tries to say ("If
>> COUNT is a natural number ...").
>
> Yes, that is how I interpreted it; just wanted to confirm.

See my other message. Likely we're served better, if we raise an error
for a non-nil COUNT not being a natural number. "Principle of least
surprise" :-)

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* RE: empty-directory predicate, native implementation
  2020-10-19  7:51 ` Michael Albinus
@ 2020-10-19 15:25   ` Drew Adams
  0 siblings, 0 replies; 71+ messages in thread
From: Drew Adams @ 2020-10-19 15:25 UTC (permalink / raw)
  To: Michael Albinus; +Cc: Eli Zaretskii, Arthur Miller, emacs-devel

> > IOW, what's different, AFAICS, is the match data: the match.
> >
> > So if you use the regexp only with `string-match-p' (which
> > doesn't care about the match data), or if you use it only
> > with `directory-files', then there's no real difference in
> > the effect.  But if you use it for some context where the
> > matched parts are important, that is, where the match-data
> > matters, then there's a big difference.
> 
> Yes. But to be fair, the docstring of directory-files-no-dot-files-regexp
> didn't promise to return any kind of match data. Using it was just using
> an undocumented side effect.

Sure.  It's just a regexp.  Its value says what it's good for.

> > I didn't complain about Emacs changing the value of the
> > variable - no lobbying is needed.  What I said was that
> > "it's not clear to me" why people were claiming that the
> > new regexp is "more correct" than the old one.  (No one
> > ever responded to that, explaining in what way the old
> > one was somehow incorrect.)
> 
> I believe this statement was rather for the different instances of
> regexps over the code, all of them claiming to match just "." and
> "..". And some of them might have been wrong.

My reading of that statement was that the new regexp
was somehow more correct than the old one, at least
for the occurrences in the code.  I asked how/where
it was more correct.

But in this current thread Stefan has mentioned that
it is more correct in that it matches also file names
containing newline chars.  So far, that's the only
indication I've seen of how the new is more correct
than the old.

(Aside from whether/how it might be more correct,
the new is no doubt quicker.)

> > [BTW, neither manual nor doc string for `directory-files'
> > says what MATCH is matched against, other than "file names".
> > But apparently it's matched only against the nondirectory
> > part of file names, even if FULL is non-nil.]
> 
> I've fixed the docstrings of directory-files-no-dot-files-regexp,
> directory-files and directory-files-and-attributes.

Cool.  Thanks for that.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
       [not found]                                                 ` <VI1PR06MB45264E1CB34EECE86672581C96100@VI1PR06MB4526.eurprd06.prod.outlook.com>
@ 2020-11-02 17:02                                                   ` Michael Albinus
  2020-11-03 15:20                                                     ` Arthur Miller
  0 siblings, 1 reply; 71+ messages in thread
From: Michael Albinus @ 2020-11-02 17:02 UTC (permalink / raw)
  To: Arthur Miller; +Cc: emacs-devel

Arthur Miller <arthur.miller@live.com> writes:

Hi Arthur,

> See if patch works; I have done pull this morning, so I hope it is all
> up-to-date.

I have pushed your patch to master. While testing, I have pushed another
patch (in my name) for some oddities I have seen, most of them are
rather aesthetic. The major changes are moving directory-empty-p form
dired.el to files.el, and moving all the new tests to
lisp/dired-test.el. And fixing some test errors seen in Tramp. See the
diff in git.

> Best regards; and thanks for the patience and help!

Best regards, Michael.



^ permalink raw reply	[flat|nested] 71+ messages in thread

* Re: empty-directory predicate, native implementation
  2020-11-02 17:02                                                   ` Michael Albinus
@ 2020-11-03 15:20                                                     ` Arthur Miller
  0 siblings, 0 replies; 71+ messages in thread
From: Arthur Miller @ 2020-11-03 15:20 UTC (permalink / raw)
  To: Michael Albinus; +Cc: emacs-devel

Michael Albinus <michael.albinus@gmx.de> writes:

> Arthur Miller <arthur.miller@live.com> writes:
>
> Hi Arthur,
>
>> See if patch works; I have done pull this morning, so I hope it is all
>> up-to-date.
>
> I have pushed your patch to master. While testing, I have pushed another
> patch (in my name) for some oddities I have seen, most of them are
> rather aesthetic. The major changes are moving directory-empty-p form
> dired.el to files.el, and moving all the new tests to
> lisp/dired-test.el. And fixing some test errors seen in Tramp. See the
> diff in git.

Cool to see it done; thanks. I didn't really know wherte to stash that
directory-empty-p; good you found better place than dired.el.

best regards too
/a



^ permalink raw reply	[flat|nested] 71+ messages in thread

end of thread, other threads:[~2020-11-03 15:20 UTC | newest]

Thread overview: 71+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <<VI1PR06MB4526ACBABDE795DDD49A5A5896040@VI1PR06MB4526.eurprd06.prod.outlook.com>
     [not found] ` <<83y2ka18t7.fsf@gnu.org>
     [not found]   ` <<87y2kaj799.fsf@gmx.de>
     [not found]     ` <<83blh60wgr.fsf@gnu.org>
     [not found]       ` <<VI1PR06MB452688C9C71D5463D9497A2A96050@VI1PR06MB4526.eurprd06.prod.outlook.com>
     [not found]         ` <<87h7qxjh7g.fsf@gmx.de>
     [not found]           ` <<VI1PR06MB45269B3924B44A555428F00596050@VI1PR06MB4526.eurprd06.prod.outlook.com>
     [not found]             ` <<878sc8kgy8.fsf@gmx.de>
     [not found]               ` <<VI1PR06MB4526FDD3D3EB4867AF837C8F96050@VI1PR06MB4526.eurprd06.prod.outlook.com>
     [not found]                 ` <<87imbcls71.fsf@gmx.de>
     [not found]                   ` <<83eem0zt0b.fsf@gnu.org>
     [not found]                     ` <<87k0vsrd6m.fsf@gmx.de>
     [not found]                       ` <<83a6wozs7h.fsf@gnu.org>
     [not found]                         ` <<VI1PR06MB45267C7D83E77C3F307FF34E96020@VI1PR06MB4526.eurprd06.prod.outlook.com>
     [not found]                           ` <<87sgafq2e2.fsf@gmx.de>
     [not found]                             ` <<AM6PR06MB4518BCD25B93987390D7D6D596020@AM6PR06MB4518.eurprd06.prod.outlook.com>
     [not found]                               ` <<87h7qvptm3.fsf@gmx.de>
     [not found]                                 ` <<VI1PR06MB452605D66CDE84BAA25A257696030@VI1PR06MB4526.eurprd06.prod.outlook.com>
     [not found]                                   ` <<871rhxp8we.fsf@gmx.de>
     [not found]                                     ` <<VI1PR06MB45261F3309D31EC7DEDE4C8B96000@VI1PR06MB4526.eurprd06.prod.outlook.com>
     [not found]                                       ` <<237bd21b-96c7-4433-a5bc-34b64a9f4250@default>
     [not found]                                         ` <<83ft6cs10u.fsf@gnu.org>
2020-10-18  4:05                                           ` empty-directory predicate, native implementation Drew Adams
2020-10-18 21:13 Drew Adams
2020-10-18 22:15 ` Stefan Monnier
2020-10-19  7:54   ` Michael Albinus
2020-10-19  0:24 ` Arthur Miller
2020-10-19  0:37   ` Drew Adams
2020-10-19  2:15     ` Arthur Miller
2020-10-19  7:51 ` Michael Albinus
2020-10-19 15:25   ` Drew Adams
  -- strict thread matches above, loose matches on Subject: below --
2020-10-13  2:22 Arthur Miller
2020-10-13  8:01 ` Michael Albinus
2020-10-13 11:42   ` Arthur Miller
2020-10-13 13:16     ` Michael Albinus
2020-10-13 18:32       ` Arthur Miller
2020-10-13 18:39         ` Michael Albinus
2020-10-13 23:20           ` Arthur Miller
2020-10-14  9:19             ` Michael Albinus
2020-10-14 13:53               ` Arthur Miller
2020-10-13 14:48 ` Eli Zaretskii
2020-10-13 18:43   ` Arthur Miller
2020-10-13 19:12     ` Eli Zaretskii
2020-10-13 19:59       ` Arthur Miller
2020-10-14 14:08         ` Eli Zaretskii
2020-10-14 14:43           ` Arthur Miller
2020-10-13 18:44   ` Michael Albinus
2020-10-13 19:14     ` Eli Zaretskii
2020-10-13 20:08       ` Arthur Miller
2020-10-14  1:52       ` Arthur Miller
2020-10-14  9:21         ` Michael Albinus
2020-10-14 13:56           ` Arthur Miller
2020-10-14 14:41             ` Michael Albinus
2020-10-14 15:07               ` Arthur Miller
2020-10-14 15:53                 ` Michael Albinus
2020-10-14 16:12                   ` Eli Zaretskii
2020-10-14 16:21                     ` Michael Albinus
2020-10-14 16:29                       ` Eli Zaretskii
2020-10-15  5:53                         ` Arthur Miller
2020-10-15  9:12                           ` Michael Albinus
2020-10-15 11:33                             ` Arthur Miller
2020-10-15 12:21                               ` Michael Albinus
2020-10-15 13:29                                 ` Arthur Miller
2020-10-15 14:01                                 ` Arthur Miller
2020-10-15 14:41                                   ` Michael Albinus
2020-10-15 15:22                                     ` Arthur Miller
2020-10-16 23:31                                 ` Arthur Miller
2020-10-17  8:13                                   ` Michael Albinus
2020-10-17 19:03                                     ` Arthur Miller
2020-10-17 20:03                                       ` Drew Adams
2020-10-17 20:27                                         ` Arthur Miller
2020-10-17 21:18                                           ` Drew Adams
2020-10-17 22:06                                             ` Arthur Miller
2020-10-17 21:02                                         ` Arthur Miller
2020-10-17 21:27                                           ` Drew Adams
2020-10-17 21:58                                             ` Arthur Miller
2020-10-18 12:06                                               ` Michael Albinus
2020-10-18  2:47                                         ` Eli Zaretskii
2020-10-18 11:52                                       ` Michael Albinus
2020-10-18 16:15                                         ` Drew Adams
2020-10-18 16:43                                           ` Michael Albinus
2020-10-18 20:15                                           ` Stefan Monnier
2020-10-18 21:25                                             ` Drew Adams
2020-10-19  0:03                                           ` Arthur Miller
2020-10-18 22:21                                         ` Arthur Miller
2020-10-19  8:04                                           ` Michael Albinus
2020-10-19 14:01                                             ` Arthur Miller
2020-10-19 14:50                                               ` Michael Albinus
     [not found]                                         ` <VI1PR06MB45266BE5DFC72AEB27567A6C961E0@VI1PR06MB4526.eurprd06.prod.outlook.com>
     [not found]                                           ` <87a6wixoim.fsf@gmx.de>
     [not found]                                             ` <VI1PR06MB4526280D5B81531D06E58BC1961D0@VI1PR06MB4526.eurprd06.prod.outlook.com>
     [not found]                                               ` <87wnzev6i3.fsf@gmx.de>
     [not found]                                                 ` <VI1PR06MB45264E1CB34EECE86672581C96100@VI1PR06MB4526.eurprd06.prod.outlook.com>
2020-11-02 17:02                                                   ` Michael Albinus
2020-11-03 15:20                                                     ` Arthur Miller
2020-10-15 13:38                               ` Stefan Monnier
2020-10-16 23:33                                 ` Arthur Miller
2020-10-14 14:49             ` Arthur Miller

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).