summaryrefslogtreecommitdiffstats
path: root/src/ex_docmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ex_docmd.c')
-rw-r--r--src/ex_docmd.c286
1 files changed, 202 insertions, 84 deletions
diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 192f45d194..90a009d935 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -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))
@@ -5453,6 +5485,104 @@ getargopt(exarg_T *eap)
}
/*
+ * 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.
*/
static void
@@ -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);
}
/*