diff --git a/watch.1 b/watch.1 index 802ab841..cbfa3b32 100644 --- a/watch.1 +++ b/watch.1 @@ -1,4 +1,4 @@ -.TH WATCH 1 "2009 May 11" " " "Linux User's Manual" +.TH WATCH 1 "2010 Mar 01" " " "Linux User's Manual" .SH NAME watch \- execute a program periodically, showing output fullscreen .SH SYNOPSIS @@ -8,6 +8,7 @@ watch \- execute a program periodically, showing output fullscreen .RB [ \-n .IR seconds ] .RB [ \-\-beep ] +.RB [ \-\-color ] .RB [ \-\-differences[=\fIcumulative\fP]] .RB [ \-\-errexit ] .RB [ \-\-exec ] @@ -57,6 +58,10 @@ or options, which will cause .B watch to exit if the return value from the program is non-zero. +.PP +By default \fBwatch\fR will normally not pass escape characters, however +if you use the \fI\-\-c\fR or \fI\-\-color\fR option, then +\fBwatch\fR will interpret ANSI color sequences for the foreground. .SH NOTE Note that diff --git a/watch.c b/watch.c index 25f8964f..bfd15e68 100644 --- a/watch.c +++ b/watch.c @@ -32,6 +32,7 @@ #endif static struct option longopts[] = { + {"color", no_argument, 0, 'c' }, {"differences", optional_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, {"interval", required_argument, 0, 'n'}, @@ -44,7 +45,7 @@ static struct option longopts[] = { }; static char usage[] = - "Usage: %s [-bdhntvx] [--beep] [--differences[=cumulative]] [--exec] [--help] [--interval=] [--no-title] [--version] \n"; + "Usage: %s [-bdhntvx] [--beep] [--color] [--differences[=cumulative]] [--exec] [--help] [--interval=] [--no-title] [--version] \n"; static char *progname; @@ -55,6 +56,74 @@ static int first_screen = 1; static int show_title = 2; // number of lines used, 2 or 0 #define min(x,y) ((x) > (y) ? (y) : (x)) +#define MAX_ANSIBUF 10 + +static void init_ansi_colors(void) +{ + int i; + short ncurses_colors[] = { + COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, + COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE }; + + for (i=0; i< 8; i++) + init_pair(i+1, ncurses_colors[i], -1); +} + +static void set_ansi_attribute(const int attrib) +{ + switch (attrib) + { + case -1: + return; + case 0: + standend(); + return; + case 1: + attrset(A_BOLD); + return; + } + if (attrib >= 30 && attrib <= 37) { + color_set(attrib-29,NULL); + return; + } +} + +static void process_ansi(FILE *fp) +{ + int i,c, num1, num2; + char buf[MAX_ANSIBUF]; + char *nextnum; + + + c= getc(fp); + if (c != '[') { + ungetc(c, fp); + return; + } + for(i=0; i '9' && c != ';') + { + while(--i >= 0) + ungetc(buf[i],fp); + return; + } + buf[i] = (char)c; + } + num1 = strtol(buf, &nextnum, 10); + if (nextnum != buf && nextnum[0] != '\0') + num2 = strtol(nextnum+1, NULL, 10); + else + num2 = -1; + set_ansi_attribute(num1); + set_ansi_attribute(num2); +} static void do_usage(void) NORETURN; static void do_usage(void) @@ -145,6 +214,7 @@ main(int argc, char *argv[]) option_differences_cumulative = 0, option_exec = 0, option_beep = 0, + option_color = 0, option_errexit = 0, option_help = 0, option_version = 0; double interval = 2; @@ -158,12 +228,15 @@ main(int argc, char *argv[]) setlocale(LC_ALL, ""); progname = argv[0]; - while ((optc = getopt_long(argc, argv, "+bed::hn:vtx", longopts, (int *) 0)) + while ((optc = getopt_long(argc, argv, "+bced::hn:vtx", longopts, (int *) 0)) != EOF) { switch (optc) { case 'b': option_beep = 1; break; + case 'c': + option_color = 1; + break; case 'd': option_differences = 1; if (optarg) @@ -251,6 +324,14 @@ main(int argc, char *argv[]) /* Set up tty for curses use. */ curses_started = 1; initscr(); + if (option_color) { + if (has_colors()) { + start_color(); + use_default_colors(); + init_ansi_colors(); + } else + option_color = 0; + } nonl(); noecho(); cbreak(); @@ -350,7 +431,13 @@ main(int argc, char *argv[]) c = getc(p); while (c != EOF && !isprint(c) && c != '\n' - && c != '\t'); + && c != '\t' + && (c != L'\033' || option_color != 1)); + if (c == L'\033' && option_color == 1) { + x--; + process_ansi(p); + continue; + } if (c == '\n') if (!oldeolseen && x == 0) { x = -1;