watch: enhancing ANSI color & style support
This commit adds support for background colors and additional ANSI styles (faint, italic, underlined, blinking, inversed).
This commit is contained in:
parent
a0561fb4eb
commit
b3e36c552b
2
watch.1
2
watch.1
@ -53,7 +53,7 @@ Exit when the output of
|
|||||||
changes.
|
changes.
|
||||||
.TP
|
.TP
|
||||||
\fB\-c\fR, \fB\-\-color\fR
|
\fB\-c\fR, \fB\-\-color\fR
|
||||||
Interpret ANSI color sequences.
|
Interpret ANSI color and style sequences.
|
||||||
.TP
|
.TP
|
||||||
\fB\-x\fR, \fB\-\-exec\fR
|
\fB\-x\fR, \fB\-\-exec\fR
|
||||||
.I command
|
.I command
|
||||||
|
113
watch.c
113
watch.c
@ -89,7 +89,7 @@ static void __attribute__ ((__noreturn__))
|
|||||||
_(" %s [options] command\n"), program_invocation_short_name);
|
_(" %s [options] command\n"), program_invocation_short_name);
|
||||||
fputs(USAGE_OPTIONS, out);
|
fputs(USAGE_OPTIONS, out);
|
||||||
fputs(_(" -b, --beep beep if command has a non-zero exit\n"), out);
|
fputs(_(" -b, --beep beep if command has a non-zero exit\n"), out);
|
||||||
fputs(_(" -c, --color interpret ANSI color sequences\n"), out);
|
fputs(_(" -c, --color interpret ANSI color and style sequences\n"), out);
|
||||||
fputs(_(" -d, --differences[=<permanent>]\n"
|
fputs(_(" -d, --differences[=<permanent>]\n"
|
||||||
" highlight changes between updates\n"), out);
|
" highlight changes between updates\n"), out);
|
||||||
fputs(_(" -e, --errexit exit if command has a non-zero exit\n"), out);
|
fputs(_(" -e, --errexit exit if command has a non-zero exit\n"), out);
|
||||||
@ -106,34 +106,90 @@ static void __attribute__ ((__noreturn__))
|
|||||||
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
|
exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nr_of_colors;
|
||||||
|
static int attributes;
|
||||||
|
static int fg_col;
|
||||||
|
static int bg_col;
|
||||||
|
|
||||||
static void init_ansi_colors(void)
|
static void init_ansi_colors(void)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
short ncurses_colors[] = {
|
short ncurses_colors[] = {
|
||||||
COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
|
COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
|
||||||
COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE
|
COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE
|
||||||
};
|
};
|
||||||
|
|
||||||
for (i = 0; i < 8; i++)
|
nr_of_colors = sizeof(ncurses_colors) / sizeof(short);
|
||||||
init_pair(i + 1, ncurses_colors[i], -1);
|
|
||||||
|
for (bg_col = 0; bg_col < nr_of_colors; bg_col++)
|
||||||
|
for (fg_col = 0; fg_col < nr_of_colors; fg_col++)
|
||||||
|
init_pair(bg_col * nr_of_colors + fg_col + 1, ncurses_colors[fg_col], ncurses_colors[bg_col]);
|
||||||
|
|
||||||
|
/* default settings */
|
||||||
|
attributes = A_NORMAL;
|
||||||
|
fg_col = COLOR_WHITE;
|
||||||
|
bg_col = COLOR_BLACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void set_ansi_attribute(const int attrib)
|
static void set_ansi_attribute(const int attrib)
|
||||||
{
|
{
|
||||||
switch (attrib) {
|
switch (attrib) {
|
||||||
case -1:
|
case -1: /* restore last settings */
|
||||||
return;
|
break;
|
||||||
case 0:
|
case 0: /* restore default settings */
|
||||||
standend();
|
attributes = A_NORMAL;
|
||||||
return;
|
fg_col = COLOR_WHITE;
|
||||||
case 1:
|
bg_col = COLOR_BLACK;
|
||||||
attrset(A_BOLD);
|
break;
|
||||||
return;
|
case 1: /* set bold / increased intensity */
|
||||||
}
|
attributes |= A_BOLD;
|
||||||
if (attrib >= 30 && attrib <= 37) {
|
break;
|
||||||
color_set(attrib - 29, NULL);
|
case 2: /* set decreased intensity (if supported) */
|
||||||
return;
|
attributes |= A_DIM;
|
||||||
|
break;
|
||||||
|
#ifdef A_ITALIC
|
||||||
|
case 3: /* set italic (if supported) */
|
||||||
|
attributes |= A_ITALIC;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case 4: /* set underline */
|
||||||
|
attributes |= A_UNDERLINE;
|
||||||
|
break;
|
||||||
|
case 5: /* set blinking */
|
||||||
|
attributes |= A_BLINK;
|
||||||
|
break;
|
||||||
|
case 7: /* set inversed */
|
||||||
|
attributes |= A_REVERSE;
|
||||||
|
break;
|
||||||
|
case 21: /* unset bold / increased intensity */
|
||||||
|
attributes &= ~A_BOLD;
|
||||||
|
break;
|
||||||
|
case 22: /* unset bold / any intensity modifier */
|
||||||
|
attributes &= ~(A_BOLD | A_DIM);
|
||||||
|
break;
|
||||||
|
#ifdef A_ITALIC
|
||||||
|
case 23: /* unset italic */
|
||||||
|
attributes &= A_ITALIC;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case 24: /* unset underline */
|
||||||
|
attributes &= ~A_UNDERLINE;
|
||||||
|
break;
|
||||||
|
case 25: /* unset blinking */
|
||||||
|
attributes &= ~A_BLINK;
|
||||||
|
break;
|
||||||
|
case 27: /* unset inversed */
|
||||||
|
attributes &= ~A_REVERSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (attrib >= 30 && attrib <= 37) { /* set foreground color */
|
||||||
|
fg_col = attrib - 30;
|
||||||
|
} else if (attrib >= 40 && attrib <= 47) { /* set background color */
|
||||||
|
bg_col = attrib - 40;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attrset(attributes | COLOR_PAIR(bg_col * nr_of_colors + fg_col + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process_ansi(FILE * fp)
|
static void process_ansi(FILE * fp)
|
||||||
@ -414,7 +470,8 @@ static int run_command(char *restrict command, char **restrict command_argv)
|
|||||||
xerr(5, _("fdopen"));
|
xerr(5, _("fdopen"));
|
||||||
|
|
||||||
for (y = show_title; y < height; y++) {
|
for (y = show_title; y < height; y++) {
|
||||||
int eolseen = 0, tabpending = 0;
|
int eolseen = 0, tabpending = 0, tabwaspending;
|
||||||
|
set_ansi_attribute(-1);
|
||||||
#ifdef WITH_WATCH8BIT
|
#ifdef WITH_WATCH8BIT
|
||||||
wint_t carry = WEOF;
|
wint_t carry = WEOF;
|
||||||
#endif
|
#endif
|
||||||
@ -426,6 +483,10 @@ static int run_command(char *restrict command, char **restrict command_argv)
|
|||||||
#endif
|
#endif
|
||||||
int attr = 0;
|
int attr = 0;
|
||||||
|
|
||||||
|
if (tabwaspending && (flags & WATCH_COLOR))
|
||||||
|
set_ansi_attribute(-1);
|
||||||
|
tabwaspending = 0;
|
||||||
|
|
||||||
if (!eolseen) {
|
if (!eolseen) {
|
||||||
/* if there is a tab pending, just
|
/* if there is a tab pending, just
|
||||||
* spit spaces until the next stop
|
* spit spaces until the next stop
|
||||||
@ -475,16 +536,25 @@ static int run_command(char *restrict command, char **restrict command_argv)
|
|||||||
carry = c; /* character on the next line */
|
carry = c; /* character on the next line */
|
||||||
continue; /* because it won't fit here */
|
continue; /* because it won't fit here */
|
||||||
}
|
}
|
||||||
if (c == WEOF || c == L'\n' || c == L'\t')
|
if (c == WEOF || c == L'\n' || c == L'\t') {
|
||||||
c = L' ';
|
c = L' ';
|
||||||
|
if (flags & WATCH_COLOR)
|
||||||
|
attrset(A_NORMAL);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
if (c == EOF || c == '\n' || c == '\t')
|
if (c == EOF || c == '\n' || c == '\t') {
|
||||||
c = ' ';
|
c = ' ';
|
||||||
|
if (flags & WATCH_COLOR)
|
||||||
|
attrset(A_NORMAL);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (tabpending && (((x + 1) % 8) == 0))
|
if (tabpending && (((x + 1) % 8) == 0)) {
|
||||||
tabpending = 0;
|
tabpending = 0;
|
||||||
|
tabwaspending = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
move(y, x);
|
move(y, x);
|
||||||
|
|
||||||
if (!first_screen && !exit_early && (flags & WATCH_CHGEXIT)) {
|
if (!first_screen && !exit_early && (flags & WATCH_CHGEXIT)) {
|
||||||
#ifdef WITH_WATCH8BIT
|
#ifdef WITH_WATCH8BIT
|
||||||
cchar_t oldc;
|
cchar_t oldc;
|
||||||
@ -538,6 +608,7 @@ static int run_command(char *restrict command, char **restrict command_argv)
|
|||||||
|
|
||||||
fclose(p);
|
fclose(p);
|
||||||
|
|
||||||
|
|
||||||
/* harvest child process and get status, propagated from command */
|
/* harvest child process and get status, propagated from command */
|
||||||
if (waitpid(child, &status, 0) < 0)
|
if (waitpid(child, &status, 0) < 0)
|
||||||
xerr(8, _("waitpid"));
|
xerr(8, _("waitpid"));
|
||||||
@ -733,6 +804,8 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if (run_command(command, command_argv))
|
if (run_command(command, command_argv))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
if (precise_timekeeping) {
|
if (precise_timekeeping) {
|
||||||
watch_usec_t cur_time = get_time_usec();
|
watch_usec_t cur_time = get_time_usec();
|
||||||
next_loop += USECS_PER_SEC * interval;
|
next_loop += USECS_PER_SEC * interval;
|
||||||
|
Loading…
Reference in New Issue
Block a user