summaryrefslogtreecommitdiff
path: root/editors/vi.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-04-25 11:51:55 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2021-04-28 11:29:33 +0200
commit7a8ceb4eb25f1b136bf9a79b04d46dc4d7f440a7 (patch)
treebbc4bc69aa3e42f2750c4fe5b5a6a97f2b9eb419 /editors/vi.c
parent81f9a0035b857206ac03afb729be3c8438f218b9 (diff)
downloadbusybox-7a8ceb4eb25f1b136bf9a79b04d46dc4d7f440a7.tar.gz
vi: changes to line addresses for colon commands
Make line addresses behave more like vi: - Vi allows the user to enter an arbitrary number of addresses, though only the last two are used. This simplifies get_address() by reducing the amount of state that needs to be carried. - When a command requires a single address the last one entered is used. - If addresses are separated by a ';' instead of a ',' the current line is updated to the left address. This may be useful when a search is used to specify a range, e.g. ':/first/;/last/d'. - When the last address is empty it should refer to the current line. function old new delta colon 3855 3834 -21 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-21) Total: -21 bytes Signed-off-by: Ron Yorston <rmy@pobox.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'editors/vi.c')
-rw-r--r--editors/vi.c110
1 files changed, 60 insertions, 50 deletions
diff --git a/editors/vi.c b/editors/vi.c
index caf01acd3..77c42641e 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -2473,37 +2473,43 @@ static char *get_one_address(char *p, int *result) // get colon addr, if present
return p;
}
-# define GET_FIRST 0
-# define GET_SECOND 1
-# define GOT_FIRST 2
-# define GOT_SECOND 3
-# define GOT 2
+# define GET_ADDRESS 0
+# define GET_SEPARATOR 1
-static char *get_address(char *p, int *b, int *e) // get two colon addrs, if present
+// Read line addresses for a colon command. The user can enter as
+// many as they like but only the last two will be used.
+static char *get_address(char *p, int *b, int *e)
{
- int state = GET_FIRST;
+ int state = GET_ADDRESS;
+ char *save_dot = dot;
//----- get the address' i.e., 1,3 'a,'b -----
for (;;) {
if (isblank(*p)) {
p++;
- } else if (*p == '%' && state == GET_FIRST) { // alias for 1,$
+ } else if (*p == '%' && state == GET_ADDRESS) { // alias for 1,$
p++;
*b = 1;
*e = count_lines(text, end-1);
- state = GOT_SECOND;
- } else if (*p == ',' && state == GOT_FIRST) {
+ state = GET_SEPARATOR;
+ } else if (state == GET_SEPARATOR && (*p == ',' || *p == ';')) {
+ if (*p == ';')
+ dot = find_line(*e);
p++;
- state = GET_SECOND;
- } else if (state == GET_FIRST || state == GET_SECOND) {
- p = get_one_address(p, state == GET_FIRST ? b : e);
+ *b = *e;
+ state = GET_ADDRESS;
+ } else if (state == GET_ADDRESS) {
+ p = get_one_address(p, e);
if (p == NULL)
break;
- state |= GOT;
+ state = GET_SEPARATOR;
} else {
+ if (state == GET_SEPARATOR && *e < 0)
+ *e = count_lines(text, dot);
break;
}
}
+ dot = save_dot;
return p;
}
@@ -2637,8 +2643,6 @@ static void colon(char *buf)
li = i = 0;
b = e = -1;
- q = text; // assume 1,$ for the range
- r = end - 1;
li = count_lines(text, end - 1);
fn = current_filename;
@@ -2673,27 +2677,33 @@ static void colon(char *buf)
useforce = TRUE;
*buf1 = '\0'; // get rid of !
}
- if (b >= 0) {
- // if there is only one addr, then the addr
- // is the line number of the single line the
- // user wants. So, reset the end
- // pointer to point at end of the "b" line
- q = find_line(b); // what line is #b
- r = end_line(q);
- li = 1;
- }
- if (e >= 0) {
- // we were given two addrs. change the
- // end pointer to the addr given by user.
- r = find_line(e); // what line is #e
- r = end_line(r);
- li = e - b + 1;
+ // assume the command will want a range, certain commands
+ // (read, substitute) need to adjust these assumptions
+ if (e < 0) {
+ q = text; // no addr, use 1,$ for the range
+ r = end - 1;
+ } else {
+ // at least one addr was given, get its details
+ q = r = find_line(e);
+ if (b < 0) {
+ // if there is only one addr, then it's the line
+ // number of the single line the user wants.
+ // Reset the end pointer to the end of that line.
+ r = end_line(q);
+ li = 1;
+ } else {
+ // we were given two addrs. change the
+ // start pointer to the addr given by user.
+ q = find_line(b); // what line is #b
+ r = end_line(r);
+ li = e - b + 1;
+ }
}
// ------------ now look for the command ------------
i = strlen(cmd);
if (i == 0) { // :123CR goto line #123
- if (b >= 0) {
- dot = find_line(b); // what line is #b
+ if (e >= 0) {
+ dot = find_line(e); // what line is #e
dot_skip_over_ws();
}
}
@@ -2711,12 +2721,12 @@ static void colon(char *buf)
}
# endif
else if (cmd[0] == '=' && !cmd[1]) { // where is the address
- if (b < 0) { // no addr given- use defaults
- b = e = count_lines(text, dot);
+ if (e < 0) { // no addr given- use defaults
+ e = count_lines(text, dot);
}
- status_line("%d", b);
+ status_line("%d", e);
} else if (strncmp(cmd, "delete", i) == 0) { // delete lines
- if (b < 0) { // no addr given- use defaults
+ if (e < 0) { // no addr given- use defaults
q = begin_line(dot); // assume .,. for the range
r = end_line(dot);
}
@@ -2767,7 +2777,7 @@ static void colon(char *buf)
li, (int)(end - text)
);
} else if (strncmp(cmd, "file", i) == 0) { // what File is this
- if (b != -1 || e != -1) {
+ if (e >= 0) {
status_line_bold("No address allowed on this command");
goto ret;
}
@@ -2787,7 +2797,7 @@ static void colon(char *buf)
rawmode();
Hit_Return();
} else if (strncmp(cmd, "list", i) == 0) { // literal print line
- if (b < 0) { // no addr given- use defaults
+ if (e < 0) { // no addr given- use defaults
q = begin_line(dot); // assume .,. for the range
r = end_line(dot);
}
@@ -2861,12 +2871,12 @@ static void colon(char *buf)
status_line_bold("No filename given");
goto ret;
}
- if (b < 0) { // no addr given- use defaults
- q = begin_line(dot); // assume "dot"
- }
- // read after current line- unless user said ":0r foo"
- if (b != 0) {
- q = next_line(q);
+ if (e < 0) { // no addr given- read after current line
+ q = begin_line(dot);
+ } else if (e == 0) { // user said ":0r foo"
+ q = text;
+ } else { // addr given- read after that line
+ q = next_line(find_line(e));
// read after last line
if (q == end-1)
++q;
@@ -2969,13 +2979,13 @@ static void colon(char *buf)
}
len_R = strlen(R);
- q = begin_line(q);
- if (b < 0) { // maybe :s/foo/bar/
+ if (e < 0) { // no addr given
q = begin_line(dot); // start with cur line
- b = count_lines(text, q); // cur line number
+ r = end_line(dot);
+ b = e = count_lines(text, q); // cur line number
+ } else if (b < 0) { // one addr given
+ b = e;
}
- if (e < 0)
- e = b; // maybe :.s/foo/bar/
for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0
char *ls = q; // orig line start