[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: a fix for color ls with wrapped lines.
From: |
Jim Meyering |
Subject: |
Re: a fix for color ls with wrapped lines. |
Date: |
Wed, 31 Dec 2008 19:09:12 +0100 |
Jan Engelhardt <address@hidden> wrote:
> On Wednesday 2008-12-31 13:06, Jim Meyering wrote:
>>>
>>> You have to use a long filename (not just z.foo) that wraps in the
>>> terminal. See the video at
>>> http://jengelh.medozas.de/files/coreutils7ls.ogv for details.
>>> Version used was v7.0-114-g921feef.
>>>
>>> Standard ./configure and (slightly abridged) make, as shown.
>>
>>I see now.
>>It doesn't even need to be last, if you run the ls
>>command from the "bottom" of the window:
>
> Right, all it needs is a "bgcolor still active" (inside
> \e[42m ... \e[0m) and a vertical scroll.
>
>>While the patch produces obviously better output in this case, the resulting
>>colorized ls output is always bigger by two bytes per colored file name.
>> (it also hard-codes the existing lc+no+rc escapes, which it'd be
>>better not to do, since they're user-settable)
>
> I do not have the patch in inbox or sent anymore (it was sent by Alexander
> anyway) - was not it three chars - "\e[K"?
>
> { LEN_STR_PAIR("\e[m\e[K") } /* ec */
It would have been three, but for the fact that it makes ls
emit "\e[m\e[K" in place of "\e[0m" (note the omitted "0").
>>Would one of you care to adjust the patch so the additional escape
>>sequence is emitted only when needed (i.e., when ls thinks a colored name
>>has wrapped)?
>
> How would ls know that? `stty cols` (and other ways of obtaining the
> column count) may very well emit 0 (can happen on serial or 'dumb'
> terminals) or a value that is not right (probably not happening).
It gets line_length from the TIOCGWINSZ ioctl, the COLUMNS envvar,
or the --width option.
Here's an alternate patch that seems to do the job.
But it may have bugs, because I did it far too quickly
and haven't reviewed it at all.
This will need at least tests corresponding to -1,
-l (two: the name itself spans, or the -> link_name crosses
the line_length limit), -C formats.
diff --git a/src/ls.c b/src/ls.c
index b03aebc..59d1fae 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -231,18 +231,21 @@ static size_t calculate_columns (bool by_columns);
static void print_current_files (void);
static void print_dir (char const *name, char const *realname,
bool command_line_arg);
-static void print_file_name_and_frills (const struct fileinfo *f);
+static size_t print_file_name_and_frills (const struct fileinfo *f,
+ size_t start_col);
static void print_horizontal (void);
static int format_user_width (uid_t u);
static int format_group_width (gid_t g);
static void print_long_format (const struct fileinfo *f);
static void print_many_per_line (void);
-static void print_name_with_quoting (const char *p, mode_t mode,
- int linkok, bool stat_ok,
- enum filetype type,
- struct obstack *stack, nlink_t nlink);
+static size_t print_name_with_quoting (const char *p, mode_t mode,
+ int linkok, bool stat_ok,
+ enum filetype type,
+ struct obstack *stack,
+ nlink_t nlink,
+ size_t start_col);
static void prep_non_filename_text (void);
-static void print_type_indicator (bool stat_ok, mode_t mode,
+static bool print_type_indicator (bool stat_ok, mode_t mode,
enum filetype type);
static void print_with_commas (void);
static void queue_directory (char const *name, char const *realname,
@@ -521,14 +524,15 @@ enum indicator_no
C_LEFT, C_RIGHT, C_END, C_RESET, C_NORM, C_FILE, C_DIR, C_LINK,
C_FIFO, C_SOCK,
C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC, C_DOOR, C_SETUID, C_SETGID,
- C_STICKY, C_OTHER_WRITABLE, C_STICKY_OTHER_WRITABLE, C_CAP, C_HARDLINK
+ C_STICKY, C_OTHER_WRITABLE, C_STICKY_OTHER_WRITABLE, C_CAP, C_HARDLINK,
+ C_CLR_TO_EOL
};
static const char *const indicator_name[]=
{
"lc", "rc", "ec", "rs", "no", "fi", "di", "ln", "pi", "so",
"bd", "cd", "mi", "or", "ex", "do", "su", "sg", "st",
- "ow", "tw", "ca", "hl", NULL
+ "ow", "tw", "ca", "hl", "cl", NULL
};
struct color_ext_type
@@ -563,6 +567,7 @@ static struct bin_str color_indicator[] =
{ LEN_STR_PAIR ("30;42") }, /* tw: ow w/ sticky: black on
green */
{ LEN_STR_PAIR ("30;41") }, /* ca: black on red */
{ LEN_STR_PAIR ("44;37") }, /* hl: white on blue */
+ { LEN_STR_PAIR ("\033[K") }, /* cl: clear to end of line */
};
/* FIXME: comment */
@@ -3284,7 +3289,7 @@ print_current_files (void)
case one_per_line:
for (i = 0; i < cwd_n_used; i++)
{
- print_file_name_and_frills (sorted_file[i]);
+ print_file_name_and_frills (sorted_file[i], 0);
putchar ('\n');
}
break;
@@ -3636,9 +3641,9 @@ print_long_format (const struct fileinfo *f)
}
DIRED_FPUTS (buf, stdout, p - buf);
- print_name_with_quoting (f->name, FILE_OR_LINK_MODE (f), f->linkok,
- f->stat_ok, f->filetype, &dired_obstack,
- f->stat.st_nlink);
+ size_t w = print_name_with_quoting (f->name, FILE_OR_LINK_MODE (f),
f->linkok,
+ f->stat_ok, f->filetype, &dired_obstack,
+ f->stat.st_nlink, p - buf);
if (f->filetype == symbolic_link)
{
@@ -3647,7 +3652,7 @@ print_long_format (const struct fileinfo *f)
DIRED_FPUTS_LITERAL (" -> ", stdout);
print_name_with_quoting (f->linkname, f->linkmode, f->linkok - 1,
f->stat_ok, f->filetype, NULL,
- f->stat.st_nlink);
+ f->stat.st_nlink, (p - buf) + w + 4);
if (indicator_style != none)
print_type_indicator (true, f->linkmode, unknown);
}
@@ -3822,10 +3827,11 @@ quote_name (FILE *out, const char *name, struct
quoting_options const *options,
return len;
}
-static void
+static size_t
print_name_with_quoting (const char *p, mode_t mode, int linkok,
bool stat_ok, enum filetype type,
- struct obstack *stack, nlink_t nlink)
+ struct obstack *stack, nlink_t nlink,
+ size_t start_col)
{
bool used_color_this_time
= (print_with_color
@@ -3834,7 +3840,8 @@ print_name_with_quoting (const char *p, mode_t mode, int
linkok,
if (stack)
PUSH_CURRENT_DIRED_POS (stack);
- dired_pos += quote_name (stdout, p, filename_quoting_options, NULL);
+ size_t width = quote_name (stdout, p, filename_quoting_options, NULL);
+ dired_pos += width;
if (stack)
PUSH_CURRENT_DIRED_POS (stack);
@@ -3843,7 +3850,11 @@ print_name_with_quoting (const char *p, mode_t mode, int
linkok,
{
process_signals ();
prep_non_filename_text ();
+ if (start_col / line_length != (start_col + width - 1) / line_length)
+ put_indicator (&color_indicator[C_CLR_TO_EOL]);
}
+
+ return width;
}
static void
@@ -3863,8 +3874,8 @@ prep_non_filename_text (void)
Also print file size, inode number, and filetype indicator character,
as requested by switches. */
-static void
-print_file_name_and_frills (const struct fileinfo *f)
+static size_t
+print_file_name_and_frills (const struct fileinfo *f, size_t start_col)
{
char buf[MAX (LONGEST_HUMAN_READABLE + 1, INT_BUFSIZE_BOUND (uintmax_t))];
@@ -3880,11 +3891,14 @@ print_file_name_and_frills (const struct fileinfo *f)
if (print_scontext)
printf ("%*s ", format == with_commas ? 0 : scontext_width, f->scontext);
- print_name_with_quoting (f->name, FILE_OR_LINK_MODE (f), f->linkok,
- f->stat_ok, f->filetype, NULL, f->stat.st_nlink);
+ size_t width = print_name_with_quoting (f->name, FILE_OR_LINK_MODE (f),
+ f->linkok, f->stat_ok, f->filetype,
+ NULL, f->stat.st_nlink, start_col);
if (indicator_style != none)
- print_type_indicator (f->stat_ok, f->stat.st_mode, f->filetype);
+ width += print_type_indicator (f->stat_ok, f->stat.st_mode, f->filetype);
+
+ return width;
}
/* Given these arguments describing a file, return the single-byte
@@ -3921,12 +3935,13 @@ get_type_indicator (bool stat_ok, mode_t mode, enum
filetype type)
return c;
}
-static void
+static bool
print_type_indicator (bool stat_ok, mode_t mode, enum filetype type)
{
char c = get_type_indicator (stat_ok, mode, type);
if (c)
DIRED_PUTCHAR (c);
+ return !!c;
}
#ifdef HAVE_CAP
@@ -4128,7 +4143,7 @@ print_many_per_line (void)
struct fileinfo const *f = sorted_file[filesno];
size_t name_length = length_of_file_name_and_frills (f);
size_t max_name_length = line_fmt->col_arr[col++];
- print_file_name_and_frills (f);
+ print_file_name_and_frills (f, pos);
filesno += rows;
if (filesno >= cwd_n_used)
@@ -4153,7 +4168,7 @@ print_horizontal (void)
size_t max_name_length = line_fmt->col_arr[0];
/* Print first entry. */
- print_file_name_and_frills (f);
+ print_file_name_and_frills (f, 0);
/* Now the rest. */
for (filesno = 1; filesno < cwd_n_used; ++filesno)
@@ -4172,7 +4187,7 @@ print_horizontal (void)
}
f = sorted_file[filesno];
- print_file_name_and_frills (f);
+ print_file_name_and_frills (f, pos);
name_length = length_of_file_name_and_frills (f);
max_name_length = line_fmt->col_arr[col];
@@ -4210,7 +4225,7 @@ print_with_commas (void)
putchar (separator);
}
- print_file_name_and_frills (f);
+ print_file_name_and_frills (f, pos);
pos += len;
}
putchar ('\n');