Has noone before me now written a tool to make stdin editable &
memorable?
For example, I see the Gnu calculator `dc` rejects the vi recall
command Esc k, the emacs recall command Ctrl+P, and the X Windows
recall command Up:
$ dc
0 1
dsa+larp
1
^[k
dc: 033 unimplemented
dc: stack empty
^P
dc: 020 unimplemented
^[[A
dc: 033 unimplemented
...
Google offers me a few incomplete workarounds, such as `emacs -nw -f
eshell` and bash >() "process substitution" and the <termios.h>
tcgetattr cfmakeraw tcsetaddr of my own C-x DEL
backwards-kill-sentence demo:
http://members.aol.com/plscsi/tools/1sh/
But what I want is a small tool that adds a convenient, familiar, edit
& recall front end to any interactive program that accepts commands
from the standard input. Am I alone in waiting this tool? Is this
tool not already broadly distributed?
Pat LaVarre
I'm not entierly sure this is what you want, but I thought it
might be worth mentioning. The AST tools from AT&T comes with
a utility called 'ie' (input editing, I presume). I've never
used this command and I don't currently have it installed for
testing.
The command has an on-line manual page here:
http://www.research.att.com/~gsf/man/man1/ie.html
It is part of the ast-open package, which may be downloaded in
source or binary form from here:
http://www.research.att.com/sw/download/
Cheers,
Andreas
--
Andreas Kähäri
Look at what zsh did with nslookup.
Get zsh 4.1, issue
autoload nslookup
nslookup
functions nslookup
for the details. You can easily adapt it for any command.
--
Stéphane
>How do I make stdin editable and recall its history, when I discover
>some unfriendly interactive program reads command lines from stdin
>without helping me edit or recall those lines?
[snip]
>But what I want is a small tool that adds a convenient, familiar, edit
>& recall front end to any interactive program that accepts commands
>from the standard input. Am I alone in waiting this tool? Is this
>tool not already broadly distributed?
Do you mean to have this tool included as part of every "interactive program
that accepts commands from the standard input"? Or would this tool be an add-on?
If it is to be part of /every/ stdin process, I see great problems with it.
Three examples where it would be a problem:
1) du | sort -nr | head -20
There are three stdins here, each associated with a (potentially) interactive
program. Are you suggesting that all three stdins should be recorded?
2) /usr/sbin/popa3d is definitely an "interactive program that accepts commands
from the standard input". It's standard input just happens to be connected to a
TCP socket, and implements one of the standard mail transfer protocols. Would
this be exempt from recording?
3) /usr/sbin/swat is also definitely an "interactive program that accepts
commands from the standard input". It's standard input just happens to be
connected to a TCP socket, and implements an HTTP interface to control a local
SMB server. Would this be exempt from recording?
--
Lew Pitcher
IT Consultant, Enterprise Technology Solutions
Toronto Dominion Bank Financial Group
(Opinions expressed are my own, not my employers')
Key question, aye, I agree with you, definitely an add-on, not a
feature of stdin per se.
Indeed the two currently working EXAMPLES of
http://members.aol.com/plscsi/tools/1sh/ are add-ons, the second is:
$ 1sh | dc
3 k
22
7
/ p
3.142
^D
$
Pat LaVarre
As yet I can detail Three dissatisfactory workarounds:
> [1] ...
X terminals let me scan by eye to find an old echoed command, then
copy that command by mouse and keyboard.
> [2] `emacs -nw -f eshell`
eshell by design often launches slowly, distorts output, defaults to
distort input.
> <termios.h> tcgetattr cfmakeraw tcsetaddr ...
> bash >() "process substitution"
An example that works is:
$ FD=>(dc) PS1= bash
echo '0 1'>>$FD
echo 'dsa+larp'>>$FD
1
echo 'dsa+larp'>>$FD
2
echo 'dsa+larp'>>$FD
3
echo 'dsa+larp'>>$FD
5
echo 'dsa+larp'>>$FD
8
echo 'dsa+larp'>>$FD
13
...
I find bash process substitution works at least as well as cfmakeraw
piped into stdin, but at the cost of much extra typing. I imagine I
could define a function to reduce the extra typing down to:
x dc
y 0 1
y dsa+larp
y dsa+larp
But I'm here saying I'd like to get free of the y, for example so I
can share the console log of my interaction without having to begin by
explaining bash process substitution to people.
> [3] <termios.h> tcgetattr cfmakeraw tcsetaddr
> of my own C-x DEL backwards-kill-sentence demo:
> http://members.aol.com/plscsi/tools/1sh/
Specifically, my 2003 Sep 14 proof-of-concept demo redefines Ctrl+C to
mean discard the input line.
For example, if I type something as violently wrongheaded as
ddsa+larp, I can press one Ctrl+C rather than eight Ctrl+H to recover.
I call that "proof-of-concept" because I believe via the same
mechanism a small matter of programming could also understand Up,
Ctrl+P, Esc K, etc.
Pat LaVarre
P.S.
> $ dc
> 0 1
> dsa+larp
> 1
Why dsa+larp?
`dsa+larp` is a translation into the `dc` language of the Fibonacci
iterator e.g. repeatedly applying `dsa+larp` to the seed 0 1 produces
the sequence 1 2 3 5 8 13 21 34 55 89 144 ... i.e. each number is the
sum of the two numbers before it. Transliterating to Forth yields (
dup to a + a swap dup . cr ), translating more loosely to Forth yields
( tuck + dup . ). Leaving the problem of output unsolved as an
exercise for the reader yields the incisive or cryptic ( tuck + ).
Thanks for the hints, I will pursue further.
> ...
At first glance here I see:
$ cat /etc/redhat-release
Red Hat Linux release 9 (Shrike)
$ man zsh
$ zsh --version
zsh 4.0.6 (i386-redhat-linux-gnu)
$
Nearby I see:
$ uname -snr
Linux Knoppix 2.4.21-xfs
$ zsh --version
bash: zsh: command not found
$
Back here I see the following, except with different hostname & IP
digits:
$ zsh
patlhost% autoload nslookup
patlhost% nslookup
Note: nslookup is deprecated and may be removed from future releases.
Consider using the `dig' or `host' programs instead. Run nslookup
with
the `-sil[ent]' option to prevent this message from appearing.
> functions nslookup
Server: 987.654.32.10
Address: 987.654.32.10#12
** server can't find functions: SERVFAIL
> quit
Server: 987.654.32.10
Address: 987.654.32.10#12
** server can't find functions: SERVFAIL
> exit
patlhost%
> You can easily adapt it for any command.
I may check Google, but meanwhile man recommends:
http://www.zsh.org/pub/zsh/
I see that's an `ls -l`, so I chose:
http://www.zsh.org/pub/zsh/FAQ
I searched some on "redirection". I dislike seeing that the way
chosen to make an ftp more usable was to throw away the ftp I have and
write a new one.
Pat LaVarre
Closely related & great fun, aye. I see:
"DESCRIPTION
"ie executes a dynamically linked command with ksh-style input editing
on the standard input terminal ...
"DETAILS
"Input editing is implemented by intercepting the read(2) system call
on file descriptor 0 with a dll that is preloaded at process startup
before main() is called ...
Pat LaVarre
> How do I make stdin editable and recall its history, when I discover
> some unfriendly interactive program reads command lines from stdin
> without helping me edit or recall those lines?
>
> Has noone before me now written a tool to make stdin editable &
> memorable?
>
> For example, I see the Gnu calculator `dc` rejects the vi recall
> command Esc k, the emacs recall command Ctrl+P, and the X Windows
> recall command Up:
If you run your shell within Emacs via `M-x shell', shell.el tracks
everything you enter in its shell-command-history variable (accessible
via `M-p', `M-r', and other commands), even when you're interacting
with another program.
--
Kevin Rodgers
« functions nslookup » is not to be typed from within nslookup,
but at shell prompt, to see the definition of the nslookup zsh
function.
You must have noticed that you got a zsh line editor at your
nslookup prompt (with history and usual moving keys), didn't you?
~$ print $ZSH_VERSION
4.1.1-dev-1
~$ functions nslookup
nslookup () {
if [[ $argv[(I)-] -eq 0 && $argv[(I)[^-]*] -ne 0 ]]
then
command nslookup "$@"
return
fi
setopt localoptions localtraps completealiases
local tmp line compcontext=nslookup curcontext='nslookup:::' pmpt
local pager opager="$PAGER"
typeset +g -x PAGER=cat
zmodload -e zsh/zpty || zmodload -i zsh/zpty
trap 'return 130' INT
trap 'zpty -d nslookup' EXIT
pmpt=()
zstyle -s ':nslookup' prompt tmp && pmpt=(-p "$tmp")
zstyle -s ':nslookup' rprompt tmp && pmpt=("$pmpt[@]" -r "$tmp")
zstyle -s ':nslookup' pager tmp && [[ -z "$pager" ]] && pager="${opager:-more}"
(( $#pmpt )) || pmpt=(-p '> ')
zpty nslookup command nslookup "${(q)@}"
zpty -r nslookup line '*
> '
print -nr "$line"
while line=''
vared -he "$pmpt[@]" line
do
print -s "$line"
[[ "$line" = exit ]] && break
zpty -w nslookup "$line"
zpty -r nslookup line '(|*
)> '
if [[ -n "$pager" && ${#${(f)line}} -gt LINES ]]
then
print -nr "$line" | eval "$pager"
else
print -nr "$line"
fi
done
zpty -w nslookup 'exit'
}
If you replace "nslookup" everywhere above with any
command with a prompt you want to wrap (be sure to change the
prompt description (after zpty -r)), you'll get the same
behavior. For a command without a prompt such as dc, try:
add_LE () {
setopt localoptions localtraps
local line
zmodload -i zsh/zpty zsh/zselect
trap 'return 130' INT
trap 'zpty -d $1' EXIT
zpty -b $1 command "${(q)@}"
while line=''
vared -he line
do
print -s "$line"
[[ "$line" = q ]] && break
zpty -w $1 "$line"
zselect -t 5 # sleeps for half a tenth of second
zpty -r $1
done
}
Then:
add_LE dc
or:
add_LE sh
--
Stéphane
"`emacs -nw -f eshell` by design often launches slowly, distorts
output, and defaults to distort input."
I think I see distortion by design in such features as requiring me to
learn to type C-c C-d to mean C-d.
But I think I see distortion by accident in such features as the
handling of chars outside of US-ASCII.
For example, suppose we try a UK Shift+3 = pound-sign = '£' = utf-16
x00A3 = utf-8 x C2 A3.
Mac OS X: echo works, but emacs gives me: B#
Knoppix Linux: echo works, emacs C-h C-k tells me I typed M-#
RedHat Linux: gui works, echo gives me maybe a box-drawing char, emacs
C-h C-k tells me I typed a glyph that resembles utf-16 x00C2
latin-capital-letter-a-with-circumflex, but in fact prints the same
box-drawing char as echo.
Pat LaVarre
Did I not sufficiently emphasise: as yet I have tried only zsh 4.0.6,
I have not yet found & distributed & installed 4.1.
> you got a zsh line editor
> at your nslookup prompt
> (with history and usual moving keys),
> didn't you?
No, for example I see ^[[A when I press the up arrow key.
> add_LE () { ...
$ zsh
hostname% prompt='~$ '
~$ print $ZSH_VERSION
4.0.6
~$ add_LE dc
add_LE:3: failed to load module: zsh/zselect
> ...
If I apply the patch:
- zmodload -i zsh/zpty zsh/zselect
+ zmodload -i zsh/zpty
- zselect -t 5 # sleeps for half a tenth of second
then I get history that works, but the `dc` output is delayed.
For example, wrong zsh followed by correct bash (1sh|dc also correct)
is:
~$ add_LE dc
2 3 * p
5 7 * p
6
~$ exit
$ dc
2 3 * p
6
5 7 * p
35
$
> > > Get zsh 4.1, issue
> >
> > Thanks for the hints, I will pursue further.
I will.
Pat LaVarre
>>>For example, ... the Gnu calculator `dc` ...
>>>
>>>Has noone before me now written a tool
>>>to make stdin editable & memorable?
>>
[quoting me, now]
>>If you run ... within Emacs via `M-x shell',
>>shell.el tracks everything you enter ...
>
> "`emacs -nw -f eshell` by design often launches slowly, distorts
> output, and defaults to distort input."
I did not suggest using eshell.
> I think I see distortion by design in such features as requiring me to
> learn to type C-c C-d to mean C-d.
A small price to pay for the features you are asking for (and more), IMHO.
--
Kevin Rodgers
nslookup wrapper was introduced in zsh 3.1.6-pws-4 four years
ago.
>> you got a zsh line editor
>> at your nslookup prompt
>> (with history and usual moving keys),
>> didn't you?
>
> No, for example I see ^[[A when I press the up arrow key.
When running "nslookup" after a "autoload nslookup"?
[...]
> If I apply the patch:
>
> - zmodload -i zsh/zpty zsh/zselect
> + zmodload -i zsh/zpty
> - zselect -t 5 # sleeps for half a tenth of second
>
> then I get history that works, but the `dc` output is delayed.
replacing "zselect -t 5" with /bin/true should be enough. You
need just to introduce a delay long enough so that dc has the
time to write its output.
--
Stéphane
Sorry I misunderstood you, thanks very much for finding the time to
say that I did. Indeed I cannot confidently say if in past lives with
emacs I saw shell or eshell fail me: the difference in name is too
small.
Now I wonder if your M-x shell suggestion includes:
emacs -nw -f shell
I say emacs -nw because that's all the emacs I have everywhere. X
emacs appears less widely distributed e.g. absent from vanilla Mac OS
X.
I see -f shell input appears less distorted that does -f eshell input
e.g. I'm delighted to discover C-d often works i.e. becomes
comint-delchar-or-maybe-eof rather than delete-char.
I'm hunting for balance here.
I want just enough input/ output distortion to make stdin editable and
memorable, and not a jot more. I can't be alone in feeling that wish,
can I?
I can't yet see clearly what balance works. I mean to be here asking
what we think.
I know in practice I don't bother launching emacs to give command
retrieval to dc. Hardly anybody does, right? The people who run dc
in emacs launch emacs early and leave it launched. They don't launch
it for dc alone, right? They don't work in ways the often crash the
kernel, right?
Me, to make dc stdin editable & memorable, I resort to mouse copy
paste of the console log. That's a very ordinary choice, isn't it?
Although not quite satisfactory.
> > I'm hunting for balance here.
I wonder if we can arrive inductively at a compelling balance. To get
an editable history of stdin, I see I'll happily tolerate much:
1) Line-buffered input by default: input doesn't pass thru til eol.
2) Local echoing by default: input appears echoed to /dev/tty, and
therefore appears echoed again if the process with an uneditable stdin
echoes input.
3) Suspending together by default: `fg` brings the editor and the rest
of the pipe back to life, just like it does already with -f shell
after C-z suspend-emacs.
3) Requiring a prefix like C-q quoted-insert to pass thru editing keys
such as Ctrl+H (aka C-h) thru to the running program.
4) Requiring some suffix I haven't yet found in emacs e/shell to say
to proceed to pass thru the line-buffered input without appending an
eol. I see Emacs names this idea eshell-send-input with QUEUE-P nil
and NO-NEWLINE non-nil.
So far, most anyone would agree so far, right?
For stdin, we now have "reasonable sacrifice" precisely outlined?
Sure, by default, emacs demands more input distortion than this in
return for an editable history. But I imagine I could google my past
lives to remember how to overcome that I want C-c to pass thru, I see
by default I need C-c C-c comint-interrupt-subjob. I want C-d to
finish, I see by default I need C-x C-c save-buffers-kill-emacs.
These issues we can disregard as personal preferences over which key
means what.
What I totally choke over is:
1) Having to give up UK ASCII in favour of US ASCII.
Is there a reasonable way to tell emacs e/shell to leave my output
alone?
It's 2003 and my up arrow doesn't work.
Where did I go wrong.
How nuts am I?
Pat LaVarre
Because of your patience, I think finally now I understand. In the
log below, I did not type the second help input line, instead I
retrieved it via up arrow. The ^D did not appeared echoed, those are
the two places where I typed Ctrl+D.
Sorry I'm often not at the same host from one reply to the next, so I
can't easily say what would have happened there if I had tried an
experiment other than what I posted.
Next I will try a ~/bin/zdc script. I will begin with:
#!/bin/sh
dc "$@"
But then I plan to try starting with #!/bin/zsh instead, to see if
thereby I can give an editable history to dc.
Pat LaVarre
% tcsh
%
% ls -l `which zsh`
-rwxr-xr-x 1 root wheel 828780 Sep 1 21:18 /bin/zsh
%
% zsh --version
zsh 4.0.4 (powerpc-apple-darwin6.0)
%
% setenv PS1 'zsh$ '
%
% zsh
zsh$
zsh$ print $ZSH_VERSION
4.0.4
zsh$
zsh$ autoload nslookup
zsh$
zsh$ nslookup
nslookup:15: failed to load module: zsh/zpty
nslookup:27: command not found: zpty
nslookup:29: command not found: zpty
> help
nslookup:37: command not found: zpty
nslookup:39: command not found: zpty
> help
nslookup:37: command not found: zpty
nslookup:39: command not found: zpty
> exit
nslookup:48: command not found: zpty
zsh: command not found: zpty
zsh$
zsh$ ^D
%
% ^D
%
I'll push a little harder, but I'm guessing my effort's not going
well:
$
$ PS1='~$ ' zsh
~$
~$ print $ZSH_VERSION
4.0.4
~$
~$ zpty
zsh: command not found: zpty
~$
I imagine I'm back to needing to fetch zsh from the web myself, rather
than hoping to find it working for me already?
Pat LaVarre
zpty is a zsh module, it generally needs to be loaded as there's
no reason why a distribution maintainer would choose to have it
embedded in the zsh core.
zmodload zsh/zpty
(maybe "zmodload zpty" in 4.0.4)
first.
But as you get the error when running the "nslookup" function,
and the "nslookup" function loads the module (zmodload
-e zsh/zpty || zmodload -i zsh/zpty), zsh is likely not to be
properly installed on your system.
--
Stéphane
> Now I wonder if your M-x shell suggestion includes:
> emacs -nw -f shell
Sure, it's the same thing.
> I say emacs -nw because that's all the emacs I have everywhere. X
> emacs appears less widely distributed e.g. absent from vanilla Mac OS
> X.
Word on the Emacs development list is that Mac OS X support is good and
getting better. Try installing the latest CVS version from sourceforge.net.
> I see -f shell input appears less distorted that does -f eshell input
> e.g. I'm delighted to discover C-d often works i.e. becomes
> comint-delchar-or-maybe-eof rather than delete-char.
Good.
> I'm hunting for balance here.
>
> I want just enough input/ output distortion to make stdin editable and
> memorable, and not a jot more. I can't be alone in feeling that wish,
> can I?
>
> I can't yet see clearly what balance works. I mean to be here asking
> what we think.
>
> I know in practice I don't bother launching emacs to give command
> retrieval to dc. Hardly anybody does, right? The people who run dc
> in emacs launch emacs early and leave it launched. They don't launch
> it for dc alone, right? They don't work in ways the often crash the
> kernel, right?
Right on both counts.
...
> 4) Requiring some suffix I haven't yet found in emacs e/shell to say
> to proceed to pass thru the line-buffered input without appending an
> eol. I see Emacs names this idea eshell-send-input with QUEUE-P nil
> and NO-NEWLINE non-nil.
For shell and other comint-derived modes, see the comint-send-string function
(cf. comint-send-input, which is bound to RET).
> So far, most anyone would agree so far, right?
>
> For stdin, we now have "reasonable sacrifice" precisely outlined?
>
> Sure, by default, emacs demands more input distortion than this in
> return for an editable history. But I imagine I could google my past
> lives to remember how to overcome that I want C-c to pass thru, I see
> by default I need C-c C-c comint-interrupt-subjob. I want C-d to
> finish, I see by default I need C-x C-c save-buffers-kill-emacs.
> These issues we can disregard as personal preferences over which key
> means what.
>
> What I totally choke over is:
>
> 1) Having to give up UK ASCII in favour of US ASCII.
>
> Is there a reasonable way to tell emacs e/shell to leave my output
> alone?
You'll have to be more specific, and you'll get better help if you ask in the
gnu.emacs.help newsgroup.
> It's 2003 and my up arrow doesn't work.
In shell and other comint-derived modes, comint-previous-input is on M-p
and <C-up>. But as you said, that's just a key binding issue.
--
Kevin Rodgers
/bin/zsh adds editable history to stdin.
In the tty log below, I used C-a C-k C-y C-y C-y ... to retype the
repeating text for me, then I used C-p to retrieve the whole line, I
entered completed lines, and I finished with C-d:
$ uname
Linux
$ cat /etc/redhat-release
Red Hat Linux release 9 (Shrike)
$ zedi dc
0 1
dsa+lar dn32P dsa+lar dn32P dsa+lar dn32P dsa+lar p
1 2 3 5
dsa+lar dn32P dsa+lar dn32P dsa+lar dn32P dsa+lar p
8 13 21 34
$
Furthermore, by calling dc from within a #!bin/zsh script, I got a
stdin history independent of the shell's history.
Caveats as yet include: 1) The /bin/true kluge may fail in
circumstances I do not understand. 2) As yet I've only tried
zedi-ting on one host. 3) zedi doesn't yet cope if the command issues
its own prompts, like nslookup does.
I began with the script Stéphane posted, and then edited only outside
the { } and the # commented lines inside.
Pat LaVarre
$ cat /etc/redhat-release
Red Hat Linux release 9 (Shrike)
$
$ cat `which zedi`
#!/bin/zsh
zshedit () {
setopt localoptions localtraps
local line
zmodload -i zsh/zpty # zsh/zselect
trap 'return 130' INT
trap 'zpty -d $1' EXIT
zpty -b $1 command "${(q)@}"
while line=''
vared -he line
do
print -s "$line"
[[ "$line" = q ]] && break
zpty -w $1 "$line"
/bin/true # zselect -t 5 # sleeps for half a tenth of
second
zpty -r $1
done
}
zshedit "$@"
$
But in Mac OS X that zedi abuse of zsh bursts error messages and
swallows the dc output, besides making stdin editable and memorable.
For example:
% zsh --version
zsh 4.0.4 (powerpc-apple-darwin6.0)
%
% zedi dc
zshedit:3: failed to load module: zsh/zpty
zshedit:6: command not found: zpty
0 1
zshedit:12: command not found: zpty
zshedit:13: no such file or directory: /bin/true
zshedit:14: command not found: zpty
dsa+larp
zshedit:12: command not found: zpty
zshedit:13: no such file or directory: /bin/true
zshedit:14: command not found: zpty
dsa+larp
zshedit:12: command not found: zpty
zshedit:13: no such file or directory: /bin/true
zshedit:14: command not found: zpty
/Users/.../bin/zedi:21: command not found: zpty
%
% which true
/usr/bin/true
%
% which zpty
zpty: Command not found.
%
% zedi cat
zshedit:3: failed to load module: zsh/zpty
zshedit:6: command not found: zpty
ok
zshedit:12: command not found: zpty
zshedit:13: no such file or directory: /bin/true
zshedit:14: command not found: zpty
/Users/.../bin/zedi:21: command not found: zpty
%
Pat LaVarre