Skip to content

Instantly share code, notes, and snippets.

@cehoffman
Created August 7, 2011 00:04
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cehoffman/1129908 to your computer and use it in GitHub Desktop.
Save cehoffman/1129908 to your computer and use it in GitHub Desktop.
ZSH STDERR Colorizing
/* $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);
}
}
}
}
@ku1ik
Copy link

ku1ik commented Dec 13, 2011

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

@Yopai
Copy link

Yopai commented Apr 29, 2016

How funny :
I just went here by following the link in an issue of stderr related to its structure :
ku1ik/stderred#38

stderred has an advantage : a full explanation on how to install it.

Just giving a .c will be insufficient for many people, and won't make it popular. (And, as I don't have time to try how to install it, I won't...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment