This code is interesting. I do see one problem: commands that take up more than one line won't be stored in the history properly, so each line will get its own entry. But this is a nice use of pipes!

On Jan 23, 2009, at 5:03 AM, pavel.klinkovsky@gmail.com wrote:

Hi all,

In Plan9 I missed the simple way to repeat previous (or previous of
previous etc.) command in the terminal.
I prepared a very small (an stupid) program to allow that.

Compile the following source code and run it in that way:
8.out | rc -i

You can insert the commands, and if you want to walk through the
"history", just press CTRL+K (backward) or CTRL+L (foreward).

That is all, folks. ;-)

Pavel


#include <u.h>
#include <libc.h>

enum
{
KCtrlD = 0x04,
KCtrlK = 0x0B,
KCtrlL = 0x0C,
KDelete = 0x7F,

MaxLen = 128,
MaxDepth = 10
};

struct Line
{
int len;
char buf[MaxLen];
};
typedef struct Line Line;

void
main(void)
{
// Console control file descriptor
int cfd;
// End flag
int end = 0;
// Actual read character
char c;
// Array of BackSpaces
char bs[MaxLen];
// Array of Lines
Line line[MaxDepth];
// Index of actual line
int act = 0;
// Index of stored line
int stored = 0;

memset(bs, '\b', sizeof(bs));
memset(line, 0, sizeof(line));

cfd = open("/dev/consctl", OWRITE);
if (cfd < 0)
sysfatal("%r");
write(cfd, "rawon", 5);

while (!end) {
if (read(0, &c, sizeof(c)) < 0)
sysfatal("%r");

switch (c) {
case KCtrlD:
case KDelete:
end++;
break;

case '\b':
if (line[act].len > 0) {
line[act].len--;
write(2, &c, sizeof(c));
}
break;

case '\n':
if (line[act].len > 0)
write(1, line[act].buf, line[act].len);
write(1, &c, sizeof(c));
write(2, &c, sizeof(c));
act = stored = (act + 1) % MaxDepth;
line[act].len = 0;
break;

case KCtrlK:
write(2, bs, line[act].len);
stored = (stored + MaxDepth - 1) % MaxDepth;
line[act] = line[stored];
write(2, line[act].buf, line[act].len);
break;

case KCtrlL:
write(2, bs, line[act].len);
stored = (stored + 1) % MaxDepth;
line[act] = line[stored];
write(2, line[act].buf, line[act].len);
break;

case -0x11:
read(0, &c, sizeof(c));
read(0, &c, sizeof(c));
break;

default:
if (line[act].len < MaxLen) {
line[act].buf[line[act].len++] = c;
write(2, &c, sizeof(c));
}
break;
}
}

close(cfd);

exits(nil);
}