--- ls.c Sun Apr 29 11:42:47 2001 +++ ls.c.dirsfirstrangein Sat Nov 3 20:36:29 2001 @@ -293,6 +293,10 @@ const struct fileinfo *file2)); static int rev_cmp_extension PARAMS ((const struct fileinfo *file2, const struct fileinfo *file1)); +static int compare_dirsfirst PARAMS ((const struct fileinfo *file1, + const struct fileinfo *file2)); +static int rev_cmp_dirsfirst PARAMS ((const struct fileinfo *file2, + const struct fileinfo *file1)); static int compare_version PARAMS ((const struct fileinfo *file1, const struct fileinfo *file2)); static int rev_cmp_version PARAMS ((const struct fileinfo *file2, @@ -422,7 +426,7 @@ static int full_time; -/* The file characteristic to sort by. Controlled by -t, -S, -U, -X, -v. */ +/* The file characteristic to sort by. Controlled by -t, -S, -U, -X, -v, -e. */ enum sort_type { @@ -431,7 +435,8 @@ sort_extension, /* -X */ sort_time, /* -t */ sort_size, /* -S */ - sort_version /* -v */ + sort_version, /* -v */ + sort_dirsfirst /* -e */ }; static enum sort_type sort_type; @@ -720,12 +725,12 @@ static char const *const sort_args[] = { - "none", "time", "size", "extension", "version", 0 + "none", "time", "size", "extension", "version", "dirsfirst", 0 }; static enum sort_type const sort_types[] = { - sort_none, sort_time, sort_size, sort_extension, sort_version + sort_none, sort_time, sort_size, sort_extension, sort_version, sort_dirsfirst }; static char const *const time_args[] = @@ -771,6 +776,8 @@ for the separating white space. */ #define MIN_COLUMN_WIDTH 3 +/* Default sorting function is strcoll(), considering the locale. */ +static int (*strcmpfunc)() = strcoll; /* This zero-based index is used solely with the --dired option. When that option is in effect, this counter is incremented for each @@ -877,7 +884,7 @@ } format_needs_stat = sort_type == sort_time || sort_type == sort_size - || format == long_format + || sort_type == sort_dirsfirst || format == long_format || trace_links || trace_dirs || print_block_size || print_inode; format_needs_type = (format_needs_stat == 0 && (print_with_color || indicator_style != none)); @@ -1076,7 +1083,7 @@ } while ((c = getopt_long (argc, argv, - "abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1", + "abcdefghijklmnopqrstuvw:xABCDFGHI:LNQRST:UX1", long_options, NULL)) != -1) { switch (c) @@ -1101,6 +1108,11 @@ immediate_dirs = 1; break; + case 'e': + sort_type = sort_dirsfirst; + sort_type_specified = 1; + break; + case 'f': /* Same as enabling -a -U and disabling -l -s. */ all_files = 1; @@ -1136,6 +1148,10 @@ print_inode = 1; break; + case 'j': + strcmpfunc = strcasecmp; + break; + case 'k': output_block_size = 1024; break; @@ -2169,6 +2185,9 @@ case sort_version: func = sort_reverse ? rev_cmp_version : compare_version; break; + case sort_dirsfirst: + func = sort_reverse ? rev_cmp_dirsfirst : compare_dirsfirst; + break; default: abort (); } @@ -2265,7 +2284,7 @@ static int compare_name (const struct fileinfo *file1, const struct fileinfo *file2) { - return strcoll (file1->name, file2->name); + return strcmpfunc (file1->name, file2->name); //strcoll } static int @@ -2317,6 +2336,22 @@ return cmp; } +static int +compare_dirsfirst (const struct fileinfo *file1, const struct fileinfo *file2) +{ + if (S_ISDIR(file1->stat.st_mode) == S_ISDIR(file2->stat.st_mode)) + return compare_name (file1, file2); + return S_ISDIR(file1->stat.st_mode) ? -1 : 1; +} + +static int +rev_cmp_dirsfirst (const struct fileinfo *file2, const struct fileinfo *file1) +{ + if (S_ISDIR(file1->stat.st_mode) == S_ISDIR(file2->stat.st_mode)) + return compare_name (file1, file2); + return S_ISDIR(file1->stat.st_mode) ? -1 : 1; +} + /* List all the files now in the table. */ static void @@ -3268,6 +3303,7 @@ types. WHEN may be `never', `always', or `auto'\n\ -d, --directory list directory entries instead of contents\n\ -D, --dired generate output designed for Emacs' dired mode\n\ + -e sort alphabetically with directories first\n\ -f do not sort, enable -aU, disable -lst\n\ -F, --classify append indicator (one of */=@|) to entries\n\ --format=WORD across -x, commas -m, horizontal -x, long -l,\n\ @@ -3284,6 +3320,7 @@ --indicator-style=WORD append indicator with style WORD to entry names:\n\ none (default), classify (-F), file-type (-p)\n\ -i, --inode print index number of each file\n\ + -j sort alphabetically, ranging in noncapitals\n\ -I, --ignore=PATTERN do not list implied entries matching shell PATTERN\n\ -k, --kilobytes like --block-size=1024\n\ -l use a long listing format\n\ @@ -3307,7 +3344,7 @@ printf (_("\ -S sort by file size\n\ --sort=WORD extension -X, none -U, size -S, time -t,\n\ - version -v\n\ + version -v, dirsfirst -e\n\ status -c, time -t, atime -u, access -u, use -u\n\ --time=WORD show time as WORD instead of modification time:\n\ atime, access, use, ctime or status; use\n\