};
#define APPEND_CHAR(C) obstack_1grow (&lsc_obstack, C)
-#define APPEND_TWO_CHAR_STRING(S) \
- do \
- { \
- APPEND_CHAR (S[0]); \
- APPEND_CHAR (S[1]); \
- } \
- while (0)
/* Accumulate in this obstack the value for the LS_COLORS environment
variable. */
};
verify (ARRAY_CARDINALITY (slack_codes) == ARRAY_CARDINALITY (ls_codes));
+/* Whether to output escaped ls color codes for display. */
+static bool print_ls_colors;
+
+/* For long options that have no equivalent short option, use a
+ non-character as a pseudo short option, starting with CHAR_MAX + 1. */
+enum
+{
+ PRINT_LS_COLORS_OPTION = CHAR_MAX + 1,
+};
+
static struct option const long_options[] =
{
{"bourne-shell", no_argument, NULL, 'b'},
{"csh", no_argument, NULL, 'c'},
{"c-shell", no_argument, NULL, 'c'},
{"print-database", no_argument, NULL, 'p'},
+ {"print-ls-colors", no_argument, NULL, PRINT_LS_COLORS_OPTION},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
-b, --sh, --bourne-shell output Bourne shell code to set LS_COLORS\n\
-c, --csh, --c-shell output C shell code to set LS_COLORS\n\
-p, --print-database output defaults\n\
+ --print-ls-colors output fully escaped colors for display\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
*arg = ximemdup0 (arg_start, p - arg_start);
}
-/* FIXME: Write a string to standard out, while watching for "dangerous"
- sequences like unescaped : and = characters. */
+/* Accumulate STR to LS_COLORS data.
+ If outputting shell syntax, then escape appropriately. */
static void
append_quoted (char const *str)
while (*str != '\0')
{
- switch (*str)
- {
- case '\'':
- APPEND_CHAR ('\'');
- APPEND_CHAR ('\\');
- APPEND_CHAR ('\'');
- need_backslash = true;
- break;
-
- case '\\':
- case '^':
- need_backslash = !need_backslash;
- break;
-
- case ':':
- case '=':
- if (need_backslash)
+ if (! print_ls_colors)
+ switch (*str)
+ {
+ case '\'':
+ APPEND_CHAR ('\'');
APPEND_CHAR ('\\');
- FALLTHROUGH;
+ APPEND_CHAR ('\'');
+ need_backslash = true;
+ break;
- default:
- need_backslash = true;
- break;
- }
+ case '\\':
+ case '^':
+ need_backslash = !need_backslash;
+ break;
+
+ case ':':
+ case '=':
+ if (need_backslash)
+ APPEND_CHAR ('\\');
+ FALLTHROUGH;
+
+ default:
+ need_backslash = true;
+ break;
+ }
APPEND_CHAR (*str);
++str;
}
}
+/* Accumulate entry to LS_COLORS data.
+ Use shell syntax unless PRINT_LS_COLORS is set. */
+
+static void
+append_entry (char prefix, char const *item, char const *arg)
+{
+ if (print_ls_colors)
+ {
+ append_quoted ("\x1B[");
+ append_quoted (arg);
+ APPEND_CHAR ('m');
+ }
+ if (prefix)
+ APPEND_CHAR (prefix);
+ append_quoted (item);
+ APPEND_CHAR (print_ls_colors ? '\t' : '=');
+ append_quoted (arg);
+ if (print_ls_colors)
+ append_quoted ("\x1B[0m");
+ APPEND_CHAR (print_ls_colors ? '\n' : ':');
+}
+
/* Read the file open on FP (with name FILENAME). First, look for a
'TERM name' directive where name matches the current terminal type.
Once found, translate and accumulate the associated directives onto
if (state != ST_TERMNO)
{
if (keywd[0] == '.')
- {
- APPEND_CHAR ('*');
- append_quoted (keywd);
- APPEND_CHAR ('=');
- append_quoted (arg);
- APPEND_CHAR (':');
- }
+ append_entry ('*', keywd, arg);
else if (keywd[0] == '*')
- {
- append_quoted (keywd);
- APPEND_CHAR ('=');
- append_quoted (arg);
- APPEND_CHAR (':');
- }
+ append_entry (0, keywd, arg);
else if (c_strcasecmp (keywd, "OPTIONS") == 0
|| c_strcasecmp (keywd, "COLOR") == 0
|| c_strcasecmp (keywd, "EIGHTBIT") == 0)
break;
if (slack_codes[i] != NULL)
- {
- APPEND_TWO_CHAR_STRING (ls_codes[i]);
- APPEND_CHAR ('=');
- append_quoted (arg);
- APPEND_CHAR (':');
- }
+ append_entry (0, ls_codes[i], arg);
else
- {
- unrecognized = true;
- }
+ unrecognized = true;
}
}
else
- {
- unrecognized = true;
- }
+ unrecognized = true;
}
if (unrecognized && (state == ST_TERMSURE || state == ST_TERMYES))
print_database = true;
break;
+ case PRINT_LS_COLORS_OPTION:
+ print_ls_colors = true;
+ break;
+
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
/* It doesn't make sense to use --print with either of
--bourne or --c-shell. */
- if (print_database && syntax != SHELL_SYNTAX_UNKNOWN)
+ if ((print_database | print_ls_colors) && syntax != SHELL_SYNTAX_UNKNOWN)
+ {
+ error (0, 0,
+ _("the options to output non shell syntax,\n"
+ "and to select a shell syntax are mutually exclusive"));
+ usage (EXIT_FAILURE);
+ }
+
+ if (print_database && print_ls_colors)
{
error (0, 0,
- _("the options to output dircolors' internal database and\n"
- "to select a shell syntax are mutually exclusive"));
+ _("options --print-database and --print-ls-colors "
+ "are mutually exclusive"));
usage (EXIT_FAILURE);
}
if ((!print_database) < argc)
{
- error (0, 0, _("extra operand %s"), quote (argv[!print_database]));
+ error (0, 0, _("extra operand %s"),
+ quote (argv[!print_database]));
if (print_database)
fprintf (stderr, "%s\n",
_("file operands cannot be combined with "
else
{
/* If shell syntax was not explicitly specified, try to guess it. */
- if (syntax == SHELL_SYNTAX_UNKNOWN)
+ if (syntax == SHELL_SYNTAX_UNKNOWN && ! print_ls_colors)
{
syntax = guess_shell_syntax ();
if (syntax == SHELL_SYNTAX_UNKNOWN)
prefix = "setenv LS_COLORS '";
suffix = "'\n";
}
- fputs (prefix, stdout);
+ if (! print_ls_colors)
+ fputs (prefix, stdout);
fwrite (s, 1, len, stdout);
- fputs (suffix, stdout);
+ if (! print_ls_colors)
+ fputs (suffix, stdout);
}
}
['term-4', '-b', {IN => "TERM N*match\nowt 40;33\n"},
{OUT => "LS_COLORS='';\nexport LS_COLORS\n"}],
+ ['print-clash1', '-p', '--print-ls',
+ {ERR => "dircolors: options --print-database and --print-ls-colors " .
+ "are mutually exclusive\n" .
+ "Try 'dircolors --help' for more information.\n"},
+ {EXIT => 1}],
+ ['print-clash2', '-b', '--print-database',
+ {ERR => "dircolors: the options to output non shell syntax,\n" .
+ "and to select a shell syntax are mutually exclusive\n" .
+ "Try 'dircolors --help' for more information.\n"},
+ {EXIT => 1}],
+
+ ['print-ls-colors', '--print-ls-colors', {IN => "OWT 40;33\n"},
+ {OUT => "\x1B[40;33mtw\t40;33\x1B[0m\n"}],
+
# CAREFUL: always specify the -b option, unless explicitly testing
- # for csh syntax output.
+ # for csh syntax output, or --print-ls-color output.
);
my $save_temps = $ENV{DEBUG};