Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: coloring STDERR to terminal

On Wed, 30 Jun 2004, Vincent Lefevre wrote:

> On 2004-06-30 03:52:46 -0700, Bart Schaefer wrote:
> > 
> >  coproc while read line; do
> >           print '\e[91m'${(q)line}'\e[0m' > /dev/tty
> >           print -n $'\0'
> >         done
> Thanks for the explanation. But in fact, I didn't add the
>   print -n $'\0'
> line, so there is no R problem in my case. So, is this line really
> useful?

(See next message excerpted below.)

> Also, when I quit zsh, the coprocess is not killed (the NO_HUP option
> is set, but a coprocess can be seen as a particular case). Is it a bug?


> And is it possible to hide the coprocess from the jobs table?

Older versions of zsh did that -- the coprocess was not managed as a job 
at all, in fact -- but it was changed because (with the old behavior) 
there was no clean way to send termination signals etc. to the coprocess.

So at present, no, it's not possible to hide the coprocess.

It just occurred to me that

 exec 2>>( while ... & )

accomplishes the same thing without using the coprocess at all.  However, 
it doesn't give you a handle on the stdout of the "colorizer" so it's more 
difficult to synchronize it with the printing of the prompt.

On Wed, 30 Jun 2004, Vincent Lefevre wrote:
> Hmm... I now see. It seems I got confused by the zshbuiltins man page,
> which says:
>               -p     Input is read from the coprocess.
> Is it
>   1) from the coprocess output, or
>   2) sharing the coprocess input?

It's (1).

> First I supposed (2); I think that this is really what I want.

There's no way for two processes to read from the same descriptor without 
stealing bytes from each other (or synchronizing in some out-of-band way 
so that they don't do so).  Zsh multios work by creating an intervening
process that reads from one descriptor and writes duplicate bytes on two
(or more) other descriptors, for just this reason.

> But looking at the explanations, it seems to be (1); however, in this
> case, there seems to be a race condition anyway, as the coprocess may
> be too late to write its input to the tty, i.e. the following is
> possible, isn't it?
> 1) I type Ctrl-d.
> 2) "zsh: you have running jobs." is written by zsh to stderr (will be
>    read by the coprocess).
> 3) precmd() is called (but there are still no bytes sent by the
>    coprocess).

At this point the "read -p" in precmd() will block, because the coproc
has not yet executed "print -n $'\0'".  So your step (4) won't happen:

> 4) The new prompt is displayed (sent to the tty).

And instead you go directly here:

> 5) The coprocess reads a line.
> 6) The coprocess sends "zsh: you have running jobs." to the tty.
> 7) The coprocess sends a byte to stdout (too late!).

At this point "read -p" gets that byte and precmd() proceeds and the 
prompt is printed.

There _is_ a race condition when, at step (2), _more_than_one_ line is 
written to stderr, because then the coprocess may "print -n" one or more 
bytes "too soon".

You might be able to get away with something involving having preexec
start up a process and then precmd wait for it and kill it off.

Messages sorted by: Reverse Date, Date, Thread, Author