Mercurial > vim
diff src/ex_docmd.c @ 10739:380e706814da v8.0.0259
patch 8.0.0259: tab commands do not handle count correctly
commit https://github.com/vim/vim/commit/2f72c70657129c16e6b0e413752a775c804f02f8
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Jan 29 14:48:10 2017 +0100
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)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sun, 29 Jan 2017 15:00:05 +0100 |
parents | 78927b31c73a |
children | 3f70b142e8da |
line wrap: on
line diff
--- 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) - { - tp = find_tabpage((int)eap->line2); + tab_number = get_tabpage_arg(eap); + if (eap->errmsg == NULL) + { + 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() -#endif - ) - tabpage_close(eap->forceit); + && !curbuf_locked() +#endif + ) + 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) - { - 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 */ + tab_number = get_tabpage_arg(eap); + if (eap->errmsg == NULL) + { + 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); } /*