aboutsummaryrefslogtreecommitdiff
path: root/shell
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 /shell
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
Diffstat (limited to 'shell')
-rw-r--r--shell/Config.in8
-rw-r--r--shell/ash.c17
-rw-r--r--shell/cmdedit.c393
-rw-r--r--shell/cmdedit.h4
4 files changed, 388 insertions, 34 deletions
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 */