diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-21 19:18:59 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-21 19:18:59 +0000 |
| commit | 47bdb3ac482e8ccfa073b1c17fdf52d3721952b6 (patch) | |
| tree | c1b572a5d0e3a9a30ca9011a16aad9bb0633a201 /shell | |
| parent | 82b39e83ab13660f0b76a52519e1ac44e30fff7c (diff) | |
| download | busybox-w32-47bdb3ac482e8ccfa073b1c17fdf52d3721952b6.tar.gz busybox-w32-47bdb3ac482e8ccfa073b1c17fdf52d3721952b6.tar.bz2 busybox-w32-47bdb3ac482e8ccfa073b1c17fdf52d3721952b6.zip | |
cmdedit: small optimizations
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/cmdedit.c | 177 |
1 files changed, 104 insertions, 73 deletions
diff --git a/shell/cmdedit.c b/shell/cmdedit.c index 617f3a29a..1143ded77 100644 --- a/shell/cmdedit.c +++ b/shell/cmdedit.c | |||
| @@ -28,6 +28,51 @@ | |||
| 28 | - not true viewing if length prompt less terminal width | 28 | - not true viewing if length prompt less terminal width |
| 29 | */ | 29 | */ |
| 30 | 30 | ||
| 31 | /* | ||
| 32 | CONFIG_FEATURE_COMMAND_EDITING=y | ||
| 33 | # CONFIG_FEATURE_COMMAND_EDITING_VI is not set | ||
| 34 | CONFIG_FEATURE_COMMAND_HISTORY=15 | ||
| 35 | # CONFIG_FEATURE_COMMAND_SAVEHISTORY is not set | ||
| 36 | # CONFIG_FEATURE_COMMAND_TAB_COMPLETION is not set | ||
| 37 | # CONFIG_FEATURE_COMMAND_USERNAME_COMPLETION is not set | ||
| 38 | # CONFIG_FEATURE_SH_FANCY_PROMPT is not set | ||
| 39 | Sizes with the above: | ||
| 40 | # size cmdedit.o | ||
| 41 | text data bss dec hex filename | ||
| 42 | 2374 4 228 2606 a2e cmdedit.o | ||
| 43 | # nm --size-sort cmdedit.o | ||
| 44 | 00000004 b cmdedit_prmt_len | ||
| 45 | 00000004 b cmdedit_prompt | ||
| 46 | 00000004 d cmdedit_termw | ||
| 47 | 00000004 b cmdedit_x | ||
| 48 | 00000004 b cmdedit_y | ||
| 49 | 00000004 b command_ps | ||
| 50 | 00000004 b cur_history | ||
| 51 | 00000004 b cursor | ||
| 52 | 00000004 b handlers_sets | ||
| 53 | 00000004 b len | ||
| 54 | 00000004 b n_history | ||
| 55 | 00000004 b previous_SIGWINCH_handler | ||
| 56 | 00000009 t beep | ||
| 57 | 00000017 t goto_new_line | ||
| 58 | 0000001a t input_end | ||
| 59 | 0000001b t input_backspace | ||
| 60 | 0000001e t input_forward | ||
| 61 | 00000027 t get_next_history | ||
| 62 | 00000036 t put_prompt | ||
| 63 | 00000039 t redraw | ||
| 64 | 0000003c b initial_settings | ||
| 65 | 0000003c b new_settings | ||
| 66 | 00000040 b history | ||
| 67 | 00000047 t input_delete | ||
| 68 | 0000004d t get_previous_history | ||
| 69 | 00000059 t cmdedit_reset_term | ||
| 70 | 0000006c t cmdedit_set_out_char | ||
| 71 | 00000087 t input_backward | ||
| 72 | 000000a1 t win_changed | ||
| 73 | 0000053c T cmdedit_read_input | ||
| 74 | */ | ||
| 75 | |||
| 31 | #include <sys/ioctl.h> | 76 | #include <sys/ioctl.h> |
| 32 | #include "busybox.h" | 77 | #include "busybox.h" |
| 33 | #include "cmdedit.h" | 78 | #include "cmdedit.h" |
| @@ -86,7 +131,7 @@ enum { | |||
| 86 | 131 | ||
| 87 | static int cmdedit_x; /* real x terminal position */ | 132 | static int cmdedit_x; /* real x terminal position */ |
| 88 | static int cmdedit_y; /* pseudoreal y terminal position */ | 133 | static int cmdedit_y; /* pseudoreal y terminal position */ |
| 89 | static int cmdedit_prmt_len; /* length of prompt without colores string */ | 134 | static int cmdedit_prmt_len; /* length of prompt (without colors etc) */ |
| 90 | 135 | ||
| 91 | static int cursor; | 136 | static int cursor; |
| 92 | static int len; | 137 | static int len; |
| @@ -179,40 +224,34 @@ static void beep(void) | |||
| 179 | } | 224 | } |
| 180 | 225 | ||
| 181 | /* Move back one character */ | 226 | /* Move back one character */ |
| 182 | /* special for slow terminal */ | 227 | /* (optimized for slow terminals) */ |
| 183 | static void input_backward(int num) | 228 | static void input_backward(unsigned num) |
| 184 | { | 229 | { |
| 230 | int count_y; | ||
| 231 | |||
| 185 | if (num > cursor) | 232 | if (num > cursor) |
| 186 | num = cursor; | 233 | num = cursor; |
| 187 | cursor -= num; /* new cursor (in command, not terminal) */ | 234 | if (!num) |
| 235 | return; | ||
| 236 | cursor -= num; | ||
| 188 | 237 | ||
| 189 | if (cmdedit_x >= num) { | 238 | if (cmdedit_x >= num) { |
| 190 | cmdedit_x -= num; | 239 | cmdedit_x -= num; |
| 191 | if (num <= 4) | 240 | if (num <= 4) { |
| 192 | while (num > 0) { | 241 | do putchar('\b'); while (--num); |
| 193 | putchar('\b'); | 242 | return; |
| 194 | num--; | 243 | } |
| 195 | } | 244 | printf("\033[%uD", num); |
| 196 | else | 245 | return; |
| 197 | printf("\033[%dD", num); | ||
| 198 | } else { | ||
| 199 | /* Need to go one or more lines up */ | ||
| 200 | int count_y; | ||
| 201 | |||
| 202 | //if (cmdedit_x) { | ||
| 203 | // /* back to first column */ | ||
| 204 | // putchar('\r'); | ||
| 205 | // num -= cmdedit_x; | ||
| 206 | //} | ||
| 207 | num -= cmdedit_x;// | ||
| 208 | count_y = 1 + num / cmdedit_termw; | ||
| 209 | //printf("\033[%dA", count_y); | ||
| 210 | cmdedit_y -= count_y; | ||
| 211 | cmdedit_x = cmdedit_termw * count_y - num; | ||
| 212 | //printf("\033[%dC", cmdedit_x); | ||
| 213 | /* go to 1st col; go up; go to correct column */ | ||
| 214 | printf("\r" "\033[%dA" "\033[%dC", count_y, cmdedit_x);// | ||
| 215 | } | 246 | } |
| 247 | |||
| 248 | /* Need to go one or more lines up */ | ||
| 249 | num -= cmdedit_x; | ||
| 250 | count_y = 1 + (num / cmdedit_termw); | ||
| 251 | cmdedit_y -= count_y; | ||
| 252 | cmdedit_x = cmdedit_termw * count_y - num; | ||
| 253 | /* go to 1st col; go up; go to correct column */ | ||
| 254 | printf("\r" "\033[%dA" "\033[%dC", count_y, cmdedit_x); | ||
| 216 | } | 255 | } |
| 217 | 256 | ||
| 218 | static void put_prompt(void) | 257 | static void put_prompt(void) |
| @@ -220,6 +259,7 @@ static void put_prompt(void) | |||
| 220 | out1str(cmdedit_prompt); | 259 | out1str(cmdedit_prompt); |
| 221 | cmdedit_x = cmdedit_prmt_len; /* count real x terminal position */ | 260 | cmdedit_x = cmdedit_prmt_len; /* count real x terminal position */ |
| 222 | cursor = 0; | 261 | cursor = 0; |
| 262 | // Huh? what if cmdedit_prmt_len >= width? | ||
| 223 | cmdedit_y = 0; /* new quasireal y */ | 263 | cmdedit_y = 0; /* new quasireal y */ |
| 224 | } | 264 | } |
| 225 | 265 | ||
| @@ -1105,23 +1145,15 @@ static void cmdedit_reset_term(void) | |||
| 1105 | fflush(stdout); | 1145 | fflush(stdout); |
| 1106 | } | 1146 | } |
| 1107 | 1147 | ||
| 1108 | static void cmdedit_setwidth(int w, int redraw_flg) | 1148 | static void cmdedit_setwidth(unsigned w, int redraw_flg) |
| 1109 | { | 1149 | { |
| 1110 | cmdedit_termw = cmdedit_prmt_len + 2; | 1150 | cmdedit_termw = w; |
| 1111 | if (w <= cmdedit_termw) { | 1151 | if (redraw_flg) { |
| 1112 | cmdedit_termw = cmdedit_termw % w; | 1152 | /* new y for current cursor */ |
| 1113 | } | 1153 | int new_y = (cursor + cmdedit_prmt_len) / w; |
| 1114 | if (w > cmdedit_termw) { | 1154 | /* redraw */ |
| 1115 | cmdedit_termw = w; | 1155 | redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), len - cursor); |
| 1116 | 1156 | fflush(stdout); | |
| 1117 | if (redraw_flg) { | ||
| 1118 | /* new y for current cursor */ | ||
| 1119 | int new_y = (cursor + cmdedit_prmt_len) / w; | ||
| 1120 | |||
| 1121 | /* redraw */ | ||
| 1122 | redraw((new_y >= cmdedit_y ? new_y : cmdedit_y), len - cursor); | ||
| 1123 | fflush(stdout); | ||
| 1124 | } | ||
| 1125 | } | 1157 | } |
| 1126 | } | 1158 | } |
| 1127 | 1159 | ||
| @@ -1310,7 +1342,7 @@ static void parse_prompt(const char *prmt_ptr) | |||
| 1310 | 1342 | ||
| 1311 | /* leave out the "vi-mode"-only case labels if vi editing isn't | 1343 | /* leave out the "vi-mode"-only case labels if vi editing isn't |
| 1312 | * configured. */ | 1344 | * configured. */ |
| 1313 | #define vi_case(caselabel) USE_FEATURE_COMMAND_EDITING(caselabel) | 1345 | #define vi_case(caselabel) USE_FEATURE_COMMAND_EDITING(case caselabel) |
| 1314 | 1346 | ||
| 1315 | /* convert uppercase ascii to equivalent control char, for readability */ | 1347 | /* convert uppercase ascii to equivalent control char, for readability */ |
| 1316 | #undef CTRL | 1348 | #undef CTRL |
| @@ -1328,9 +1360,10 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1328 | smalluint prevc; | 1360 | smalluint prevc; |
| 1329 | #endif | 1361 | #endif |
| 1330 | /* prepare before init handlers */ | 1362 | /* prepare before init handlers */ |
| 1331 | cmdedit_y = 0; /* quasireal y, not true work if line > xt*yt */ | 1363 | cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ |
| 1332 | len = 0; | 1364 | len = 0; |
| 1333 | command_ps = command; | 1365 | command_ps = command; |
| 1366 | command[0] = '\0'; | ||
| 1334 | 1367 | ||
| 1335 | getTermSettings(0, (void *) &initial_settings); | 1368 | getTermSettings(0, (void *) &initial_settings); |
| 1336 | memcpy(&new_settings, &initial_settings, sizeof(struct termios)); | 1369 | memcpy(&new_settings, &initial_settings, sizeof(struct termios)); |
| @@ -1341,12 +1374,10 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1341 | new_settings.c_cc[VMIN] = 1; | 1374 | new_settings.c_cc[VMIN] = 1; |
| 1342 | new_settings.c_cc[VTIME] = 0; | 1375 | new_settings.c_cc[VTIME] = 0; |
| 1343 | /* Turn off CTRL-C, so we can trap it */ | 1376 | /* Turn off CTRL-C, so we can trap it */ |
| 1344 | # ifndef _POSIX_VDISABLE | 1377 | #ifndef _POSIX_VDISABLE |
| 1345 | # define _POSIX_VDISABLE '\0' | 1378 | #define _POSIX_VDISABLE '\0' |
| 1346 | # endif | 1379 | #endif |
| 1347 | new_settings.c_cc[VINTR] = _POSIX_VDISABLE; | 1380 | new_settings.c_cc[VINTR] = _POSIX_VDISABLE; |
| 1348 | command[0] = 0; | ||
| 1349 | |||
| 1350 | setTermSettings(0, (void *) &new_settings); | 1381 | setTermSettings(0, (void *) &new_settings); |
| 1351 | handlers_sets |= SET_RESET_TERM; | 1382 | handlers_sets |= SET_RESET_TERM; |
| 1352 | 1383 | ||
| @@ -1372,30 +1403,30 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1372 | switch (ic) { | 1403 | switch (ic) { |
| 1373 | case '\n': | 1404 | case '\n': |
| 1374 | case '\r': | 1405 | case '\r': |
| 1375 | vi_case( case '\n'|vbit: ) | 1406 | vi_case('\n'|vbit:) |
| 1376 | vi_case( case '\r'|vbit: ) | 1407 | vi_case('\r'|vbit:) |
| 1377 | /* Enter */ | 1408 | /* Enter */ |
| 1378 | goto_new_line(); | 1409 | goto_new_line(); |
| 1379 | break_out = 1; | 1410 | break_out = 1; |
| 1380 | break; | 1411 | break; |
| 1381 | case CTRL('A'): | 1412 | case CTRL('A'): |
| 1382 | vi_case( case '0'|vbit: ) | 1413 | vi_case('0'|vbit:) |
| 1383 | /* Control-a -- Beginning of line */ | 1414 | /* Control-a -- Beginning of line */ |
| 1384 | input_backward(cursor); | 1415 | input_backward(cursor); |
| 1385 | break; | 1416 | break; |
| 1386 | case CTRL('B'): | 1417 | case CTRL('B'): |
| 1387 | vi_case( case 'h'|vbit: ) | 1418 | vi_case('h'|vbit:) |
| 1388 | vi_case( case '\b'|vbit: ) | 1419 | vi_case('\b'|vbit:) |
| 1389 | vi_case( case '\x7f'|vbit: ) /* DEL */ | 1420 | vi_case('\x7f'|vbit:) /* DEL */ |
| 1390 | /* Control-b -- Move back one character */ | 1421 | /* Control-b -- Move back one character */ |
| 1391 | input_backward(1); | 1422 | input_backward(1); |
| 1392 | break; | 1423 | break; |
| 1393 | case CTRL('C'): | 1424 | case CTRL('C'): |
| 1394 | vi_case( case CTRL('C')|vbit: ) | 1425 | vi_case(CTRL('C')|vbit:) |
| 1395 | /* Control-c -- stop gathering input */ | 1426 | /* Control-c -- stop gathering input */ |
| 1396 | goto_new_line(); | 1427 | goto_new_line(); |
| 1397 | #if !ENABLE_ASH | 1428 | #if !ENABLE_ASH |
| 1398 | command[0] = 0; | 1429 | command[0] = '\0'; |
| 1399 | len = 0; | 1430 | len = 0; |
| 1400 | lastWasTab = FALSE; | 1431 | lastWasTab = FALSE; |
| 1401 | put_prompt(); | 1432 | put_prompt(); |
| @@ -1427,13 +1458,13 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1427 | } | 1458 | } |
| 1428 | break; | 1459 | break; |
| 1429 | case CTRL('E'): | 1460 | case CTRL('E'): |
| 1430 | vi_case( case '$'|vbit: ) | 1461 | vi_case('$'|vbit:) |
| 1431 | /* Control-e -- End of line */ | 1462 | /* Control-e -- End of line */ |
| 1432 | input_end(); | 1463 | input_end(); |
| 1433 | break; | 1464 | break; |
| 1434 | case CTRL('F'): | 1465 | case CTRL('F'): |
| 1435 | vi_case( case 'l'|vbit: ) | 1466 | vi_case('l'|vbit:) |
| 1436 | vi_case( case ' '|vbit: ) | 1467 | vi_case(' '|vbit:) |
| 1437 | /* Control-f -- Move forward one character */ | 1468 | /* Control-f -- Move forward one character */ |
| 1438 | input_forward(); | 1469 | input_forward(); |
| 1439 | break; | 1470 | break; |
| @@ -1454,22 +1485,22 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1454 | printf("\033[J"); | 1485 | printf("\033[J"); |
| 1455 | break; | 1486 | break; |
| 1456 | case CTRL('L'): | 1487 | case CTRL('L'): |
| 1457 | vi_case( case CTRL('L')|vbit: ) | 1488 | vi_case(CTRL('L')|vbit:) |
| 1458 | /* Control-l -- clear screen */ | 1489 | /* Control-l -- clear screen */ |
| 1459 | printf("\033[H"); | 1490 | printf("\033[H"); |
| 1460 | redraw(0, len - cursor); | 1491 | redraw(0, len - cursor); |
| 1461 | break; | 1492 | break; |
| 1462 | #if MAX_HISTORY > 0 | 1493 | #if MAX_HISTORY > 0 |
| 1463 | case CTRL('N'): | 1494 | case CTRL('N'): |
| 1464 | vi_case( case CTRL('N')|vbit: ) | 1495 | vi_case(CTRL('N')|vbit:) |
| 1465 | vi_case( case 'j'|vbit: ) | 1496 | vi_case('j'|vbit:) |
| 1466 | /* Control-n -- Get next command in history */ | 1497 | /* Control-n -- Get next command in history */ |
| 1467 | if (get_next_history()) | 1498 | if (get_next_history()) |
| 1468 | goto rewrite_line; | 1499 | goto rewrite_line; |
| 1469 | break; | 1500 | break; |
| 1470 | case CTRL('P'): | 1501 | case CTRL('P'): |
| 1471 | vi_case( case CTRL('P')|vbit: ) | 1502 | vi_case(CTRL('P')|vbit:) |
| 1472 | vi_case( case 'k'|vbit: ) | 1503 | vi_case('k'|vbit:) |
| 1473 | /* Control-p -- Get previous command from history */ | 1504 | /* Control-p -- Get previous command from history */ |
| 1474 | if (cur_history > 0) { | 1505 | if (cur_history > 0) { |
| 1475 | get_previous_history(); | 1506 | get_previous_history(); |
| @@ -1480,7 +1511,7 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1480 | break; | 1511 | break; |
| 1481 | #endif | 1512 | #endif |
| 1482 | case CTRL('U'): | 1513 | case CTRL('U'): |
| 1483 | vi_case( case CTRL('U')|vbit: ) | 1514 | vi_case(CTRL('U')|vbit:) |
| 1484 | /* Control-U -- Clear line before cursor */ | 1515 | /* Control-U -- Clear line before cursor */ |
| 1485 | if (cursor) { | 1516 | if (cursor) { |
| 1486 | strcpy(command, command + cursor); | 1517 | strcpy(command, command + cursor); |
| @@ -1488,7 +1519,7 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1488 | } | 1519 | } |
| 1489 | break; | 1520 | break; |
| 1490 | case CTRL('W'): | 1521 | case CTRL('W'): |
| 1491 | vi_case( case CTRL('W')|vbit: ) | 1522 | vi_case(CTRL('W')|vbit:) |
| 1492 | /* Control-W -- Remove the last word */ | 1523 | /* Control-W -- Remove the last word */ |
| 1493 | while (cursor > 0 && isspace(command[cursor-1])) | 1524 | while (cursor > 0 && isspace(command[cursor-1])) |
| 1494 | input_backspace(); | 1525 | input_backspace(); |
| @@ -1639,8 +1670,8 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1639 | goto prepare_to_die; | 1670 | goto prepare_to_die; |
| 1640 | /* different vt100 emulations */ | 1671 | /* different vt100 emulations */ |
| 1641 | if (c == '[' || c == 'O') { | 1672 | if (c == '[' || c == 'O') { |
| 1642 | vi_case( case '['|vbit: ) | 1673 | vi_case('['|vbit:) |
| 1643 | vi_case( case 'O'|vbit: ) | 1674 | vi_case('O'|vbit:) |
| 1644 | if (safe_read(0, &c, 1) < 1) | 1675 | if (safe_read(0, &c, 1) < 1) |
| 1645 | goto prepare_to_die; | 1676 | goto prepare_to_die; |
| 1646 | } | 1677 | } |
| @@ -1650,7 +1681,7 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1650 | if (safe_read(0, &dummy, 1) < 1) | 1681 | if (safe_read(0, &dummy, 1) < 1) |
| 1651 | goto prepare_to_die; | 1682 | goto prepare_to_die; |
| 1652 | if (dummy != '~') | 1683 | if (dummy != '~') |
| 1653 | c = 0; | 1684 | c = '\0'; |
| 1654 | } | 1685 | } |
| 1655 | switch (c) { | 1686 | switch (c) { |
| 1656 | #if ENABLE_FEATURE_COMMAND_TAB_COMPLETION | 1687 | #if ENABLE_FEATURE_COMMAND_TAB_COMPLETION |
| @@ -1671,8 +1702,8 @@ int cmdedit_read_input(char *prompt, char command[BUFSIZ]) | |||
| 1671 | /* Down Arrow -- Get next command in history */ | 1702 | /* Down Arrow -- Get next command in history */ |
| 1672 | if (!get_next_history()) | 1703 | if (!get_next_history()) |
| 1673 | break; | 1704 | break; |
| 1674 | /* Rewrite the line with the selected history item */ | ||
| 1675 | rewrite_line: | 1705 | rewrite_line: |
| 1706 | /* Rewrite the line with the selected history item */ | ||
| 1676 | /* change command */ | 1707 | /* change command */ |
| 1677 | len = strlen(strcpy(command, history[cur_history])); | 1708 | len = strlen(strcpy(command, history[cur_history])); |
| 1678 | /* redraw and go to eol (bol, in vi */ | 1709 | /* redraw and go to eol (bol, in vi */ |
