zsh-workers
 help / color / mirror / code / Atom feed
From: "Bart Schaefer" <schaefer@candle.brasslantern.com>
To: Mario Lang <mlang@home.delysid.org>
Cc: zsh-workers@sunsite.dk
Subject: Re: ZSpeak! Only Zsh can do this!
Date: Fri, 23 Mar 2001 08:42:09 +0000	[thread overview]
Message-ID: <1010323084209.ZM21757@candle.brasslantern.com> (raw)
In-Reply-To: <1010322065223.ZM19693@candle.brasslantern.com>

On Mar 22,  6:52am (that's GMT), I wrote:
} Subject: Re: ZSpeak! Only Zsh can do this!
}
} On Mar 21,  6:18pm, Mario Lang wrote:
} } Subject: Re: ZSpeak! Only Zsh can do this!
} }
} } Another really nice to have(tm) feature would be stdout buffering.
} } What I mean is that the shell should have an array (much like history)
} } which contains the outputs (stdout and stderr separated)
} } from the last commands.
} 
} However ... it might be possible to construct something based on the
} zpty module, where stdout and stderr would (unless redirected) each go
} to a separate pty, and both ptys would be managed by a front-end that
} slurped up the output from each as it appeared.

This seemed like such an interesting idea that I tried it.

It should be pretty obvious how to modify this to do something else with
the captured output, e.g., write it to a speech synthesizer instead of
stuffing it into an array parameter ...

This may also need to be tweaked in the event that a command does not
begin producing output within one second; "zpty -r -t" is a rather blunt
instrument with which to be doing precision work.


#!/bin/zsh

# zplitty -- run a command with stdout and stderr directed to separate ttys,
# from which that output can be captured for later reference.
#
# Usage:
#    zplitty command args ...
#
# Output from the command is captured in the arrays $stdout and $stderr,
# one line per array element.  Beware of running commands that produce
# voluminous output; "zplitty yes" will consume all available memory
# unless interrupted. 
#
# zplitty can be used in a pipeline or with redirected I/O, but depending
# on its location in the pipeline it may be run in a subshell, in which
# case the parent shell is not able to make use of the captured output.
#
# zplitty requires the zsh/zpty module and uses the function zttyrun to
# set up two ptys, ztdout and ztderr, to which output can be redirected
# by referencing $ztdout and $ztderr.  Be careful not to redirect too
# much output to a pty unless something is reading it with "zpty -r".
#
# The command zttystop closes these two ptys and discards the captured
# output; zttyrun must be run again before a new zplitty can be started.
# The stdout or stderr arrays can be reset at any time without zttystop
# simply by assigning an empty array as usual.
#
# Note that some interactive commands (examples are zsh, vim, and less)
# insist that their standard input and output be the same device.  Zsh
# attempts to re-open its standard input for this, while vim and less do
# the same with their standard error.  This causes "zplitty zsh" to stop
# (SIGTTOU) and "zplitty vim" or "zplitty less" to hang (reading from
# $ztderr, whence they'll never get any input).  Some other interactive
# programs may (mis)behave in similar ways; use zplitty with caution.

zmodload -i zsh/zpty || return

zttywait () {
    stty onlret -ocrnl -onlcr	# May need to adjust this for your OS
    tty
    read -e
}

zttyget() {
    setopt localoptions extendedglob noshwordsplit
    zpty $1 zttywait
    zpty -r $1 $1
    : ${(P)1::=${(P)1%%[[:space:]]#}}
}

zttyrun() {
    setopt localoptions noshwordsplit
    typeset -g ztdout='' ztderr=''
    typeset -g -a stdout stderr
    zttyget ztdout
    zttyget ztderr
}

zttystop() {
    unset stdout stderr ztdout ztderr
    zpty -w ztdout exit &&
    zpty -rt ztdout &&
    zpty -d ztdout
    zpty -w ztderr exit &&
    zpty -rt ztderr &&
    zpty -d ztderr
}

zplitty() {
    setopt localoptions noshwordsplit nonotify noksharrays
    local out err
    ${@:?} > $ztdout 2> $ztderr &
    sleep 1	# Let the background command get started
    while zpty -r -t ztdout out || zpty -r -t ztderr err
    do
	(( $+out )) && {
	    stdout[$#stdout+1]=$out
	    print -Rn $out
	}
	(( $+err )) && {
	    stderr[$#stderr+1]=$err
	    print -u2 -Rn $err
	}
	unset out err
    done
}

zttyrun
[[ -o kshautoload ]] || zplitty "$@"

# end of zplitty

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


  reply	other threads:[~2001-03-23  8:43 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-03-19 10:07 Sven Wischnowsky
2001-03-21 17:18 ` Mario Lang
2001-03-22  6:52   ` Bart Schaefer
2001-03-23  8:42     ` Bart Schaefer [this message]
  -- strict thread matches above, loose matches on Subject: below --
2001-03-16 14:21 Mario Lang
2001-03-16 14:39 ` Peter Stephenson
2001-03-16 18:23 ` Bart Schaefer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1010323084209.ZM21757@candle.brasslantern.com \
    --to=schaefer@candle.brasslantern.com \
    --cc=mlang@home.delysid.org \
    --cc=zsh-workers@sunsite.dk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).