[alt.sources] pmlined 1.0 - the poor man's line discipline

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (11/01/90)

This is pmlined 1.0, the poor man's line discipline. Like every utility
in the poor man's series, pmlined has some feature missing from almost
all the competition: in this case, the ability to make your BSD system
feel like a good old IBM VM/CMS box.

pmlined lets you edit input lines on the status line of your terminal.
You can switch between this and the native tty mode with ^A. pmlined
should be easy to play with, unlike most line discipline implementations
running around. Feel free to add features.

Send comments to me or to alt.sources.d.

---Dan

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README pmlined.c termcap
# Wrapped by brnstnd@kramden on Wed Oct 31 16:09:12 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(2446 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
Xpmlined 1.0, 10/31/90.
XPlaced into the public domain by Daniel J. Bernstein.
XComments to him at brnstnd@nyu.edu.
X
X
XThis is pmlined, the poor man's line discipline.
X
Xpmlined provides a tty editing mode that should make former IBM users
Xfeel right at home. You edit the current line on the status line
X(through stderr). Long lines scroll horizontally. When you press return,
Xpmlined sends the line to stdout. All the usual editing characters,
Xincluding ^U, ^W, backspace, delete, and ^V, work normally. ^A switches
Xbetween this editing mode and the usual tty mode.
X
XOf course, pmlined is also the smallest line discipline implementation
Xknown to man.
X
XOther than that, it's pretty poor. This version is just a prototype. It
Xcould be made much more efficient; there are a lot of features missing.
XFeel free to play with it, though. The code is short and (I hope) easy
Xto understand.
X
Xpmlined was originally called botwana. It was not named after a small
XAfrican country rumored to manufacture clone IBM 3270 terminals.
X
X
XRequirements:
X
X  A termcap entry with ``ts'', ``fs'', and ``ce''. Enclosed is a generic
X  VT termcap supporting the status line; you may have to rewrite your
X  termcap entry analogously.
X
X  The pty program, for use as described below.
X
X
XTo use pmlined, type the following:
X
X  pmlined | pty $SHELL
X
XIt should feel just like a normal shell, except that you edit lines on
Xthe bottom of your screen before entering them. If you really are an IBM
Xprogrammer, you might feel more comfortable with a shell prompt of R;
Xfollowed by a newline. You may want to % alias ibm 'pmlined | pty'.
X
XA different use of pmlined is to make clean typescripts. If you have the
Xscript clone in the pty package,
X
X  pmlined | script
X
Xwill let you correct editing errors before they enter the script.
X  
X
XCaveats:
X
X  You have to type something after the final ^D, or pmlined will not
X  realize that the output has ended.
X
X  pmlined does not react automatically to changes in the tty mode. When
X  you run vi, for instance, you have to remember to type ^A to use
X  character-at-a-time mode. A somewhat less pure design could deal with
X  this automatically.
X
X  pmlined doesn't understand tabs.
X
X  pmlined's key bindings are hardwired.
X
X  pmlined doesn't have macros, or a command history, or help, or
X  variables, or file completion, or signal characters, or anything else
X  you'd expect out of a fancy line discipline. But it's easy to extend.
X
X
XGood luck!
END_OF_FILE
if test 2446 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'pmlined.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'pmlined.c'\"
else
echo shar: Extracting \"'pmlined.c'\" \(2883 characters\)
sed "s/^X//" >'pmlined.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <signal.h>
X#include <curses.h>
X
X#define LINELEN 1000
X#define PRLINELEN 2000
X
Xoutc(ch)
Xchar ch;
X{
X putc(ch,stderr);
X}
X
Xsigpipe()
X{
X close(0); /* guaranteeing that the next character we read will be an EOF */
X}
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X char bp[1024];
X char ts[256];
X char fs[256];
X char ce[256];
X char *cptr;
X char errbuf[BUFSIZ];
X char line[LINELEN];
X char linepr[PRLINELEN];
X int ch;
X char *chpr;
X int x;
X int xpr;
X int flagcharmode = 0;
X int co;
X
X signal(SIGPIPE,sigpipe);
X setbuf(stderr,errbuf);
X
X tgetent(bp,getenv("TERM"));
X cptr = ts;
X if (!tgetstr("ts",&cptr))
X   ; /*XXX*/
X cptr = fs;
X if (!tgetstr("fs",&cptr))
X   ; /*XXX*/
X cptr = ce;
X if (!tgetstr("ce",&cptr))
X   ; /*XXX*/
X co = tgetnum("co");
X#define TS tputs(ts,1,outc)
X#define CE tputs(ce,1,outc)
X#define FS tputs(fs,1,outc)
X
X for (;;)
X   if (flagcharmode)
X    {
X     if ((ch = getchar()) == EOF)
X       break;
X     if (ch == 0001)
X       flagcharmode = 0;
X     else
X      {
X       putchar(ch);
X       fflush(stdout);
X      }
X    }
X   else
X    {
X     TS; CE; putc('_',stderr); FS; fflush(stderr);
X     x = xpr = 0;
X     line[x] = linepr[xpr] = '\0';
X     while ((ch = getchar()) != '\n')
X      {
X       if (ch == 4)
X	 break;
X       if (ch == EOF)
X	 break;
X       if (ch == '\r')
X	{
X	 ch = '\n';
X	 break;
X	}
X       if (ch == 1)
X	{
X	 flagcharmode = 1;
X	 break;
X	}
X       switch(ch)
X        {
X	 case 21: x = xpr = 0;
X                  line[x] = linepr[xpr] = '\0';
X		  break;
X	 case 23: while (x && (line[x - 1] == ' '))
X		   {
X		    x--;
X		    xpr--;
X		   }
X	          while (x && (line[x - 1] != ' '))
X		   {
X		    x--;
X		    chpr = unctrl(line[x]);
X		    while (*(chpr++))
X		      xpr--;
X		   }
X  		  linepr[xpr] = '\0';
X  		  line[x] = '\0';
X  		  break;
X         case '\b':
X         case 127: if (!x)
X		     break;
X		   x--;
X  		   chpr = unctrl(line[x]);
X  		   while (*(chpr++))
X  		     xpr--;
X  		   linepr[xpr] = '\0';
X  		   line[x] = '\0';
X  		   break;
X	 case 22: ch = getchar();
X         default: if ((x == LINELEN - 1) || (xpr == PRLINELEN - 1))
X		   {
X		    putchar(7);
X		    break;
X		   }
X		  line[x++] = ch;
X  		  line[x] = '\0';
X  		  chpr = unctrl(ch);
X  		  while(*chpr)
X  		    linepr[xpr++] = *(chpr++);
X  		  linepr[xpr] = '\0';
X        }
X       TS; if (x > co-4) { fputs("<- ",stderr); fputs(linepr + x-co+7,stderr); }
X       else fputs(linepr,stderr); putc('_',stderr); CE; FS; fflush(stderr);
X      }
X     if ((ch == EOF) || (ch == 4))
X      {
X       fputs(line,stdout);
X       putchar(4);
X       fflush(stdout);
X       if (ch == EOF)
X	 break;
X       /* On a normal ^D, we won't die until after our output does. */
X      }
X     else if (ch == 1)
X      {
X       fputs(line,stdout); fflush(stdout);
X       TS; CE; FS; fflush(stderr);
X      }
X     else
X      {
X       puts(line); fflush(stdout);
X      }
X    }
X TS; CE; FS; fflush(stderr);
X exit(0);
X}
END_OF_FILE
if test 2883 -ne `wc -c <'pmlined.c'`; then
    echo shar: \"'pmlined.c'\" unpacked with wrong size!
fi
# end of 'pmlined.c'
fi
if test -f 'termcap' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'termcap'\"
else
echo shar: Extracting \"'termcap'\" \(466 characters\)
sed "s/^X//" >'termcap' <<'END_OF_FILE'
Xv4|vt102-24|DEC vt102 with 24 lines:.al=\E[L:.am:bl=^G:bs:cd=50\E[J:ce=3\E[K:cl=50\E[;H\E[2J:cm=5\E[%i%2;%2H:co#80:cs=5\E[%i%d;%dr:dc=2\E[P:.dl=\E[M:do=3\E[B:ds=3\E[K:es:fs=\E8:hs:le=2\E[D:li#23:me=2\E[m:nd=2\E[C:pt:Rc=\E8:Sc=\E7:se=2\E[m:sf=2^J:sg=0:so=2\E[1m:sr=5\EM:ta=^I:ts=5\E7\E[?6h\E[24;0H:ue=2\E[m:ug=0:up=2\E[A:us=2\E[4m:is=\E7\E[1;23r\E>\E[?1;3;4;5l\E[?6;7;8h\E8:if=/usr/lib/tabset/vt100:rs=\E7\E[1;23r\E>\E[?1;3;4;5l\E[?6;7;8h\E8:ho=5\E[;H:cr=^M:ic=\E[@:
END_OF_FILE
if test 466 -ne `wc -c <'termcap'`; then
    echo shar: \"'termcap'\" unpacked with wrong size!
fi
# end of 'termcap'
fi
echo shar: End of shell archive.
exit 0