commiting:
0000025: vi-editing mode for ash
This commit is contained in:
parent
8eeb655661
commit
3f11b1bf63
2
AUTHORS
2
AUTHORS
@ -157,3 +157,5 @@ Tito Ragusa <farmatito@tiscali.it>
|
|||||||
devfsd and size optimizations in strings, openvt, chvt, deallocvt, hdparm,
|
devfsd and size optimizations in strings, openvt, chvt, deallocvt, hdparm,
|
||||||
fdformat, lsattr, chattr, id and eject.
|
fdformat, lsattr, chattr, id and eject.
|
||||||
|
|
||||||
|
Paul Fox <pgf@foxharp.boston.ma.us>
|
||||||
|
vi editing mode for ash, various other patches/fixes
|
||||||
|
@ -201,6 +201,14 @@ config CONFIG_FEATURE_COMMAND_EDITING
|
|||||||
help
|
help
|
||||||
Enable command editing in shell.
|
Enable command editing in shell.
|
||||||
|
|
||||||
|
config CONFIG_FEATURE_COMMAND_EDITING_VI
|
||||||
|
bool "vi-style line editing commands"
|
||||||
|
default n
|
||||||
|
depends on CONFIG_FEATURE_COMMAND_EDITING
|
||||||
|
help
|
||||||
|
Enable vi-style line editing in the shell. This mode can be
|
||||||
|
turned on and off with "set -o vi" and "set +o vi".
|
||||||
|
|
||||||
config CONFIG_FEATURE_COMMAND_HISTORY
|
config CONFIG_FEATURE_COMMAND_HISTORY
|
||||||
int "history size"
|
int "history size"
|
||||||
default 15
|
default 15
|
||||||
|
17
shell/ash.c
17
shell/ash.c
@ -1949,19 +1949,21 @@ struct shparam {
|
|||||||
#define bflag optlist[11]
|
#define bflag optlist[11]
|
||||||
#define uflag optlist[12]
|
#define uflag optlist[12]
|
||||||
#define qflag optlist[13]
|
#define qflag optlist[13]
|
||||||
|
#define viflag optlist[14]
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define nolog optlist[14]
|
#define nolog optlist[15]
|
||||||
#define debug optlist[15]
|
#define debug optlist[16]
|
||||||
#define NOPTS 16
|
#endif
|
||||||
#else
|
|
||||||
#define NOPTS 14
|
#ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
|
||||||
|
#define setvimode(on) viflag = 0 /* forcibly keep the option off */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* $NetBSD: options.c,v 1.33 2003/01/22 20:36:04 dsl Exp $ */
|
/* $NetBSD: options.c,v 1.33 2003/01/22 20:36:04 dsl Exp $ */
|
||||||
|
|
||||||
|
|
||||||
static const char *const optletters_optnames[NOPTS] = {
|
static const char *const optletters_optnames[] = {
|
||||||
"e" "errexit",
|
"e" "errexit",
|
||||||
"f" "noglob",
|
"f" "noglob",
|
||||||
"I" "ignoreeof",
|
"I" "ignoreeof",
|
||||||
@ -1976,6 +1978,7 @@ static const char *const optletters_optnames[NOPTS] = {
|
|||||||
"b" "notify",
|
"b" "notify",
|
||||||
"u" "nounset",
|
"u" "nounset",
|
||||||
"q" "quietprofile",
|
"q" "quietprofile",
|
||||||
|
"\0" "vi",
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
"\0" "nolog",
|
"\0" "nolog",
|
||||||
"\0" "debug",
|
"\0" "debug",
|
||||||
@ -1985,6 +1988,7 @@ static const char *const optletters_optnames[NOPTS] = {
|
|||||||
#define optletters(n) optletters_optnames[(n)][0]
|
#define optletters(n) optletters_optnames[(n)][0]
|
||||||
#define optnames(n) (&optletters_optnames[(n)][1])
|
#define optnames(n) (&optletters_optnames[(n)][1])
|
||||||
|
|
||||||
|
#define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
|
||||||
|
|
||||||
static char optlist[NOPTS];
|
static char optlist[NOPTS];
|
||||||
|
|
||||||
@ -8862,6 +8866,7 @@ optschanged(void)
|
|||||||
#endif
|
#endif
|
||||||
setinteractive(iflag);
|
setinteractive(iflag);
|
||||||
setjobctl(mflag);
|
setjobctl(mflag);
|
||||||
|
setvimode(viflag);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
393
shell/cmdedit.c
393
shell/cmdedit.c
@ -441,27 +441,61 @@ static void redraw(int y, int back_cursor)
|
|||||||
input_backward(back_cursor);
|
input_backward(back_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Delete the char in front of the cursor */
|
#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
|
||||||
static void input_delete(void)
|
static char delbuf[BUFSIZ]; /* a place to store deleted characters */
|
||||||
|
static char *delp = delbuf;
|
||||||
|
static int newdelflag; /* whether delbuf should be reused yet */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Delete the char in front of the cursor, optionally saving it
|
||||||
|
* for later putback */
|
||||||
|
static void input_delete(int save)
|
||||||
{
|
{
|
||||||
int j = cursor;
|
int j = cursor;
|
||||||
|
|
||||||
if (j == len)
|
if (j == len)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
|
||||||
|
if (save) {
|
||||||
|
if (newdelflag) {
|
||||||
|
delp = delbuf;
|
||||||
|
newdelflag = 0;
|
||||||
|
}
|
||||||
|
if (delp - delbuf < BUFSIZ)
|
||||||
|
*delp++ = command_ps[j];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
strcpy(command_ps + j, command_ps + j + 1);
|
strcpy(command_ps + j, command_ps + j + 1);
|
||||||
len--;
|
len--;
|
||||||
input_end(); /* rewtite new line */
|
input_end(); /* rewrite new line */
|
||||||
cmdedit_set_out_char(0); /* destroy end char */
|
cmdedit_set_out_char(0); /* destroy end char */
|
||||||
input_backward(cursor - j); /* back to old pos cursor */
|
input_backward(cursor - j); /* back to old pos cursor */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
|
||||||
|
static void put(void)
|
||||||
|
{
|
||||||
|
int ocursor, j = delp - delbuf;
|
||||||
|
if (j == 0)
|
||||||
|
return;
|
||||||
|
ocursor = cursor;
|
||||||
|
/* open hole and then fill it */
|
||||||
|
memmove(command_ps + cursor + j, command_ps + cursor, len - cursor + 1);
|
||||||
|
strncpy(command_ps + cursor, delbuf, j);
|
||||||
|
len += j;
|
||||||
|
input_end(); /* rewrite new line */
|
||||||
|
input_backward(cursor-ocursor-j+1); /* at end of new text */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Delete the char in back of the cursor */
|
/* Delete the char in back of the cursor */
|
||||||
static void input_backspace(void)
|
static void input_backspace(void)
|
||||||
{
|
{
|
||||||
if (cursor > 0) {
|
if (cursor > 0) {
|
||||||
input_backward(1);
|
input_backward(1);
|
||||||
input_delete();
|
input_delete(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,7 +507,6 @@ static void input_forward(void)
|
|||||||
cmdedit_set_out_char(command_ps[cursor + 1]);
|
cmdedit_set_out_char(command_ps[cursor + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void cmdedit_setwidth(int w, int redraw_flg)
|
static void cmdedit_setwidth(int w, int redraw_flg)
|
||||||
{
|
{
|
||||||
cmdedit_termw = cmdedit_prmt_len + 2;
|
cmdedit_termw = cmdedit_prmt_len + 2;
|
||||||
@ -1217,18 +1250,147 @@ enum {
|
|||||||
* ESC-h -- Delete forward one word
|
* ESC-h -- Delete forward one word
|
||||||
* CTL-t -- Transpose two characters
|
* CTL-t -- Transpose two characters
|
||||||
*
|
*
|
||||||
* Furthermore, the "vi" command editing keys are not implemented.
|
* Minimalist vi-style command line editing available if configured.
|
||||||
|
* vi mode implemented 2005 by Paul Fox <pgf@foxharp.boston.ma.us>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
|
||||||
|
static int vi_mode;
|
||||||
|
|
||||||
|
void setvimode ( int viflag )
|
||||||
|
{
|
||||||
|
vi_mode = viflag;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vi_Word_motion(char *command, int eat)
|
||||||
|
{
|
||||||
|
while (cursor < len && !isspace(command[cursor]))
|
||||||
|
input_forward();
|
||||||
|
if (eat) while (cursor < len && isspace(command[cursor]))
|
||||||
|
input_forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vi_word_motion(char *command, int eat)
|
||||||
|
{
|
||||||
|
if (isalnum(command[cursor]) || command[cursor] == '_') {
|
||||||
|
while (cursor < len &&
|
||||||
|
(isalnum(command[cursor+1]) ||
|
||||||
|
command[cursor+1] == '_'))
|
||||||
|
input_forward();
|
||||||
|
} else if (ispunct(command[cursor])) {
|
||||||
|
while (cursor < len &&
|
||||||
|
(ispunct(command[cursor+1])))
|
||||||
|
input_forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor < len)
|
||||||
|
input_forward();
|
||||||
|
|
||||||
|
if (eat && cursor < len && isspace(command[cursor]))
|
||||||
|
while (cursor < len && isspace(command[cursor]))
|
||||||
|
input_forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vi_End_motion(char *command)
|
||||||
|
{
|
||||||
|
input_forward();
|
||||||
|
while (cursor < len && isspace(command[cursor]))
|
||||||
|
input_forward();
|
||||||
|
while (cursor < len-1 && !isspace(command[cursor+1]))
|
||||||
|
input_forward();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vi_end_motion(char *command)
|
||||||
|
{
|
||||||
|
if (cursor >= len-1)
|
||||||
|
return;
|
||||||
|
input_forward();
|
||||||
|
while (cursor < len-1 && isspace(command[cursor]))
|
||||||
|
input_forward();
|
||||||
|
if (cursor >= len-1)
|
||||||
|
return;
|
||||||
|
if (isalnum(command[cursor]) || command[cursor] == '_') {
|
||||||
|
while (cursor < len-1 &&
|
||||||
|
(isalnum(command[cursor+1]) ||
|
||||||
|
command[cursor+1] == '_'))
|
||||||
|
input_forward();
|
||||||
|
} else if (ispunct(command[cursor])) {
|
||||||
|
while (cursor < len-1 &&
|
||||||
|
(ispunct(command[cursor+1])))
|
||||||
|
input_forward();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vi_Back_motion(char *command)
|
||||||
|
{
|
||||||
|
while (cursor > 0 && isspace(command[cursor-1]))
|
||||||
|
input_backward(1);
|
||||||
|
while (cursor > 0 && !isspace(command[cursor-1]))
|
||||||
|
input_backward(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vi_back_motion(char *command)
|
||||||
|
{
|
||||||
|
if (cursor <= 0)
|
||||||
|
return;
|
||||||
|
input_backward(1);
|
||||||
|
while (cursor > 0 && isspace(command[cursor]))
|
||||||
|
input_backward(1);
|
||||||
|
if (cursor <= 0)
|
||||||
|
return;
|
||||||
|
if (isalnum(command[cursor]) || command[cursor] == '_') {
|
||||||
|
while (cursor > 0 &&
|
||||||
|
(isalnum(command[cursor-1]) ||
|
||||||
|
command[cursor-1] == '_'))
|
||||||
|
input_backward(1);
|
||||||
|
} else if (ispunct(command[cursor])) {
|
||||||
|
while (cursor > 0 &&
|
||||||
|
(ispunct(command[cursor-1])))
|
||||||
|
input_backward(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the normal emacs mode and vi's insert mode are the same.
|
||||||
|
* commands entered when in vi command mode ("escape mode") get
|
||||||
|
* an extra bit added to distinguish them. this lets them share
|
||||||
|
* much of the code in the big switch and while loop. i
|
||||||
|
* experimented with an ugly macro to make the case labels for
|
||||||
|
* these cases go away entirely when vi mode isn't configured, in
|
||||||
|
* hopes of letting the jump tables get smaller:
|
||||||
|
* #define vcase(caselabel) caselabel
|
||||||
|
* and then
|
||||||
|
* case CNTRL('A'):
|
||||||
|
* case vcase(VICMD('0'):)
|
||||||
|
* but it didn't seem to make any difference in code size,
|
||||||
|
* and the macro-ized code was too ugly.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define VI_cmdbit 0x100
|
||||||
|
#define VICMD(somecmd) ((somecmd)|VI_cmdbit)
|
||||||
|
|
||||||
|
/* convert uppercase ascii to equivalent control char, for readability */
|
||||||
|
#define CNTRL(uc_char) ((uc_char) - 0x40)
|
||||||
|
|
||||||
|
|
||||||
int cmdedit_read_input(char *prompt, char command[BUFSIZ])
|
int cmdedit_read_input(char *prompt, char command[BUFSIZ])
|
||||||
{
|
{
|
||||||
|
|
||||||
int break_out = 0;
|
int break_out = 0;
|
||||||
int lastWasTab = FALSE;
|
int lastWasTab = FALSE;
|
||||||
unsigned char c = 0;
|
unsigned char c;
|
||||||
|
#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
|
||||||
|
unsigned int ic, prevc;
|
||||||
|
int vi_cmdmode = 0;
|
||||||
|
#endif
|
||||||
/* prepare before init handlers */
|
/* prepare before init handlers */
|
||||||
cmdedit_y = 0; /* quasireal y, not true work if line > xt*yt */
|
cmdedit_y = 0; /* quasireal y, not true work if line > xt*yt */
|
||||||
len = 0;
|
len = 0;
|
||||||
@ -1265,22 +1427,38 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
|
|||||||
/* if we can't read input then exit */
|
/* if we can't read input then exit */
|
||||||
goto prepare_to_die;
|
goto prepare_to_die;
|
||||||
|
|
||||||
switch (c) {
|
#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
|
||||||
|
newdelflag = 1;
|
||||||
|
ic = c;
|
||||||
|
if (vi_cmdmode)
|
||||||
|
ic |= VI_cmdbit;
|
||||||
|
switch (ic)
|
||||||
|
#else
|
||||||
|
switch (c)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\r':
|
case '\r':
|
||||||
|
case VICMD('\n'):
|
||||||
|
case VICMD('\r'):
|
||||||
/* Enter */
|
/* Enter */
|
||||||
goto_new_line();
|
goto_new_line();
|
||||||
break_out = 1;
|
break_out = 1;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case CNTRL('A'):
|
||||||
|
case VICMD('0'):
|
||||||
/* Control-a -- Beginning of line */
|
/* Control-a -- Beginning of line */
|
||||||
input_backward(cursor);
|
input_backward(cursor);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case CNTRL('B'):
|
||||||
|
case VICMD('h'):
|
||||||
|
case VICMD('\b'):
|
||||||
|
case VICMD(DEL):
|
||||||
/* Control-b -- Move back one character */
|
/* Control-b -- Move back one character */
|
||||||
input_backward(1);
|
input_backward(1);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case CNTRL('C'):
|
||||||
|
case VICMD(CNTRL('C')):
|
||||||
/* Control-c -- stop gathering input */
|
/* Control-c -- stop gathering input */
|
||||||
goto_new_line();
|
goto_new_line();
|
||||||
#ifndef CONFIG_ASH
|
#ifndef CONFIG_ASH
|
||||||
@ -1293,7 +1471,7 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
|
|||||||
break_out = -1; /* to control traps */
|
break_out = -1; /* to control traps */
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 4:
|
case CNTRL('D'):
|
||||||
/* Control-d -- Delete one character, or exit
|
/* Control-d -- Delete one character, or exit
|
||||||
* if the len=0 and no chars to delete */
|
* if the len=0 and no chars to delete */
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
@ -1310,14 +1488,17 @@ prepare_to_die:
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
input_delete();
|
input_delete(0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case CNTRL('E'):
|
||||||
|
case VICMD('$'):
|
||||||
/* Control-e -- End of line */
|
/* Control-e -- End of line */
|
||||||
input_end();
|
input_end();
|
||||||
break;
|
break;
|
||||||
case 6:
|
case CNTRL('F'):
|
||||||
|
case VICMD('l'):
|
||||||
|
case VICMD(' '):
|
||||||
/* Control-f -- Move forward one character */
|
/* Control-f -- Move forward one character */
|
||||||
input_forward();
|
input_forward();
|
||||||
break;
|
break;
|
||||||
@ -1331,24 +1512,29 @@ prepare_to_die:
|
|||||||
input_tab(&lastWasTab);
|
input_tab(&lastWasTab);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 11:
|
case CNTRL('K'):
|
||||||
/* Control-k -- clear to end of line */
|
/* Control-k -- clear to end of line */
|
||||||
*(command + cursor) = 0;
|
*(command + cursor) = 0;
|
||||||
len = cursor;
|
len = cursor;
|
||||||
printf("\033[J");
|
printf("\033[J");
|
||||||
break;
|
break;
|
||||||
case 12:
|
case CNTRL('L'):
|
||||||
|
case VICMD(CNTRL('L')):
|
||||||
/* Control-l -- clear screen */
|
/* Control-l -- clear screen */
|
||||||
printf("\033[H");
|
printf("\033[H");
|
||||||
redraw(0, len-cursor);
|
redraw(0, len-cursor);
|
||||||
break;
|
break;
|
||||||
#if MAX_HISTORY >= 1
|
#if MAX_HISTORY >= 1
|
||||||
case 14:
|
case CNTRL('N'):
|
||||||
|
case VICMD(CNTRL('N')):
|
||||||
|
case VICMD('j'):
|
||||||
/* Control-n -- Get next command in history */
|
/* Control-n -- Get next command in history */
|
||||||
if (get_next_history())
|
if (get_next_history())
|
||||||
goto rewrite_line;
|
goto rewrite_line;
|
||||||
break;
|
break;
|
||||||
case 16:
|
case CNTRL('P'):
|
||||||
|
case VICMD(CNTRL('P')):
|
||||||
|
case VICMD('k'):
|
||||||
/* Control-p -- Get previous command from history */
|
/* Control-p -- Get previous command from history */
|
||||||
if (cur_history > 0) {
|
if (cur_history > 0) {
|
||||||
get_previous_history();
|
get_previous_history();
|
||||||
@ -1358,26 +1544,167 @@ prepare_to_die:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 21:
|
case CNTRL('U'):
|
||||||
|
case VICMD(CNTRL('U')):
|
||||||
/* Control-U -- Clear line before cursor */
|
/* Control-U -- Clear line before cursor */
|
||||||
if (cursor) {
|
if (cursor) {
|
||||||
strcpy(command, command + cursor);
|
strcpy(command, command + cursor);
|
||||||
redraw(cmdedit_y, len -= cursor);
|
redraw(cmdedit_y, len -= cursor);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 23:
|
case CNTRL('W'):
|
||||||
|
case VICMD(CNTRL('W')):
|
||||||
/* Control-W -- Remove the last word */
|
/* Control-W -- Remove the last word */
|
||||||
while (cursor > 0 && isspace(command[cursor-1]))
|
while (cursor > 0 && isspace(command[cursor-1]))
|
||||||
input_backspace();
|
input_backspace();
|
||||||
while (cursor > 0 &&!isspace(command[cursor-1]))
|
while (cursor > 0 &&!isspace(command[cursor-1]))
|
||||||
input_backspace();
|
input_backspace();
|
||||||
break;
|
break;
|
||||||
|
#if CONFIG_FEATURE_COMMAND_EDITING_VI
|
||||||
|
case VICMD('i'):
|
||||||
|
vi_cmdmode = 0;
|
||||||
|
break;
|
||||||
|
case VICMD('I'):
|
||||||
|
input_backward(cursor);
|
||||||
|
vi_cmdmode = 0;
|
||||||
|
break;
|
||||||
|
case VICMD('a'):
|
||||||
|
input_forward();
|
||||||
|
vi_cmdmode = 0;
|
||||||
|
break;
|
||||||
|
case VICMD('A'):
|
||||||
|
input_end();
|
||||||
|
vi_cmdmode = 0;
|
||||||
|
break;
|
||||||
|
case VICMD('x'):
|
||||||
|
input_delete(1);
|
||||||
|
break;
|
||||||
|
case VICMD('X'):
|
||||||
|
if (cursor > 0) {
|
||||||
|
input_backward(1);
|
||||||
|
input_delete(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VICMD('W'):
|
||||||
|
vi_Word_motion(command, 1);
|
||||||
|
break;
|
||||||
|
case VICMD('w'):
|
||||||
|
vi_word_motion(command, 1);
|
||||||
|
break;
|
||||||
|
case VICMD('E'):
|
||||||
|
vi_End_motion(command);
|
||||||
|
break;
|
||||||
|
case VICMD('e'):
|
||||||
|
vi_end_motion(command);
|
||||||
|
break;
|
||||||
|
case VICMD('B'):
|
||||||
|
vi_Back_motion(command);
|
||||||
|
break;
|
||||||
|
case VICMD('b'):
|
||||||
|
vi_back_motion(command);
|
||||||
|
break;
|
||||||
|
case VICMD('C'):
|
||||||
|
vi_cmdmode = 0;
|
||||||
|
/* fall through */
|
||||||
|
case VICMD('D'):
|
||||||
|
goto clear_to_eol;
|
||||||
|
|
||||||
|
case VICMD('c'):
|
||||||
|
vi_cmdmode = 0;
|
||||||
|
/* fall through */
|
||||||
|
case VICMD('d'):
|
||||||
|
{
|
||||||
|
int nc, sc;
|
||||||
|
sc = cursor;
|
||||||
|
prevc = ic;
|
||||||
|
if (safe_read(0, &c, 1) < 1)
|
||||||
|
goto prepare_to_die;
|
||||||
|
if (c == (prevc & 0xff)) {
|
||||||
|
/* "cc", "dd" */
|
||||||
|
input_backward(cursor);
|
||||||
|
goto clear_to_eol;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch(c) {
|
||||||
|
case 'w':
|
||||||
|
case 'W':
|
||||||
|
case 'e':
|
||||||
|
case 'E':
|
||||||
|
switch (c) {
|
||||||
|
case 'w': /* "dw", "cw" */
|
||||||
|
vi_word_motion(command, vi_cmdmode);
|
||||||
|
break;
|
||||||
|
case 'W': /* 'dW', 'cW' */
|
||||||
|
vi_Word_motion(command, vi_cmdmode);
|
||||||
|
break;
|
||||||
|
case 'e': /* 'de', 'ce' */
|
||||||
|
vi_end_motion(command);
|
||||||
|
input_forward();
|
||||||
|
break;
|
||||||
|
case 'E': /* 'dE', 'cE' */
|
||||||
|
vi_End_motion(command);
|
||||||
|
input_forward();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nc = cursor;
|
||||||
|
input_backward(cursor - sc);
|
||||||
|
while (nc-- > cursor)
|
||||||
|
input_delete(1);
|
||||||
|
break;
|
||||||
|
case 'b': /* "db", "cb" */
|
||||||
|
case 'B': /* implemented as B */
|
||||||
|
if (c == 'b')
|
||||||
|
vi_back_motion(command);
|
||||||
|
else
|
||||||
|
vi_Back_motion(command);
|
||||||
|
while (sc-- > cursor)
|
||||||
|
input_delete(1);
|
||||||
|
break;
|
||||||
|
case ' ': /* "d ", "c " */
|
||||||
|
input_delete(1);
|
||||||
|
break;
|
||||||
|
case '$': /* "d$", "c$" */
|
||||||
|
clear_to_eol:
|
||||||
|
while (cursor < len)
|
||||||
|
input_delete(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case VICMD('p'):
|
||||||
|
input_forward();
|
||||||
|
/* fallthrough */
|
||||||
|
case VICMD('P'):
|
||||||
|
put();
|
||||||
|
break;
|
||||||
|
case VICMD('r'):
|
||||||
|
if (safe_read(0, &c, 1) < 1)
|
||||||
|
goto prepare_to_die;
|
||||||
|
if (c == 0)
|
||||||
|
beep();
|
||||||
|
else {
|
||||||
|
*(command + cursor) = c;
|
||||||
|
putchar(c);
|
||||||
|
putchar('\b');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* CONFIG_FEATURE_COMMAND_EDITING_VI */
|
||||||
case ESC:{
|
case ESC:{
|
||||||
|
#if CONFIG_FEATURE_COMMAND_EDITING_VI
|
||||||
|
if (vi_mode) {
|
||||||
|
/* ESC: insert mode --> command mode */
|
||||||
|
vi_cmdmode = 1;
|
||||||
|
input_backward(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* escape sequence follows */
|
/* escape sequence follows */
|
||||||
if (safe_read(0, &c, 1) < 1)
|
if (safe_read(0, &c, 1) < 1)
|
||||||
goto prepare_to_die;
|
goto prepare_to_die;
|
||||||
/* different vt100 emulations */
|
/* different vt100 emulations */
|
||||||
if (c == '[' || c == 'O') {
|
if (c == '[' || c == 'O') {
|
||||||
|
case VICMD('['):
|
||||||
|
case VICMD('O'):
|
||||||
if (safe_read(0, &c, 1) < 1)
|
if (safe_read(0, &c, 1) < 1)
|
||||||
goto prepare_to_die;
|
goto prepare_to_die;
|
||||||
}
|
}
|
||||||
@ -1409,13 +1736,17 @@ prepare_to_die:
|
|||||||
case 'B':
|
case 'B':
|
||||||
/* Down Arrow -- Get next command in history */
|
/* Down Arrow -- Get next command in history */
|
||||||
if (!get_next_history())
|
if (!get_next_history())
|
||||||
break;
|
break;
|
||||||
/* Rewrite the line with the selected history item */
|
/* Rewrite the line with the selected history item */
|
||||||
rewrite_line:
|
rewrite_line:
|
||||||
/* change command */
|
/* change command */
|
||||||
len = strlen(strcpy(command, history[cur_history]));
|
len = strlen(strcpy(command, history[cur_history]));
|
||||||
/* redraw and go to end line */
|
/* redraw and go to eol (bol, in vi */
|
||||||
|
#if CONFIG_FEATURE_COMMAND_EDITING_VI
|
||||||
|
redraw(cmdedit_y, vi_mode ? 9999:0);
|
||||||
|
#else
|
||||||
redraw(cmdedit_y, 0);
|
redraw(cmdedit_y, 0);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 'C':
|
case 'C':
|
||||||
@ -1428,7 +1759,7 @@ rewrite_line:
|
|||||||
break;
|
break;
|
||||||
case '3':
|
case '3':
|
||||||
/* Delete */
|
/* Delete */
|
||||||
input_delete();
|
input_delete(0);
|
||||||
break;
|
break;
|
||||||
case '1':
|
case '1':
|
||||||
case 'H':
|
case 'H':
|
||||||
@ -1450,7 +1781,7 @@ rewrite_line:
|
|||||||
default: /* If it's regular input, do the normal thing */
|
default: /* If it's regular input, do the normal thing */
|
||||||
#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
|
#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
|
||||||
/* Control-V -- Add non-printable symbol */
|
/* Control-V -- Add non-printable symbol */
|
||||||
if (c == 22) {
|
if (c == CNTRL('V')) {
|
||||||
if (safe_read(0, &c, 1) < 1)
|
if (safe_read(0, &c, 1) < 1)
|
||||||
goto prepare_to_die;
|
goto prepare_to_die;
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
@ -1459,8 +1790,14 @@ rewrite_line:
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (!Isprint(c)) /* Skip non-printable characters */
|
{
|
||||||
break;
|
#if CONFIG_FEATURE_COMMAND_EDITING_VI
|
||||||
|
if (vi_cmdmode) /* don't self-insert */
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
if (!Isprint(c)) /* Skip non-printable characters */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (len >= (BUFSIZ - 2)) /* Need to leave space for enter */
|
if (len >= (BUFSIZ - 2)) /* Need to leave space for enter */
|
||||||
break;
|
break;
|
||||||
|
@ -12,4 +12,8 @@ void load_history ( const char *fromfile );
|
|||||||
void save_history ( const char *tofile );
|
void save_history ( const char *tofile );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_FEATURE_COMMAND_EDITING_VI
|
||||||
|
void setvimode ( int viflag );
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* CMDEDIT_H */
|
#endif /* CMDEDIT_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user