0
0
mirror of https://github.com/vim/vim.git synced 2025-09-29 04:34:16 -04:00

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.
This commit is contained in:
Bram Moolenaar
2018-08-10 23:13:12 +02:00
parent 0ee81cb638
commit ee8415bc59
3 changed files with 179 additions and 163 deletions

View File

@@ -1719,7 +1719,6 @@ do_one_cmd(
cmdmod_T save_cmdmod;
int ni; /* set when Not Implemented */
char_u *cmd;
int address_count = 1;
vim_memset(&ea, 0, sizeof(ea));
ea.line1 = 1;
@@ -2045,168 +2044,9 @@ do_one_cmd(
get_wincmd_addr_type(skipwhite(p), &ea);
}
/* 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;
#ifdef FEAT_QUICKFIX
case ADDR_QUICKFIX:
ea.line2 = qf_get_cur_valid_idx(&ea);
break;
#endif
}
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;
#ifdef FEAT_QUICKFIX
case ADDR_QUICKFIX:
ea.line1 = 1;
ea.line2 = qf_get_size(&ea);
if (ea.line2 == 0)
ea.line2 = 1;
break;
#endif
}
++ea.addr_count;
}
/* '*' - visual area */
else if (*ea.cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL)
{
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;
/*
* 5. Parse the command.
@@ -2988,6 +2828,179 @@ doend:
#pragma optimize( "", on )
#endif
/*
* 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)
{
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;
#ifdef FEAT_QUICKFIX
case ADDR_QUICKFIX:
eap->line2 = qf_get_cur_valid_idx(eap);
break;
#endif
}
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;
#ifdef FEAT_QUICKFIX
case ADDR_QUICKFIX:
eap->line1 = 1;
eap->line2 = qf_get_size(eap);
if (eap->line2 == 0)
eap->line2 = 1;
break;
#endif
}
++eap->addr_count;
}
else if (*eap->cmd == '*' && vim_strchr(p_cpo, CPO_STAR) == NULL)
{
pos_T *fp;
// '*' - visual area
if (eap->addr_type != ADDR_LINES)
{
*errormsg = (char_u *)_(e_invrange);
return FAIL;
}
++eap->cmd;
if (!eap->skip)
{
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.
@@ -4292,7 +4305,7 @@ set_one_cmd_context(
}
/*
* skip a range specifier of the form: addr [,addr] [;addr] ..
* 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 "'".