To: Bram (As a Vimboss) To: Christian Brabandt (As a visual <C-A>/<C-X> first patch author) To: Jason Schulz (As a support for bin 'nrformats' patch author)
Hi, I refactored visual <C-A>/<C-X> to support vcol et al. This mean is <TAB> code free! Contents of patch. - visual <C-A>/<C-X> support vcol. (<TAB> code free) - 'test_increment' convert from old style test to new style test. and added some test items. - Processing was allowed to separate. (line loop process and add/subtract process) (We have to use the existing function block_prep() to process the block-wise) - We removed the halfway right-to-left processing. (Remove RLADDSUBFIX() macro) (This is causing the actual problem) $ vim -Nu NONE -c "set rightleft" i123 45<Esc> <C-A> " Unexpected swap the numbers of strings occurred. Christian Brabandt and Jason Schulz and List> I was wondering if you could review this patch. Jason Schulz> Sorry to such just your patch was included. I have just completed the doing has been working since last fall :-) Thanks. -- Best regards, Hirohito Higashi (a.k.a h_east) -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
diff --git a/src/Makefile b/src/Makefile index 500287f..8a38d36 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1944,7 +1944,6 @@ test1 \ test_erasebackword \ test_eval \ test_fixeol \ - test_increment \ test_insertcount \ test_listchars \ test_listlbr \ @@ -1977,11 +1976,17 @@ test1 \ cd testdir; rm -f [email protected]; $(MAKE) -f Makefile [email protected] VIMPROG=../$(VIMTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE) test_assert \ + test_backspace_opt \ test_cdo \ + test_increment \ + test_lispwords \ + test_menu \ + test_quickfix \ test_searchpos \ test_set \ test_sort \ test_undolevels \ + test_unlet \ test_viml \ test_alot: cd testdir; rm -f [email protected] test.log messages; $(MAKE) -f Makefile [email protected] VIMPROG=../$(VIMTARGET) $(GUI_TESTARG) SCRIPTSOURCE=../$(SCRIPTSOURCE) diff --git a/src/normal.c b/src/normal.c index 640c060..afaf43d 100644 --- a/src/normal.c +++ b/src/normal.c @@ -40,7 +40,6 @@ static void find_start_of_word __ARGS((pos_T *)); static void find_end_of_word __ARGS((pos_T *)); static int get_mouse_class __ARGS((char_u *p)); #endif -static void prep_redo_visual __ARGS((cmdarg_T *cap)); static void prep_redo_cmd __ARGS((cmdarg_T *cap)); static void prep_redo __ARGS((int regname, long, int, int, int, int, int)); static int checkclearop __ARGS((oparg_T *oap)); @@ -1392,6 +1391,7 @@ do_pending_operator(cap, old_col, gui_yank) static linenr_T redo_VIsual_line_count; /* number of lines */ static colnr_T redo_VIsual_vcol; /* number of cols or end column */ static long redo_VIsual_count; /* count for Visual operator */ + static int redo_VIsual_arg; /* extra argument */ #ifdef FEAT_VIRTUALEDIT int include_line_break = FALSE; #endif @@ -1699,6 +1699,7 @@ do_pending_operator(cap, old_col, gui_yank) redo_VIsual_vcol = resel_VIsual_vcol; redo_VIsual_line_count = resel_VIsual_line_count; redo_VIsual_count = cap->count0; + redo_VIsual_arg = cap->arg; } } @@ -2108,6 +2109,24 @@ do_pending_operator(cap, old_col, gui_yank) oap->op_type == OP_FOLDDELREC, oap->is_VIsual); break; #endif + case OP_ADD: + case OP_SUBTRACT: + if (empty_region_error) + { + vim_beep(BO_OPER); + CancelRedo(); + } + else + { + VIsual_active = TRUE; +#ifdef FEAT_LINEBREAK + curwin->w_p_lbr = lbr_saved; +#endif + op_addsub(oap, cap->count1, redo_VIsual_arg); + VIsual_active = FALSE; + } + check_cursor_col(); + break; default: clearopbeep(oap); } @@ -3603,43 +3622,6 @@ find_ident_at_pos(wp, lnum, startcol, string, find_type) } /* - * Add commands to reselect Visual mode into the redo buffer. - */ - static void -prep_redo_visual(cap) - cmdarg_T *cap; -{ - ResetRedobuff(); - AppendCharToRedobuff(VIsual_mode); - if (VIsual_mode == 'V' && curbuf->b_visual.vi_end.lnum - != curbuf->b_visual.vi_start.lnum) - { - AppendNumberToRedobuff(curbuf->b_visual.vi_end.lnum - - curbuf->b_visual.vi_start.lnum); - AppendCharToRedobuff('j'); - } - else if (VIsual_mode == 'v' || VIsual_mode == Ctrl_V) - { - /* block visual mode or char visual mmode*/ - if (curbuf->b_visual.vi_end.lnum != curbuf->b_visual.vi_start.lnum) - { - AppendNumberToRedobuff(curbuf->b_visual.vi_end.lnum - - curbuf->b_visual.vi_start.lnum); - AppendCharToRedobuff('j'); - } - if (curbuf->b_visual.vi_curswant == MAXCOL) - AppendCharToRedobuff('$'); - else if (curbuf->b_visual.vi_end.col > curbuf->b_visual.vi_start.col) - { - AppendNumberToRedobuff(curbuf->b_visual.vi_end.col - - curbuf->b_visual.vi_start.col - 1); - AppendCharToRedobuff(' '); - } - } - AppendNumberToRedobuff(cap->count1); -} - -/* * Prepare for redo of a normal command. */ static void @@ -4243,30 +4225,16 @@ nv_help(cap) nv_addsub(cap) cmdarg_T *cap; { - int visual = VIsual_active; - - if (cap->oap->op_type == OP_NOP - && do_addsub((int)cap->cmdchar, cap->count1, cap->arg) == OK) + if (!VIsual_active && cap->oap->op_type == OP_NOP) { - if (visual) - { - prep_redo_visual(cap); - if (cap->arg) - AppendCharToRedobuff('g'); - AppendCharToRedobuff(cap->cmdchar); - } - else - prep_redo_cmd(cap); + cap->oap->op_type = cap->cmdchar == Ctrl_A ? OP_ADD : OP_SUBTRACT; + op_addsub(cap->oap, cap->count1, cap->arg); + cap->oap->op_type = OP_NOP; } + else if (VIsual_active) + nv_operator(cap); else - clearopbeep(cap->oap); - if (visual) - { - VIsual_active = FALSE; - redo_VIsual_busy = FALSE; - may_clear_cmdline(); - redraw_later(INVERTED); - } + clearop(cap->oap); } /* @@ -7924,6 +7892,7 @@ nv_g_cmd(cap) { cap->arg = TRUE; cap->cmdchar = cap->nchar; + cap->nchar = NUL; nv_addsub(cap); } else diff --git a/src/ops.c b/src/ops.c index d02b784..66a9d5d 100644 --- a/src/ops.c +++ b/src/ops.c @@ -112,6 +112,7 @@ static void dis_msg __ARGS((char_u *p, int skip_esc)); static char_u *skip_comment __ARGS((char_u *line, int process, int include_space, int *is_comment)); #endif static void block_prep __ARGS((oparg_T *oap, struct block_def *, linenr_T, int)); +static int do_addsub __ARGS((int op_type, pos_T *pos, int length, linenr_T Prenum1)); #if defined(FEAT_CLIPBOARD) || defined(FEAT_EVAL) static void str_to_reg __ARGS((struct yankreg *y_ptr, int yank_type, char_u *str, long len, long blocklen, int str_list)); #endif @@ -158,6 +159,8 @@ static char opchars[][3] = {'z', 'D', TRUE}, /* OP_FOLDDELREC */ {'g', 'w', TRUE}, /* OP_FORMAT2 */ {'g', '@', FALSE}, /* OP_FUNCTION */ + {Ctrl_A, NUL, FALSE}, /* OP_ADD */ + {Ctrl_X, NUL, FALSE}, /* OP_SUBTRACT */ }; /* @@ -175,6 +178,10 @@ get_op_type(char1, char2) return OP_REPLACE; if (char1 == '~') /* when tilde is an operator */ return OP_TILDE; + if (char1 == 'g' && char2 == Ctrl_A) /* add */ + return OP_ADD; + if (char1 == 'g' && char2 == Ctrl_X) /* subtract */ + return OP_SUBTRACT; for (i = 0; ; ++i) if (opchars[i][0] == char1 && opchars[i][1] == char2) break; @@ -5339,42 +5346,126 @@ block_prep(oap, bdp, lnum, is_del) bdp->textstart = pstart; } -#ifdef FEAT_RIGHTLEFT -static void reverse_line __ARGS((char_u *s)); - - static void -reverse_line(s) - char_u *s; +/* + * Handle the add/subtract operator. + */ + void +op_addsub(oap, Prenum1, g_cmd) + oparg_T *oap; + linenr_T Prenum1; /* Amount of add/subtract */ + int g_cmd; /* was g<c-a>/g<c-x> */ { - int i, j; - char_u c; - - if ((i = (int)STRLEN(s) - 1) <= 0) - return; + pos_T pos; + struct block_def bd; + int did_change = FALSE; + linenr_T amount = Prenum1; - curwin->w_cursor.col = i - curwin->w_cursor.col; - for (j = 0; j < i; j++, i--) + if (!VIsual_active) { - c = s[i]; s[i] = s[j]; s[j] = c; + pos = curwin->w_cursor; + if (u_save_cursor() == FAIL) + return; + did_change = do_addsub(oap->op_type, &pos, 0, amount); + if (did_change) + changed_lines(pos.lnum, 0, pos.lnum + 1, 0L); } -} + else + { + int one_change; + int length; -# define RLADDSUBFIX(ptr) if (curwin->w_p_rl) reverse_line(ptr); -#else -# define RLADDSUBFIX(ptr) + if (u_save((linenr_T)(oap->start.lnum - 1), + (linenr_T)(oap->end.lnum + 1)) == FAIL) + return; + + pos = oap->start; + for (; pos.lnum <= oap->end.lnum; ++pos.lnum) + { + if (oap->block_mode) /* Visual block mode */ + { + block_prep(oap, &bd, pos.lnum, FALSE); + pos.col = bd.textcol; + length = bd.textlen; + } + else + { + if (oap->motion_type == MLINE) + { + curwin->w_cursor.col = 0; + pos.col = 0; + length = (colnr_T)STRLEN(ml_get(pos.lnum)); + } + else if (oap->motion_type == MCHAR) + { + if (!oap->inclusive) + dec(&(oap->end)); + length = (colnr_T)STRLEN(ml_get(pos.lnum)); + pos.col = 0; + if (pos.lnum == oap->start.lnum) + { + pos.col += oap->start.col; + length -= oap->start.col; + } + if (pos.lnum == oap->end.lnum) + { + length = (int)STRLEN(ml_get(oap->end.lnum)); + if (oap->end.col >= length) + oap->end.col = length - 1; + length = oap->end.col - pos.col + 1; + } + } + } + one_change = do_addsub(oap->op_type, &pos, length, amount); + did_change |= one_change; + +#ifdef FEAT_NETBEANS_INTG + if (netbeans_active() && one_change) + { + char_u *ptr = ml_get_buf(curbuf, pos.lnum, FALSE); + + netbeans_removed(curbuf, pos.lnum, pos.col, (long)length); + netbeans_inserted(curbuf, pos.lnum, pos.col, + &ptr[pos.col], length); + } #endif + if (g_cmd && one_change) + amount += Prenum1; + } + if (did_change) + changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L); + + if (!did_change && oap->is_VIsual) + /* No change: need to remove the Visual selection */ + redraw_curbuf_later(INVERTED); + + /* + * Set '[ and '] marks. + */ + curbuf->b_op_start = oap->start; + curbuf->b_op_end = oap->end; + + if (did_change && oap->line_count > p_report) + { + if (oap->line_count == 1) + MSG(_("1 line changed")); + else + smsg((char_u *)_("%ld lines changed"), oap->line_count); + } + } +} /* - * add or subtract 'Prenum1' from a number in a line - * 'command' is CTRL-A for add, CTRL-X for subtract + * Add or subtract 'Prenum1' from a number in a line + * op_type is OP_ADD or OP_SUBTRACT * - * return FAIL for failure, OK otherwise + * Returns TRUE if some character was changed. */ - int -do_addsub(command, Prenum1, g_cmd) - int command; + static int +do_addsub(op_type, pos, length, Prenum1) + int op_type; + pos_T *pos; + int length; linenr_T Prenum1; - int g_cmd; /* was g<c-a>/g<c-x> */ { int col; char_u *buf1; @@ -5382,11 +5473,9 @@ do_addsub(command, Prenum1, g_cmd) int pre; /* 'X'/'x': hex; '0': octal; 'B'/'b': bin */ static int hexupper = FALSE; /* 0xABC */ unsigned long n; - unsigned long offset = 0; /* line offset for Ctrl_V mode */ long_u oldn; char_u *ptr; int c; - int length = 0; /* character length of the number */ int todel; int dohex; int dooct; @@ -5397,68 +5486,27 @@ do_addsub(command, Prenum1, g_cmd) int negative = FALSE; int was_positive = TRUE; int visual = VIsual_active; - int i; - int lnum = curwin->w_cursor.lnum; - int lnume = curwin->w_cursor.lnum; - int startcol = 0; int did_change = FALSE; pos_T t = curwin->w_cursor; int maxlen = 0; - int pos = 0; - int bit = 0; - int bits = sizeof(unsigned long) * 8; dohex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL); /* "heX" */ dooct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL); /* "Octal" */ dobin = (vim_strchr(curbuf->b_p_nf, 'b') != NULL); /* "Bin" */ doalp = (vim_strchr(curbuf->b_p_nf, 'p') != NULL); /* "alPha" */ + curwin->w_cursor = *pos; + ptr = ml_get(pos->lnum); + col = pos->col; + + if (*ptr == NUL) + goto theend; + /* * First check if we are on a hexadecimal number, after the "0x". */ - col = curwin->w_cursor.col; - if (VIsual_active) + if (!VIsual_active) { - if (lt(curwin->w_cursor, VIsual)) - { - curwin->w_cursor = VIsual; - VIsual = t; - } - - ptr = ml_get(VIsual.lnum); - RLADDSUBFIX(ptr); - if (VIsual_mode == 'V') - { - VIsual.col = 0; - curwin->w_cursor.col = (colnr_T)STRLEN(ptr); - } - else if (VIsual_mode == Ctrl_V && VIsual.col > curwin->w_cursor.col) - { - t = VIsual; - VIsual.col = curwin->w_cursor.col; - curwin->w_cursor.col = t.col; - } - - /* store visual area for 'gv' */ - curbuf->b_visual.vi_start = VIsual; - curbuf->b_visual.vi_end = curwin->w_cursor; - curbuf->b_visual.vi_mode = VIsual_mode; - curbuf->b_visual.vi_curswant = curwin->w_curswant; - - if (VIsual_mode != 'v') - startcol = VIsual.col < curwin->w_cursor.col ? VIsual.col - : curwin->w_cursor.col; - else - startcol = VIsual.col; - col = startcol; - lnum = VIsual.lnum; - lnume = curwin->w_cursor.lnum; - } - else - { - ptr = ml_get_curline(); - RLADDSUBFIX(ptr); - if (dobin) while (col > 0 && vim_isbdigit(ptr[col])) --col; @@ -5477,8 +5525,7 @@ do_addsub(command, Prenum1, g_cmd) { /* In case of binary/hexadecimal pattern overlap match, rescan */ - - col = curwin->w_cursor.col; + col = pos->col; while (col > 0 && vim_isdigit(ptr[col])) col--; @@ -5505,7 +5552,7 @@ do_addsub(command, Prenum1, g_cmd) /* * Search forward and then backward to find the start of number. */ - col = curwin->w_cursor.col; + col = pos->col; while (ptr[col] != NUL && !vim_isdigit(ptr[col]) @@ -5519,308 +5566,251 @@ do_addsub(command, Prenum1, g_cmd) } } - for (i = lnum; i <= lnume; i++) + if (visual) { - colnr_T stop = 0; - - t = curwin->w_cursor; - curwin->w_cursor.lnum = i; - ptr = ml_get_curline(); - RLADDSUBFIX(ptr); - if ((int)STRLEN(ptr) <= col) - /* try again on next line */ - continue; - if (visual) + while (ptr[col] != NUL && length > 0 + && !vim_isdigit(ptr[col]) + && !(doalp && ASCII_ISALPHA(ptr[col]))) { - if (VIsual_mode == 'v' - && i == lnume) - stop = curwin->w_cursor.col; - else if (VIsual_mode == Ctrl_V - && curbuf->b_visual.vi_curswant != MAXCOL) - stop = curwin->w_cursor.col; + ++col; + --length; + } - while (ptr[col] != NUL - && !vim_isdigit(ptr[col]) - && !(doalp && ASCII_ISALPHA(ptr[col]))) - { - if (col > 0 && col == stop) - break; - ++col; - } + if (length == 0) + goto theend; - if (col > startcol && ptr[col - 1] == '-') - { - negative = TRUE; - was_positive = FALSE; - } - } - /* - * If a number was found, and saving for undo works, replace the number. - */ - firstdigit = ptr[col]; - if ((!VIM_ISDIGIT(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit))) - || u_save_cursor() != OK) + if (col > pos->col && ptr[col - 1] == '-') { - if (lnum < lnume) - { - if (visual && VIsual_mode != Ctrl_V) - col = 0; - else - col = startcol; - /* Try again on next line */ - continue; - } - beep_flush(); - return FAIL; + negative = TRUE; + was_positive = FALSE; } + } + + /* + * If a number was found, and saving for undo works, replace the number. + */ + firstdigit = ptr[col]; + if (!VIM_ISDIGIT(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit))) + { + beep_flush(); + goto theend; + } - if (doalp && ASCII_ISALPHA(firstdigit)) + if (doalp && ASCII_ISALPHA(firstdigit)) + { + /* decrement or increment alphabetic character */ + if (op_type == OP_SUBTRACT) { - /* decrement or increment alphabetic character */ - if (command == Ctrl_X) + if (CharOrd(firstdigit) < Prenum1) { - if (CharOrd(firstdigit) < Prenum1) - { - if (isupper(firstdigit)) - firstdigit = 'A'; - else - firstdigit = 'a'; - } + if (isupper(firstdigit)) + firstdigit = 'A'; else -#ifdef EBCDIC - firstdigit = EBCDIC_CHAR_ADD(firstdigit, -Prenum1); -#else - firstdigit -= Prenum1; -#endif + firstdigit = 'a'; } else - { - if (26 - CharOrd(firstdigit) - 1 < Prenum1) - { - if (isupper(firstdigit)) - firstdigit = 'Z'; - else - firstdigit = 'z'; - } - else #ifdef EBCDIC - firstdigit = EBCDIC_CHAR_ADD(firstdigit, Prenum1); + firstdigit = EBCDIC_CHAR_ADD(firstdigit, -Prenum1); #else - firstdigit += Prenum1; + firstdigit -= Prenum1; #endif - } - curwin->w_cursor.col = col; - did_change = TRUE; - (void)del_char(FALSE); - ins_char(firstdigit); - curwin->w_cursor.col = col; } else { - if (col > 0 && ptr[col - 1] == '-' && !visual) + if (26 - CharOrd(firstdigit) - 1 < Prenum1) { - /* negative number */ - --col; - negative = TRUE; - } - /* get the number value (unsigned) */ - if (visual && VIsual_mode != 'V') - { - if (VIsual_mode == 'v') - { - if (i == lnum) - maxlen = (lnum == lnume - ? curwin->w_cursor.col - col + 1 - : (int)STRLEN(ptr) - col); - else - maxlen = (i == lnume ? curwin->w_cursor.col - col + 1 - : (int)STRLEN(ptr) - col); - } - else if (VIsual_mode == Ctrl_V) - maxlen = (curbuf->b_visual.vi_curswant == MAXCOL - ? (int)STRLEN(ptr) - col - : curwin->w_cursor.col - col + 1); + if (isupper(firstdigit)) + firstdigit = 'Z'; + else + firstdigit = 'z'; } + else +#ifdef EBCDIC + firstdigit = EBCDIC_CHAR_ADD(firstdigit, Prenum1); +#else + firstdigit += Prenum1; +#endif + } + curwin->w_cursor.col = col; + did_change = TRUE; + (void)del_char(FALSE); + ins_char(firstdigit); + curwin->w_cursor.col = col; + } + else + { + if (col > 0 && ptr[col - 1] == '-' && !visual) + { + /* negative number */ + --col; + negative = TRUE; + } + /* get the number value (unsigned) */ + if (visual && VIsual_mode != 'V') + maxlen = (curbuf->b_visual.vi_curswant == MAXCOL + ? (int)STRLEN(ptr) - col + : length); - vim_str2nr(ptr + col, &pre, &length, - 0 + (dobin ? STR2NR_BIN : 0) - + (dooct ? STR2NR_OCT : 0) - + (dohex ? STR2NR_HEX : 0), - NULL, &n, maxlen); - - /* ignore leading '-' for hex and octal and bin numbers */ - if (pre && negative) - { - ++col; - --length; - negative = FALSE; - } + vim_str2nr(ptr + col, &pre, &length, + 0 + (dobin ? STR2NR_BIN : 0) + + (dooct ? STR2NR_OCT : 0) + + (dohex ? STR2NR_HEX : 0), + NULL, &n, maxlen); - /* add or subtract */ - subtract = FALSE; - if (command == Ctrl_X) - subtract ^= TRUE; - if (negative) - subtract ^= TRUE; + /* ignore leading '-' for hex and octal and bin numbers */ + if (pre && negative) + { + ++col; + --length; + negative = FALSE; + } + /* add or subtract */ + subtract = FALSE; + if (op_type == OP_SUBTRACT) + subtract ^= TRUE; + if (negative) + subtract ^= TRUE; + + oldn = n; + if (subtract) + n -= (unsigned long)Prenum1; + else + n += (unsigned long)Prenum1; - oldn = n; + /* handle wraparound for decimal numbers */ + if (!pre) + { if (subtract) - n -= (unsigned long)Prenum1; - else - n += (unsigned long)Prenum1; - - /* handle wraparound for decimal numbers */ - if (!pre) { - if (subtract) - { - if (n > oldn) - { - n = 1 + (n ^ (unsigned long)-1); - negative ^= TRUE; - } - } - else + if (n > oldn) { - /* add */ - if (n < oldn) - { - n = (n ^ (unsigned long)-1); - negative ^= TRUE; - } + n = 1 + (n ^ (unsigned long)-1); + negative ^= TRUE; } - if (n == 0) - negative = FALSE; } - - if (visual && !was_positive && !negative && col > 0) - { - /* need to remove the '-' */ - col--; - length++; - } - - - /* - * Delete the old number. - */ - curwin->w_cursor.col = col; - did_change = TRUE; - todel = length; - c = gchar_cursor(); - - /* - * Don't include the '-' in the length, only the length of the - * part after it is kept the same. - */ - if (c == '-') - --length; - while (todel-- > 0) + else { - if (c < 0x100 && isalpha(c)) + /* add */ + if (n < oldn) { - if (isupper(c)) - hexupper = TRUE; - else - hexupper = FALSE; + n = (n ^ (unsigned long)-1); + negative ^= TRUE; } - /* del_char() will mark line needing displaying */ - (void)del_char(FALSE); - c = gchar_cursor(); } + if (n == 0) + negative = FALSE; + } - /* - * Prepare the leading characters in buf1[]. - * When there are many leading zeros it could be very long. - * Allocate a bit too much. - */ - buf1 = alloc((unsigned)length + NUMBUFLEN); - if (buf1 == NULL) - return FAIL; - ptr = buf1; - if (negative && (!visual || (visual && was_positive))) - { - *ptr++ = '-'; - } - if (pre) - { - *ptr++ = '0'; - --length; - } - if (pre == 'b' || pre == 'B' || - pre == 'x' || pre == 'X') - { - *ptr++ = pre; - --length; - } + if (visual && !was_positive && !negative && col > 0) + { + /* need to remove the '-' */ + col--; + length++; + } - /* - * Put the number characters in buf2[]. - */ - if (pre == 'b' || pre == 'B') - { - /* leading zeros */ - for (bit = bits; bit > 0; bit--) - if ((n >> (bit - 1)) & 0x1) break; - for (pos = 0; bit > 0; bit--) - buf2[pos++] = ((n >> (bit - 1)) & 0x1) ? '1' : '0'; + /* + * Delete the old number. + */ + curwin->w_cursor.col = col; + did_change = TRUE; + todel = length; + c = gchar_cursor(); - buf2[pos] = '\0'; + /* + * Don't include the '-' in the length, only the length of the + * part after it is kept the same. + */ + if (c == '-') + --length; + while (todel-- > 0) + { + if (c < 0x100 && isalpha(c)) + { + if (isupper(c)) + hexupper = TRUE; + else + hexupper = FALSE; } - else if (pre == 0) - sprintf((char *)buf2, "%lu", n); - else if (pre == '0') - sprintf((char *)buf2, "%lo", n); - else if (pre && hexupper) - sprintf((char *)buf2, "%lX", n); - else - sprintf((char *)buf2, "%lx", n); - length -= (int)STRLEN(buf2); + /* del_char() will mark line needing displaying */ + (void)del_char(FALSE); + c = gchar_cursor(); + } - /* - * Adjust number of zeros to the new number of digits, so the - * total length of the number remains the same. - * Don't do this when - * the result may look like an octal number. - */ - if (firstdigit == '0' && !(dooct && pre == 0)) - while (length-- > 0) - *ptr++ = '0'; - *ptr = NUL; - STRCAT(buf1, buf2); - ins_str(buf1); /* insert the new number */ - vim_free(buf1); - if (lnum < lnume) - curwin->w_cursor.col = t.col; - else if (did_change && curwin->w_cursor.col) - --curwin->w_cursor.col; + /* + * Prepare the leading characters in buf1[]. + * When there are many leading zeros it could be very long. + * Allocate a bit too much. + */ + buf1 = alloc((unsigned)length + NUMBUFLEN); + if (buf1 == NULL) + goto theend; + ptr = buf1; + if (negative && (!visual || (visual && was_positive))) + { + *ptr++ = '-'; + } + if (pre) + { + *ptr++ = '0'; + --length; + } + if (pre == 'b' || pre == 'B' || + pre == 'x' || pre == 'X') + { + *ptr++ = pre; + --length; } - if (g_cmd) + /* + * Put the number characters in buf2[]. + */ + if (pre == 'b' || pre == 'B') { - offset = (unsigned long)Prenum1; - g_cmd = 0; + int i; + int bit = 0; + int bits = sizeof(unsigned long) * 8; + + /* leading zeros */ + for (bit = bits; bit > 0; bit--) + if ((n >> (bit - 1)) & 0x1) break; + + for (i = 0; bit > 0; bit--) + buf2[i++] = ((n >> (bit - 1)) & 0x1) ? '1' : '0'; + + buf2[i] = '\0'; } - /* reset */ - subtract = FALSE; - negative = FALSE; - was_positive = TRUE; - if (visual && VIsual_mode == Ctrl_V) - col = startcol; + else if (pre == 0) + sprintf((char *)buf2, "%lu", n); + else if (pre == '0') + sprintf((char *)buf2, "%lo", n); + else if (pre && hexupper) + sprintf((char *)buf2, "%lX", n); else - col = 0; - Prenum1 += offset; - curwin->w_set_curswant = TRUE; -#ifdef FEAT_RIGHTLEFT - ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE); - RLADDSUBFIX(ptr); -#endif + sprintf((char *)buf2, "%lx", n); + length -= (int)STRLEN(buf2); + + /* + * Adjust number of zeros to the new number of digits, so the + * total length of the number remains the same. + * Don't do this when + * the result may look like an octal number. + */ + if (firstdigit == '0' && !(dooct && pre == 0)) + while (length-- > 0) + *ptr++ = '0'; + *ptr = NUL; + STRCAT(buf1, buf2); + ins_str(buf1); /* insert the new number */ + vim_free(buf1); + if (did_change && curwin->w_cursor.col) + --curwin->w_cursor.col; } + +theend: if (visual) - /* cursor at the top of the selection */ - curwin->w_cursor = VIsual; - return OK; + curwin->w_cursor = t; + return did_change; } #ifdef FEAT_VIMINFO diff --git a/src/proto/ops.pro b/src/proto/ops.pro index aaffa02..27e0f11 100644 --- a/src/proto/ops.pro +++ b/src/proto/ops.pro @@ -43,7 +43,7 @@ void op_formatexpr __ARGS((oparg_T *oap)); int fex_format __ARGS((linenr_T lnum, long count, int c)); void format_lines __ARGS((linenr_T line_count, int avoid_fex)); int paragraph_start __ARGS((linenr_T lnum)); -int do_addsub __ARGS((int command, linenr_T Prenum1, int g_cmd)); +void op_addsub __ARGS((oparg_T *oap, linenr_T Prenum1, int g_cmd)); int read_viminfo_register __ARGS((vir_T *virp, int force)); void write_viminfo_registers __ARGS((FILE *fp)); void x11_export_final_selection __ARGS((void)); diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak index 2ad039c..de5c45e 100644 --- a/src/testdir/Make_all.mak +++ b/src/testdir/Make_all.mak @@ -174,6 +174,7 @@ SCRIPTS_GUI = test16.out # Keep test_alot.res as the last one, sort the others. NEW_TESTS = test_assert.res \ test_cdo.res \ + test_increment.res \ test_quickfix.res \ test_viml.res \ test_alot.res diff --git a/src/testdir/test_increment.in b/src/testdir/test_increment.in deleted file mode 100644 index f5d8ff9..0000000 --- a/src/testdir/test_increment.in +++ /dev/null @@ -1,734 +0,0 @@ -Tests for using Ctrl-A/Ctrl-X on visual selections - -Test cases -========== - -1) Ctrl-A on visually selected number -Text: -foobar-10 - Expected: - 1) Ctrl-A on start of line: - foobar-9 - 2) Ctrl-A on visually selected "-10": - foobar-9 - 3) Ctrl-A on visually selected "10": - foobar-11 - 4) Ctrl-X on visually selected "-10" - foobar-11 - 5) Ctrl-X on visually selected "10" - foobar-9 - -2) Ctrl-A on visually selected lines -Text: -10 -20 -30 -40 - - Expected: - 1) Ctrl-A on visually selected lines: -11 -21 -31 -41 - - 2) Ctrl-X on visually selected lines: -9 -19 -29 -39 - -3) g Ctrl-A on visually selected lines, with non-numbers in between -Text: -10 - -20 - -30 - -40 - - Expected: - 1) 2 g Ctrl-A on visually selected lines: -12 - -24 - -36 - -48 - 2) 2 g Ctrl-X on visually selected lines -8 - -16 - -24 - -32 - -4) Ctrl-A on non-number -Text: -foobar-10 - Expected: - 1) visually select foobar: - foobar-10 - -5) g<Ctrl-A> on letter -Test: -a -a -a -a - Expected: - 1) g Ctrl-A on visually selected lines - b - c - d - e - -6) g<Ctrl-A> on letter -Test: -z -z -z -z - Expected: - 1) g Ctrl-X on visually selected lines - y - x - w - v - -7) <Ctrl-A> on letter -Test: -2 -1 -0 --1 --2 - - Expected: - 1) Ctrl-A on visually selected lines - 3 - 2 - 1 - 0 - -1 - - 2) Ctrl-X on visually selected lines - 1 - 0 - -1 - -2 - -3 -8) Block increment on 0x9 -Text: -0x9 -0x9 - Expected: - 1) Ctrl-A on visually block selected region (cursor at beginning): - 0xa - 0xa - 2) Ctrl-A on visually block selected region (cursor at end) - 0xa - 0xa - -9) Increment and redo -Text: -2 -2 - -3 -3 - - Expected: - 1) 2 Ctrl-A on first 2 visually selected lines - 4 - 4 - 2) redo (.) on 3 - 5 - 5 -10) sequentially decrement 1 -Text: -1 -1 -1 -1 - Expected: - 1) g Ctrl-X on visually selected lines - 0 - -1 - -2 - -3 - -11) visually block selected indented lines -Text: - 1 -1 - 1 - 1 - Expexted: - 1) g Ctrl-A on block selected indented lines - 2 -1 - 3 - 4 - -12) visually selected several columns -Text: -0 0 -0 0 -0 0 - Expected: - 1) 'v' select last zero and first zeroes - 0 1 - 1 0 - 1 0 - -13) visually selected part of columns -Text: -max: 100px -max: 200px -max: 300px -max: 400px - Expected: - 1) 'v' on first two numbers Ctrl-A - max: 110px - max: 220px - max: 330px - max: 400px - 2) 'v' on first two numbers Ctrl-X - max: 90px - max: 190px - max: 290px - max: 400px - -14) redo in block mode -Text: -1 1 -1 1 - Expected: - 1) Ctrl-a on first column, redo on second column - 2 2 - 2 2 - -15) block select single numbers -Text: -101 - Expected: - 1) Ctrl-a on visually selected zero - 111 - -16) increment right aligned numbers -Text: - 1 - 19 - 119 - Expected: - 1) Ctrl-a on line selected region - 2 - 20 - 120 - -17) block-wise increment and redo -Text: - 100 - 1 - - 100 - 1 - - Expected: - 1) Ctrl-V j $ on first block, afterwards '.' on second - 101 - 2 - - 101 - 2 - -18) repeat of g<Ctrl-a> -Text: - 0 - 0 - 0 - 0 - - Expected: - 1) V 4j g<ctrl-a>, repeat twice afterwards with . - 3 - 6 - 9 - 12 - -19) increment on number with nrformat including alpha -Text: - 1 - 1a - - Expected: - 1) <Ctrl-V>j$ <ctrl-a> - 2 - 2a - -20) increment a single letter -Text: - a - - Expected: - 1) <Ctrl-a> and cursor is on a - b - -21) block-wise increment on part of hexadecimal -Text: -0x123456 - - Expected: - 1) Ctrl-V f3 <ctrl-a> -0x124456 - -22) Block increment on 0b0 -Text: -0b1 -0b1 - Expected: - 1) Ctrl-A on visually block selected region (cursor at beginning): - 0b10 - 0b10 - 2) Ctrl-A on visually block selected region (cursor at end) - 0b10 - 0b10 - -23) block-wise increment on part of binary -Text: -0b1001 - - Expected: - 1) Ctrl-V 5l <ctrl-a> -0b1011 - -24) increment hexadecimal -Text: -0x0b1001 - - Expected: - 1) <ctrl-a> -0x0b1002 - -25) increment binary with nrformats including alpha -Text: -0b1001a - - Expected: - 1) <ctrl-a> -0b1010a - -26) increment binary with 64 bits -Text: -0b1111111111111111111111111111111111111111111111111111111111111110 - - Expected: - 1) <ctrl-a> -0b1111111111111111111111111111111111111111111111111111111111111111 - - -STARTTEST -:so small.vim -:" -:" Avoid CTRL-X being mapped in Visual mode for MS-Windows -:vmapclear -:" -:" Test 1 -:/^S1=/+,/^E1=/-y a -:/^E1=/+put a -:/^E1=/+2put a -f-v$:/^E1=/+3put a -f1v$:/^E1=/+4put a -f-v$:/^E1=/+5put a -f1v$ - -:" Test 2 -:/^S2=/+,/^E2=/-y a -:/^E2=/+put a -V3k$3j:.+put a -V3k$ - -:" Test 3 -:/^S3=/+,/^E3=/-y a -:/^E3=/+put a -V6k2g6j:.+put a -V6k2g - -:" Test 4 -:/^S4=/+,/^E4=/-y a -:/^E4=/+put a -vf- - -:" Test 5 -:set nrformats+=alpha -:/^S5=/+,/^E5=/-y a -:/^E5=/+put a -v3kg - -:" Test 6 -:/^S6=/+,/^E6=/-y a -:/^E6=/+put a -v3kg - -:" Test 7 -:set nrformats&vim -:/^S7=/+,/^E7=/-y a -:/^E7=/+put a -V4k4j:.+put a -V4k - -:" Test 8 -:/^S8=/+,/^E8=/-y a -:/^E8=/+put a -kj$j:.+put a -k$+ - -:" Test 9 -:/^S9=/+,/^E9=/-y a -:/^E9=/+put a -5kVj23j. - -:" Test 10 -:/^S10=/+,/^E10=/-y a -:/^E10=/+put a -V3kg - -: Test 11 -:/^S11=/+,/^E11=/-y a -:/^E11=/+put a -3kf13jg - -:" Test 12 -:/^S12=/+,/^E12=/-y a -:/^E12=/+put a -2k$v++ - -:" Test 13 -:/^S13=/+,/^E13=/-y a -:/^E13=/+put a -3kf1l2j3j:.+put a -3kf1l2j - -:" Test 14 -:/^S14=/+,/^E14=/-y a -:/^E14=/+put a -kw. - -:" Test 15 -:/^S15=/+,/^E15=/-y a -:/^E15=/+put a -lv - -:" Test 16 -:/^S16=/+,/^E16=/-y a -:/^E16=/+put a -V3k - -:" Test 17 -:/^S17=/+,/^E17=/-y a -:/^E17=/+put a -4kj$2j. - -:" Test 18 -:/^S18=/+,/^E18=/-y a -:/^E18=/+put a -V3kg.. - -:" Test 19 -:set nrformats+=alpha -:/^S19=/+,/^E19=/-y a -:/^E19=/+put a -k$ -:set nrformats&vim - -:" Test 20 -:set nrformats+=alpha -:/^S20=/+,/^E20=/-y a -:/^E20=/+put a -:.put =col('.') -:set nrformats&vim - -:" Test 21 -:/^S21=/+,/^E21=/-y a -:/^E21=/+put a -:set nrformats&vim -f3 - -:" Test 22 -:/^S22=/+,/^E22=/-y a -:/^E22=/+put a -kj$j:.+put a -k$+ - -:" Test 23 -:/^S23=/+,/^E23=/-y a -:/^E23=/+put a -:set nrformats&vim -4l - -:" Test 24 -:/^S24=/+,/^E24=/-y a -:/^E24=/+put a -:set nrformats&vim -$ - -:" Test 25 -:set nrformats+=alpha -:/^S25=/+,/^E25=/-y a -:/^E25=/+put a -k$ -:set nrformats&vim - -:" Test 26 -:set nrformats+=alpha -:/^S26=/+,/^E26=/-y a -:/^E26=/+put a -k$ -:set nrformats&vim - -:" Save the report -:/^# Test 1/,$w! test.out -:qa! - - -# Test 1 -S1====== -foobar-10 -E1====== - - - -# Test 2 -S2===== -10 -20 -30 -40 -E2===== - - - -# Test 3 -S3===== -10 - -20 - -30 - -40 -E3===== - - - -# Test 4 -S4===== -foobar-10 -E4===== - - - -# Test 5 -S5==== -a -a -a -a -E5==== - - -# Test 6 -S6==== -z -z -z -z -E6==== - - - -# Test 7 -S7==== -2 -1 -0 --1 --2 -E7==== - - - -# Test 8 -S8==== -0x9 -0x9 -E8==== - - - - -# Test 9 -S9==== -2 -2 - -3 -3 - -E9==== - - - - -# Test 10 -S10==== -1 -1 -1 -1 -E10==== - - - - -# Test 11 -S11==== - 1 -1 - 1 - 1 -E11==== - - - -# Test 12 -S12==== -0 0 -0 0 -0 0 -E12==== - - - -# Test 13 -S13==== -max: 100px -max: 200px -max: 300px -max: 400px -E13==== - - - -# Test 14 -S14==== -1 1 -1 1 -E14==== - - - -# Test 15 -S15==== -101 -E15==== - - - -# Test 16 -S16==== - 1 - 19 - 119 -E16==== - - - -# Test 17 -S17==== - 100 - 1 - - 100 - 1 -E17==== - - -# Test 18 -S18==== -0 -0 -0 -0 -E18==== - - - -# Test 19 -S19==== -1 -1a -E19==== - - - -# Test 20 -S20==== -a -E20==== - - - -# Test 21 -S21==== -0x123456 -E21==== - - - -# Test 22 -S22==== -0b1 -0b1 -E22==== - - - - -# Test 23 -S23==== -0b1001 -E23==== - - - - -# Test 24 -S24==== -0x0b1001 -E24==== - - - - -# Test 25 -S25==== -0b1001a -E25==== - - - - -# Test 26 -S26==== -0b11111111111111111111111111111110 -E26==== - - - -ENDTEST - diff --git a/src/testdir/test_increment.ok b/src/testdir/test_increment.ok deleted file mode 100644 index 77ce9d4..0000000 --- a/src/testdir/test_increment.ok +++ /dev/null @@ -1,340 +0,0 @@ -# Test 1 -S1====== -foobar-10 -E1====== - -foobar-9 -foobar-9 -foobar-11 -foobar-11 -foobar-9 - - -# Test 2 -S2===== -10 -20 -30 -40 -E2===== - -11 -21 -31 -41 - -9 -19 -29 -39 - -# Test 3 -S3===== -10 - -20 - -30 - -40 -E3===== - -12 - -24 - -36 - -48 - -8 - -16 - -24 - -32 - -# Test 4 -S4===== -foobar-10 -E4===== - -foobar-10 - - -# Test 5 -S5==== -a -a -a -a -E5==== - -b -c -d -e - -# Test 6 -S6==== -z -z -z -z -E6==== - -y -x -w -v - - -# Test 7 -S7==== -2 -1 -0 --1 --2 -E7==== - -3 -2 -1 -0 --1 - -1 -0 --1 --2 --3 - -# Test 8 -S8==== -0x9 -0x9 -E8==== - -0xa -0xa - -0xa -0xa - - -# Test 9 -S9==== -2 -2 - -3 -3 - -E9==== - -4 -4 - -5 -5 - - - - -# Test 10 -S10==== -1 -1 -1 -1 -E10==== - -0 --1 --2 --3 - - - -# Test 11 -S11==== - 1 -1 - 1 - 1 -E11==== - - 2 -1 - 3 - 4 - - -# Test 12 -S12==== -0 0 -0 0 -0 0 -E12==== - -0 1 -1 0 -1 0 - - -# Test 13 -S13==== -max: 100px -max: 200px -max: 300px -max: 400px -E13==== - -max: 110px -max: 210px -max: 310px -max: 400px - -max: 90px -max: 190px -max: 290px -max: 400px - -# Test 14 -S14==== -1 1 -1 1 -E14==== - -2 2 -2 2 - - -# Test 15 -S15==== -101 -E15==== - -111 - - -# Test 16 -S16==== - 1 - 19 - 119 -E16==== - - 2 - 20 - 120 - - -# Test 17 -S17==== - 100 - 1 - - 100 - 1 -E17==== - - 101 - 2 - - 101 - 1 - -# Test 18 -S18==== -0 -0 -0 -0 -E18==== - -3 -6 -9 -12 - - -# Test 19 -S19==== -1 -1a -E19==== - -2 -2a - - -# Test 20 -S20==== -a -E20==== - -b -1 - - -# Test 21 -S21==== -0x123456 -E21==== - -0x124456 - - -# Test 22 -S22==== -0b1 -0b1 -E22==== - -0b10 -0b10 - -0b10 -0b10 - - -# Test 23 -S23==== -0b1001 -E23==== - -0b1011 - - - -# Test 24 -S24==== -0x0b1001 -E24==== - -0x0b1002 - - - -# Test 25 -S25==== -0b1001a -E25==== - -0b1010a - - - -# Test 26 -S26==== -0b11111111111111111111111111111110 -E26==== - -0b11111111111111111111111111111111 - - -ENDTEST - diff --git a/src/testdir/test_increment.vim b/src/testdir/test_increment.vim new file mode 100644 index 0000000..56777df --- /dev/null +++ b/src/testdir/test_increment.vim @@ -0,0 +1,383 @@ +" Tests for using Ctrl-A/Ctrl-X on visual selections + +func SetUp() + new dummy + set nrformats&vim +endfunc + +func TearDown() + bwipe! +endfunc + +" Ctrl-A on visually selected number +func Test_visual_increment_01() + call setline(1, repeat(["foobaar-10"], 5)) + + call cursor(1, 1) + exec "norm! \<C-A>" + call assert_equal("foobaar-9", getline('.')) + call assert_equal([0, 1, 9, 0], getpos('.')) + + call cursor(2, 1) + exec "norm! f-v$\<C-A>" + call assert_equal("foobaar-9", getline('.')) + call assert_equal([0, 2, 8, 0], getpos('.')) + + call cursor(3, 1) + exec "norm! f1v$\<C-A>" + call assert_equal("foobaar-11", getline('.')) + call assert_equal([0, 3, 9, 0], getpos('.')) + + call cursor(4, 1) + exec "norm! f-v$\<C-X>" + call assert_equal("foobaar-11", getline('.')) + call assert_equal([0, 4, 8, 0], getpos('.')) + + call cursor(5, 1) + exec "norm! f1v$\<C-X>" + call assert_equal("foobaar-9", getline('.')) + call assert_equal([0, 5, 9, 0], getpos('.')) +endfunc + +" Ctrl-A on visually selected lines +func Test_visual_increment_02() + call setline(1, ["10", "20", "30", "40"]) + exec "norm! GV3k$\<C-A>" + call assert_equal(["11", "21", "31", "41"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, ["10", "20", "30", "40"]) + exec "norm! GV3k$\<C-X>" + call assert_equal(["9", "19", "29", "39"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" g Ctrl-A on visually selected lines, with non-numbers in between +func Test_visual_increment_03() + call setline(1, ["10", "", "20", "", "30", "", "40"]) + exec "norm! GV6k2g\<C-A>" + call assert_equal(["12", "", "24", "", "36", "", "48"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, ["10", "", "20", "", "30", "", "40"]) + exec "norm! GV6k2g\<C-X>" + call assert_equal(["8", "", "16", "", "24", "", "32"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Ctrl-A on non-number +func Test_visual_increment_04() + call setline(1, ["foobar-10"]) + exec "norm! vf-\<C-A>" + call assert_equal(["foobar-10"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" g<Ctrl-A> on letter +func Test_visual_increment_05() + set nrformats+=alpha + call setline(1, repeat(["a"], 4)) + exec "norm! GV3kg\<C-A>" + call assert_equal(["b", "c", "d", "e"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" g<Ctrl-X> on letter +func Test_visual_increment_06() + set nrformats+=alpha + call setline(1, repeat(["z"], 4)) + exec "norm! GV3kg\<C-X>" + call assert_equal(["y", "x", "w", "v"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" <Ctrl-A> on letter +func Test_visual_increment_07() + call setline(1, ["2", "1", "0", "-1", "-2"]) + exec "norm! GV4k\<C-A>" + call assert_equal(["3", "2", "1", "0", "-1"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, ["2", "1", "0", "-1", "-2"]) + exec "norm! GV4k\<C-X>" + call assert_equal(["1", "0", "-1", "-2", "-3"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Block increment on 0x9 +func Test_visual_increment_08() + call setline(1, repeat(["0x9"], 2)) + exec "norm! \<C-V>j$\<C-A>" + call assert_equal(["0xa", "0xa"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, repeat(["0x9"], 2)) + exec "norm! gg$\<C-V>+\<C-A>" + call assert_equal(["0xa", "0xa"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Increment and redo +func Test_visual_increment_09() + call setline(1, ["2", "2", "", "3", "3", ""]) + exec "norm! ggVj2\<C-A>3j." + call assert_equal(["4", "4", "", "5", "5", ""], getline(1, '$')) + call assert_equal([0, 4, 1, 0], getpos('.')) +endfunc + +" sequentially decrement 1 +func Test_visual_increment_10() + call setline(1, repeat(["1"], 4)) + exec "norm! GV3kg\<C-X>" + call assert_equal(["0", "-1", "-2", "-3"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" visually block selected indented lines +func Test_visual_increment_11() + call setline(1, [" 1", "1", " 1", " 1"]) + exec "norm! f1\<C-V>3jg\<C-A>" + call assert_equal([" 2", "1", " 3", " 4"], getline(1, '$')) + call assert_equal([0, 1, 5, 0], getpos('.')) +endfunc + +" visually selected several columns +func Test_visual_increment_12() + call setline(1, repeat(["0 0"], 3)) + exec "norm! $v++\<C-A>" + call assert_equal(["0 1", "1 0", "1 0"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) +endfunc + +" visually selected part of columns +func Test_visual_increment_13() + call setline(1, ["max: 100px", "max: 200px", "max: 300px", "max: 400px"]) + exec "norm! f1\<C-V>l2j\<C-A>" + call assert_equal(["max: 110px", "max: 210px", "max: 310px", "max: 400px"], getline(1, '$')) + call assert_equal([0, 1, 6, 0], getpos('.')) + + call setline(1, ["max: 100px", "max: 200px", "max: 300px", "max: 400px"]) + exec "norm! ggf1\<C-V>l2j\<C-X>" + call assert_equal(["max: 90px", "max: 190px", "max: 290px", "max: 400px"], getline(1, '$')) + call assert_equal([0, 1, 6, 0], getpos('.')) +endfunc + +" redo in block mode +func Test_visual_increment_14() + call setline(1, repeat(["1 1"], 2)) + exec "norm! G\<C-V>k\<C-A>w." + call assert_equal(["2 2", "2 2"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) +endfunc + +" block select single numbers +func Test_visual_increment_15() + call setline(1, ["101"]) + exec "norm! lv\<C-A>" + call assert_equal(["111"], getline(1, '$')) + call assert_equal([0, 1, 2, 0], getpos('.')) +endfunc + +" increment right aligned numbers +func Test_visual_increment_16() + call setline(1, [" 1", " 19", " 119"]) + exec "norm! VG\<C-A>" + call assert_equal([" 2", " 20", " 120"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" block-wise increment and redo +func Test_visual_increment_17() + call setline(1, [" 100", " 1", "", " 100", " 1"]) + exec "norm! \<C-V>j$\<C-A>2j." + call assert_equal([" 101", " 2", "", " 101", " 1"], getline(1, '$')) + call assert_equal([0, 3, 1, 0], getpos('.')) +endfunc + +" repeat of g<Ctrl-a> +func Test_visual_increment_18() + call setline(1, repeat(["0"], 4)) + exec "norm! GV3kg\<C-A>" + exec "norm! .." + call assert_equal(["3", "6", "9", "12"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" increment on number with nrformat including alpha +func Test_visual_increment_19() + set nrformats+=alpha + call setline(1, ["1", "1a"]) + exec "norm! \<C-V>G$\<C-A>" + call assert_equal(["2", "2a"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" increment a single letter +func Test_visual_increment_20() + set nrformats+=alpha + call setline(1, ["a"]) + exec "norm! \<C-A>" + call assert_equal(["b"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" block-wise increment on part of hexadecimal +func Test_visual_increment_21() + call setline(1, ["0x123456"]) + exec "norm! \<C-V>f3\<C-A>" + call assert_equal(["0x124456"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" block increment on 0b0 +func Test_visual_increment_22() + call setline(1, repeat(["0b1"], 2)) + exec "norm! \<C-V>j$\<C-A>" + call assert_equal(repeat(["0b10"], 2), getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, repeat(["0b1"], 2)) + exec "norm! $\<C-V>+\<C-A>" + call assert_equal(repeat(["0b10"], 2), getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" block-wise increment on part of binary +func Test_visual_increment_23() + call setline(1, ["0b1001"]) + exec "norm! \<C-V>4l\<C-A>" + call assert_equal(["0b1011"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" increment hexadecimal +func Test_visual_increment_24() + call setline(1, ["0x0b1001"]) + exec "norm! \<C-V>$\<C-A>" + call assert_equal(["0x0b1002"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" increment binary with nrformats including alpha +func Test_visual_increment_25() + set nrformats+=alpha + call setline(1, ["0b1001a"]) + exec "norm! \<C-V>$\<C-A>" + call assert_equal(["0b1010a"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" increment binary with 64 bits +func Test_visual_increment_26() + set nrformats+=alpha + call setline(1, ["0b11111111111111111111111111111110"]) + exec "norm! \<C-V>$\<C-A>" + call assert_equal(["0b11111111111111111111111111111111"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Tab code and linewise-visual inc/dec +func Test_visual_increment_27() + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! Vj\<C-A>" + call assert_equal(["x\<TAB>11", "\<TAB>0"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! ggVj\<C-X>" + call assert_equal(["x\<TAB>9", "\<TAB>-2"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Tab code and linewise-visual inc/dec with 'nrformats'+=alpha +func Test_visual_increment_28() + set nrformats+=alpha + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! Vj\<C-A>" + call assert_equal(["y\<TAB>10", "\<TAB>0"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! ggVj\<C-X>" + call assert_equal(["w\<TAB>10", "\<TAB>-2"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Tab code and character-visual inc/dec +func Test_visual_increment_29() + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! f1vjf1\<C-A>" + call assert_equal(["x\<TAB>11", "\<TAB>0"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) + + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! ggf1vjf1\<C-X>" + call assert_equal(["x\<TAB>9", "\<TAB>-2"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) +endfunc + +" Tab code and blockwise-visual inc/dec +func Test_visual_increment_30() + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! f1\<C-V>jl\<C-A>" + call assert_equal(["x\<TAB>11", "\<TAB>0"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) + + call setline(1, ["x\<TAB>10", "\<TAB>-1"]) + exec "norm! ggf1\<C-V>jl\<C-X>" + call assert_equal(["x\<TAB>9", "\<TAB>-2"], getline(1, '$')) + call assert_equal([0, 1, 3, 0], getpos('.')) +endfunc + +" Tab code and blockwise-visual decrement with 'linebreak' and 'showbreak' +func Test_visual_increment_31() + 28vnew dummy_31 + set linebreak showbreak=+ + call setline(1, ["x\<TAB>\<TAB>\<TAB>10", "\<TAB>\<TAB>\<TAB>\<TAB>-1"]) + exec "norm! ggf0\<C-V>jg_\<C-X>" + call assert_equal(["x\<TAB>\<TAB>\<TAB>1-1", "\<TAB>\<TAB>\<TAB>\<TAB>-2"], getline(1, '$')) + call assert_equal([0, 1, 6, 0], getpos('.')) + bwipe! +endfunc + +" Tab code and blockwise-visual increment with $ +func Test_visual_increment_32() + call setline(1, ["\<TAB>123", "456"]) + exec "norm! gg0\<C-V>j$\<C-A>" + call assert_equal(["\<TAB>124", "457"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Tab code and blockwise-visual increment and redo +func Test_visual_increment_33() + call setline(1, ["\<TAB>123", " 456789"]) + exec "norm! gg0\<C-V>j\<C-A>" + call assert_equal(["\<TAB>123", " 457789"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) + + exec "norm! .." + call assert_equal(["\<TAB>123", " 459789"], getline(1, '$')) + call assert_equal([0, 1, 1, 0], getpos('.')) +endfunc + +" Tab code, spaces and character-visual increment and redo +func Test_visual_increment_34() + call setline(1, ["\<TAB>123", " 123", "\<TAB>123", "\<TAB>123"]) + exec "norm! ggvjf3\<C-A>..." + call assert_equal(["\<TAB>127", " 127", "\<TAB>123", "\<TAB>123"], getline(1, '$')) + call assert_equal([0, 1, 2, 0], getpos('.')) +endfunc + +"" Tab code, spaces and blockwise-visual increment and redo +"func Test_visual_increment_35() +" call setline(1, [" 123", "\<TAB>456789"]) +" exec "norm! G0\<C-V>kl\<C-A>" +" call assert_equal([" 123", "\<TAB>556789"], getline(1, '$')) +" call assert_equal([0, 1, 8, 0], getpos('.')) +" +" exec "norm! ..." +" call assert_equal([" 123", "\<TAB>856789"], getline(1, '$')) +" call assert_equal([0, 1, 8, 0], getpos('.')) +"endfunc + +" vim: tabstop=2 shiftwidth=2 expandtab diff --git a/src/vim.h b/src/vim.h index 1a176be..7e44d73 100644 --- a/src/vim.h +++ b/src/vim.h @@ -1457,6 +1457,10 @@ typedef UINT32_TYPEDEF UINT32_T; #define OP_FOLDDELREC 25 /* "zD" delete folds recursively */ #define OP_FORMAT2 26 /* "gw" format operator, keeps cursor pos */ #define OP_FUNCTION 27 /* "g@" call 'operatorfunc' */ +#define OP_ADD 28 /* "<C-A>" Add to the number or alphabetic + character */ +#define OP_SUBTRACT 29 /* "<C-C>" Subtract to the number or alphabetic + character */ /* * Motion types, used for operators and for yank/delete registers.
