mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:8.0.0259
Problem: Tab commands do not handle count correctly. (Ken Hamada)
Solution: Add ADDR_TABS_RELATIVE. (Hirohito Higashi)
2f72c70657
This commit is contained in:
parent
386a5f379b
commit
0f3afdaa1b
@ -34,7 +34,8 @@ local ADDR_ARGUMENTS = 2
|
|||||||
local ADDR_LOADED_BUFFERS = 3
|
local ADDR_LOADED_BUFFERS = 3
|
||||||
local ADDR_BUFFERS = 4
|
local ADDR_BUFFERS = 4
|
||||||
local ADDR_TABS = 5
|
local ADDR_TABS = 5
|
||||||
local ADDR_QUICKFIX = 6
|
local ADDR_TABS_RELATIVE = 6
|
||||||
|
local ADDR_QUICKFIX = 7
|
||||||
local ADDR_OTHER = 99
|
local ADDR_OTHER = 99
|
||||||
|
|
||||||
-- The following table is described in ex_cmds_defs.h file.
|
-- The following table is described in ex_cmds_defs.h file.
|
||||||
@ -2650,12 +2651,12 @@ return {
|
|||||||
{
|
{
|
||||||
command='tab',
|
command='tab',
|
||||||
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
|
flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
|
||||||
addr_type=ADDR_LINES,
|
addr_type=ADDR_TABS,
|
||||||
func='ex_wrongmodifier',
|
func='ex_wrongmodifier',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
command='tabclose',
|
command='tabclose',
|
||||||
flags=bit.bor(RANGE, NOTADR, COUNT, BANG, TRLBAR, CMDWIN),
|
flags=bit.bor(BANG, RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN),
|
||||||
addr_type=ADDR_TABS,
|
addr_type=ADDR_TABS,
|
||||||
func='ex_tabclose',
|
func='ex_tabclose',
|
||||||
},
|
},
|
||||||
@ -2680,7 +2681,7 @@ return {
|
|||||||
{
|
{
|
||||||
command='tabfirst',
|
command='tabfirst',
|
||||||
flags=bit.bor(TRLBAR),
|
flags=bit.bor(TRLBAR),
|
||||||
addr_type=ADDR_LINES,
|
addr_type=ADDR_TABS,
|
||||||
func='ex_tabnext',
|
func='ex_tabnext',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2692,13 +2693,13 @@ return {
|
|||||||
{
|
{
|
||||||
command='tablast',
|
command='tablast',
|
||||||
flags=bit.bor(TRLBAR),
|
flags=bit.bor(TRLBAR),
|
||||||
addr_type=ADDR_LINES,
|
addr_type=ADDR_TABS,
|
||||||
func='ex_tabnext',
|
func='ex_tabnext',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
command='tabnext',
|
command='tabnext',
|
||||||
flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
|
flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR),
|
||||||
addr_type=ADDR_LINES,
|
addr_type=ADDR_TABS,
|
||||||
func='ex_tabnext',
|
func='ex_tabnext',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2709,32 +2710,32 @@ return {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
command='tabonly',
|
command='tabonly',
|
||||||
flags=bit.bor(BANG, RANGE, NOTADR, TRLBAR, CMDWIN),
|
flags=bit.bor(BANG, RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN),
|
||||||
addr_type=ADDR_TABS,
|
addr_type=ADDR_TABS,
|
||||||
func='ex_tabonly',
|
func='ex_tabonly',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
command='tabprevious',
|
command='tabprevious',
|
||||||
flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
|
flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR),
|
||||||
addr_type=ADDR_LINES,
|
addr_type=ADDR_TABS_RELATIVE,
|
||||||
func='ex_tabnext',
|
func='ex_tabnext',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
command='tabNext',
|
command='tabNext',
|
||||||
flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR),
|
flags=bit.bor(RANGE, NOTADR, ZEROR, EXTRA, NOSPC, TRLBAR),
|
||||||
addr_type=ADDR_LINES,
|
addr_type=ADDR_TABS_RELATIVE,
|
||||||
func='ex_tabnext',
|
func='ex_tabnext',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
command='tabrewind',
|
command='tabrewind',
|
||||||
flags=bit.bor(TRLBAR),
|
flags=bit.bor(TRLBAR),
|
||||||
addr_type=ADDR_LINES,
|
addr_type=ADDR_TABS,
|
||||||
func='ex_tabnext',
|
func='ex_tabnext',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
command='tabs',
|
command='tabs',
|
||||||
flags=bit.bor(TRLBAR, CMDWIN),
|
flags=bit.bor(TRLBAR, CMDWIN),
|
||||||
addr_type=ADDR_LINES,
|
addr_type=ADDR_TABS,
|
||||||
func='ex_tabs',
|
func='ex_tabs',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -72,7 +72,8 @@
|
|||||||
#define ADDR_LOADED_BUFFERS 3
|
#define ADDR_LOADED_BUFFERS 3
|
||||||
#define ADDR_BUFFERS 4
|
#define ADDR_BUFFERS 4
|
||||||
#define ADDR_TABS 5
|
#define ADDR_TABS 5
|
||||||
#define ADDR_QUICKFIX 6
|
#define ADDR_TABS_RELATIVE 6 // Tab page that only relative
|
||||||
|
#define ADDR_QUICKFIX 7
|
||||||
#define ADDR_OTHER 99
|
#define ADDR_OTHER 99
|
||||||
|
|
||||||
typedef struct exarg exarg_T;
|
typedef struct exarg exarg_T;
|
||||||
|
@ -1522,8 +1522,7 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
|||||||
ea.line2 = curwin->w_cursor.lnum;
|
ea.line2 = curwin->w_cursor.lnum;
|
||||||
break;
|
break;
|
||||||
case ADDR_WINDOWS:
|
case ADDR_WINDOWS:
|
||||||
lnum = CURRENT_WIN_NR;
|
ea.line2 = CURRENT_WIN_NR;
|
||||||
ea.line2 = lnum;
|
|
||||||
break;
|
break;
|
||||||
case ADDR_ARGUMENTS:
|
case ADDR_ARGUMENTS:
|
||||||
ea.line2 = curwin->w_arg_idx + 1;
|
ea.line2 = curwin->w_arg_idx + 1;
|
||||||
@ -1536,8 +1535,10 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
|||||||
ea.line2 = curbuf->b_fnum;
|
ea.line2 = curbuf->b_fnum;
|
||||||
break;
|
break;
|
||||||
case ADDR_TABS:
|
case ADDR_TABS:
|
||||||
lnum = CURRENT_TAB_NR;
|
ea.line2 = CURRENT_TAB_NR;
|
||||||
ea.line2 = lnum;
|
break;
|
||||||
|
case ADDR_TABS_RELATIVE:
|
||||||
|
ea.line2 = 1;
|
||||||
break;
|
break;
|
||||||
case ADDR_QUICKFIX:
|
case ADDR_QUICKFIX:
|
||||||
ea.line2 = qf_get_cur_valid_idx(&ea);
|
ea.line2 = qf_get_cur_valid_idx(&ea);
|
||||||
@ -1587,6 +1588,10 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
|||||||
goto doend;
|
goto doend;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ADDR_TABS_RELATIVE:
|
||||||
|
errormsg = (char_u *)_(e_invrange);
|
||||||
|
goto doend;
|
||||||
|
break;
|
||||||
case ADDR_ARGUMENTS:
|
case ADDR_ARGUMENTS:
|
||||||
if (ARGCOUNT == 0) {
|
if (ARGCOUNT == 0) {
|
||||||
ea.line1 = ea.line2 = 0;
|
ea.line1 = ea.line2 = 0;
|
||||||
@ -1973,6 +1978,9 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
|||||||
case ADDR_TABS:
|
case ADDR_TABS:
|
||||||
ea.line2 = LAST_TAB_NR;
|
ea.line2 = LAST_TAB_NR;
|
||||||
break;
|
break;
|
||||||
|
case ADDR_TABS_RELATIVE:
|
||||||
|
ea.line2 = 1;
|
||||||
|
break;
|
||||||
case ADDR_ARGUMENTS:
|
case ADDR_ARGUMENTS:
|
||||||
if (ARGCOUNT == 0) {
|
if (ARGCOUNT == 0) {
|
||||||
ea.line1 = ea.line2 = 0;
|
ea.line1 = ea.line2 = 0;
|
||||||
@ -2028,11 +2036,11 @@ static char_u * do_one_cmd(char_u **cmdlinep,
|
|||||||
ea.line1 = ea.line2;
|
ea.line1 = ea.line2;
|
||||||
ea.line2 += n - 1;
|
ea.line2 += n - 1;
|
||||||
++ea.addr_count;
|
++ea.addr_count;
|
||||||
/*
|
// Be vi compatible: no error message for out of range.
|
||||||
* Be vi compatible: no error message for out of range.
|
if (ea.addr_type == ADDR_LINES
|
||||||
*/
|
&& ea.line2 > curbuf->b_ml.ml_line_count) {
|
||||||
if (ea.line2 > curbuf->b_ml.ml_line_count)
|
|
||||||
ea.line2 = curbuf->b_ml.ml_line_count;
|
ea.line2 = curbuf->b_ml.ml_line_count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3459,6 +3467,11 @@ static linenr_T get_address(exarg_T *eap,
|
|||||||
case ADDR_TABS:
|
case ADDR_TABS:
|
||||||
lnum = CURRENT_TAB_NR;
|
lnum = CURRENT_TAB_NR;
|
||||||
break;
|
break;
|
||||||
|
case ADDR_TABS_RELATIVE:
|
||||||
|
EMSG(_(e_invrange));
|
||||||
|
cmd = NULL;
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
case ADDR_QUICKFIX:
|
case ADDR_QUICKFIX:
|
||||||
lnum = qf_get_cur_valid_idx(eap);
|
lnum = qf_get_cur_valid_idx(eap);
|
||||||
break;
|
break;
|
||||||
@ -3493,6 +3506,11 @@ static linenr_T get_address(exarg_T *eap,
|
|||||||
case ADDR_TABS:
|
case ADDR_TABS:
|
||||||
lnum = LAST_TAB_NR;
|
lnum = LAST_TAB_NR;
|
||||||
break;
|
break;
|
||||||
|
case ADDR_TABS_RELATIVE:
|
||||||
|
EMSG(_(e_invrange));
|
||||||
|
cmd = NULL;
|
||||||
|
goto error;
|
||||||
|
break;
|
||||||
case ADDR_QUICKFIX:
|
case ADDR_QUICKFIX:
|
||||||
lnum = qf_get_size(eap);
|
lnum = qf_get_size(eap);
|
||||||
if (lnum == 0) {
|
if (lnum == 0) {
|
||||||
@ -3641,6 +3659,9 @@ static linenr_T get_address(exarg_T *eap,
|
|||||||
case ADDR_TABS:
|
case ADDR_TABS:
|
||||||
lnum = CURRENT_TAB_NR;
|
lnum = CURRENT_TAB_NR;
|
||||||
break;
|
break;
|
||||||
|
case ADDR_TABS_RELATIVE:
|
||||||
|
lnum = 1;
|
||||||
|
break;
|
||||||
case ADDR_QUICKFIX:
|
case ADDR_QUICKFIX:
|
||||||
lnum = qf_get_cur_valid_idx(eap);
|
lnum = qf_get_cur_valid_idx(eap);
|
||||||
break;
|
break;
|
||||||
@ -3655,7 +3676,12 @@ static linenr_T get_address(exarg_T *eap,
|
|||||||
n = 1;
|
n = 1;
|
||||||
else
|
else
|
||||||
n = getdigits(&cmd);
|
n = getdigits(&cmd);
|
||||||
if (addr_type == ADDR_LOADED_BUFFERS || addr_type == ADDR_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(
|
lnum = compute_buffer_local_count(
|
||||||
addr_type, lnum, (i == '-') ? -1 * n : n);
|
addr_type, lnum, (i == '-') ? -1 * n : n);
|
||||||
} else {
|
} else {
|
||||||
@ -3777,6 +3803,9 @@ static char_u *invalid_range(exarg_T *eap)
|
|||||||
return (char_u *)_(e_invrange);
|
return (char_u *)_(e_invrange);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ADDR_TABS_RELATIVE:
|
||||||
|
// Do nothing
|
||||||
|
break;
|
||||||
case ADDR_QUICKFIX:
|
case ADDR_QUICKFIX:
|
||||||
assert(eap->line2 >= 0);
|
assert(eap->line2 >= 0);
|
||||||
if (eap->line2 != 1 && (size_t)eap->line2 > qf_get_size(eap)) {
|
if (eap->line2 != 1 && (size_t)eap->line2 > qf_get_size(eap)) {
|
||||||
@ -4285,6 +4314,104 @@ static int getargopt(exarg_T *eap)
|
|||||||
return OK;
|
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.
|
* ":abbreviate" and friends.
|
||||||
*/
|
*/
|
||||||
@ -5938,8 +6065,9 @@ static void ex_tabclose(exarg_T *eap)
|
|||||||
else if (first_tabpage->tp_next == NULL)
|
else if (first_tabpage->tp_next == NULL)
|
||||||
EMSG(_("E784: Cannot close last tab page"));
|
EMSG(_("E784: Cannot close last tab page"));
|
||||||
else {
|
else {
|
||||||
if (eap->addr_count > 0) {
|
int tab_number = get_tabpage_arg(eap);
|
||||||
tp = find_tabpage((int)eap->line2);
|
if (eap->errmsg == NULL) {
|
||||||
|
tp = find_tabpage(tab_number);
|
||||||
if (tp == NULL) {
|
if (tp == NULL) {
|
||||||
beep_flush();
|
beep_flush();
|
||||||
return;
|
return;
|
||||||
@ -5947,44 +6075,43 @@ static void ex_tabclose(exarg_T *eap)
|
|||||||
if (tp != curtab) {
|
if (tp != curtab) {
|
||||||
tabpage_close_other(tp, eap->forceit);
|
tabpage_close_other(tp, eap->forceit);
|
||||||
return;
|
return;
|
||||||
|
} else if (!text_locked() && !curbuf_locked()) {
|
||||||
|
tabpage_close(eap->forceit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!text_locked()
|
|
||||||
&& !curbuf_locked()
|
|
||||||
)
|
|
||||||
tabpage_close(eap->forceit);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/// ":tabonly": close all tab pages except the current one
|
||||||
* ":tabonly": close all tab pages except the current one
|
|
||||||
*/
|
|
||||||
static void ex_tabonly(exarg_T *eap)
|
static void ex_tabonly(exarg_T *eap)
|
||||||
{
|
{
|
||||||
if (cmdwin_type != 0)
|
if (cmdwin_type != 0) {
|
||||||
cmdwin_result = K_IGNORE;
|
cmdwin_result = K_IGNORE;
|
||||||
else if (first_tabpage->tp_next == NULL)
|
} else if (first_tabpage->tp_next == NULL) {
|
||||||
MSG(_("Already only one tab page"));
|
MSG(_("Already only one tab page"));
|
||||||
else {
|
} else {
|
||||||
if (eap->addr_count > 0)
|
int tab_number = get_tabpage_arg(eap);
|
||||||
goto_tabpage(eap->line2);
|
if (eap->errmsg == NULL) {
|
||||||
/* Repeat this up to a 1000 times, because autocommands may mess
|
goto_tabpage(tab_number);
|
||||||
* up the lists. */
|
// Repeat this up to a 1000 times, because autocommands may
|
||||||
for (int done = 0; done < 1000; ++done) {
|
// mess up the lists.
|
||||||
FOR_ALL_TABS(tp) {
|
for (int done = 0; done < 1000; done++) {
|
||||||
if (tp->tp_topframe != topframe) {
|
FOR_ALL_TABS(tp) {
|
||||||
tabpage_close_other(tp, eap->forceit);
|
if (tp->tp_topframe != topframe) {
|
||||||
/* if we failed to close it quit */
|
tabpage_close_other(tp, eap->forceit);
|
||||||
if (valid_tabpage(tp))
|
// if we failed to close it quit
|
||||||
done = 1000;
|
if (valid_tabpage(tp)) {
|
||||||
/* start over, "tp" is now invalid */
|
done = 1000;
|
||||||
|
}
|
||||||
|
// start over, "tp" is now invalid
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(first_tabpage);
|
||||||
|
if (first_tabpage->tp_next == NULL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(first_tabpage);
|
|
||||||
if (first_tabpage->tp_next == NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6473,6 +6600,8 @@ void tabpage_new(void)
|
|||||||
*/
|
*/
|
||||||
static void ex_tabnext(exarg_T *eap)
|
static void ex_tabnext(exarg_T *eap)
|
||||||
{
|
{
|
||||||
|
int tab_number;
|
||||||
|
|
||||||
switch (eap->cmdidx) {
|
switch (eap->cmdidx) {
|
||||||
case CMD_tabfirst:
|
case CMD_tabfirst:
|
||||||
case CMD_tabrewind:
|
case CMD_tabrewind:
|
||||||
@ -6483,10 +6612,34 @@ static void ex_tabnext(exarg_T *eap)
|
|||||||
break;
|
break;
|
||||||
case CMD_tabprevious:
|
case CMD_tabprevious:
|
||||||
case CMD_tabNext:
|
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;
|
break;
|
||||||
default: /* CMD_tabnext */
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6496,53 +6649,10 @@ static void ex_tabnext(exarg_T *eap)
|
|||||||
*/
|
*/
|
||||||
static void ex_tabmove(exarg_T *eap)
|
static void ex_tabmove(exarg_T *eap)
|
||||||
{
|
{
|
||||||
int tab_number;
|
int tab_number = get_tabpage_arg(eap);
|
||||||
|
if (eap->errmsg == NULL) {
|
||||||
if (eap->arg && *eap->arg != NUL) {
|
tabpage_move(tab_number);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -94,10 +94,6 @@ function Test_tabpage()
|
|||||||
call assert_equal(7, tabpagenr())
|
call assert_equal(7, tabpagenr())
|
||||||
tabmove
|
tabmove
|
||||||
call assert_equal(10, tabpagenr())
|
call assert_equal(10, tabpagenr())
|
||||||
tabmove -20
|
|
||||||
call assert_equal(1, tabpagenr())
|
|
||||||
tabmove +20
|
|
||||||
call assert_equal(10, tabpagenr())
|
|
||||||
0tabmove
|
0tabmove
|
||||||
call assert_equal(1, tabpagenr())
|
call assert_equal(1, tabpagenr())
|
||||||
$tabmove
|
$tabmove
|
||||||
@ -110,7 +106,16 @@ function Test_tabpage()
|
|||||||
call assert_equal(4, tabpagenr())
|
call assert_equal(4, tabpagenr())
|
||||||
7tabmove 5
|
7tabmove 5
|
||||||
call assert_equal(5, tabpagenr())
|
call assert_equal(5, tabpagenr())
|
||||||
|
call assert_fails("99tabmove", 'E16:')
|
||||||
|
call assert_fails("+99tabmove", 'E16:')
|
||||||
|
call assert_fails("-99tabmove", 'E16:')
|
||||||
call assert_fails("tabmove foo", 'E474:')
|
call assert_fails("tabmove foo", 'E474:')
|
||||||
|
call assert_fails("tabmove 99", 'E474:')
|
||||||
|
call assert_fails("tabmove +99", 'E474:')
|
||||||
|
call assert_fails("tabmove -99", 'E474:')
|
||||||
|
call assert_fails("tabmove -3+", 'E474:')
|
||||||
|
call assert_fails("tabmove $3", 'E474:')
|
||||||
|
1tabonly!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" Test autocommands
|
" Test autocommands
|
||||||
@ -118,7 +123,6 @@ function Test_tabpage_with_autocmd()
|
|||||||
if !has('autocmd')
|
if !has('autocmd')
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
tabonly!
|
|
||||||
command -nargs=1 -bar C :call add(s:li, '=== ' . <q-args> . ' ===')|<args>
|
command -nargs=1 -bar C :call add(s:li, '=== ' . <q-args> . ' ===')|<args>
|
||||||
augroup TestTabpageGroup
|
augroup TestTabpageGroup
|
||||||
au!
|
au!
|
||||||
@ -183,8 +187,10 @@ function Test_tabpage_with_autocmd()
|
|||||||
|
|
||||||
autocmd TabDestructive TabEnter * nested :C tabnext 2 | C tabclose 3
|
autocmd TabDestructive TabEnter * nested :C tabnext 2 | C tabclose 3
|
||||||
let s:li = []
|
let s:li = []
|
||||||
C tabnext 3
|
call assert_equal(3, tabpagenr('$'))
|
||||||
call assert_equal(['=== tabnext 3 ===', 'BufLeave', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', '=== tabnext 2 ===', 'BufLeave', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', '=== tabnext 2 ===', '=== tabclose 3 ===', 'BufEnter', '=== tabclose 3 ==='], s:li)
|
C tabnext 2
|
||||||
|
call assert_equal(2, tabpagenr('$'))
|
||||||
|
call assert_equal(['=== tabnext 2 ===', 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter', '=== tabnext 2 ===', '=== tabclose 3 ==='], s:li)
|
||||||
call assert_equal(['2/2'], [tabpagenr().'/'.tabpagenr('$')])
|
call assert_equal(['2/2'], [tabpagenr().'/'.tabpagenr('$')])
|
||||||
|
|
||||||
delcommand C
|
delcommand C
|
||||||
@ -192,8 +198,7 @@ function Test_tabpage_with_autocmd()
|
|||||||
augroup! TabDestructive
|
augroup! TabDestructive
|
||||||
autocmd! TestTabpageGroup
|
autocmd! TestTabpageGroup
|
||||||
augroup! TestTabpageGroup
|
augroup! TestTabpageGroup
|
||||||
tabonly!
|
1tabonly!
|
||||||
bw!
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function Test_tabpage_with_tab_modifier()
|
function Test_tabpage_with_tab_modifier()
|
||||||
@ -224,8 +229,223 @@ function Test_tabpage_with_tab_modifier()
|
|||||||
call assert_fails('-99tab help', 'E16:')
|
call assert_fails('-99tab help', 'E16:')
|
||||||
|
|
||||||
delfunction s:check_tab
|
delfunction s:check_tab
|
||||||
tabonly!
|
1tabonly!
|
||||||
bw!
|
endfunction
|
||||||
|
|
||||||
|
function Check_tab_count(pre_nr, cmd, post_nr)
|
||||||
|
exec 'tabnext' a:pre_nr
|
||||||
|
normal! G
|
||||||
|
exec a:cmd
|
||||||
|
call assert_equal(a:post_nr, tabpagenr(), a:cmd)
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test for [count] of tabnext
|
||||||
|
function Test_tabpage_with_tabnext()
|
||||||
|
for n in range(4)
|
||||||
|
tabedit
|
||||||
|
call setline(1, ['', '', '3'])
|
||||||
|
endfor
|
||||||
|
|
||||||
|
call Check_tab_count(1, 'tabnext', 2)
|
||||||
|
call Check_tab_count(1, '3tabnext', 3)
|
||||||
|
call Check_tab_count(1, '.tabnext', 1)
|
||||||
|
call Check_tab_count(1, '.+1tabnext', 2)
|
||||||
|
call Check_tab_count(2, '+tabnext', 3)
|
||||||
|
call Check_tab_count(2, '+2tabnext', 4)
|
||||||
|
call Check_tab_count(4, '-tabnext', 3)
|
||||||
|
call Check_tab_count(4, '-2tabnext', 2)
|
||||||
|
call Check_tab_count(3, '$tabnext', 5)
|
||||||
|
call assert_fails('0tabnext', 'E16:')
|
||||||
|
call assert_fails('99tabnext', 'E16:')
|
||||||
|
call assert_fails('+99tabnext', 'E16:')
|
||||||
|
call assert_fails('-99tabnext', 'E16:')
|
||||||
|
call Check_tab_count(1, 'tabnext 3', 3)
|
||||||
|
call Check_tab_count(2, 'tabnext +', 3)
|
||||||
|
call Check_tab_count(2, 'tabnext +2', 4)
|
||||||
|
call Check_tab_count(4, 'tabnext -', 3)
|
||||||
|
call Check_tab_count(4, 'tabnext -2', 2)
|
||||||
|
call Check_tab_count(3, 'tabnext $', 5)
|
||||||
|
call assert_fails('tabnext 0', 'E474:')
|
||||||
|
call assert_fails('tabnext .', 'E474:')
|
||||||
|
call assert_fails('tabnext -+', 'E474:')
|
||||||
|
call assert_fails('tabnext +2-', 'E474:')
|
||||||
|
call assert_fails('tabnext $3', 'E474:')
|
||||||
|
call assert_fails('tabnext 99', 'E474:')
|
||||||
|
call assert_fails('tabnext +99', 'E474:')
|
||||||
|
call assert_fails('tabnext -99', 'E474:')
|
||||||
|
|
||||||
|
1tabonly!
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Test for [count] of tabprevious
|
||||||
|
function Test_tabpage_with_tabprevious()
|
||||||
|
for n in range(5)
|
||||||
|
tabedit
|
||||||
|
call setline(1, ['', '', '3'])
|
||||||
|
endfor
|
||||||
|
|
||||||
|
for cmd in ['tabNext', 'tabprevious']
|
||||||
|
call Check_tab_count(6, cmd, 5)
|
||||||
|
call Check_tab_count(6, '3' . cmd, 3)
|
||||||
|
call Check_tab_count(6, '8' . cmd, 4)
|
||||||
|
call Check_tab_count(6, cmd . ' 3', 3)
|
||||||
|
call Check_tab_count(6, cmd . ' 8', 4)
|
||||||
|
for n in range(2)
|
||||||
|
for c in ['0', '.+3', '+', '+2' , '-', '-2' , '$', '+99', '-99']
|
||||||
|
if n == 0 " pre count
|
||||||
|
let entire_cmd = c . cmd
|
||||||
|
let err_code = 'E16:'
|
||||||
|
else
|
||||||
|
let entire_cmd = cmd . ' ' . c
|
||||||
|
let err_code = 'E474:'
|
||||||
|
endif
|
||||||
|
call assert_fails(entire_cmd, err_code)
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
|
||||||
|
1tabonly!
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function s:reconstruct_tabpage_for_test(nr)
|
||||||
|
let n = (a:nr > 2) ? a:nr - 2 : 1
|
||||||
|
1tabonly!
|
||||||
|
0tabedit n0
|
||||||
|
for n in range(1, n)
|
||||||
|
exec '$tabedit n' . n
|
||||||
|
if n == 1
|
||||||
|
call setline(1, ['', '', '3'])
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Test for [count] of tabclose
|
||||||
|
function Test_tabpage_with_tabclose()
|
||||||
|
|
||||||
|
" pre count
|
||||||
|
call s:reconstruct_tabpage_for_test(6)
|
||||||
|
call Check_tab_count(3, 'tabclose!', 3)
|
||||||
|
call Check_tab_count(1, '3tabclose', 1)
|
||||||
|
call Check_tab_count(4, '4tabclose', 3)
|
||||||
|
call Check_tab_count(3, '1tabclose', 2)
|
||||||
|
call Check_tab_count(2, 'tabclose', 1)
|
||||||
|
call assert_equal(1, tabpagenr('$'))
|
||||||
|
call assert_equal('', bufname(''))
|
||||||
|
|
||||||
|
call s:reconstruct_tabpage_for_test(6)
|
||||||
|
call Check_tab_count(2, '$tabclose', 2)
|
||||||
|
call Check_tab_count(4, '.tabclose', 4)
|
||||||
|
call Check_tab_count(3, '.+tabclose', 3)
|
||||||
|
call Check_tab_count(3, '.-2tabclose', 2)
|
||||||
|
call Check_tab_count(1, '.+1tabclose!', 1)
|
||||||
|
call assert_equal(1, tabpagenr('$'))
|
||||||
|
call assert_equal('', bufname(''))
|
||||||
|
|
||||||
|
" post count
|
||||||
|
call s:reconstruct_tabpage_for_test(6)
|
||||||
|
call Check_tab_count(3, 'tabclose!', 3)
|
||||||
|
call Check_tab_count(1, 'tabclose 3', 1)
|
||||||
|
call Check_tab_count(4, 'tabclose 4', 3)
|
||||||
|
call Check_tab_count(3, 'tabclose 1', 2)
|
||||||
|
call Check_tab_count(2, 'tabclose', 1)
|
||||||
|
call assert_equal(1, tabpagenr('$'))
|
||||||
|
call assert_equal('', bufname(''))
|
||||||
|
|
||||||
|
call s:reconstruct_tabpage_for_test(6)
|
||||||
|
call Check_tab_count(2, 'tabclose $', 2)
|
||||||
|
call Check_tab_count(4, 'tabclose', 4)
|
||||||
|
call Check_tab_count(3, 'tabclose +', 3)
|
||||||
|
call Check_tab_count(3, 'tabclose -2', 2)
|
||||||
|
call Check_tab_count(1, 'tabclose! +1', 1)
|
||||||
|
call assert_equal(1, tabpagenr('$'))
|
||||||
|
call assert_equal('', bufname(''))
|
||||||
|
|
||||||
|
call s:reconstruct_tabpage_for_test(6)
|
||||||
|
for n in range(2)
|
||||||
|
for c in ['0', '$3', '99', '+99', '-99']
|
||||||
|
if n == 0 " pre count
|
||||||
|
let entire_cmd = c . 'tabclose'
|
||||||
|
let err_code = 'E16:'
|
||||||
|
else
|
||||||
|
let entire_cmd = 'tabclose ' . c
|
||||||
|
let err_code = 'E474:'
|
||||||
|
endif
|
||||||
|
call assert_fails(entire_cmd, err_code)
|
||||||
|
call assert_equal(6, tabpagenr('$'))
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
|
||||||
|
call assert_fails('3tabclose', 'E37:')
|
||||||
|
call assert_fails('tabclose 3', 'E37:')
|
||||||
|
call assert_fails('tabclose -+', 'E474:')
|
||||||
|
call assert_fails('tabclose +2-', 'E474:')
|
||||||
|
call assert_equal(6, tabpagenr('$'))
|
||||||
|
|
||||||
|
1tabonly!
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Test for [count] of tabonly
|
||||||
|
function Test_tabpage_with_tabonly()
|
||||||
|
|
||||||
|
" Test for the normal behavior (pre count only)
|
||||||
|
let tc = [ [4, '.', '!'], [2, '.+', ''], [3, '.-2', '!'], [1, '.+1', '!'] ]
|
||||||
|
for c in tc
|
||||||
|
call s:reconstruct_tabpage_for_test(6)
|
||||||
|
let entire_cmd = c[1] . 'tabonly' . c[2]
|
||||||
|
call Check_tab_count(c[0], entire_cmd, 1)
|
||||||
|
call assert_equal(1, tabpagenr('$'))
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" Test for the normal behavior
|
||||||
|
let tc2 = [ [3, '', ''], [1, '3', ''], [4, '4', '!'], [3, '1', '!'],
|
||||||
|
\ [2, '', '!'],
|
||||||
|
\ [2, '$', '!'], [3, '+', '!'], [3, '-2', '!'], [3, '+1', '!']
|
||||||
|
\ ]
|
||||||
|
for n in range(2)
|
||||||
|
for c in tc2
|
||||||
|
call s:reconstruct_tabpage_for_test(6)
|
||||||
|
if n == 0 " pre count
|
||||||
|
let entire_cmd = c[1] . 'tabonly' . c[2]
|
||||||
|
else
|
||||||
|
let entire_cmd = 'tabonly' . c[2] . ' ' . c[1]
|
||||||
|
endif
|
||||||
|
call Check_tab_count(c[0], entire_cmd, 1)
|
||||||
|
call assert_equal(1, tabpagenr('$'))
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" Test for the error behavior
|
||||||
|
for n in range(2)
|
||||||
|
for c in ['0', '$3', '99', '+99', '-99']
|
||||||
|
call s:reconstruct_tabpage_for_test(6)
|
||||||
|
if n == 0 " pre count
|
||||||
|
let entire_cmd = c . 'tabonly'
|
||||||
|
let err_code = 'E16:'
|
||||||
|
else
|
||||||
|
let entire_cmd = 'tabonly ' . c
|
||||||
|
let err_code = 'E474:'
|
||||||
|
endif
|
||||||
|
call assert_fails(entire_cmd, err_code)
|
||||||
|
call assert_equal(6, tabpagenr('$'))
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" Test for the error behavior (post count only)
|
||||||
|
for c in tc
|
||||||
|
call s:reconstruct_tabpage_for_test(6)
|
||||||
|
let entire_cmd = 'tabonly' . c[2] . ' ' . c[1]
|
||||||
|
let err_code = 'E474:'
|
||||||
|
call assert_fails(entire_cmd, err_code)
|
||||||
|
call assert_equal(6, tabpagenr('$'))
|
||||||
|
endfor
|
||||||
|
|
||||||
|
call assert_fails('tabonly -+', 'E474:')
|
||||||
|
call assert_fails('tabonly +2-', 'E474:')
|
||||||
|
call assert_equal(6, tabpagenr('$'))
|
||||||
|
|
||||||
|
1tabonly!
|
||||||
|
new
|
||||||
|
only!
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
func Test_tabnext_on_buf_unload1()
|
func Test_tabnext_on_buf_unload1()
|
||||||
|
@ -99,10 +99,6 @@ describe('tab pages', function()
|
|||||||
eq(7, eval('tabpagenr()'))
|
eq(7, eval('tabpagenr()'))
|
||||||
execute('tabmove')
|
execute('tabmove')
|
||||||
eq(10, eval('tabpagenr()'))
|
eq(10, eval('tabpagenr()'))
|
||||||
execute('tabmove -20')
|
|
||||||
eq(1, eval('tabpagenr()'))
|
|
||||||
execute('tabmove +20')
|
|
||||||
eq(10, eval('tabpagenr()'))
|
|
||||||
execute('0tabmove')
|
execute('0tabmove')
|
||||||
eq(1, eval('tabpagenr()'))
|
eq(1, eval('tabpagenr()'))
|
||||||
execute('$tabmove')
|
execute('$tabmove')
|
||||||
@ -172,7 +168,7 @@ describe('tab pages', function()
|
|||||||
C tabnext 1
|
C tabnext 1
|
||||||
autocmd TabDestructive TabEnter * nested
|
autocmd TabDestructive TabEnter * nested
|
||||||
\ :C tabnext 2 | C tabclose 3
|
\ :C tabnext 2 | C tabclose 3
|
||||||
C tabnext 3
|
C tabnext 2
|
||||||
let g:r+=[tabpagenr().'/'.tabpagenr('$')]
|
let g:r+=[tabpagenr().'/'.tabpagenr('$')]
|
||||||
endfunction
|
endfunction
|
||||||
call Test()
|
call Test()
|
||||||
@ -233,22 +229,14 @@ describe('tab pages', function()
|
|||||||
WinEnter
|
WinEnter
|
||||||
TabEnter
|
TabEnter
|
||||||
BufEnter
|
BufEnter
|
||||||
=== tabnext 3 ===
|
=== tabnext 2 ===
|
||||||
BufLeave
|
|
||||||
WinLeave
|
WinLeave
|
||||||
TabLeave
|
TabLeave
|
||||||
WinEnter
|
WinEnter
|
||||||
TabEnter
|
TabEnter
|
||||||
=== tabnext 2 ===
|
=== tabnext 2 ===
|
||||||
BufLeave
|
|
||||||
WinLeave
|
|
||||||
TabLeave
|
|
||||||
WinEnter
|
|
||||||
TabEnter
|
|
||||||
=== tabnext 2 ===
|
|
||||||
=== tabclose 3 ===
|
|
||||||
BufEnter
|
|
||||||
=== tabclose 3 ===
|
=== tabclose 3 ===
|
||||||
2/2]])
|
2/2]])
|
||||||
|
eq(2, eval("tabpagenr('$')"))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
Loading…
Reference in New Issue
Block a user