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 /shell | |
| 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
Diffstat (limited to 'shell')
| -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 |
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 | ||
| 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 */ |
