diff options
Diffstat (limited to 'editors/vi.c')
-rw-r--r-- | editors/vi.c | 90 |
1 files changed, 59 insertions, 31 deletions
diff --git a/editors/vi.c b/editors/vi.c index 96e6af318..fb46dc381 100644 --- a/editors/vi.c +++ b/editors/vi.c | |||
@@ -159,6 +159,14 @@ | |||
159 | //config: and will generally malloc() larger objects and less frequently. | 159 | //config: and will generally malloc() larger objects and less frequently. |
160 | //config: Unless you want more (or less) frequent "undo points" while typing, | 160 | //config: Unless you want more (or less) frequent "undo points" while typing, |
161 | //config: you should probably leave this unchanged. | 161 | //config: you should probably leave this unchanged. |
162 | //config: | ||
163 | //config:config FEATURE_VI_VERBOSE_STATUS | ||
164 | //config: bool "Enable verbose status reporting" | ||
165 | //config: default y | ||
166 | //config: depends on VI | ||
167 | //config: help | ||
168 | //config: Enable more verbose reporting of the results of yank, change, | ||
169 | //config: delete, undo and substitution commands. | ||
162 | 170 | ||
163 | //applet:IF_VI(APPLET(vi, BB_DIR_BIN, BB_SUID_DROP)) | 171 | //applet:IF_VI(APPLET(vi, BB_DIR_BIN, BB_SUID_DROP)) |
164 | 172 | ||
@@ -1357,14 +1365,17 @@ static void not_implemented(const char *s) | |||
1357 | // copy text into a register | 1365 | // copy text into a register |
1358 | static char *text_yank(char *p, char *q, int dest, int buftype) | 1366 | static char *text_yank(char *p, char *q, int dest, int buftype) |
1359 | { | 1367 | { |
1368 | char *oldreg = reg[dest]; | ||
1360 | int cnt = q - p; | 1369 | int cnt = q - p; |
1361 | if (cnt < 0) { // they are backwards- reverse them | 1370 | if (cnt < 0) { // they are backwards- reverse them |
1362 | p = q; | 1371 | p = q; |
1363 | cnt = -cnt; | 1372 | cnt = -cnt; |
1364 | } | 1373 | } |
1365 | free(reg[dest]); // if already a yank register, free it | 1374 | // Don't free register yet. This prevents the memory allocator |
1375 | // from reusing the free block so we can detect if it's changed. | ||
1366 | reg[dest] = xstrndup(p, cnt + 1); | 1376 | reg[dest] = xstrndup(p, cnt + 1); |
1367 | regtype[dest] = buftype; | 1377 | regtype[dest] = buftype; |
1378 | free(oldreg); | ||
1368 | return p; | 1379 | return p; |
1369 | } | 1380 | } |
1370 | 1381 | ||
@@ -1415,6 +1426,22 @@ static char *swap_context(char *p) // goto new context for '' command make this | |||
1415 | } | 1426 | } |
1416 | return p; | 1427 | return p; |
1417 | } | 1428 | } |
1429 | |||
1430 | # if ENABLE_FEATURE_VI_VERBOSE_STATUS | ||
1431 | static void yank_status(const char *op, const char *p, int cnt) | ||
1432 | { | ||
1433 | int lines, chars; | ||
1434 | |||
1435 | lines = chars = 0; | ||
1436 | while (*p) { | ||
1437 | ++chars; | ||
1438 | if (*p++ == '\n') | ||
1439 | ++lines; | ||
1440 | } | ||
1441 | status_line("%s %d lines (%d chars) from [%c]", | ||
1442 | op, lines * cnt, chars * cnt, what_reg()); | ||
1443 | } | ||
1444 | # endif | ||
1418 | #endif /* FEATURE_VI_YANKMARK */ | 1445 | #endif /* FEATURE_VI_YANKMARK */ |
1419 | 1446 | ||
1420 | #if ENABLE_FEATURE_VI_UNDO | 1447 | #if ENABLE_FEATURE_VI_UNDO |
@@ -1687,10 +1714,12 @@ static void undo_pop(void) | |||
1687 | u_start = text + undo_entry->start; | 1714 | u_start = text + undo_entry->start; |
1688 | text_hole_make(u_start, undo_entry->length); | 1715 | text_hole_make(u_start, undo_entry->length); |
1689 | memcpy(u_start, undo_entry->undo_text, undo_entry->length); | 1716 | memcpy(u_start, undo_entry->undo_text, undo_entry->length); |
1717 | # if ENABLE_FEATURE_VI_VERBOSE_STATUS | ||
1690 | status_line("Undo [%d] %s %d chars at position %d", | 1718 | status_line("Undo [%d] %s %d chars at position %d", |
1691 | modified_count, "restored", | 1719 | modified_count, "restored", |
1692 | undo_entry->length, undo_entry->start | 1720 | undo_entry->length, undo_entry->start |
1693 | ); | 1721 | ); |
1722 | # endif | ||
1694 | break; | 1723 | break; |
1695 | case UNDO_INS: | 1724 | case UNDO_INS: |
1696 | case UNDO_INS_CHAIN: | 1725 | case UNDO_INS_CHAIN: |
@@ -1698,10 +1727,12 @@ static void undo_pop(void) | |||
1698 | u_start = undo_entry->start + text; | 1727 | u_start = undo_entry->start + text; |
1699 | u_end = u_start - 1 + undo_entry->length; | 1728 | u_end = u_start - 1 + undo_entry->length; |
1700 | text_hole_delete(u_start, u_end, NO_UNDO); | 1729 | text_hole_delete(u_start, u_end, NO_UNDO); |
1730 | # if ENABLE_FEATURE_VI_VERBOSE_STATUS | ||
1701 | status_line("Undo [%d] %s %d chars at position %d", | 1731 | status_line("Undo [%d] %s %d chars at position %d", |
1702 | modified_count, "deleted", | 1732 | modified_count, "deleted", |
1703 | undo_entry->length, undo_entry->start | 1733 | undo_entry->length, undo_entry->start |
1704 | ); | 1734 | ); |
1735 | # endif | ||
1705 | break; | 1736 | break; |
1706 | } | 1737 | } |
1707 | repeat = 0; | 1738 | repeat = 0; |
@@ -2150,16 +2181,6 @@ static uintptr_t string_insert(char *p, const char *s, int undo) // insert the s | |||
2150 | bias = text_hole_make(p, i); | 2181 | bias = text_hole_make(p, i); |
2151 | p += bias; | 2182 | p += bias; |
2152 | memcpy(p, s, i); | 2183 | memcpy(p, s, i); |
2153 | #if ENABLE_FEATURE_VI_YANKMARK | ||
2154 | { | ||
2155 | int cnt; | ||
2156 | for (cnt = 0; *s != '\0'; s++) { | ||
2157 | if (*s == '\n') | ||
2158 | cnt++; | ||
2159 | } | ||
2160 | status_line("Put %d lines (%d chars) from [%c]", cnt, i, what_reg()); | ||
2161 | } | ||
2162 | #endif | ||
2163 | return bias; | 2184 | return bias; |
2164 | } | 2185 | } |
2165 | #endif | 2186 | #endif |
@@ -2821,6 +2842,9 @@ static void colon(char *buf) | |||
2821 | size_t len_F, len_R; | 2842 | size_t len_F, len_R; |
2822 | int gflag = 0; // global replace flag | 2843 | int gflag = 0; // global replace flag |
2823 | int subs = 0; // number of substitutions | 2844 | int subs = 0; // number of substitutions |
2845 | # if ENABLE_FEATURE_VI_VERBOSE_STATUS | ||
2846 | int last_line = 0, lines = 0; | ||
2847 | # endif | ||
2824 | 2848 | ||
2825 | // F points to the "find" pattern | 2849 | // F points to the "find" pattern |
2826 | // R points to the "replace" pattern | 2850 | // R points to the "replace" pattern |
@@ -2860,6 +2884,12 @@ static void colon(char *buf) | |||
2860 | subs ? ALLOW_UNDO_CHAIN: ALLOW_UNDO); | 2884 | subs ? ALLOW_UNDO_CHAIN: ALLOW_UNDO); |
2861 | // can't do this above, no undo => no third argument | 2885 | // can't do this above, no undo => no third argument |
2862 | subs++; | 2886 | subs++; |
2887 | # if ENABLE_FEATURE_VI_VERBOSE_STATUS | ||
2888 | if (last_line != i) { | ||
2889 | last_line = i; | ||
2890 | ++lines; | ||
2891 | } | ||
2892 | # endif | ||
2863 | // insert the "replace" patern | 2893 | // insert the "replace" patern |
2864 | bias = string_insert(found, R, ALLOW_UNDO_CHAIN); | 2894 | bias = string_insert(found, R, ALLOW_UNDO_CHAIN); |
2865 | found += bias; | 2895 | found += bias; |
@@ -2880,6 +2910,10 @@ static void colon(char *buf) | |||
2880 | status_line_bold("No match"); | 2910 | status_line_bold("No match"); |
2881 | } else { | 2911 | } else { |
2882 | dot_skip_over_ws(); | 2912 | dot_skip_over_ws(); |
2913 | # if ENABLE_FEATURE_VI_VERBOSE_STATUS | ||
2914 | if (subs > 1) | ||
2915 | status_line("%d substitutions on %d lines", subs, lines); | ||
2916 | # endif | ||
2883 | } | 2917 | } |
2884 | # endif /* FEATURE_VI_SEARCH */ | 2918 | # endif /* FEATURE_VI_SEARCH */ |
2885 | } else if (strncmp(cmd, "version", i) == 0) { // show software version | 2919 | } else if (strncmp(cmd, "version", i) == 0) { // show software version |
@@ -3434,8 +3468,9 @@ static void do_cmd(int c) | |||
3434 | status_line_bold("Nothing in register %c", what_reg()); | 3468 | status_line_bold("Nothing in register %c", what_reg()); |
3435 | break; | 3469 | break; |
3436 | } | 3470 | } |
3437 | // are we putting whole lines or strings | ||
3438 | cnt = 0; | 3471 | cnt = 0; |
3472 | i = cmdcnt ?: 1; | ||
3473 | // are we putting whole lines or strings | ||
3439 | if (regtype[YDreg] == WHOLE) { | 3474 | if (regtype[YDreg] == WHOLE) { |
3440 | if (c == 'P') { | 3475 | if (c == 'P') { |
3441 | dot_begin(); // putting lines- Put above | 3476 | dot_begin(); // putting lines- Put above |
@@ -3453,7 +3488,7 @@ static void do_cmd(int c) | |||
3453 | dot_right(); // move to right, can move to NL | 3488 | dot_right(); // move to right, can move to NL |
3454 | // how far to move cursor if register doesn't have a NL | 3489 | // how far to move cursor if register doesn't have a NL |
3455 | if (strchr(p, '\n') == NULL) | 3490 | if (strchr(p, '\n') == NULL) |
3456 | cnt = (cmdcnt ?: 1) * strlen(p) - 1; | 3491 | cnt = i * strlen(p) - 1; |
3457 | } | 3492 | } |
3458 | do { | 3493 | do { |
3459 | // dot is adjusted if text[] is reallocated so we don't have to | 3494 | // dot is adjusted if text[] is reallocated so we don't have to |
@@ -3463,6 +3498,9 @@ static void do_cmd(int c) | |||
3463 | # endif | 3498 | # endif |
3464 | } while (--cmdcnt > 0); | 3499 | } while (--cmdcnt > 0); |
3465 | dot += cnt; | 3500 | dot += cnt; |
3501 | # if ENABLE_FEATURE_VI_YANKMARK && ENABLE_FEATURE_VI_VERBOSE_STATUS | ||
3502 | yank_status("Put", p, i); | ||
3503 | # endif | ||
3466 | end_cmd_q(); // stop adding to q | 3504 | end_cmd_q(); // stop adding to q |
3467 | break; | 3505 | break; |
3468 | case 'U': // U- Undo; replace current line with original version | 3506 | case 'U': // U- Undo; replace current line with original version |
@@ -3473,6 +3511,9 @@ static void do_cmd(int c) | |||
3473 | p += string_insert(p, reg[Ureg], ALLOW_UNDO_CHAIN); // insert orig line | 3511 | p += string_insert(p, reg[Ureg], ALLOW_UNDO_CHAIN); // insert orig line |
3474 | dot = p; | 3512 | dot = p; |
3475 | dot_skip_over_ws(); | 3513 | dot_skip_over_ws(); |
3514 | # if ENABLE_FEATURE_VI_YANKMARK && ENABLE_FEATURE_VI_VERBOSE_STATUS | ||
3515 | yank_status("Undo", reg[Ureg], 1); | ||
3516 | # endif | ||
3476 | } | 3517 | } |
3477 | break; | 3518 | break; |
3478 | #endif /* FEATURE_VI_YANKMARK */ | 3519 | #endif /* FEATURE_VI_YANKMARK */ |
@@ -3878,7 +3919,9 @@ static void do_cmd(int c) | |||
3878 | int yf = YANKDEL; // assume either "c" or "d" | 3919 | int yf = YANKDEL; // assume either "c" or "d" |
3879 | int buftype; | 3920 | int buftype; |
3880 | #if ENABLE_FEATURE_VI_YANKMARK | 3921 | #if ENABLE_FEATURE_VI_YANKMARK |
3922 | # if ENABLE_FEATURE_VI_VERBOSE_STATUS | ||
3881 | char *savereg = reg[YDreg]; | 3923 | char *savereg = reg[YDreg]; |
3924 | # endif | ||
3882 | if (c == 'y' || c == 'Y') | 3925 | if (c == 'y' || c == 'Y') |
3883 | yf = YANKONLY; | 3926 | yf = YANKONLY; |
3884 | #endif | 3927 | #endif |
@@ -3901,27 +3944,12 @@ static void do_cmd(int c) | |||
3901 | } | 3944 | } |
3902 | // if CHANGING, not deleting, start inserting after the delete | 3945 | // if CHANGING, not deleting, start inserting after the delete |
3903 | if (c == 'c') { | 3946 | if (c == 'c') { |
3904 | //strcpy(buf, "Change"); | ||
3905 | goto dc_i; // start inserting | 3947 | goto dc_i; // start inserting |
3906 | } | 3948 | } |
3907 | #if ENABLE_FEATURE_VI_YANKMARK | 3949 | #if ENABLE_FEATURE_VI_YANKMARK && ENABLE_FEATURE_VI_VERBOSE_STATUS |
3908 | // only update status if a yank has actually happened | 3950 | // only update status if a yank has actually happened |
3909 | if (reg[YDreg] != savereg) { | 3951 | if (reg[YDreg] != savereg) |
3910 | if (c == 'd') { | 3952 | yank_status(c == 'd' ? "Delete" : "Yank", reg[YDreg], 1); |
3911 | strcpy(buf, "Delete"); | ||
3912 | } | ||
3913 | if (c == 'y' || c == 'Y') { | ||
3914 | strcpy(buf, "Yank"); | ||
3915 | } | ||
3916 | p = reg[YDreg]; | ||
3917 | q = p + strlen(p); | ||
3918 | for (cnt = 0; p <= q; p++) { | ||
3919 | if (*p == '\n') | ||
3920 | cnt++; | ||
3921 | } | ||
3922 | status_line("%s %u lines (%u chars) using [%c]", | ||
3923 | buf, cnt, (unsigned)strlen(reg[YDreg]), what_reg()); | ||
3924 | } | ||
3925 | #endif | 3953 | #endif |
3926 | dc6: | 3954 | dc6: |
3927 | end_cmd_q(); // stop adding to q | 3955 | end_cmd_q(); // stop adding to q |