aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpgf <pgf@69ca8d6d-28ef-0310-b511-8ec308f3f277>2005-08-04 19:04:46 +0000
committerpgf <pgf@69ca8d6d-28ef-0310-b511-8ec308f3f277>2005-08-04 19:04:46 +0000
commit9ed75acbe404efb10d292f5b1cd3fa9988846dea (patch)
treefd76457b91cc91d8ae6091729f981acd1b321888
parent68d6abfa3b67065ed32c71798cceff7aeb6a7714 (diff)
downloadbusybox-w32-9ed75acbe404efb10d292f5b1cd3fa9988846dea.tar.gz
busybox-w32-9ed75acbe404efb10d292f5b1cd3fa9988846dea.tar.bz2
busybox-w32-9ed75acbe404efb10d292f5b1cd3fa9988846dea.zip
commiting:
0000025: vi-editing mode for ash git-svn-id: svn://busybox.net/trunk/busybox@11044 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r--AUTHORS2
-rw-r--r--shell/Config.in8
-rw-r--r--shell/ash.c17
-rw-r--r--shell/cmdedit.c393
-rw-r--r--shell/cmdedit.h4
5 files changed, 390 insertions, 34 deletions
diff --git a/AUTHORS b/AUTHORS
index 24501f1d0..3582e0ba6 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -157,3 +157,5 @@ Tito Ragusa <farmatito@tiscali.it>
157 devfsd and size optimizations in strings, openvt, chvt, deallocvt, hdparm, 157 devfsd and size optimizations in strings, openvt, chvt, deallocvt, hdparm,
158 fdformat, lsattr, chattr, id and eject. 158 fdformat, lsattr, chattr, id and eject.
159 159
160Paul Fox <pgf@foxharp.boston.ma.us>
161 vi editing mode for ash, various other patches/fixes
diff --git a/shell/Config.in b/shell/Config.in
index 1a3c388a4..0d39e5bae 100644
--- a/shell/Config.in
+++ b/shell/Config.in
@@ -201,6 +201,14 @@ config CONFIG_FEATURE_COMMAND_EDITING
201 help 201 help
202 Enable command editing in shell. 202 Enable command editing in shell.
203 203
204config CONFIG_FEATURE_COMMAND_EDITING_VI
205 bool "vi-style line editing commands"
206 default n
207 depends on CONFIG_FEATURE_COMMAND_EDITING
208 help
209 Enable vi-style line editing in the shell. This mode can be
210 turned on and off with "set -o vi" and "set +o vi".
211
204config CONFIG_FEATURE_COMMAND_HISTORY 212config CONFIG_FEATURE_COMMAND_HISTORY
205 int "history size" 213 int "history size"
206 default 15 214 default 15
diff --git a/shell/ash.c b/shell/ash.c
index 783204933..7f77594a7 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -1949,19 +1949,21 @@ struct shparam {
1949#define bflag optlist[11] 1949#define bflag optlist[11]
1950#define uflag optlist[12] 1950#define uflag optlist[12]
1951#define qflag optlist[13] 1951#define qflag optlist[13]
1952#define viflag optlist[14]
1952 1953
1953#ifdef DEBUG 1954#ifdef DEBUG
1954#define nolog optlist[14] 1955#define nolog optlist[15]
1955#define debug optlist[15] 1956#define debug optlist[16]
1956#define NOPTS 16 1957#endif
1957#else 1958
1958#define NOPTS 14 1959#ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
1960#define setvimode(on) viflag = 0 /* forcibly keep the option off */
1959#endif 1961#endif
1960 1962
1961/* $NetBSD: options.c,v 1.33 2003/01/22 20:36:04 dsl Exp $ */ 1963/* $NetBSD: options.c,v 1.33 2003/01/22 20:36:04 dsl Exp $ */
1962 1964
1963 1965
1964static const char *const optletters_optnames[NOPTS] = { 1966static const char *const optletters_optnames[] = {
1965 "e" "errexit", 1967 "e" "errexit",
1966 "f" "noglob", 1968 "f" "noglob",
1967 "I" "ignoreeof", 1969 "I" "ignoreeof",
@@ -1976,6 +1978,7 @@ static const char *const optletters_optnames[NOPTS] = {
1976 "b" "notify", 1978 "b" "notify",
1977 "u" "nounset", 1979 "u" "nounset",
1978 "q" "quietprofile", 1980 "q" "quietprofile",
1981 "\0" "vi",
1979#ifdef DEBUG 1982#ifdef DEBUG
1980 "\0" "nolog", 1983 "\0" "nolog",
1981 "\0" "debug", 1984 "\0" "debug",
@@ -1985,6 +1988,7 @@ static const char *const optletters_optnames[NOPTS] = {
1985#define optletters(n) optletters_optnames[(n)][0] 1988#define optletters(n) optletters_optnames[(n)][0]
1986#define optnames(n) (&optletters_optnames[(n)][1]) 1989#define optnames(n) (&optletters_optnames[(n)][1])
1987 1990
1991#define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
1988 1992
1989static char optlist[NOPTS]; 1993static char optlist[NOPTS];
1990 1994
@@ -8862,6 +8866,7 @@ optschanged(void)
8862#endif 8866#endif
8863 setinteractive(iflag); 8867 setinteractive(iflag);
8864 setjobctl(mflag); 8868 setjobctl(mflag);
8869 setvimode(viflag);
8865} 8870}
8866 8871
8867static inline void 8872static inline void
diff --git a/shell/cmdedit.c b/shell/cmdedit.c
index 3380dffe9..c67283f4a 100644
--- a/shell/cmdedit.c
+++ b/shell/cmdedit.c
@@ -441,27 +441,61 @@ static void redraw(int y, int back_cursor)
441 input_backward(back_cursor); 441 input_backward(back_cursor);
442} 442}
443 443
444/* Delete the char in front of the cursor */ 444#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
445static void input_delete(void) 445static char delbuf[BUFSIZ]; /* a place to store deleted characters */
446static char *delp = delbuf;
447static int newdelflag; /* whether delbuf should be reused yet */
448#endif
449
450/* Delete the char in front of the cursor, optionally saving it
451 * for later putback */
452static void input_delete(int save)
446{ 453{
447 int j = cursor; 454 int j = cursor;
448 455
449 if (j == len) 456 if (j == len)
450 return; 457 return;
451 458
459#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
460 if (save) {
461 if (newdelflag) {
462 delp = delbuf;
463 newdelflag = 0;
464 }
465 if (delp - delbuf < BUFSIZ)
466 *delp++ = command_ps[j];
467 }
468#endif
469
452 strcpy(command_ps + j, command_ps + j + 1); 470 strcpy(command_ps + j, command_ps + j + 1);
453 len--; 471 len--;
454 input_end(); /* rewtite new line */ 472 input_end(); /* rewrite new line */
455 cmdedit_set_out_char(0); /* destroy end char */ 473 cmdedit_set_out_char(0); /* destroy end char */
456 input_backward(cursor - j); /* back to old pos cursor */ 474 input_backward(cursor - j); /* back to old pos cursor */
457} 475}
458 476
477#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
478static void put(void)
479{
480 int ocursor, j = delp - delbuf;
481 if (j == 0)
482 return;
483 ocursor = cursor;
484 /* open hole and then fill it */
485 memmove(command_ps + cursor + j, command_ps + cursor, len - cursor + 1);
486 strncpy(command_ps + cursor, delbuf, j);
487 len += j;
488 input_end(); /* rewrite new line */
489 input_backward(cursor-ocursor-j+1); /* at end of new text */
490}
491#endif
492
459/* Delete the char in back of the cursor */ 493/* Delete the char in back of the cursor */
460static void input_backspace(void) 494static void input_backspace(void)
461{ 495{
462 if (cursor > 0) { 496 if (cursor > 0) {
463 input_backward(1); 497 input_backward(1);
464 input_delete(); 498 input_delete(0);
465 } 499 }
466} 500}
467 501
@@ -473,7 +507,6 @@ static void input_forward(void)
473 cmdedit_set_out_char(command_ps[cursor + 1]); 507 cmdedit_set_out_char(command_ps[cursor + 1]);
474} 508}
475 509
476
477static void cmdedit_setwidth(int w, int redraw_flg) 510static void cmdedit_setwidth(int w, int redraw_flg)
478{ 511{
479 cmdedit_termw = cmdedit_prmt_len + 2; 512 cmdedit_termw = cmdedit_prmt_len + 2;
@@ -1217,18 +1250,147 @@ enum {
1217 * ESC-h -- Delete forward one word 1250 * ESC-h -- Delete forward one word
1218 * CTL-t -- Transpose two characters 1251 * CTL-t -- Transpose two characters
1219 * 1252 *
1220 * Furthermore, the "vi" command editing keys are not implemented. 1253 * Minimalist vi-style command line editing available if configured.
1254 * vi mode implemented 2005 by Paul Fox <pgf@foxharp.boston.ma.us>
1221 * 1255 *
1222 */ 1256 */
1223 1257
1258#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
1259static int vi_mode;
1260
1261void setvimode ( int viflag )
1262{
1263 vi_mode = viflag;
1264}
1265
1266void
1267vi_Word_motion(char *command, int eat)
1268{
1269 while (cursor < len && !isspace(command[cursor]))
1270 input_forward();
1271 if (eat) while (cursor < len && isspace(command[cursor]))
1272 input_forward();
1273}
1274
1275void
1276vi_word_motion(char *command, int eat)
1277{
1278 if (isalnum(command[cursor]) || command[cursor] == '_') {
1279 while (cursor < len &&
1280 (isalnum(command[cursor+1]) ||
1281 command[cursor+1] == '_'))
1282 input_forward();
1283 } else if (ispunct(command[cursor])) {
1284 while (cursor < len &&
1285 (ispunct(command[cursor+1])))
1286 input_forward();
1287 }
1288
1289 if (cursor < len)
1290 input_forward();
1291
1292 if (eat && cursor < len && isspace(command[cursor]))
1293 while (cursor < len && isspace(command[cursor]))
1294 input_forward();
1295}
1296
1297void
1298vi_End_motion(char *command)
1299{
1300 input_forward();
1301 while (cursor < len && isspace(command[cursor]))
1302 input_forward();
1303 while (cursor < len-1 && !isspace(command[cursor+1]))
1304 input_forward();
1305}
1306
1307void
1308vi_end_motion(char *command)
1309{
1310 if (cursor >= len-1)
1311 return;
1312 input_forward();
1313 while (cursor < len-1 && isspace(command[cursor]))
1314 input_forward();
1315 if (cursor >= len-1)
1316 return;
1317 if (isalnum(command[cursor]) || command[cursor] == '_') {
1318 while (cursor < len-1 &&
1319 (isalnum(command[cursor+1]) ||
1320 command[cursor+1] == '_'))
1321 input_forward();
1322 } else if (ispunct(command[cursor])) {
1323 while (cursor < len-1 &&
1324 (ispunct(command[cursor+1])))
1325 input_forward();
1326 }
1327}
1328
1329void
1330vi_Back_motion(char *command)
1331{
1332 while (cursor > 0 && isspace(command[cursor-1]))
1333 input_backward(1);
1334 while (cursor > 0 && !isspace(command[cursor-1]))
1335 input_backward(1);
1336}
1337
1338void
1339vi_back_motion(char *command)
1340{
1341 if (cursor <= 0)
1342 return;
1343 input_backward(1);
1344 while (cursor > 0 && isspace(command[cursor]))
1345 input_backward(1);
1346 if (cursor <= 0)
1347 return;
1348 if (isalnum(command[cursor]) || command[cursor] == '_') {
1349 while (cursor > 0 &&
1350 (isalnum(command[cursor-1]) ||
1351 command[cursor-1] == '_'))
1352 input_backward(1);
1353 } else if (ispunct(command[cursor])) {
1354 while (cursor > 0 &&
1355 (ispunct(command[cursor-1])))
1356 input_backward(1);
1357 }
1358}
1359#endif
1360
1361/*
1362 * the normal emacs mode and vi's insert mode are the same.
1363 * commands entered when in vi command mode ("escape mode") get
1364 * an extra bit added to distinguish them. this lets them share
1365 * much of the code in the big switch and while loop. i
1366 * experimented with an ugly macro to make the case labels for
1367 * these cases go away entirely when vi mode isn't configured, in
1368 * hopes of letting the jump tables get smaller:
1369 * #define vcase(caselabel) caselabel
1370 * and then
1371 * case CNTRL('A'):
1372 * case vcase(VICMD('0'):)
1373 * but it didn't seem to make any difference in code size,
1374 * and the macro-ized code was too ugly.
1375 */
1376
1377#define VI_cmdbit 0x100
1378#define VICMD(somecmd) ((somecmd)|VI_cmdbit)
1379
1380/* convert uppercase ascii to equivalent control char, for readability */
1381#define CNTRL(uc_char) ((uc_char) - 0x40)
1382
1224 1383
1225int cmdedit_read_input(char *prompt, char command[BUFSIZ]) 1384int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1226{ 1385{
1227 1386
1228 int break_out = 0; 1387 int break_out = 0;
1229 int lastWasTab = FALSE; 1388 int lastWasTab = FALSE;
1230 unsigned char c = 0; 1389 unsigned char c;
1231 1390#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
1391 unsigned int ic, prevc;
1392 int vi_cmdmode = 0;
1393#endif
1232 /* prepare before init handlers */ 1394 /* prepare before init handlers */
1233 cmdedit_y = 0; /* quasireal y, not true work if line > xt*yt */ 1395 cmdedit_y = 0; /* quasireal y, not true work if line > xt*yt */
1234 len = 0; 1396 len = 0;
@@ -1265,22 +1427,38 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1265 /* if we can't read input then exit */ 1427 /* if we can't read input then exit */
1266 goto prepare_to_die; 1428 goto prepare_to_die;
1267 1429
1268 switch (c) { 1430#ifdef CONFIG_FEATURE_COMMAND_EDITING_VI
1431 newdelflag = 1;
1432 ic = c;
1433 if (vi_cmdmode)
1434 ic |= VI_cmdbit;
1435 switch (ic)
1436#else
1437 switch (c)
1438#endif
1439 {
1269 case '\n': 1440 case '\n':
1270 case '\r': 1441 case '\r':
1442 case VICMD('\n'):
1443 case VICMD('\r'):
1271 /* Enter */ 1444 /* Enter */
1272 goto_new_line(); 1445 goto_new_line();
1273 break_out = 1; 1446 break_out = 1;
1274 break; 1447 break;
1275 case 1: 1448 case CNTRL('A'):
1449 case VICMD('0'):
1276 /* Control-a -- Beginning of line */ 1450 /* Control-a -- Beginning of line */
1277 input_backward(cursor); 1451 input_backward(cursor);
1278 break; 1452 break;
1279 case 2: 1453 case CNTRL('B'):
1454 case VICMD('h'):
1455 case VICMD('\b'):
1456 case VICMD(DEL):
1280 /* Control-b -- Move back one character */ 1457 /* Control-b -- Move back one character */
1281 input_backward(1); 1458 input_backward(1);
1282 break; 1459 break;
1283 case 3: 1460 case CNTRL('C'):
1461 case VICMD(CNTRL('C')):
1284 /* Control-c -- stop gathering input */ 1462 /* Control-c -- stop gathering input */
1285 goto_new_line(); 1463 goto_new_line();
1286#ifndef CONFIG_ASH 1464#ifndef CONFIG_ASH
@@ -1293,7 +1471,7 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ])
1293 break_out = -1; /* to control traps */ 1471 break_out = -1; /* to control traps */
1294#endif 1472#endif
1295 break; 1473 break;
1296 case 4: 1474 case CNTRL('D'):
1297 /* Control-d -- Delete one character, or exit 1475 /* Control-d -- Delete one character, or exit
1298 * if the len=0 and no chars to delete */ 1476 * if the len=0 and no chars to delete */
1299 if (len == 0) { 1477 if (len == 0) {
@@ -1310,14 +1488,17 @@ prepare_to_die:
1310 break; 1488 break;
1311#endif 1489#endif
1312 } else { 1490 } else {
1313 input_delete(); 1491 input_delete(0);
1314 } 1492 }
1315 break; 1493 break;
1316 case 5: 1494 case CNTRL('E'):
1495 case VICMD('$'):
1317 /* Control-e -- End of line */ 1496 /* Control-e -- End of line */
1318 input_end(); 1497 input_end();
1319 break; 1498 break;
1320 case 6: 1499 case CNTRL('F'):
1500 case VICMD('l'):
1501 case VICMD(' '):
1321 /* Control-f -- Move forward one character */ 1502 /* Control-f -- Move forward one character */
1322 input_forward(); 1503 input_forward();
1323 break; 1504 break;
@@ -1331,24 +1512,29 @@ prepare_to_die:
1331 input_tab(&lastWasTab); 1512 input_tab(&lastWasTab);
1332#endif 1513#endif
1333 break; 1514 break;
1334 case 11: 1515 case CNTRL('K'):
1335 /* Control-k -- clear to end of line */ 1516 /* Control-k -- clear to end of line */
1336 *(command + cursor) = 0; 1517 *(command + cursor) = 0;
1337 len = cursor; 1518 len = cursor;
1338 printf("\033[J"); 1519 printf("\033[J");
1339 break; 1520 break;
1340 case 12: 1521 case CNTRL('L'):
1522 case VICMD(CNTRL('L')):
1341 /* Control-l -- clear screen */ 1523 /* Control-l -- clear screen */
1342 printf("\033[H"); 1524 printf("\033[H");
1343 redraw(0, len-cursor); 1525 redraw(0, len-cursor);
1344 break; 1526 break;
1345#if MAX_HISTORY >= 1 1527#if MAX_HISTORY >= 1
1346 case 14: 1528 case CNTRL('N'):
1529 case VICMD(CNTRL('N')):
1530 case VICMD('j'):
1347 /* Control-n -- Get next command in history */ 1531 /* Control-n -- Get next command in history */
1348 if (get_next_history()) 1532 if (get_next_history())
1349 goto rewrite_line; 1533 goto rewrite_line;
1350 break; 1534 break;
1351 case 16: 1535 case CNTRL('P'):
1536 case VICMD(CNTRL('P')):
1537 case VICMD('k'):
1352 /* Control-p -- Get previous command from history */ 1538 /* Control-p -- Get previous command from history */
1353 if (cur_history > 0) { 1539 if (cur_history > 0) {
1354 get_previous_history(); 1540 get_previous_history();
@@ -1358,26 +1544,167 @@ prepare_to_die:
1358 } 1544 }
1359 break; 1545 break;
1360#endif 1546#endif
1361 case 21: 1547 case CNTRL('U'):
1548 case VICMD(CNTRL('U')):
1362 /* Control-U -- Clear line before cursor */ 1549 /* Control-U -- Clear line before cursor */
1363 if (cursor) { 1550 if (cursor) {
1364 strcpy(command, command + cursor); 1551 strcpy(command, command + cursor);
1365 redraw(cmdedit_y, len -= cursor); 1552 redraw(cmdedit_y, len -= cursor);
1366 } 1553 }
1367 break; 1554 break;
1368 case 23: 1555 case CNTRL('W'):
1556 case VICMD(CNTRL('W')):
1369 /* Control-W -- Remove the last word */ 1557 /* Control-W -- Remove the last word */
1370 while (cursor > 0 && isspace(command[cursor-1])) 1558 while (cursor > 0 && isspace(command[cursor-1]))
1371 input_backspace(); 1559 input_backspace();
1372 while (cursor > 0 &&!isspace(command[cursor-1])) 1560 while (cursor > 0 &&!isspace(command[cursor-1]))
1373 input_backspace(); 1561 input_backspace();
1374 break; 1562 break;
1563#if CONFIG_FEATURE_COMMAND_EDITING_VI
1564 case VICMD('i'):
1565 vi_cmdmode = 0;
1566 break;
1567 case VICMD('I'):
1568 input_backward(cursor);
1569 vi_cmdmode = 0;
1570 break;
1571 case VICMD('a'):
1572 input_forward();
1573 vi_cmdmode = 0;
1574 break;
1575 case VICMD('A'):
1576 input_end();
1577 vi_cmdmode = 0;
1578 break;
1579 case VICMD('x'):
1580 input_delete(1);
1581 break;
1582 case VICMD('X'):
1583 if (cursor > 0) {
1584 input_backward(1);
1585 input_delete(1);
1586 }
1587 break;
1588 case VICMD('W'):
1589 vi_Word_motion(command, 1);
1590 break;
1591 case VICMD('w'):
1592 vi_word_motion(command, 1);
1593 break;
1594 case VICMD('E'):
1595 vi_End_motion(command);
1596 break;
1597 case VICMD('e'):
1598 vi_end_motion(command);
1599 break;
1600 case VICMD('B'):
1601 vi_Back_motion(command);
1602 break;
1603 case VICMD('b'):
1604 vi_back_motion(command);
1605 break;
1606 case VICMD('C'):
1607 vi_cmdmode = 0;
1608 /* fall through */
1609 case VICMD('D'):
1610 goto clear_to_eol;
1611
1612 case VICMD('c'):
1613 vi_cmdmode = 0;
1614 /* fall through */
1615 case VICMD('d'):
1616 {
1617 int nc, sc;
1618 sc = cursor;
1619 prevc = ic;
1620 if (safe_read(0, &c, 1) < 1)
1621 goto prepare_to_die;
1622 if (c == (prevc & 0xff)) {
1623 /* "cc", "dd" */
1624 input_backward(cursor);
1625 goto clear_to_eol;
1626 break;
1627 }
1628 switch(c) {
1629 case 'w':
1630 case 'W':
1631 case 'e':
1632 case 'E':
1633 switch (c) {
1634 case 'w': /* "dw", "cw" */
1635 vi_word_motion(command, vi_cmdmode);
1636 break;
1637 case 'W': /* 'dW', 'cW' */
1638 vi_Word_motion(command, vi_cmdmode);
1639 break;
1640 case 'e': /* 'de', 'ce' */
1641 vi_end_motion(command);
1642 input_forward();
1643 break;
1644 case 'E': /* 'dE', 'cE' */
1645 vi_End_motion(command);
1646 input_forward();
1647 break;
1648 }
1649 nc = cursor;
1650 input_backward(cursor - sc);
1651 while (nc-- > cursor)
1652 input_delete(1);
1653 break;
1654 case 'b': /* "db", "cb" */
1655 case 'B': /* implemented as B */
1656 if (c == 'b')
1657 vi_back_motion(command);
1658 else
1659 vi_Back_motion(command);
1660 while (sc-- > cursor)
1661 input_delete(1);
1662 break;
1663 case ' ': /* "d ", "c " */
1664 input_delete(1);
1665 break;
1666 case '$': /* "d$", "c$" */
1667 clear_to_eol:
1668 while (cursor < len)
1669 input_delete(1);
1670 break;
1671 }
1672 }
1673 break;
1674 case VICMD('p'):
1675 input_forward();
1676 /* fallthrough */
1677 case VICMD('P'):
1678 put();
1679 break;
1680 case VICMD('r'):
1681 if (safe_read(0, &c, 1) < 1)
1682 goto prepare_to_die;
1683 if (c == 0)
1684 beep();
1685 else {
1686 *(command + cursor) = c;
1687 putchar(c);
1688 putchar('\b');
1689 }
1690 break;
1691#endif /* CONFIG_FEATURE_COMMAND_EDITING_VI */
1375 case ESC:{ 1692 case ESC:{
1693#if CONFIG_FEATURE_COMMAND_EDITING_VI
1694 if (vi_mode) {
1695 /* ESC: insert mode --> command mode */
1696 vi_cmdmode = 1;
1697 input_backward(1);
1698 break;
1699 }
1700#endif
1376 /* escape sequence follows */ 1701 /* escape sequence follows */
1377 if (safe_read(0, &c, 1) < 1) 1702 if (safe_read(0, &c, 1) < 1)
1378 goto prepare_to_die; 1703 goto prepare_to_die;
1379 /* different vt100 emulations */ 1704 /* different vt100 emulations */
1380 if (c == '[' || c == 'O') { 1705 if (c == '[' || c == 'O') {
1706 case VICMD('['):
1707 case VICMD('O'):
1381 if (safe_read(0, &c, 1) < 1) 1708 if (safe_read(0, &c, 1) < 1)
1382 goto prepare_to_die; 1709 goto prepare_to_die;
1383 } 1710 }
@@ -1409,13 +1736,17 @@ prepare_to_die:
1409 case 'B': 1736 case 'B':
1410 /* Down Arrow -- Get next command in history */ 1737 /* Down Arrow -- Get next command in history */
1411 if (!get_next_history()) 1738 if (!get_next_history())
1412 break; 1739 break;
1413 /* Rewrite the line with the selected history item */ 1740 /* Rewrite the line with the selected history item */
1414rewrite_line: 1741rewrite_line:
1415 /* change command */ 1742 /* change command */
1416 len = strlen(strcpy(command, history[cur_history])); 1743 len = strlen(strcpy(command, history[cur_history]));
1417 /* redraw and go to end line */ 1744 /* redraw and go to eol (bol, in vi */
1745#if CONFIG_FEATURE_COMMAND_EDITING_VI
1746 redraw(cmdedit_y, vi_mode ? 9999:0);
1747#else
1418 redraw(cmdedit_y, 0); 1748 redraw(cmdedit_y, 0);
1749#endif
1419 break; 1750 break;
1420#endif 1751#endif
1421 case 'C': 1752 case 'C':
@@ -1428,7 +1759,7 @@ rewrite_line:
1428 break; 1759 break;
1429 case '3': 1760 case '3':
1430 /* Delete */ 1761 /* Delete */
1431 input_delete(); 1762 input_delete(0);
1432 break; 1763 break;
1433 case '1': 1764 case '1':
1434 case 'H': 1765 case 'H':
@@ -1450,7 +1781,7 @@ rewrite_line:
1450 default: /* If it's regular input, do the normal thing */ 1781 default: /* If it's regular input, do the normal thing */
1451#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT 1782#ifdef CONFIG_FEATURE_NONPRINTABLE_INVERSE_PUT
1452 /* Control-V -- Add non-printable symbol */ 1783 /* Control-V -- Add non-printable symbol */
1453 if (c == 22) { 1784 if (c == CNTRL('V')) {
1454 if (safe_read(0, &c, 1) < 1) 1785 if (safe_read(0, &c, 1) < 1)
1455 goto prepare_to_die; 1786 goto prepare_to_die;
1456 if (c == 0) { 1787 if (c == 0) {
@@ -1459,8 +1790,14 @@ rewrite_line:
1459 } 1790 }
1460 } else 1791 } else
1461#endif 1792#endif
1462 if (!Isprint(c)) /* Skip non-printable characters */ 1793 {
1463 break; 1794#if CONFIG_FEATURE_COMMAND_EDITING_VI
1795 if (vi_cmdmode) /* don't self-insert */
1796 break;
1797#endif
1798 if (!Isprint(c)) /* Skip non-printable characters */
1799 break;
1800 }
1464 1801
1465 if (len >= (BUFSIZ - 2)) /* Need to leave space for enter */ 1802 if (len >= (BUFSIZ - 2)) /* Need to leave space for enter */
1466 break; 1803 break;
diff --git a/shell/cmdedit.h b/shell/cmdedit.h
index 4c0c09d76..f8482f4a7 100644
--- a/shell/cmdedit.h
+++ b/shell/cmdedit.h
@@ -12,4 +12,8 @@ void load_history ( const char *fromfile );
12void save_history ( const char *tofile ); 12void save_history ( const char *tofile );
13#endif 13#endif
14 14
15#if CONFIG_FEATURE_COMMAND_EDITING_VI
16void setvimode ( int viflag );
17#endif
18
15#endif /* CMDEDIT_H */ 19#endif /* CMDEDIT_H */