summaryrefslogtreecommitdiff
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 96e6af3..fb46dc3 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -159,6 +159,14 @@
//config: and will generally malloc() larger objects and less frequently.
//config: Unless you want more (or less) frequent "undo points" while typing,
//config: you should probably leave this unchanged.
+//config:
+//config:config FEATURE_VI_VERBOSE_STATUS
+//config: bool "Enable verbose status reporting"
+//config: default y
+//config: depends on VI
+//config: help
+//config: Enable more verbose reporting of the results of yank, change,
+//config: delete, undo and substitution commands.
//applet:IF_VI(APPLET(vi, BB_DIR_BIN, BB_SUID_DROP))
@@ -1357,14 +1365,17 @@ static void not_implemented(const char *s)
// copy text into a register
static char *text_yank(char *p, char *q, int dest, int buftype)
{
+ char *oldreg = reg[dest];
int cnt = q - p;
if (cnt < 0) { // they are backwards- reverse them
p = q;
cnt = -cnt;
}
- free(reg[dest]); // if already a yank register, free it
+ // Don't free register yet. This prevents the memory allocator
+ // from reusing the free block so we can detect if it's changed.
reg[dest] = xstrndup(p, cnt + 1);
regtype[dest] = buftype;
+ free(oldreg);
return p;
}
@@ -1415,6 +1426,22 @@ static char *swap_context(char *p) // goto new context for '' command make this
}
return p;
}
+
+# if ENABLE_FEATURE_VI_VERBOSE_STATUS
+static void yank_status(const char *op, const char *p, int cnt)
+{
+ int lines, chars;
+
+ lines = chars = 0;
+ while (*p) {
+ ++chars;
+ if (*p++ == '\n')
+ ++lines;
+ }
+ status_line("%s %d lines (%d chars) from [%c]",
+ op, lines * cnt, chars * cnt, what_reg());
+}
+# endif
#endif /* FEATURE_VI_YANKMARK */
#if ENABLE_FEATURE_VI_UNDO
@@ -1687,10 +1714,12 @@ static void undo_pop(void)
u_start = text + undo_entry->start;
text_hole_make(u_start, undo_entry->length);
memcpy(u_start, undo_entry->undo_text, undo_entry->length);
+# if ENABLE_FEATURE_VI_VERBOSE_STATUS
status_line("Undo [%d] %s %d chars at position %d",
modified_count, "restored",
undo_entry->length, undo_entry->start
);
+# endif
break;
case UNDO_INS:
case UNDO_INS_CHAIN:
@@ -1698,10 +1727,12 @@ static void undo_pop(void)
u_start = undo_entry->start + text;
u_end = u_start - 1 + undo_entry->length;
text_hole_delete(u_start, u_end, NO_UNDO);
+# if ENABLE_FEATURE_VI_VERBOSE_STATUS
status_line("Undo [%d] %s %d chars at position %d",
modified_count, "deleted",
undo_entry->length, undo_entry->start
);
+# endif
break;
}
repeat = 0;
@@ -2150,16 +2181,6 @@ static uintptr_t string_insert(char *p, const char *s, int undo) // insert the s
bias = text_hole_make(p, i);
p += bias;
memcpy(p, s, i);
-#if ENABLE_FEATURE_VI_YANKMARK
- {
- int cnt;
- for (cnt = 0; *s != '\0'; s++) {
- if (*s == '\n')
- cnt++;
- }
- status_line("Put %d lines (%d chars) from [%c]", cnt, i, what_reg());
- }
-#endif
return bias;
}
#endif
@@ -2821,6 +2842,9 @@ static void colon(char *buf)
size_t len_F, len_R;
int gflag = 0; // global replace flag
int subs = 0; // number of substitutions
+# if ENABLE_FEATURE_VI_VERBOSE_STATUS
+ int last_line = 0, lines = 0;
+# endif
// F points to the "find" pattern
// R points to the "replace" pattern
@@ -2860,6 +2884,12 @@ static void colon(char *buf)
subs ? ALLOW_UNDO_CHAIN: ALLOW_UNDO);
// can't do this above, no undo => no third argument
subs++;
+# if ENABLE_FEATURE_VI_VERBOSE_STATUS
+ if (last_line != i) {
+ last_line = i;
+ ++lines;
+ }
+# endif
// insert the "replace" patern
bias = string_insert(found, R, ALLOW_UNDO_CHAIN);
found += bias;
@@ -2880,6 +2910,10 @@ static void colon(char *buf)
status_line_bold("No match");
} else {
dot_skip_over_ws();
+# if ENABLE_FEATURE_VI_VERBOSE_STATUS
+ if (subs > 1)
+ status_line("%d substitutions on %d lines", subs, lines);
+# endif
}
# endif /* FEATURE_VI_SEARCH */
} else if (strncmp(cmd, "version", i) == 0) { // show software version
@@ -3434,8 +3468,9 @@ static void do_cmd(int c)
status_line_bold("Nothing in register %c", what_reg());
break;
}
- // are we putting whole lines or strings
cnt = 0;
+ i = cmdcnt ?: 1;
+ // are we putting whole lines or strings
if (regtype[YDreg] == WHOLE) {
if (c == 'P') {
dot_begin(); // putting lines- Put above
@@ -3453,7 +3488,7 @@ static void do_cmd(int c)
dot_right(); // move to right, can move to NL
// how far to move cursor if register doesn't have a NL
if (strchr(p, '\n') == NULL)
- cnt = (cmdcnt ?: 1) * strlen(p) - 1;
+ cnt = i * strlen(p) - 1;
}
do {
// dot is adjusted if text[] is reallocated so we don't have to
@@ -3463,6 +3498,9 @@ static void do_cmd(int c)
# endif
} while (--cmdcnt > 0);
dot += cnt;
+# if ENABLE_FEATURE_VI_YANKMARK && ENABLE_FEATURE_VI_VERBOSE_STATUS
+ yank_status("Put", p, i);
+# endif
end_cmd_q(); // stop adding to q
break;
case 'U': // U- Undo; replace current line with original version
@@ -3473,6 +3511,9 @@ static void do_cmd(int c)
p += string_insert(p, reg[Ureg], ALLOW_UNDO_CHAIN); // insert orig line
dot = p;
dot_skip_over_ws();
+# if ENABLE_FEATURE_VI_YANKMARK && ENABLE_FEATURE_VI_VERBOSE_STATUS
+ yank_status("Undo", reg[Ureg], 1);
+# endif
}
break;
#endif /* FEATURE_VI_YANKMARK */
@@ -3878,7 +3919,9 @@ static void do_cmd(int c)
int yf = YANKDEL; // assume either "c" or "d"
int buftype;
#if ENABLE_FEATURE_VI_YANKMARK
+# if ENABLE_FEATURE_VI_VERBOSE_STATUS
char *savereg = reg[YDreg];
+# endif
if (c == 'y' || c == 'Y')
yf = YANKONLY;
#endif
@@ -3901,27 +3944,12 @@ static void do_cmd(int c)
}
// if CHANGING, not deleting, start inserting after the delete
if (c == 'c') {
- //strcpy(buf, "Change");
goto dc_i; // start inserting
}
-#if ENABLE_FEATURE_VI_YANKMARK
+#if ENABLE_FEATURE_VI_YANKMARK && ENABLE_FEATURE_VI_VERBOSE_STATUS
// only update status if a yank has actually happened
- if (reg[YDreg] != savereg) {
- if (c == 'd') {
- strcpy(buf, "Delete");
- }
- if (c == 'y' || c == 'Y') {
- strcpy(buf, "Yank");
- }
- p = reg[YDreg];
- q = p + strlen(p);
- for (cnt = 0; p <= q; p++) {
- if (*p == '\n')
- cnt++;
- }
- status_line("%s %u lines (%u chars) using [%c]",
- buf, cnt, (unsigned)strlen(reg[YDreg]), what_reg());
- }
+ if (reg[YDreg] != savereg)
+ yank_status(c == 'd' ? "Delete" : "Yank", reg[YDreg], 1);
#endif
dc6:
end_cmd_q(); // stop adding to q