A small extension for screen-3.8.6. It tries to emulate Emacs dynamic abbreviation expansion (bound to M-/). I find it very useful, e.g., when I want to use a result of the previous command (like `find' or `locate') in my next shell command. It is much faster than the usual cut & paste sequence. The following patch implements the changes and corrects some minor typos in documentation. ============== CUT HERE ================ diff -urd screen-3.8.6/comm.c screen-3.8.6-test/comm.c --- screen-3.8.6/comm.c Wed Oct 23 16:37:29 1996 +++ screen-3.8.6-test/comm.c Thu Feb 13 00:14:23 1997 @@ -112,6 +112,9 @@ #ifdef COPY_PASTE { "copy", NEED_FORE|ARGS_0 }, { "crlf", ARGS_1 }, +#ifdef DABBREV + { "dabbrev", NEED_FORE|ARGS_0 }, +#endif #endif { "debug", ARGS_01 }, #ifdef AUTO_NUKE diff -urd screen-3.8.6/config.h.in screen-3.8.6-test/config.h.in --- screen-3.8.6/config.h.in Mon Jan 6 19:04:46 1997 +++ screen-3.8.6-test/config.h.in Thu Feb 13 00:14:23 1997 @@ -133,6 +133,8 @@ * define COLOR to include ansi color support. This may expose * a bug in x11r6-color-xterm. * define KANJI to include support for japanese character sets. + * define DABBREV to include dynamic abbreviation expansion support. + * COPY_PASTE must be also defined for this to work. (tjc) */ #undef SIMPLESCREEN #ifndef SIMPLESCREEN @@ -148,6 +150,7 @@ # define MAPKEYS # define COLOR # define KANJI +# define DABBREV #endif /* SIMPLESCREEN */ /* diff -urd screen-3.8.6/doc/screen.1 screen-3.8.6-test/doc/screen.1 --- screen-3.8.6/doc/screen.1 Mon Nov 18 09:09:50 1996 +++ screen-3.8.6-test/doc/screen.1 Thu Feb 13 00:30:00 1997 @@ -547,7 +547,8 @@ .\" Switch to the control window. .IP "\fBC-a *\fP (displays)" Show a listing of all currently attached displays. - +.IP "\fBC-a /\fP (dabbrev)" +Dynamically expand current word. .SH CUSTOMIZATION The \*Qsocket directory\*U defaults either to $HOME/.screen or simply to @@ -1224,6 +1225,27 @@ When no parameter is given, the state is toggled. .sp .ne 3 +.BR "dabbrev" +.PP +Expands the word before cursor by searching in the preceding text on the +screen and in the scrollback buffer for words starting with that +abbreviation. Repeating \fBdabbrev\fP several times in sequence +searches for an alternative expansion by looking farther back. Lack of +more matches is signalled by a beep. Attempts to expand an empty word +(i.e., when cursor is preceded by a space) succesively yield all +previous words. Consecutive identical expansions are ignored. The word +is defined as a sequence of non-whitespace characters. When the word +wrap is on, the words split into the neighboring lines will be +joined. \fBdabbrev\fP partially emulates the behavior of `dynamic +abbreviation' expansion in Emacs (usually bound there to M-/). +.PP +This feature heavily depends on the ability to determine the +`erase' character used in your application. In case of problems +please use the same settings of `stty' before and after starting +.I screen +session. +.sp +.ne 3 .BR "debug on" | off .PP Turns runtime debugging on or off. If @@ -2282,7 +2304,7 @@ underline, ...) the text will get. .I Color is a 2 digit number and changes the -forground/background of the highlighted text. +foreground/background of the highlighted text. Some knowledge of screen's internal character representation is needed to make the characters appear in the desired way. The default is currently 10 99 (standout, default colors). @@ -3442,7 +3464,7 @@ \*Qeuc\*U and \*Qsjis\*U. .TP 13 .BI AF " (str)" -Change character forground color in an ANSI conform way. This +Change character foreground color in an ANSI conform way. This capability will almost always be set to '\eE[3%dm' ('\eE[3%p1%dm' on terminfo machines). .TP 13 diff -urd screen-3.8.6/doc/screen.texinfo screen-3.8.6-test/doc/screen.texinfo --- screen-3.8.6/doc/screen.texinfo Sun May 5 18:47:42 1996 +++ screen-3.8.6-test/doc/screen.texinfo Thu Feb 13 00:30:08 1997 @@ -708,6 +708,10 @@ (history)@* Copy and paste a previous (command) line. @xref{History}. +@item @kbd{C-a /} +(dabbrev)@* +Copy and paste a previous (command) line. @xref{Dynamic Abbreviations}. + @item @kbd{C-a >} (writebuf)@* Write the paste buffer out to the screen-exchange file. @@ -801,6 +805,8 @@ Removed. Use @code{paste} instead. @xref{Registers}. @item crlf @var{state} Select line break behavior for copying. @xref{Line Termination}. +@item dabbrev +Expand current word @dots{}. @xref{Dynamic Abbreviations}. @item debug @var{state} Suppress/allow debugging output. @xref{Debug}. @item defautonuke @var{state} @@ -875,6 +881,8 @@ Display current key bindings. @xref{Help}. @item history Find previous command beginning @dots{}. @xref{History}. +@item dabbrev +Expand current word @dots{}. @xref{Dynamic Abbreviations}. @item info Display terminal settings. @xref{Info}. @item ins_reg @var{[key]} @@ -2412,6 +2420,8 @@ * Registers:: Longer-term storage * Screen-Exchange:: Sharing data between screen users * History:: Recalling previous input +* Dynamic Abbreviations:: Dynamically expanding current word. + @end menu @node Copy, Paste, , Copy and Paste @@ -2762,7 +2772,7 @@ @kbd{C-a @key{ESC}} (@pxref{Copy}). @end deffn -@node History, , Screen-Exchange, Copy and Paste +@node History, Dynamic Abbreviations, Screen-Exchange, Copy and Paste @section History @kindex @{ @@ -2779,6 +2789,30 @@ scrollback buffer). @end deffn + +@node Dynamic Abbreviations, , History, Copy and Paste +@section Dynamic Abbreviations + +@kindex / +@deffn Command dabbrev +(@kbd{C-a /})@* Expands the word before cursor by searching in the +preceding text on the screen and in the scrollback buffer for words +starting with that abbreviation. Repeating @code{dabbrev} several times +in sequence searches for an alternative expansion by looking farther +back. Lack of more matches is signalled by a beep. Attempts to expand +an empty word (i.e., when cursor is preceded by a space) succesively +yield all previous words. Consecutive identical expansions are ignored. +The word is defined as a sequence of non-whitespace characters. When +the word wrap is on, the words split into the neighboring lines will be +joined. This command partially emulates the behavior of `dynamic +abbreviation' expansion in Emacs (usually bound there to M-/). + +This feature heavily depends on the ability to determine the +@code{erase} character used in your application. In case of problems +please use the same settings of @code{stty} before and after starting +@code{screen} session. +@end deffn + @node Subprocess Execution, Key Binding, Copy and Paste, Top @chapter Subprocess Execution Control Input or Output of a window by another filter process. @@ -3500,7 +3534,7 @@ @item AF (str)@* -Change character forground color in an ANSI conform way. This +Change character foreground color in an ANSI conform way. This capability will almost always be set to @samp{\E[3%dm} (@samp{\E[3%p1%dm} on terminfo machines). @@ -4034,7 +4068,7 @@ @var{attr} is a hexadecimal number and describes the attributes (inverse, underline, ...) the text will get. @var{color} is a 2 digit number and changes the -forground/background of the highlighted text. +foreground/background of the highlighted text. Some knowledge of screen's internal character representation is needed to make the characters appear in the desired way. The default is currently @samp{10 99} (standout, default colors). diff -urd screen-3.8.6/mark.c screen-3.8.6-test/mark.c --- screen-3.8.6/mark.c Tue Nov 7 19:05:53 1995 +++ screen-3.8.6-test/mark.c Thu Feb 13 00:14:23 1997 @@ -32,7 +32,6 @@ #include "extern.h" #ifdef COPY_PASTE - static int is_letter __P((int)); static void nextword __P((int *, int *, int, int)); static int linestart __P((int)); @@ -77,6 +76,10 @@ static struct markdata *markdata; +#ifdef DABBREV +int restart_dabbrev = 1; /* used in process.c */ +#endif + /* * VI like is_letter: 0 - whitespace @@ -449,6 +452,132 @@ return 1; } +#ifdef DABBREV +/* The following code implements `dynamic abbreviation' expansion a la + Emacs. It looks in the preceding visible screen and its history to find + expansions of a typed word. It checks consecutive expansions and + ignores one of them if they are identical. (Tomasz J. Cholewo, + t.cholewo@ieee.org) */ + +int +getprevchar (xp, yp) +int *xp, *yp; +{ + static char *linep; + static int y = -1; + while (*yp >= 0) { + if (*yp != y) { /* cache last |linep| value */ + y = *yp; + linep = WIN (y)->image; + } + if (--*xp >= 0) + return linep[*xp]; + *xp = D_width; + (*yp)--; /* go to previous line */ + if (!fore->w_wrap) + return ' '; /* separate lines */ + } + return -1; +} + +char * +getprevword (xp, yp) +int *xp, *yp; +{ +#define MAXWLEN 1000 + static char ab[MAXWLEN]; /* initialized to zeros */ + char *abword; + int c; + + abword = ab + MAXWLEN - 1; + + while ((c = getprevchar (xp, yp)) >= 0 && is_letter (c)) + if (abword > ab) /* store only |MAXWLEN| last chars */ + *(--abword) = c; + if (c < 0) { + if (abword < ab + MAXWLEN - 1) + return abword; + else + return 0; + } + + while ((c = getprevchar (xp, yp)) >= 0 && !is_letter (c)); /* skip preceding spaces */ + (*xp)++; /* can be | >= D_width| */ + return abword; +} + +/* return value 1 if u_copybuffer changed */ +int +DabbrevExpand () +{ + static int x, y, hintlen; + static char *hint = 0, *lastexpansion = 0; + + char *expansion; + int del_cnt, buf_cnt, i; + + if (restart_dabbrev) { /* initialize */ + restart_dabbrev = 0; + x = fore->w_x; + if (x > D_width) + x = D_width; + y = fore->w_y + fore->w_histheight; + + free (hint); /* |free (NULL)| is OK */ + hint = getprevword (&x, &y); + if (!hint) + return 0; /* no preceding word? */ + free (lastexpansion); + lastexpansion = strdup (hint); + hint = strdup (hint); /* make our own copy */ + if (!hint || !lastexpansion) + { + Msg(0, "Not enough memory... Sorry."); + return 0; + } + hintlen = strlen (hint); + } + + while ((expansion = getprevword (&x, &y))) { + if (!strncmp (hint, expansion, hintlen) && /* empty hint matches everything */ + strlen (expansion) > hintlen && /* trivia disallowed */ + strcmp (expansion, lastexpansion)) /* different from previous */ + break; + } + if (!expansion) /* no expansion found */ + return 0; + + UserFreeCopyBuffer(D_user); + + del_cnt = strlen (lastexpansion) - hintlen; + buf_cnt = del_cnt + strlen (expansion) - hintlen; + if (!(D_user->u_copybuffer = malloc((unsigned) (buf_cnt + 1)))) + { + Msg(0, "Not enough memory... Sorry."); + return 0; + } + for (i = 0; i < del_cnt; i++) { /* delete previous expansion */ + D_user->u_copybuffer[i] /* is this the best way to find out the ERASE character? */ +#ifdef POSIX + = D_OldMode.tio.c_cc[VERASE]; +#else + = D_OldMode.m_ttyb.sg_erase; +#endif + } + bcopy (expansion + hintlen, D_user->u_copybuffer + del_cnt, strlen (expansion) - hintlen); + D_user->u_copylen = buf_cnt; + + free (lastexpansion); + lastexpansion = strdup (expansion); + if (!lastexpansion) + { + Msg(0, "Not enough memory... Sorry."); + return 0; + } + return 1; +} +#endif /* DABBREV */ + void MarkRoutine() { @@ -715,19 +844,19 @@ case '|': revto(--rep_cnt, cy); break; - case 'w': + case 'w': /* word forward */ if (rep_cnt == 0) rep_cnt = 1; nextword(&cx, &cy, NW_MUSTMOVE, rep_cnt); revto(cx, cy); break; - case 'e': + case 'e': /* word forward last letter */ if (rep_cnt == 0) rep_cnt = 1; nextword(&cx, &cy, NW_ENDOFWORD|NW_MUSTMOVE, rep_cnt); revto(cx, cy); break; - case 'b': + case 'b': /* word back */ if (rep_cnt == 0) rep_cnt = 1; nextword(&cx, &cy, NW_BACK|NW_ENDOFWORD|NW_MUSTMOVE, rep_cnt); diff -urd screen-3.8.6/process.c screen-3.8.6-test/process.c --- screen-3.8.6/process.c Tue Dec 17 15:58:36 1996 +++ screen-3.8.6-test/process.c Thu Feb 13 00:14:23 1997 @@ -48,6 +48,10 @@ #include "extern.h" #include "logfile.h" +#ifdef DABBREV +extern int restart_dabbrev; +#endif + extern struct comm comms[]; extern char *rc_name; extern char *RcFileName, *home; @@ -444,6 +448,9 @@ ktab['~'].nr = RC_SELECT; ktab['~'].args = SaveArgs(args); } +#ifdef DABBREV + ktab['/'].nr = RC_DABBREV; +#endif /* These come last; they may want overwrite others: */ if (DefaultEsc >= 0) ktab[DefaultEsc].nr = RC_OTHER; @@ -576,9 +583,14 @@ ilen--; } slen -= ilen; + /*!!! Msg (0, "pi2: %d, %d, %d, `%.*s'", D_ESCseen, ilen, slen, ilen, ibuf); */ +#ifdef DABBREV + if (slen > 0) /* normal keystroke */ + restart_dabbrev = 1; +#endif while (slen) Process(&ibuf, &slen); - if (--ilen == 0) + if (--ilen == 0) /* ESC was last */ D_ESCseen = 1; } if (ilen <= 0) @@ -771,6 +783,12 @@ #endif /* MULTIUSER */ msgok = display && !*rc_name; + +#ifdef DABBREV /* all commands assumed to disrupt */ + if (nr != RC_DABBREV) + restart_dabbrev = 1; +#endif + switch(nr) { case RC_SELECT: @@ -1560,6 +1578,10 @@ } MarkRoutine(); break; + +#ifdef DABBREV + case RC_DABBREV: /* tjc */ +#endif case RC_HISTORY: { static char *pasteargs[] = {".", 0}; @@ -1569,8 +1591,18 @@ Msg(0, "Must be on a window layer"); break; } + +#ifdef DABBREV + if (nr == RC_DABBREV) { + if (DabbrevExpand() == 0) { + PutStr (D_BL); + break; + } + } else +#endif /* DABBREV */ if (GetHistory() == 0) break; + if (D_user->u_copybuffer == NULL) break; args = pasteargs; @@ -2726,9 +2758,11 @@ Msg(0, "%s", s); break; #endif /* MULTIUSER */ + + default: #ifdef HAVE_BRAILLE - /* key == -2: input from braille keybord, msgok always 0 */ + /* key == -2: input from braille keyboard, msgok always 0 */ DoBrailleAction(act, key == -2 ? 0 : msgok); #endif break;