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>
This commit is contained in:
parent
81f9a0035b
commit
7a8ceb4eb2
100
editors/vi.c
100
editors/vi.c
@ -2473,37 +2473,43 @@ static char *get_one_address(char *p, int *result) // get colon addr, if present
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
# define GET_FIRST 0
|
# define GET_ADDRESS 0
|
||||||
# define GET_SECOND 1
|
# define GET_SEPARATOR 1
|
||||||
# define GOT_FIRST 2
|
|
||||||
# define GOT_SECOND 3
|
|
||||||
# define GOT 2
|
|
||||||
|
|
||||||
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 -----
|
//----- get the address' i.e., 1,3 'a,'b -----
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (isblank(*p)) {
|
if (isblank(*p)) {
|
||||||
p++;
|
p++;
|
||||||
} else if (*p == '%' && state == GET_FIRST) { // alias for 1,$
|
} else if (*p == '%' && state == GET_ADDRESS) { // alias for 1,$
|
||||||
p++;
|
p++;
|
||||||
*b = 1;
|
*b = 1;
|
||||||
*e = count_lines(text, end-1);
|
*e = count_lines(text, end-1);
|
||||||
state = GOT_SECOND;
|
state = GET_SEPARATOR;
|
||||||
} else if (*p == ',' && state == GOT_FIRST) {
|
} else if (state == GET_SEPARATOR && (*p == ',' || *p == ';')) {
|
||||||
|
if (*p == ';')
|
||||||
|
dot = find_line(*e);
|
||||||
p++;
|
p++;
|
||||||
state = GET_SECOND;
|
*b = *e;
|
||||||
} else if (state == GET_FIRST || state == GET_SECOND) {
|
state = GET_ADDRESS;
|
||||||
p = get_one_address(p, state == GET_FIRST ? b : e);
|
} else if (state == GET_ADDRESS) {
|
||||||
|
p = get_one_address(p, e);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
break;
|
break;
|
||||||
state |= GOT;
|
state = GET_SEPARATOR;
|
||||||
} else {
|
} else {
|
||||||
|
if (state == GET_SEPARATOR && *e < 0)
|
||||||
|
*e = count_lines(text, dot);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
dot = save_dot;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2637,8 +2643,6 @@ static void colon(char *buf)
|
|||||||
|
|
||||||
li = i = 0;
|
li = i = 0;
|
||||||
b = e = -1;
|
b = e = -1;
|
||||||
q = text; // assume 1,$ for the range
|
|
||||||
r = end - 1;
|
|
||||||
li = count_lines(text, end - 1);
|
li = count_lines(text, end - 1);
|
||||||
fn = current_filename;
|
fn = current_filename;
|
||||||
|
|
||||||
@ -2673,27 +2677,33 @@ static void colon(char *buf)
|
|||||||
useforce = TRUE;
|
useforce = TRUE;
|
||||||
*buf1 = '\0'; // get rid of !
|
*buf1 = '\0'; // get rid of !
|
||||||
}
|
}
|
||||||
if (b >= 0) {
|
// assume the command will want a range, certain commands
|
||||||
// if there is only one addr, then the addr
|
// (read, substitute) need to adjust these assumptions
|
||||||
// is the line number of the single line the
|
if (e < 0) {
|
||||||
// user wants. So, reset the end
|
q = text; // no addr, use 1,$ for the range
|
||||||
// pointer to point at end of the "b" line
|
r = end - 1;
|
||||||
q = find_line(b); // what line is #b
|
} 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);
|
r = end_line(q);
|
||||||
li = 1;
|
li = 1;
|
||||||
}
|
} else {
|
||||||
if (e >= 0) {
|
|
||||||
// we were given two addrs. change the
|
// we were given two addrs. change the
|
||||||
// end pointer to the addr given by user.
|
// start pointer to the addr given by user.
|
||||||
r = find_line(e); // what line is #e
|
q = find_line(b); // what line is #b
|
||||||
r = end_line(r);
|
r = end_line(r);
|
||||||
li = e - b + 1;
|
li = e - b + 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// ------------ now look for the command ------------
|
// ------------ now look for the command ------------
|
||||||
i = strlen(cmd);
|
i = strlen(cmd);
|
||||||
if (i == 0) { // :123CR goto line #123
|
if (i == 0) { // :123CR goto line #123
|
||||||
if (b >= 0) {
|
if (e >= 0) {
|
||||||
dot = find_line(b); // what line is #b
|
dot = find_line(e); // what line is #e
|
||||||
dot_skip_over_ws();
|
dot_skip_over_ws();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2711,12 +2721,12 @@ static void colon(char *buf)
|
|||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
else if (cmd[0] == '=' && !cmd[1]) { // where is the address
|
else if (cmd[0] == '=' && !cmd[1]) { // where is the address
|
||||||
if (b < 0) { // no addr given- use defaults
|
if (e < 0) { // no addr given- use defaults
|
||||||
b = e = count_lines(text, dot);
|
e = count_lines(text, dot);
|
||||||
}
|
}
|
||||||
status_line("%d", b);
|
status_line("%d", e);
|
||||||
} else if (strncmp(cmd, "delete", i) == 0) { // delete lines
|
} 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
|
q = begin_line(dot); // assume .,. for the range
|
||||||
r = end_line(dot);
|
r = end_line(dot);
|
||||||
}
|
}
|
||||||
@ -2767,7 +2777,7 @@ static void colon(char *buf)
|
|||||||
li, (int)(end - text)
|
li, (int)(end - text)
|
||||||
);
|
);
|
||||||
} else if (strncmp(cmd, "file", i) == 0) { // what File is this
|
} 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");
|
status_line_bold("No address allowed on this command");
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
@ -2787,7 +2797,7 @@ static void colon(char *buf)
|
|||||||
rawmode();
|
rawmode();
|
||||||
Hit_Return();
|
Hit_Return();
|
||||||
} else if (strncmp(cmd, "list", i) == 0) { // literal print line
|
} 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
|
q = begin_line(dot); // assume .,. for the range
|
||||||
r = end_line(dot);
|
r = end_line(dot);
|
||||||
}
|
}
|
||||||
@ -2861,12 +2871,12 @@ static void colon(char *buf)
|
|||||||
status_line_bold("No filename given");
|
status_line_bold("No filename given");
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
if (b < 0) { // no addr given- use defaults
|
if (e < 0) { // no addr given- read after current line
|
||||||
q = begin_line(dot); // assume "dot"
|
q = begin_line(dot);
|
||||||
}
|
} else if (e == 0) { // user said ":0r foo"
|
||||||
// read after current line- unless user said ":0r foo"
|
q = text;
|
||||||
if (b != 0) {
|
} else { // addr given- read after that line
|
||||||
q = next_line(q);
|
q = next_line(find_line(e));
|
||||||
// read after last line
|
// read after last line
|
||||||
if (q == end-1)
|
if (q == end-1)
|
||||||
++q;
|
++q;
|
||||||
@ -2969,13 +2979,13 @@ static void colon(char *buf)
|
|||||||
}
|
}
|
||||||
len_R = strlen(R);
|
len_R = strlen(R);
|
||||||
|
|
||||||
q = begin_line(q);
|
if (e < 0) { // no addr given
|
||||||
if (b < 0) { // maybe :s/foo/bar/
|
|
||||||
q = begin_line(dot); // start with cur line
|
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
|
for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0
|
||||||
char *ls = q; // orig line start
|
char *ls = q; // orig line start
|
||||||
|
Loading…
Reference in New Issue
Block a user