From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3251 invoked from network); 3 Oct 1999 21:08:46 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 3 Oct 1999 21:08:46 -0000 Received: (qmail 4540 invoked by alias); 3 Oct 1999 21:08:31 -0000 Mailing-List: contact zsh-users-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 2652 Received: (qmail 4533 invoked from network); 3 Oct 1999 21:08:23 -0000 X-Sent: Sent from X-System: PHRED X-Running: Proudly running Slackware Linux. X-Sendmail: Delivered via Sendmail 8.9.3 Date: Sun, 3 Oct 1999 14:08:12 -0700 (MST) From: Chris Hansen X-Sender: chris@PHRED.dancris.com To: zsh-users@sunsite.auc.dk Subject: Re: coproc tutorial (Re: questions) In-Reply-To: <991003184515.ZM83@candle.brasslantern.com> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII I now understan how to coproc, when is it actually the best way? In the example tr would obviously work better. What have you used it for? Chris On Sun, 3 Oct 1999, Bart Schaefer wrote: > On Oct 3, 1:30am, Chris Hansen wrote: > } Subject: questions > } > } 1. I'm currently using 3.0.5, from the tone of the list it sounds > } like most of you would recommend an upgrade to 3.1.6, how stable is > } it? > > It's reasonably robust (as in, doesn't crash or horribly misinterpret any > commands you give it) for normal use. There are a lot of minor bugs in > the more obscure bits of the code, though, so the rate of patching is very > high at this time. > > There's also recently been a 3.0.6 release, and shortly will be a 3.0.7 > to knock off a few bugs found since. 3.0.6 is mostly bugfixes to 3.0.5 > plus a couple of things for forwards-compatibility with 3.1.6. > > } what's different?(readers digest version, promise to RTFM later) > > The best way to get this is to have a look at the Etc/NEWS file from the > distribution. I was hoping it was available somewhere on www.zsh.org, > but it doesn't appear to be. > > } 2. I'd like to use the lovely command line environment in other > } programs the same way you use ile or fep, is there a way to do that? > > That's been asked many times, but the line editor behavior is so tightly > tied to the rest of the shell that although you can have the shell with > no line editor, it's been more than anyone wants to tackle to try to have > the line editor without the shell. That's even more true now that most > of the completion system is written as shell functions. > > } 3. Could someone show me an example using coproc, the otherwise excellent > } documentation is a bit weak in that area. > > You start a coproc with > > coproc command > > The command has to be prepared to read from stdin and/or write to stdout, > or it isn't of much use as a coproc. Generally speaking, the command also > should not be one that uses buffered writes on its output, or you may end > up waiting for output that never appears. > > After it's running, you have several choices: > > Write to the coproc with "print -p ..." > Read from the coproc with "read -p ..." > Redirect output to the coproc with "othercommand >&p" > Redirect input from the coproc with "othercommand <&p" > > So here's a very simple example of a coproc that converts all the text > you send it into upper case ("zsh% " is the shell prompt): > > zsh% coproc while read line; do print -r -- "$line:u"; done > > Note that you can put an entire control structure into a coproc; it works > just like putting "&" at the end. The coproc shows up in the job table > as a background job; you can bring it into the foreground, kill it, etc. > In fact, it's a no-op to put an "&" at the end of a "coproc ...", because > zsh is going to background the job already. > > With that coproc running, I can say > > zsh% print -p foo ; read -ep > FOO > > (Using "read -e" means to immediately echo what was just read.) > > About that output buffering thing: You might wonder why I didn't use: > > zsh% coproc tr a-z A-Z > zsh% print -p foo ; read -ep > > It's because of the output buffering done by "tr". The "print -p foo" is > happily consumed by "tr", but it doesn't produce any output until it has > either processed a whole buffer-full of bytes (usually 1024) or until it > has seen end-of-file on its input and is about to exit. So "read -ep" > sits there forever, waiting for "tr", which is also sitting there forever > waiting for someone to send it some more bytes. > > Which brings us to an oddity about zsh's coproc: It sees end-of-file on > its input only when a new coproc is started. In other shells, using the > equivalent of the "othercommand >&p" redirection causes the shell to > discard its own copy of the coproc descriptor, so the coprocess gets an > EOF when "othercommand" closes its output (exits). Zsh, however, keeps > the coproc descriptor open so that you can repeatedly direct new output > to the same coprocess. But there can only be one magic "p" descriptor, > so when you issue a new "coproc ..." command, zsh finally does close its > copy of the descriptor. (Some "othercommand" may still have it open.) > > One idiom for closing off a coproc's input and output is to use: > > zsh% coproc exit > > That starts a new coproc (which immediately exits), causing the input and > output of the old coproc (if any) to be shut down. Some coprocesses -- > the "while" loop I used as an example is one of them -- don't notice when > their input and output are closed, and won't stop when you do this, so > you may still need to explicitly kill them off. This is a VERY important > detail if you are in the habit of using "setopt no_hup". > > Now a word about input buffering: In my example, I sent a line to the > coprocess with "print -p foo ;" leaving the "print" in the foreground. > That's because I know for a fact that the coprocess will consume one line > of input (the "while read line" loop) before producing any output at all, > so I'm sure that "print" will finish successfully. Some other coprocess > might read only a few bytes before stopping to do some other work, in > which case my "print" would block and "read -ep" might never run. It's > more usual, therefore, to send input to the coprocess from a background > job: > > zsh% cat /etc/termcap >&p & > > (I picked /etc/termcap because it's usually a huge file, so that command > will almost certainly block if not backgrounded.) > > A final oddity (and maybe this should even be considered a bug): You may > think from reading the above that you can build up your own pipelines by > chaining "coproc" together like this: > > coproc tail > coproc head >&p > > That appears to say "start `tail' as a coproc, and then start `head' as a > new coproc with its output connected to the input of the old coproc." > However, that doesn't work; zsh recreates the coproc descriptors before > processing the redirection, so what "coproc head >&p" actually does is run > "head" with its output connected back to its own input. This is a good > way to create either deadlock or an extremely CPU-intensive loop, so I > don't recommend doing it. > > -- > Bart Schaefer Brass Lantern Enterprises > http://www.well.com/user/barts http://www.brasslantern.com >