This fixes a few issues with macros in ksh emacs input mode. I'm sure
it's not widely used but I'd be glad if someone could have a look at
it so I can get the diff out of my tree.
Ok, so what does it do? Here goes:
1. Expanding a macro containing characters that themselves are macros
$ bind -m X=123
$ bind -m 2=Y
pre: 'X' => '13'
post: 'X' => '123'
2. Expanding a macro having itself as the last character
$ bind -m X=YX
pre: 'X' => hard hang requiring kill -9 to stop
post: 'X' => 'YX'
3. Having a macro that spans multiple input lines (newline,
newline-and-next) (normally ^M, ^J, ^O)
$ bind -m X=^A^Kclear^J^Y # clear the screen and continue editing
pre: 'X' => $ _
post: 'X' => $ mplayer humppa.mp3_
Comments?
/Alexander
( diffed with -U10 to make some parts more clear )
Index: emacs.c
===================================================================
RCS file: /cvs/src/bin/ksh/emacs.c,v
retrieving revision 1.41
diff -u -p -U10 -r1.41 emacs.c
--- emacs.c 2 Aug 2007 10:50:25 -0000 1.41
+++ emacs.c 2 Jun 2009 00:59:55 -0000
@@ -97,21 +97,21 @@ static char **x_histp; /* history posi
static int x_nextcmd; /* for newline-and-next */
static char *xmp; /* mark pointer */
static u_char x_last_command;
static u_char (*x_tab)[X_TABSZ]; /* key definition */
static char *(*x_atab)[X_TABSZ]; /* macro definitions */
static unsigned char x_bound[(X_TABSZ * X_NTABS + 7) / 8];
#define KILLSIZE 20
static char *killstack[KILLSIZE];
static int killsp, killtp;
static int x_curprefix;
-static char *macroptr;
+static char *macroptr = NULL;
static int prompt_skip;
static int prompt_redraw;
static int x_ins(char *);
static void x_delete(int, int);
static int x_bword(void);
static int x_fword(void);
static void x_goto(char *);
static void x_bs(int);
static int x_size_str(char *);
@@ -312,21 +312,20 @@ x_emacs(char *buf, size_t len)
const char *p;
int i;
u_char f;
xbp = xbuf = buf; xend = buf + len;
xlp = xcp = xep = buf;
*xcp = 0;
xlp_valid = true;
xmp = NULL;
x_curprefix = 0;
- macroptr = (char *) 0;
x_histp = histptr + 1;
x_last_command = XFUNC_error;
xx_cols = x_cols;
x_col = promptlen(prompt, &p);
prompt_skip = p - prompt;
x_adj_ok = 1;
prompt_redraw = 1;
if (x_col > xx_cols)
x_col = x_col - (x_col / xx_cols) * xx_cols;
@@ -354,20 +353,23 @@ x_emacs(char *buf, size_t len)
return 0;
if (ISMETA(c)) {
c = META(c);
x_curprefix = 1;
}
f = x_curprefix == -1 ? XFUNC_insert :
x_tab[x_curprefix][c&CHARMASK];
+ if (macroptr && f == XFUNC_ins_string)
+ f = XFUNC_insert;
+
if (!(x_ftab[f].xf_flags & XF_PREFIX) &&
x_last_command != XFUNC_set_arg) {
x_arg = 1;
x_arg_defaulted = 1;
}
i = c | (x_curprefix << 8);
x_curprefix = 0;
switch (i = (*x_ftab[f].xf_func)(i)) {
case KSTD:
if (!(x_ftab[f].xf_flags & XF_PREFIX))
@@ -1755,22 +1757,24 @@ static int
x_e_getc(void)
{
int c;
if (unget_char >= 0) {
c = unget_char;
unget_char = -1;
} else {
if (macroptr) {
c = *macroptr++;
- if (!*macroptr)
- macroptr = (char *) 0;
+ if (!c) {
+ macroptr = NULL;
+ c = x_getc();
+ }
} else
c = x_getc();
}
return c <= CHARMASK ? c : (c & CHARMASK);
}
static void
x_e_putc(int c)
{