implement a hack whereas you can now bind functions (and macros)

to keys with a trailing tilde (after prefix + control char); the
function is then invoked after prefices, control char and one more
character X are entered; if X is not a tilde, it is ungetc(3)d
This commit is contained in:
tg 2006-08-02 13:32:18 +00:00
parent b99aa06d9b
commit c96e31a707
2 changed files with 41 additions and 15 deletions

39
edit.c
View File

@ -5,7 +5,7 @@
#include "sh.h" #include "sh.h"
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.31 2006/08/02 12:54:48 tg Exp $"); __RCSID("$MirOS: src/bin/mksh/edit.c,v 1.32 2006/08/02 13:32:17 tg Exp $");
/* tty driver characters we are interested in */ /* tty driver characters we are interested in */
typedef struct { typedef struct {
@ -1015,6 +1015,8 @@ static void bind_if_not_bound(int, int, int);
#define XFUNC_comment 54 #define XFUNC_comment 54
#define XFUNC_version 55 #define XFUNC_version 55
/* XFUNC_* must be < 128 */
static int x_abort (int); static int x_abort (int);
static int x_beg_hist (int); static int x_beg_hist (int);
static int x_comp_comm (int); static int x_comp_comm (int);
@ -1214,6 +1216,9 @@ static struct x_defbindings const x_defbindings[] = {
{ XFUNC_next_com, 2, 'B' }, { XFUNC_next_com, 2, 'B' },
{ XFUNC_mv_forw, 2, 'C' }, { XFUNC_mv_forw, 2, 'C' },
{ XFUNC_mv_back, 2, 'D' }, { XFUNC_mv_back, 2, 'D' },
{ XFUNC_mv_begin | 0x80, 2, '1' },
{ XFUNC_mv_end | 0x80, 2, '4' },
{ XFUNC_eot_del | 0x80, 2, '3' },
}; };
int int
@ -1266,6 +1271,11 @@ x_emacs(char *buf, size_t len)
} }
f = x_curprefix == -1 ? XFUNC_insert : f = x_curprefix == -1 ? XFUNC_insert :
x_tab[x_curprefix][c & CHARMASK]; x_tab[x_curprefix][c & CHARMASK];
if (f & 0x80) {
f &= 0x7F;
if ((i = x_e_getc()) != '~')
x_e_ungetc(i);
}
if (!(x_ftab[f].xf_flags & XF_PREFIX) && if (!(x_ftab[f].xf_flags & XF_PREFIX) &&
x_last_command != XFUNC_set_arg) { x_last_command != XFUNC_set_arg) {
@ -1795,6 +1805,11 @@ x_search_hist(int c)
if ((c = x_e_getc()) < 0) if ((c = x_e_getc()) < 0)
return KSTD; return KSTD;
f = x_tab[0][c & CHARMASK]; f = x_tab[0][c & CHARMASK];
if (f & 0x80) {
f &= 0x7F;
if ((c = x_e_getc()) != '~')
x_e_ungetc(c);
}
if (c == MKCTRL('[')) if (c == MKCTRL('['))
break; break;
else if (f == XFUNC_search_hist) else if (f == XFUNC_search_hist)
@ -2210,13 +2225,15 @@ x_mapout(int c)
static void static void
x_print(int prefix, int key) x_print(int prefix, int key)
{ {
int f = x_tab[prefix][key];
if (prefix == 1) if (prefix == 1)
shprintf("%s", x_mapout(x_prefix1)); shprintf("%s", x_mapout(x_prefix1));
if (prefix == 2) if (prefix == 2)
shprintf("%s", x_mapout(x_prefix2)); shprintf("%s", x_mapout(x_prefix2));
shprintf("%s = ", x_mapout(key)); shprintf("%s%s = ", x_mapout(key), (f & 0x80) ? "~" : "");
if (x_tab[prefix][key] != XFUNC_ins_string) if ((f & 0x7F) != XFUNC_ins_string)
shprintf("%s\n", x_ftab[x_tab[prefix][key]].xf_name); shprintf("%s\n", x_ftab[f & 0x7F].xf_name);
else else
shprintf("'%s'\n", x_atab[prefix][key]); shprintf("'%s'\n", x_atab[prefix][key]);
} }
@ -2246,7 +2263,7 @@ x_bind(const char *a1, const char *a2,
if (a1 == NULL) { if (a1 == NULL) {
for (prefix = 0; prefix < X_NTABS; prefix++) for (prefix = 0; prefix < X_NTABS; prefix++)
for (key = 0; key < X_TABSZ; key++) { for (key = 0; key < X_TABSZ; key++) {
f = x_tab[prefix][key]; f = x_tab[prefix][key] & 0x7F;
if (f == XFUNC_insert || f == XFUNC_error || if (f == XFUNC_insert || f == XFUNC_error ||
(macro && f != XFUNC_ins_string)) (macro && f != XFUNC_ins_string))
continue; continue;
@ -2258,14 +2275,15 @@ x_bind(const char *a1, const char *a2,
prefix = key = 0; prefix = key = 0;
for (;; m1++) { for (;; m1++) {
key = *m1 & CHARMASK; key = *m1 & CHARMASK;
if (x_tab[prefix][key] == XFUNC_meta1) f = x_tab[prefix][key] & 0x7F;
if (f == XFUNC_meta1)
prefix = 1; prefix = 1;
else if (x_tab[prefix][key] == XFUNC_meta2) else if (f == XFUNC_meta2)
prefix = 2; prefix = 2;
else else
break; break;
} }
if (*++m1) { if (*++m1 && ((*m1 != '~') || *(m1+1))) {
char msg[256] = "bind: key sequence '"; char msg[256] = "bind: key sequence '";
const char *c = a1; const char *c = a1;
while (*c) while (*c)
@ -2295,9 +2313,10 @@ x_bind(const char *a1, const char *a2,
sp = str_save(m2, AEDIT); sp = str_save(m2, AEDIT);
} }
if (x_tab[prefix][key] == XFUNC_ins_string && x_atab[prefix][key]) if ((x_tab[prefix][key] & 0x7F) == XFUNC_ins_string &&
x_atab[prefix][key])
afree((void *)x_atab[prefix][key], AEDIT); afree((void *)x_atab[prefix][key], AEDIT);
x_tab[prefix][key] = f; x_tab[prefix][key] = f | ((*m1) ? 0x80 : 0);
x_atab[prefix][key] = sp; x_atab[prefix][key] = sp;
/* Track what the user has bound so x_emacs_keys() won't toast things */ /* Track what the user has bound so x_emacs_keys() won't toast things */

17
mksh.1
View File

@ -1,4 +1,4 @@
.\" $MirOS: src/bin/mksh/mksh.1,v 1.45 2006/08/02 11:50:28 tg Exp $ .\" $MirOS: src/bin/mksh/mksh.1,v 1.46 2006/08/02 13:32:18 tg Exp $
.\" $OpenBSD: ksh.1,v 1.116 2006/07/26 10:13:25 jmc Exp $ .\" $OpenBSD: ksh.1,v 1.116 2006/07/26 10:13:25 jmc Exp $
.\" $OpenBSD: sh.1tbl,v 1.53 2004/12/10 01:56:56 jaredy Exp $ .\" $OpenBSD: sh.1tbl,v 1.53 2004/12/10 01:56:56 jaredy Exp $
.\" .\"
@ -2451,7 +2451,8 @@ for more information.
The specified editing command is bound to the given The specified editing command is bound to the given
.Ar string , .Ar string ,
which should consist of a control character which should consist of a control character
optionally preceded by one of the two prefix characters. optionally preceded by one of the two prefix characters
and optionally succeded by a tilde character.
Future input of the Future input of the
.Ar string .Ar string
will cause the editing command to be immediately invoked. will cause the editing command to be immediately invoked.
@ -2462,14 +2463,17 @@ flag is given, the specified input
will afterwards be immediately replaced by the given will afterwards be immediately replaced by the given
.Ar substitute .Ar substitute
string which may contain editing commands. string which may contain editing commands.
If a tilde postfix is given, a tilde trailing the one or
two prefices and the control character is ignored, any
other trailing character will be processed afterwards.
.Pp .Pp
Control characters may be written using caret notation Control characters may be written using caret notation
i.e. ^X represents Control-X. i.e. ^X represents Control-X.
Note that although only two prefix characters (usually ESC and ^X) Note that although only two prefix characters (usually ESC and ^X)
are supported, some multi-character sequences can be supported. are supported, some multi-character sequences can be supported.
.Pp .Pp
The following default bindings show how the arrow keys The following default bindings show how the arrow keys, the
on an ANSI terminal or xterm are bound home, end and delete key on an ANSI terminal or xterm are bound
(of course some escape sequences won't work out quite this nicely): (of course some escape sequences won't work out quite this nicely):
.Bd -literal -offset indent .Bd -literal -offset indent
bind '^[['=prefix-2 bind '^[['=prefix-2
@ -2477,6 +2481,9 @@ bind '^XA'=up-history
bind '^XB'=down-history bind '^XB'=down-history
bind '^XC'=forward-char bind '^XC'=forward-char
bind '^XD'=backward-char bind '^XD'=backward-char
bind '^X1~'=beginning-of-line
bind '^X3~'=eot-or-delete
bind '^X4~'=end-of-line
.Ed .Ed
.Pp .Pp
.It Ic break Op Ar level .It Ic break Op Ar level
@ -5268,7 +5275,7 @@ projects and patches and suggestions from users
and many other persons. and many other persons.
.Sh BUGS .Sh BUGS
This document attempts to describe This document attempts to describe
.Nm "" R27 . .Nm "" R28 .
The O'Reilly book documents the The O'Reilly book documents the
.At .At
.Nm KSH88 .Nm KSH88