Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

ZSH STDERR Colorizing

View colorize.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
/* $Id: colorize.c 3816 2004-07-03 17:01:32Z lefevre $
*
* Colorize the standard input. Written for zsh stderr coloring.
* This was taken from a mail archive on the subject of colorizing
* the stderr stream in zsh. It was written by Vincent Lefèvre as far
* as I know. It is here so it can be used in a brew formula.
*
* The intended usage is to place a line like the following in your zshrc
* exec 2>>(colorize `tput bold; tput setaf 1` `tput sgr0` > /dev/tty &)
*
* I use the colors associative array generated by zsh to make friendly color names, e.g.
* exec 2>>(colorize $fg[yellow] $reset_color > /dev/tty &)
*/
 
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/types.h>
 
#define BUFFSIZE 512
 
static volatile sig_atomic_t usr1;
 
static void sigusr1(int sig)
{
usr1 = 1;
}
 
static void writepid(char *tmpfile)
{
FILE *f;
 
f = fopen(tmpfile, "w");
if (f == NULL)
{
perror("colorize (fopen)");
exit(EXIT_FAILURE);
}
fprintf(f, "%ld\n", (long) getpid());
if (fclose(f) != 0)
{
perror("colorize (fclose)");
exit(EXIT_FAILURE);
}
}
 
int main(int argc, char **argv)
{
pid_t zshpid = 0;
char *begstr, *endstr;
fd_set rfds;
int ret;
 
if (argc != 3 && argc != 5)
{
fprintf(stderr,
"Usage: colorize <begstr> <endstr> [ <zshpid> <tmpfile> ]\n");
exit(EXIT_FAILURE);
}
 
/* Assume that the arguments are correct. Anyway, it is not possible
to check them entirely. */
begstr = argv[1];
endstr = argv[2];
if (argc == 5)
{
/* To do the synchronization with the zsh prompt output...
Seems to be useless in practice, hence the argc == 3 case. */
zshpid = atol(argv[3]);
signal(SIGUSR1, sigusr1);
writepid(argv[4]);
}
 
fcntl(0, F_SETFL, fcntl(0, F_GETFL) | O_NONBLOCK);
 
/* To watch stdin (fd 0). */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
 
for (;;)
{
ret = select(1, &rfds, NULL, NULL, NULL);
 
if (ret < 0 && errno != EINTR)
{
perror("colorize (pselect)");
exit(EXIT_FAILURE);
}
 
if (ret > 0)
{
static unsigned char buffer[BUFFSIZE];
static int dontcol = 0;
ssize_t n;
 
while ((n = read(0, buffer, BUFFSIZE)) >= 0)
{
ssize_t i;
 
if (n == 0)
return 0; /* stdin has been closed */
for (i = 0; i < n; i++)
{
if (buffer[i] == 27)
dontcol = 1;
if (buffer[i] == '\n')
dontcol = 0;
if (!dontcol)
fputs(begstr, stdout);
putchar(buffer[i]);
if (!dontcol)
fputs(endstr, stdout);
}
}
fflush(stdout);
}
 
if (usr1)
{
usr1 = 0;
if (kill(zshpid, SIGUSR1) != 0)
{
perror("colorize (kill)");
exit(EXIT_FAILURE);
}
}
}
}

You can also check out stderred: https://github.com/sickill/stderred

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.