Index: ChangeLog
===================================================================
RCS file: /cvsroot/coreutils/coreutils/ChangeLog,v
retrieving revision 1.1565
diff -b -u -2 -r1.1565 ChangeLog
--- ChangeLog   3 Dec 2005 22:24:31 -0000   1.1565
+++ ChangeLog   9 Dec 2005 13:42:46 -0000
@@ -3,4 +3,6 @@
    * Version 6.0-cvs.

+   * src/ls.c: Added the -e,--group-directories option to group
+   directories before files (Francesco Montorsi).
    * src/rm.c (long_opts): Change the name of each undocumented, for-
    testing-only option to start with `-', so that it cannot render
Index: NEWS
===================================================================
RCS file: /cvsroot/coreutils/coreutils/NEWS,v
retrieving revision 1.349
diff -b -u -2 -r1.349 NEWS
--- NEWS    26 Nov 2005 07:51:27 -0000  1.349
+++ NEWS    9 Dec 2005 13:42:49 -0000
@@ -24,4 +24,7 @@
   attempts to have the default be the best of both worlds.

+  ls now supports the '-e,--group-directories' option to group directories
+  before files.
+
 ** Scheduled for removal

Index: THANKS
===================================================================
RCS file: /cvsroot/coreutils/coreutils/THANKS,v
retrieving revision 1.412
diff -b -u -2 -r1.412 THANKS
--- THANKS  16 Nov 2005 09:30:25 -0000  1.412
+++ THANKS  9 Dec 2005 13:42:50 -0000
@@ -152,4 +152,5 @@
 Fletcher Mattox                     fletcher@cs.utexas.edu
 Florin Iucha                        fiucha@hsys.mic.ro
+Francesco Montorsi                  fr_m@hotmail.com
 François Pinard                     pinard@iro.umontreal.ca
 Frank Adler                         fadler@allesklar.de
Index: src/ls.c
===================================================================
RCS file: /cvsroot/coreutils/coreutils/src/ls.c,v
retrieving revision 1.403
diff -b -u -2 -r1.403 ls.c
--- src/ls.c    17 Nov 2005 12:28:34 -0000  1.403
+++ src/ls.c    9 Dec 2005 13:49:09 -0000
@@ -592,4 +592,8 @@
 static bool immediate_dirs;

+/* True means that directories are grouped before files.  -e,--group-directories  */
+
+static bool group_dirs;
+
 /* Which files to ignore.  */

@@ -751,4 +755,5 @@
   {"directory", no_argument, NULL, 'd'},
   {"dired", no_argument, NULL, 'D'},
+  {"group-directories", no_argument, NULL, 'e'},
   {"full-time", no_argument, NULL, FULL_TIME_OPTION},
   {"human-readable", no_argument, NULL, 'h'},
@@ -1490,5 +1495,5 @@

   while ((c = getopt_long (argc, argv,
-              "abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1",
+               "abcdefghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1",
               long_options, NULL)) != -1)
     {
@@ -1511,4 +1516,8 @@
      break;

+    case 'e':
+      group_dirs = true;
+      break;
+
    case 'f':
      /* Same as enabling -a -U and disabling -l -s.  */
@@ -2728,4 +2737,11 @@
 }

+/* Returns true if the given fileinfo refers to a directory */
+static bool is_directory (const struct fileinfo *f)
+{
+  return f->filetype == directory || f->filetype == arg_directory;
+}
+
+
 #ifdef S_ISLNK

@@ -2810,6 +2826,5 @@
      order.  */
   for (i = files_index; i-- != 0; )
-    if ((files[i].filetype == directory || files[i].filetype == arg_directory)
-   && (!ignore_dot_and_dot_dot
+    if (is_directory(&files[i]) && (!ignore_dot_and_dot_dot
        || !basename_is_dot_or_dotdot (files[i].name)))
       {
@@ -2956,4 +2971,34 @@
 static int rev_str_extension (V a, V b) { return compstr_extension (b, a); }

+/* Groups directories at the beginning of the array */
+
+static inline int
+cmp_directories (V a, V b)
+{
+  bool a_isfolder = is_directory((struct fileinfo const *)a);
+  bool b_isfolder = is_directory((struct fileinfo const *)b);
+  if (a_isfolder && !b_isfolder)
+     return -1;        // a goes before b
+  else if (!a_isfolder && b_isfolder)
+     return 1;          // b goes before a
+
+  /* a and b are both files or both folders;
+     will be sorted later using the user-selected sortkey */
+  return 0;
+}
+
+int group_dirs_first()
+{
+  int i, n=0;
+  qsort (files, files_index, sizeof *files, cmp_directories);
+
+  /* now return the number of directories which are present in the files array */
+  for (i=0; i < files_index; i++)
+    if (is_directory(&files[i]))
+      n++;          /* found another directory */
+  return n;
+}
+
+
 /* Sort the files now in the table.  */

@@ -2962,4 +3007,9 @@
 {
   int (*func) (V, V);
+  int dirs;
+
+  /* do we have to do two separate sorts ? */
+  if (group_dirs)
+     dirs = group_dirs_first();

   /* Try strcoll.  If it fails, fall back on strcmp.  We can't safely
@@ -3040,4 +3090,9 @@
     }

+  if (group_dirs && dirs > 0) {
+    /* sort separately the directories and the files */
+    qsort (files, dirs, sizeof *files, func);
+    qsort (&files[dirs], files_index - dirs, sizeof *files, func);
+  } else
   qsort (files, files_index, sizeof *files, func);
 }
@@ -4136,4 +4191,7 @@
                                and do not dereference symbolic links\n\
   -D, --dired                generate output designed for Emacs' dired mode\n\
+"), stdout);
+      fputs(_("\
+  -e, --group-directories    group directories before files\n\
 "), stdout);
       fputs (_("\
