aboutsummaryrefslogtreecommitdiff
path: root/editors/vi.c
diff options
context:
space:
mode:
Diffstat (limited to 'editors/vi.c')
-rw-r--r--editors/vi.c90
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
1358static char *text_yank(char *p, char *q, int dest, int buftype) 1366static 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
1431static 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