diff options
author | Paul Fox <pgf@brightstareng.com> | 2005-08-04 19:04:46 +0000 |
---|---|---|
committer | Paul Fox <pgf@brightstareng.com> | 2005-08-04 19:04:46 +0000 |
commit | 3f11b1bf634536cb01d9913d1a3d10da5bf24541 (patch) | |
tree | fd76457b91cc91d8ae6091729f981acd1b321888 | |
parent | 8eeb655661a0d59be478681425682543b228b5a1 (diff) | |
download | busybox-w32-3f11b1bf634536cb01d9913d1a3d10da5bf24541.tar.gz busybox-w32-3f11b1bf634536cb01d9913d1a3d10da5bf24541.tar.bz2 busybox-w32-3f11b1bf634536cb01d9913d1a3d10da5bf24541.zip |
commiting:
0000025: vi-editing mode for ash
-rw-r--r-- | AUTHORS | 2 | ||||
-rw-r--r-- | shell/Config.in | 8 | ||||
-rw-r--r-- | shell/ash.c | 17 | ||||
-rw-r--r-- | shell/cmdedit.c | 393 | ||||
-rw-r--r-- | shell/cmdedit.h | 4 |
5 files changed, 390 insertions, 34 deletions
@@ -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 | ||
160 | Paul 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 | ||
204 | config 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 | |||
204 | config CONFIG_FEATURE_COMMAND_HISTORY | 212 | config 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 | ||
1964 | static const char *const optletters_optnames[NOPTS] = { | 1966 | static 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 | ||
1989 | static char optlist[NOPTS]; | 1993 | static 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 | ||
8867 | static inline void | 8872 | static 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 |
445 | static void input_delete(void) | 445 | static char delbuf[BUFSIZ]; /* a place to store deleted characters */ |
446 | static char *delp = delbuf; | ||
447 | static 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 */ | ||
452 | static 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 | ||
478 | static 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 */ |
460 | static void input_backspace(void) | 494 | static 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 | |||
477 | static void cmdedit_setwidth(int w, int redraw_flg) | 510 | static 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 | ||
1259 | static int vi_mode; | ||
1260 | |||
1261 | void setvimode ( int viflag ) | ||
1262 | { | ||
1263 | vi_mode = viflag; | ||
1264 | } | ||
1265 | |||
1266 | void | ||
1267 | vi_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 | |||
1275 | void | ||
1276 | vi_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 | |||
1297 | void | ||
1298 | vi_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 | |||
1307 | void | ||
1308 | vi_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 | |||
1329 | void | ||
1330 | vi_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 | |||
1338 | void | ||
1339 | vi_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 | ||
1225 | int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | 1384 | int 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 */ |
1414 | rewrite_line: | 1741 | rewrite_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 ); | |||
12 | void save_history ( const char *tofile ); | 12 | void save_history ( const char *tofile ); |
13 | #endif | 13 | #endif |
14 | 14 | ||
15 | #if CONFIG_FEATURE_COMMAND_EDITING_VI | ||
16 | void setvimode ( int viflag ); | ||
17 | #endif | ||
18 | |||
15 | #endif /* CMDEDIT_H */ | 19 | #endif /* CMDEDIT_H */ |