bug-coreutils
[Top][All Lists]
Advanced

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

Re: [PATCH] Adding --hide option to ls


From: Paul Eggert
Subject: Re: [PATCH] Adding --hide option to ls
Date: Sun, 26 Sep 2004 16:00:24 -0700
User-agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux)

Thanks for that suggestion.  I implemented it somewhat differently,
partly in an attempt to make the code a bit clearer, and installed this:

2004-09-26  Paul Eggert  <address@hidden>

        Add support for ls --hide.  Idea suggested by Bardur Arantsson.
        * NEWS: Document this.
        * doc/coreutils.texi (ls invocation): Likewise.
        * src/ls.c (file_ignored): Renamed from file_interesting, with
        inverted return value.  Accept the file name, not a struct dirent *.
        All uses changed.  Avoid the expense of calling fnmatch if the
        file is ignorable due to leading '.'.
        (all_files, really_all_files): Removed; replaced by:
        (ignore): New variable.  All uses changed.
        (IGNORE_DEFAULT, IGNORE_DOT_AND_DOTDOT, IGNORE_MINIMAL, HIDE_OPTION):
        New constants.
        (hide_patterns): New variable.
        (long_options, decode_switches, file_ignored, usage):
        Add support for --hide.
        (patterns_match): New function.
        (usage): Replace "hide" with "ignore" in explanation, to avoid
        confusion.

Index: NEWS
===================================================================
RCS file: /fetish/cu/NEWS,v
retrieving revision 1.238
diff -p -u -r1.238 NEWS
--- NEWS        24 Sep 2004 23:32:37 -0000      1.238
+++ NEWS        26 Sep 2004 22:54:20 -0000
@@ -196,6 +196,11 @@ GNU coreutils NEWS                      
   echo -e '\xHH' now outputs a byte whose hexadecimal value is HH,
   for compatibility with bash.
 
+  ls has a new --hide=PATTERN option that behaves like
+  --ignore=PATTERN, except that it is overridden by -a or -A.
+  This can be useful for aliases, e.g., if lh is an alias for
+  "ls --hide='*~'", then "lh -A" lists the file "README~".
+
   In the following cases POSIX allows the default GNU behavior,
   so when POSIXLY_CORRECT is set:
 
Index: doc/coreutils.texi
===================================================================
RCS file: /fetish/cu/doc/coreutils.texi,v
retrieving revision 1.215
diff -p -u -r1.215 coreutils.texi
--- doc/coreutils.texi  24 Sep 2004 23:33:13 -0000      1.215
+++ doc/coreutils.texi  26 Sep 2004 22:54:23 -0000
@@ -5265,8 +5265,9 @@ Also see @ref{Common options}.
 @subsection Which files are listed
 
 These options determine which files @command{ls} lists information for.
-By default, any files and the contents of any directories on the command
-line are shown.
+By default, @command{ls} lists files and the contents of any
+directories on the command line, except that in directories it ignores
+files whose names start with @samp{.}.
 
 @table @samp
 
@@ -5274,21 +5275,23 @@ line are shown.
 @itemx --all
 @opindex -a
 @opindex --all
-List all files in directories, including files that start with @samp{.}.
+In directories, do not ignore file names that start with @samp{.}.
 
 @item -A
 @itemx --almost-all
 @opindex -A
 @opindex --almost-all
-List all files in directories except for @file{.} and @file{..}.
+In directories, do not ignore all file names that start with @samp{.};
+ignore only @file{.} and @file{..}.  The @option{--all} (@option{-a})
+option overrides this option.
 
 @item -B
 @itemx --ignore-backups
 @opindex -B
 @opindex --ignore-backups
 @cindex backup files, ignoring
-Do not list files that end with @samp{~}, unless they are given on the
-command line.
+In directories, ignore files that end with @samp{~}.  This option is
+equivalent to @samp{--ignore='*~' --ignore='.*~'}.
 
 @item -d
 @itemx --directory
@@ -5324,12 +5327,26 @@ option has been specified (@option{--cla
 @option{--dereference} (@option{-L}), or
 @option{--dereference-command-line} (@option{-H})).
 
address@hidden -I PATTERN
address@hidden --ignore=PATTERN
address@hidden --hide=PATTERN
address@hidden address@hidden
+In directories, ignore files whose names match the shell pattern
address@hidden, unless the @option{--all} (@option{-a}) or
address@hidden (@option{-A}) is also given.  This
+option acts like @address@hidden except that it has no
+effect if @option{--all} (@option{-a}) or @option{--almost-all}
+(@option{-A}) is also given.
+
+This option can be useful in shell aliases.  For example, if
address@hidden is an alias for @samp{ls --hide='*~'} and @command{ly} is
+an alias for @samp{ls --ignore='*~'}, then the command @samp{lx -A}
+lists the file @file{README~} even though @samp{ly -A} would not.
+
address@hidden -I @var{pattern}
address@hidden address@hidden
 @opindex -I
 @opindex address@hidden
-Do not list files whose names match the shell pattern (not regular
-expression) @var{pattern} unless they are given on the command line.  As
+In directories, ignore files whose names match the shell pattern
+(not regular expression) @var{pattern}.  As
 in the shell, an initial @samp{.} in a file name does not match a
 wildcard at the start of @var{pattern}.  Sometimes it is useful
 to give this option several times.  For example,
Index: src/ls.c
===================================================================
RCS file: /fetish/cu/src/ls.c,v
retrieving revision 1.363
diff -p -u -r1.363 ls.c
--- src/ls.c    26 Sep 2004 07:10:53 -0000      1.363
+++ src/ls.c    26 Sep 2004 22:54:24 -0000
@@ -232,7 +232,7 @@ static size_t quote_name (FILE *out, con
                          size_t *width);
 static char *make_link_path (const char *path, const char *linkname);
 static int decode_switches (int argc, char **argv);
-static bool file_interesting (const struct dirent *next);
+static bool file_ignored (char const *name);
 static uintmax_t gobble_file (const char *name, enum filetype type,
                              bool explicit_arg, const char *dirname);
 static void print_color_indicator (const char *name, mode_t mode, int linkok);
@@ -572,17 +572,23 @@ static bool recursive;
 
 static bool immediate_dirs;
 
-/* True means don't omit files whose names start with `.'.  -A  */
+/* Which files to ignore.  */
 
-static bool all_files;
-
-/* True means don't omit files `.' and `..'
-   This flag implies `all_files'.  -a  */
-
-static bool really_all_files;
+static enum
+{
+  /* Ignore files whose names start with `.', and files specified by
+     --hide and --ignore.  */
+  IGNORE_DEFAULT,
+  
+  /* Ignore `.', `..', and files specified by --ignore.  */
+  IGNORE_DOT_AND_DOTDOT,
+     
+  /* Ignore only files specified by --ignore.  */
+  IGNORE_MINIMAL
+} ignore;
 
 /* A linked list of shell-style globbing patterns.  If a non-argument
-   file name matches any of these patterns, it is omitted.
+   file name matches any of these patterns, it is ignored.
    Controlled by -I.  Multiple -I options accumulate.
    The -B option adds `*~' and `.*~' to this list.  */
 
@@ -594,6 +600,10 @@ struct ignore_pattern
 
 static struct ignore_pattern *ignore_patterns;
 
+/* Similar to IGNORE_PATTERNS, except that -a or -A causes this
+   variable itself to be ignored.  */
+static struct ignore_pattern *hide_patterns;
+
 /* True means output nongraphic chars in file names as `?'.
    (-q, --hide-control-chars)
    qmark_funny_chars and the quoting style (-Q, --quoting-style=WORD) are
@@ -682,6 +692,7 @@ enum
   DEREFERENCE_COMMAND_LINE_SYMLINK_TO_DIR_OPTION,
   FORMAT_OPTION,
   FULL_TIME_OPTION,
+  HIDE_OPTION,
   INDICATOR_STYLE_OPTION,
   QUOTING_STYLE_OPTION,
   SHOW_CONTROL_CHARS_OPTION,
@@ -715,6 +726,7 @@ static struct option const long_options[
   {"dereference-command-line", no_argument, 0, 'H'},
   {"dereference-command-line-symlink-to-dir", no_argument, 0,
    DEREFERENCE_COMMAND_LINE_SYMLINK_TO_DIR_OPTION},
+  {"hide", required_argument, 0, HIDE_OPTION},
   {"ignore", required_argument, 0, 'I'},
   {"indicator-style", required_argument, 0, INDICATOR_STYLE_OPTION},
   {"dereference", no_argument, 0, 'L'},
@@ -1348,9 +1360,9 @@ decode_switches (int argc, char **argv)
   dereference = DEREF_UNDEFINED;
   recursive = false;
   immediate_dirs = false;
-  all_files = false;
-  really_all_files = false;
-  ignore_patterns = 0;
+  ignore = IGNORE_DEFAULT;
+  ignore_patterns = NULL;
+  hide_patterns = NULL;
 
   /* FIXME: put this in a function.  */
   {
@@ -1432,8 +1444,7 @@ decode_switches (int argc, char **argv)
       switch (c)
        {
        case 'a':
-         all_files = true;
-         really_all_files = true;
+         ignore = IGNORE_MINIMAL;
          break;
 
        case 'b':
@@ -1450,8 +1461,7 @@ decode_switches (int argc, char **argv)
 
        case 'f':
          /* Same as enabling -a -U and disabling -l -s.  */
-         all_files = true;
-         really_all_files = true;
+         ignore = IGNORE_MINIMAL;
          sort_type = sort_none;
          sort_type_specified = true;
          /* disable -l */
@@ -1544,8 +1554,8 @@ decode_switches (int argc, char **argv)
          break;
 
        case 'A':
-         really_all_files = false;
-         all_files = true;
+         if (ignore == IGNORE_DEFAULT)
+           ignore = IGNORE_DOT_AND_DOTDOT;
          break;
 
        case 'B':
@@ -1633,6 +1643,15 @@ decode_switches (int argc, char **argv)
           print_author = true;
           break;
 
+       case HIDE_OPTION:
+         {
+           struct ignore_pattern *hide = xmalloc (sizeof *hide);
+           hide->pattern = optarg;
+           hide->next = hide_patterns;
+           hide_patterns = hide;
+         }
+         break;
+
        case SORT_OPTION:
          sort_type = XARGMATCH ("--sort", optarg, sort_args, sort_types);
          sort_type_specified = true;
@@ -2245,7 +2264,7 @@ print_dir (const char *name, const char 
          break;
        }
 
-      if (file_interesting (next))
+      if (! file_ignored (next->d_name))
        {
          enum filetype type = unknown;
 
@@ -2326,25 +2345,29 @@ add_ignore_pattern (const char *pattern)
   ignore_patterns = ignore;
 }
 
-/* Return true if the file in `next' should be listed.  */
+/* Return true if one of the PATTERNS matches FILE.  */
 
 static bool
-file_interesting (const struct dirent *next)
+patterns_match (struct ignore_pattern const *patterns, char const *file)
 {
-  register struct ignore_pattern *ignore;
+  struct ignore_pattern const *p;
+  for (p = patterns; p; p = p->next)
+    if (fnmatch (p->pattern, file, FNM_PERIOD) == 0)
+      return true;
+  return false;
+}
 
-  for (ignore = ignore_patterns; ignore; ignore = ignore->next)
-    if (fnmatch (ignore->pattern, next->d_name, FNM_PERIOD) == 0)
-      return false;
-
-  if (really_all_files
-      || next->d_name[0] != '.'
-      || (all_files
-         && next->d_name[1] != '\0'
-         && (next->d_name[1] != '.' || next->d_name[2] != '\0')))
-    return true;
+/* Return true if FILE should be ignored.  */
 
-  return false;
+static bool
+file_ignored (char const *name)
+{
+  return ((ignore != IGNORE_MINIMAL
+          && name[0] == '.'
+          && (ignore == IGNORE_DEFAULT || ! name[1 + (name[1] == '.')]))
+         || (ignore == IGNORE_DEFAULT
+             && patterns_match (hide_patterns, name))
+         || patterns_match (ignore_patterns, name));
 }
 
 /* POSIX requires that a file size be printed without a sign, even
@@ -3997,7 +4020,7 @@ Sort entries alphabetically if none of -
 Mandatory arguments to long options are mandatory for short options too.\n\
 "), stdout);
       fputs (_("\
-  -a, --all                  do not hide entries starting with .\n\
+  -a, --all                  do not ignore entries starting with .\n\
   -A, --almost-all           do not list implied . and ..\n\
       --author               print the author of each file\n\
   -b, --escape               print octal escapes for nongraphic characters\n\
@@ -4035,6 +4058,8 @@ Mandatory arguments to long options are 
       --dereference-command-line-symlink-to-dir\n\
                              follow each command line symbolic link\n\
                                that points to a directory\n\
+      --hide=PATTERN         do not list implied entries matching shell 
PATTERN\n\
+                               (overridden by -a or -A)\n\
 "), stdout);
       fputs (_("\
       --indicator-style=WORD append indicator with style WORD to entry 
names:\n\




reply via email to

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