vim-patch:8.1.0266: parsing Ex address range is not a separate function
Problem: Parsing Ex address range is not a separate function.
Solution: Refactor do_one_cmd() to separate address parsing.
ee8415bc59
This commit is contained in:
parent
ece3d19b02
commit
c512dffb55
|
@ -1255,7 +1255,6 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
|||
cmdmod_T save_cmdmod;
|
||||
const int save_reg_executing = reg_executing;
|
||||
char_u *cmd;
|
||||
int address_count = 1;
|
||||
|
||||
memset(&ea, 0, sizeof(ea));
|
||||
ea.line1 = 1;
|
||||
|
@ -1571,148 +1570,9 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
|||
}
|
||||
}
|
||||
|
||||
/* repeat for all ',' or ';' separated addresses */
|
||||
ea.cmd = cmd;
|
||||
for (;; ) {
|
||||
ea.line1 = ea.line2;
|
||||
switch (ea.addr_type) {
|
||||
case ADDR_LINES:
|
||||
// default is current line number
|
||||
ea.line2 = curwin->w_cursor.lnum;
|
||||
break;
|
||||
case ADDR_WINDOWS:
|
||||
ea.line2 = CURRENT_WIN_NR;
|
||||
break;
|
||||
case ADDR_ARGUMENTS:
|
||||
ea.line2 = curwin->w_arg_idx + 1;
|
||||
if (ea.line2 > ARGCOUNT) {
|
||||
ea.line2 = ARGCOUNT;
|
||||
}
|
||||
break;
|
||||
case ADDR_LOADED_BUFFERS:
|
||||
case ADDR_BUFFERS:
|
||||
ea.line2 = curbuf->b_fnum;
|
||||
break;
|
||||
case ADDR_TABS:
|
||||
ea.line2 = CURRENT_TAB_NR;
|
||||
break;
|
||||
case ADDR_TABS_RELATIVE:
|
||||
ea.line2 = 1;
|
||||
break;
|
||||
case ADDR_QUICKFIX:
|
||||
ea.line2 = qf_get_cur_valid_idx(&ea);
|
||||
break;
|
||||
}
|
||||
ea.cmd = skipwhite(ea.cmd);
|
||||
lnum = get_address(&ea, &ea.cmd, ea.addr_type, ea.skip,
|
||||
ea.addr_count == 0, address_count++);
|
||||
if (ea.cmd == NULL) { // error detected
|
||||
goto doend;
|
||||
}
|
||||
if (lnum == MAXLNUM) {
|
||||
if (*ea.cmd == '%') { /* '%' - all lines */
|
||||
++ea.cmd;
|
||||
switch (ea.addr_type) {
|
||||
case ADDR_LINES:
|
||||
ea.line1 = 1;
|
||||
ea.line2 = curbuf->b_ml.ml_line_count;
|
||||
break;
|
||||
case ADDR_LOADED_BUFFERS: {
|
||||
buf_T *buf = firstbuf;
|
||||
while (buf->b_next != NULL && buf->b_ml.ml_mfp == NULL) {
|
||||
buf = buf->b_next;
|
||||
}
|
||||
ea.line1 = buf->b_fnum;
|
||||
buf = lastbuf;
|
||||
while (buf->b_prev != NULL && buf->b_ml.ml_mfp == NULL) {
|
||||
buf = buf->b_prev;
|
||||
}
|
||||
ea.line2 = buf->b_fnum;
|
||||
break;
|
||||
}
|
||||
case ADDR_BUFFERS:
|
||||
ea.line1 = firstbuf->b_fnum;
|
||||
ea.line2 = lastbuf->b_fnum;
|
||||
break;
|
||||
case ADDR_WINDOWS:
|
||||
case ADDR_TABS:
|
||||
if (IS_USER_CMDIDX(ea.cmdidx)) {
|
||||
ea.line1 = 1;
|
||||
ea.line2 =
|
||||
ea.addr_type == ADDR_WINDOWS ? LAST_WIN_NR : LAST_TAB_NR;
|
||||
} else {
|
||||
// there is no Vim command which uses '%' and
|
||||
// ADDR_WINDOWS or ADDR_TABS
|
||||
errormsg = (char_u *)_(e_invrange);
|
||||
goto doend;
|
||||
}
|
||||
break;
|
||||
case ADDR_TABS_RELATIVE:
|
||||
errormsg = (char_u *)_(e_invrange);
|
||||
goto doend;
|
||||
break;
|
||||
case ADDR_ARGUMENTS:
|
||||
if (ARGCOUNT == 0) {
|
||||
ea.line1 = ea.line2 = 0;
|
||||
} else {
|
||||
ea.line1 = 1;
|
||||
ea.line2 = ARGCOUNT;
|
||||
}
|
||||
break;
|
||||
case ADDR_QUICKFIX:
|
||||
ea.line1 = 1;
|
||||
ea.line2 = qf_get_size(&ea);
|
||||
if (ea.line2 == 0) {
|
||||
ea.line2 = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
++ea.addr_count;
|
||||
}
|
||||
/* '*' - visual area */
|
||||
else if (*ea.cmd == '*') {
|
||||
pos_T *fp;
|
||||
|
||||
if (ea.addr_type != ADDR_LINES) {
|
||||
errormsg = (char_u *)_(e_invrange);
|
||||
goto doend;
|
||||
}
|
||||
|
||||
++ea.cmd;
|
||||
if (!ea.skip) {
|
||||
fp = getmark('<', FALSE);
|
||||
if (check_mark(fp) == FAIL)
|
||||
goto doend;
|
||||
ea.line1 = fp->lnum;
|
||||
fp = getmark('>', FALSE);
|
||||
if (check_mark(fp) == FAIL)
|
||||
goto doend;
|
||||
ea.line2 = fp->lnum;
|
||||
++ea.addr_count;
|
||||
}
|
||||
}
|
||||
} else
|
||||
ea.line2 = lnum;
|
||||
ea.addr_count++;
|
||||
|
||||
if (*ea.cmd == ';') {
|
||||
if (!ea.skip) {
|
||||
curwin->w_cursor.lnum = ea.line2;
|
||||
// don't leave the cursor on an illegal line or column
|
||||
check_cursor();
|
||||
}
|
||||
} else if (*ea.cmd != ',') {
|
||||
break;
|
||||
}
|
||||
ea.cmd++;
|
||||
}
|
||||
|
||||
/* One address given: set start and end lines */
|
||||
if (ea.addr_count == 1) {
|
||||
ea.line1 = ea.line2;
|
||||
/* ... but only implicit: really no address given */
|
||||
if (lnum == MAXLNUM)
|
||||
ea.addr_count = 0;
|
||||
if (parse_cmd_address(&ea, &errormsg) == FAIL) {
|
||||
goto doend;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2376,6 +2236,160 @@ doend:
|
|||
return ea.nextcmd;
|
||||
}
|
||||
|
||||
// Parse the address range, if any, in "eap".
|
||||
// Return FAIL and set "errormsg" or return OK.
|
||||
int parse_cmd_address(exarg_T *eap, char_u **errormsg)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
int address_count = 1;
|
||||
linenr_T lnum;
|
||||
|
||||
// Repeat for all ',' or ';' separated addresses.
|
||||
for (;;) {
|
||||
eap->line1 = eap->line2;
|
||||
switch (eap->addr_type) {
|
||||
case ADDR_LINES:
|
||||
// default is current line number
|
||||
eap->line2 = curwin->w_cursor.lnum;
|
||||
break;
|
||||
case ADDR_WINDOWS:
|
||||
eap->line2 = CURRENT_WIN_NR;
|
||||
break;
|
||||
case ADDR_ARGUMENTS:
|
||||
eap->line2 = curwin->w_arg_idx + 1;
|
||||
if (eap->line2 > ARGCOUNT) {
|
||||
eap->line2 = ARGCOUNT;
|
||||
}
|
||||
break;
|
||||
case ADDR_LOADED_BUFFERS:
|
||||
case ADDR_BUFFERS:
|
||||
eap->line2 = curbuf->b_fnum;
|
||||
break;
|
||||
case ADDR_TABS:
|
||||
eap->line2 = CURRENT_TAB_NR;
|
||||
break;
|
||||
case ADDR_TABS_RELATIVE:
|
||||
eap->line2 = 1;
|
||||
break;
|
||||
case ADDR_QUICKFIX:
|
||||
eap->line2 = qf_get_cur_valid_idx(eap);
|
||||
break;
|
||||
}
|
||||
eap->cmd = skipwhite(eap->cmd);
|
||||
lnum = get_address(eap, &eap->cmd, eap->addr_type, eap->skip,
|
||||
eap->addr_count == 0, address_count++);
|
||||
if (eap->cmd == NULL) { // error detected
|
||||
return FAIL;
|
||||
}
|
||||
if (lnum == MAXLNUM) {
|
||||
if (*eap->cmd == '%') { // '%' - all lines
|
||||
eap->cmd++;
|
||||
switch (eap->addr_type) {
|
||||
case ADDR_LINES:
|
||||
eap->line1 = 1;
|
||||
eap->line2 = curbuf->b_ml.ml_line_count;
|
||||
break;
|
||||
case ADDR_LOADED_BUFFERS: {
|
||||
buf_T *buf = firstbuf;
|
||||
|
||||
while (buf->b_next != NULL && buf->b_ml.ml_mfp == NULL) {
|
||||
buf = buf->b_next;
|
||||
}
|
||||
eap->line1 = buf->b_fnum;
|
||||
buf = lastbuf;
|
||||
while (buf->b_prev != NULL && buf->b_ml.ml_mfp == NULL) {
|
||||
buf = buf->b_prev;
|
||||
}
|
||||
eap->line2 = buf->b_fnum;
|
||||
break;
|
||||
}
|
||||
case ADDR_BUFFERS:
|
||||
eap->line1 = firstbuf->b_fnum;
|
||||
eap->line2 = lastbuf->b_fnum;
|
||||
break;
|
||||
case ADDR_WINDOWS:
|
||||
case ADDR_TABS:
|
||||
if (IS_USER_CMDIDX(eap->cmdidx)) {
|
||||
eap->line1 = 1;
|
||||
eap->line2 = eap->addr_type == ADDR_WINDOWS
|
||||
? LAST_WIN_NR : LAST_TAB_NR;
|
||||
} else {
|
||||
// there is no Vim command which uses '%' and
|
||||
// ADDR_WINDOWS or ADDR_TABS
|
||||
*errormsg = (char_u *)_(e_invrange);
|
||||
return FAIL;
|
||||
}
|
||||
break;
|
||||
case ADDR_TABS_RELATIVE:
|
||||
*errormsg = (char_u *)_(e_invrange);
|
||||
return FAIL;
|
||||
case ADDR_ARGUMENTS:
|
||||
if (ARGCOUNT == 0) {
|
||||
eap->line1 = eap->line2 = 0;
|
||||
} else {
|
||||
eap->line1 = 1;
|
||||
eap->line2 = ARGCOUNT;
|
||||
}
|
||||
break;
|
||||
case ADDR_QUICKFIX:
|
||||
eap->line1 = 1;
|
||||
eap->line2 = qf_get_size(eap);
|
||||
if (eap->line2 == 0) {
|
||||
eap->line2 = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
eap->addr_count++;
|
||||
} else if (*eap->cmd == '*') {
|
||||
// '*' - visual area
|
||||
if (eap->addr_type != ADDR_LINES) {
|
||||
*errormsg = (char_u *)_(e_invrange);
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
eap->cmd++;
|
||||
if (!eap->skip) {
|
||||
pos_T *fp = getmark('<', false);
|
||||
if (check_mark(fp) == FAIL) {
|
||||
return FAIL;
|
||||
}
|
||||
eap->line1 = fp->lnum;
|
||||
fp = getmark('>', false);
|
||||
if (check_mark(fp) == FAIL) {
|
||||
return FAIL;
|
||||
}
|
||||
eap->line2 = fp->lnum;
|
||||
eap->addr_count++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eap->line2 = lnum;
|
||||
}
|
||||
eap->addr_count++;
|
||||
|
||||
if (*eap->cmd == ';') {
|
||||
if (!eap->skip) {
|
||||
curwin->w_cursor.lnum = eap->line2;
|
||||
// don't leave the cursor on an illegal line or column
|
||||
check_cursor();
|
||||
}
|
||||
} else if (*eap->cmd != ',') {
|
||||
break;
|
||||
}
|
||||
eap->cmd++;
|
||||
}
|
||||
|
||||
// One address given: set start and end lines.
|
||||
if (eap->addr_count == 1) {
|
||||
eap->line1 = eap->line2;
|
||||
// ... but only implicit: really no address given
|
||||
if (lnum == MAXLNUM) {
|
||||
eap->addr_count = 0;
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for an Ex command with optional tail.
|
||||
* If there is a match advance "pp" to the argument and return TRUE.
|
||||
|
@ -3556,15 +3570,13 @@ const char * set_one_cmd_context(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* skip a range specifier of the form: addr [,addr] [;addr] ..
|
||||
*
|
||||
* Backslashed delimiters after / or ? will be skipped, and commands will
|
||||
* not be expanded between /'s and ?'s or after "'".
|
||||
*
|
||||
* Also skip white space and ":" characters.
|
||||
* Returns the "cmd" pointer advanced to beyond the range.
|
||||
*/
|
||||
// Skip a range specifier of the form: addr [,addr] [;addr] ..
|
||||
//
|
||||
// Backslashed delimiters after / or ? will be skipped, and commands will
|
||||
// not be expanded between /'s and ?'s or after "'".
|
||||
//
|
||||
// Also skip white space and ":" characters.
|
||||
// Returns the "cmd" pointer advanced to beyond the range.
|
||||
char_u *skip_range(
|
||||
const char_u *cmd,
|
||||
int *ctx // pointer to xp_context or NULL
|
||||
|
|
|
@ -296,17 +296,17 @@ pos_T *movechangelist(int count)
|
|||
* - NULL if there is no mark called 'c'.
|
||||
* - -1 if mark is in other file and jumped there (only if changefile is TRUE)
|
||||
*/
|
||||
pos_T *getmark_buf(buf_T *buf, int c, int changefile)
|
||||
pos_T *getmark_buf(buf_T *buf, int c, bool changefile)
|
||||
{
|
||||
return getmark_buf_fnum(buf, c, changefile, NULL);
|
||||
}
|
||||
|
||||
pos_T *getmark(int c, int changefile)
|
||||
pos_T *getmark(int c, bool changefile)
|
||||
{
|
||||
return getmark_buf_fnum(curbuf, c, changefile, NULL);
|
||||
}
|
||||
|
||||
pos_T *getmark_buf_fnum(buf_T *buf, int c, int changefile, int *fnum)
|
||||
pos_T *getmark_buf_fnum(buf_T *buf, int c, bool changefile, int *fnum)
|
||||
{
|
||||
pos_T *posp;
|
||||
pos_T *startp, *endp;
|
||||
|
|
Loading…
Reference in New Issue