0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 8.0.0259: tab commands do not handle count correctly

Problem:    Tab commands do not handle count correctly. (Ken Hamada)
Solution:   Add ADDR_TABS_RELATIVE. (Hirohito Higashi)
This commit is contained in:
Bram Moolenaar
2017-01-29 14:48:10 +01:00
parent c9b56b2ceb
commit 2f72c70657
4 changed files with 450 additions and 109 deletions

View File

@@ -2162,8 +2162,7 @@ do_one_cmd(
ea.line2 = curwin->w_cursor.lnum;
break;
case ADDR_WINDOWS:
lnum = CURRENT_WIN_NR;
ea.line2 = lnum;
ea.line2 = CURRENT_WIN_NR;
break;
case ADDR_ARGUMENTS:
ea.line2 = curwin->w_arg_idx + 1;
@@ -2175,8 +2174,10 @@ do_one_cmd(
ea.line2 = curbuf->b_fnum;
break;
case ADDR_TABS:
lnum = CURRENT_TAB_NR;
ea.line2 = lnum;
ea.line2 = CURRENT_TAB_NR;
break;
case ADDR_TABS_RELATIVE:
ea.line2 = 1;
break;
#ifdef FEAT_QUICKFIX
case ADDR_QUICKFIX:
@@ -2235,6 +2236,10 @@ do_one_cmd(
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;
@@ -2710,6 +2715,9 @@ do_one_cmd(
case ADDR_TABS:
ea.line2 = LAST_TAB_NR;
break;
case ADDR_TABS_RELATIVE:
ea.line2 = 1;
break;
case ADDR_ARGUMENTS:
if (ARGCOUNT == 0)
ea.line1 = ea.line2 = 0;
@@ -2786,7 +2794,8 @@ do_one_cmd(
/*
* Be vi compatible: no error message for out of range.
*/
if (ea.line2 > curbuf->b_ml.ml_line_count)
if (ea.addr_type == ADDR_LINES
&& ea.line2 > curbuf->b_ml.ml_line_count)
ea.line2 = curbuf->b_ml.ml_line_count;
}
}
@@ -4427,6 +4436,11 @@ get_address(
case ADDR_TABS:
lnum = CURRENT_TAB_NR;
break;
case ADDR_TABS_RELATIVE:
EMSG(_(e_invrange));
cmd = NULL;
goto error;
break;
#ifdef FEAT_QUICKFIX
case ADDR_QUICKFIX:
lnum = qf_get_cur_valid_idx(eap);
@@ -4464,6 +4478,11 @@ get_address(
case ADDR_TABS:
lnum = LAST_TAB_NR;
break;
case ADDR_TABS_RELATIVE:
EMSG(_(e_invrange));
cmd = NULL;
goto error;
break;
#ifdef FEAT_QUICKFIX
case ADDR_QUICKFIX:
lnum = qf_get_size(eap);
@@ -4646,6 +4665,9 @@ get_address(
case ADDR_TABS:
lnum = CURRENT_TAB_NR;
break;
case ADDR_TABS_RELATIVE:
lnum = 1;
break;
#ifdef FEAT_QUICKFIX
case ADDR_QUICKFIX:
lnum = qf_get_cur_valid_idx(eap);
@@ -4662,7 +4684,14 @@ get_address(
n = 1;
else
n = getdigits(&cmd);
if (addr_type == ADDR_LOADED_BUFFERS
if (addr_type == ADDR_TABS_RELATIVE)
{
EMSG(_(e_invrange));
cmd = NULL;
goto error;
}
else if (addr_type == ADDR_LOADED_BUFFERS
|| addr_type == ADDR_BUFFERS)
lnum = compute_buffer_local_count(
addr_type, lnum, (i == '-') ? -1 * n : n);
@@ -4795,6 +4824,9 @@ invalid_range(exarg_T *eap)
if (eap->line2 > LAST_TAB_NR)
return (char_u *)_(e_invrange);
break;
case ADDR_TABS_RELATIVE:
/* Do nothing */
break;
#ifdef FEAT_QUICKFIX
case ADDR_QUICKFIX:
if (eap->line2 != 1 && eap->line2 > qf_get_size(eap))
@@ -5452,6 +5484,104 @@ getargopt(exarg_T *eap)
return OK;
}
/*
* Handle the argument for a tabpage related ex command.
* Returns a tabpage number.
* When an error is encountered then eap->errmsg is set.
*/
static int
get_tabpage_arg(exarg_T *eap)
{
int tab_number;
int unaccept_arg0 = (eap->cmdidx == CMD_tabmove) ? 0 : 1;
if (eap->arg && *eap->arg != NUL)
{
char_u *p = eap->arg;
char_u *p_save;
int relative = 0; /* argument +N/-N means: go to N places to the
* right/left relative to the current position. */
if (*p == '-')
{
relative = -1;
p++;
}
else if (*p == '+')
{
relative = 1;
p++;
}
p_save = p;
tab_number = getdigits(&p);
if (relative == 0)
{
if (STRCMP(p, "$") == 0)
tab_number = LAST_TAB_NR;
else if (p == p_save || *p_save == '-' || *p != NUL
|| tab_number > LAST_TAB_NR)
{
/* No numbers as argument. */
eap->errmsg = e_invarg;
goto theend;
}
}
else
{
if (*p_save == NUL)
tab_number = 1;
else if (p == p_save || *p_save == '-' || *p != NUL
|| tab_number == 0)
{
/* No numbers as argument. */
eap->errmsg = e_invarg;
goto theend;
}
tab_number = tab_number * relative + tabpage_index(curtab);
if (!unaccept_arg0 && relative == -1)
--tab_number;
}
if (tab_number < unaccept_arg0 || tab_number > LAST_TAB_NR)
eap->errmsg = e_invarg;
}
else if (eap->addr_count > 0)
{
if (unaccept_arg0 && eap->line2 == 0)
eap->errmsg = e_invrange;
else
{
tab_number = eap->line2;
if (!unaccept_arg0 && **eap->cmdlinep == '-')
{
--tab_number;
if (tab_number < unaccept_arg0)
eap->errmsg = e_invarg;
}
}
}
else
{
switch (eap->cmdidx)
{
case CMD_tabnext:
tab_number = tabpage_index(curtab) + 1;
if (tab_number > LAST_TAB_NR)
tab_number = 1;
break;
case CMD_tabmove:
tab_number = LAST_TAB_NR;
break;
default:
tab_number = tabpage_index(curtab);
}
}
theend:
return tab_number;
}
/*
* ":abbreviate" and friends.
*/
@@ -7444,6 +7574,7 @@ ex_win_close(
ex_tabclose(exarg_T *eap)
{
tabpage_T *tp;
int tab_number;
# ifdef FEAT_CMDWIN
if (cmdwin_type != 0)
@@ -7454,9 +7585,10 @@ ex_tabclose(exarg_T *eap)
EMSG(_("E784: Cannot close last tab page"));
else
{
if (eap->addr_count > 0)
tab_number = get_tabpage_arg(eap);
if (eap->errmsg == NULL)
{
tp = find_tabpage((int)eap->line2);
tp = find_tabpage(tab_number);
if (tp == NULL)
{
beep_flush();
@@ -7467,13 +7599,13 @@ ex_tabclose(exarg_T *eap)
tabpage_close_other(tp, eap->forceit);
return;
}
}
if (!text_locked()
else if (!text_locked()
#ifdef FEAT_AUTOCMD
&& !curbuf_locked()
&& !curbuf_locked()
#endif
)
tabpage_close(eap->forceit);
)
tabpage_close(eap->forceit);
}
}
}
@@ -7485,6 +7617,7 @@ ex_tabonly(exarg_T *eap)
{
tabpage_T *tp;
int done;
int tab_number;
# ifdef FEAT_CMDWIN
if (cmdwin_type != 0)
@@ -7495,24 +7628,27 @@ ex_tabonly(exarg_T *eap)
MSG(_("Already only one tab page"));
else
{
if (eap->addr_count > 0)
goto_tabpage(eap->line2);
/* Repeat this up to a 1000 times, because autocommands may mess
* up the lists. */
for (done = 0; done < 1000; ++done)
tab_number = get_tabpage_arg(eap);
if (eap->errmsg == NULL)
{
FOR_ALL_TABPAGES(tp)
if (tp->tp_topframe != topframe)
{
tabpage_close_other(tp, eap->forceit);
/* if we failed to close it quit */
if (valid_tabpage(tp))
done = 1000;
/* start over, "tp" is now invalid */
goto_tabpage(tab_number);
/* Repeat this up to a 1000 times, because autocommands may
* mess up the lists. */
for (done = 0; done < 1000; ++done)
{
FOR_ALL_TABPAGES(tp)
if (tp->tp_topframe != topframe)
{
tabpage_close_other(tp, eap->forceit);
/* if we failed to close it quit */
if (valid_tabpage(tp))
done = 1000;
/* start over, "tp" is now invalid */
break;
}
if (first_tabpage->tp_next == NULL)
break;
}
if (first_tabpage->tp_next == NULL)
break;
}
}
}
}
@@ -8254,6 +8390,8 @@ tabpage_new(void)
static void
ex_tabnext(exarg_T *eap)
{
int tab_number;
switch (eap->cmdidx)
{
case CMD_tabfirst:
@@ -8265,10 +8403,40 @@ ex_tabnext(exarg_T *eap)
break;
case CMD_tabprevious:
case CMD_tabNext:
goto_tabpage(eap->addr_count == 0 ? -1 : -(int)eap->line2);
if (eap->arg && *eap->arg != NUL)
{
char_u *p = eap->arg;
char_u *p_save = p;
tab_number = getdigits(&p);
if (p == p_save || *p_save == '-' || *p != NUL
|| tab_number == 0)
{
/* No numbers as argument. */
eap->errmsg = e_invarg;
return;
}
}
else
{
if (eap->addr_count == 0)
tab_number = 1;
else
{
tab_number = eap->line2;
if (tab_number < 1)
{
eap->errmsg = e_invrange;
return;
}
}
}
goto_tabpage(-tab_number);
break;
default: /* CMD_tabnext */
goto_tabpage(eap->addr_count == 0 ? 0 : (int)eap->line2);
tab_number = get_tabpage_arg(eap);
if (eap->errmsg == NULL)
goto_tabpage(tab_number);
break;
}
}
@@ -8281,59 +8449,9 @@ ex_tabmove(exarg_T *eap)
{
int tab_number;
if (eap->arg && *eap->arg != NUL)
{
char_u *p = eap->arg;
int relative = 0; /* argument +N/-N means: move N places to the
* right/left relative to the current position. */
if (*eap->arg == '-')
{
relative = -1;
p = eap->arg + 1;
}
else if (*eap->arg == '+')
{
relative = 1;
p = eap->arg + 1;
}
else
p = eap->arg;
if (relative == 0)
{
if (STRCMP(p, "$") == 0)
tab_number = LAST_TAB_NR;
else if (p == skipdigits(p))
{
/* No numbers as argument. */
eap->errmsg = e_invarg;
return;
}
else
tab_number = getdigits(&p);
}
else
{
if (*p != NUL)
tab_number = getdigits(&p);
else
tab_number = 1;
tab_number = tab_number * relative + tabpage_index(curtab);
if (relative == -1)
--tab_number;
}
}
else if (eap->addr_count != 0)
{
tab_number = eap->line2;
if (**eap->cmdlinep == '-')
--tab_number;
}
else
tab_number = LAST_TAB_NR;
tabpage_move(tab_number);
tab_number = get_tabpage_arg(eap);
if (eap->errmsg == NULL)
tabpage_move(tab_number);
}
/*