0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 7.4.1087

Problem:    CTRL-A and CTRL-X do not work properly with blockwise visual
            selection if there is a mix of Tab and spaces.
Solution:   Add OP_NR_ADD and OP_NR_SUB. (Hirohito Higashi)
This commit is contained in:
Bram Moolenaar 2016-01-10 22:13:02 +01:00
parent 507edf63df
commit d79e55016c
6 changed files with 530 additions and 424 deletions

View File

@ -40,7 +40,6 @@ static void find_start_of_word __ARGS((pos_T *));
static void find_end_of_word __ARGS((pos_T *)); static void find_end_of_word __ARGS((pos_T *));
static int get_mouse_class __ARGS((char_u *p)); static int get_mouse_class __ARGS((char_u *p));
#endif #endif
static void prep_redo_visual __ARGS((cmdarg_T *cap));
static void prep_redo_cmd __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 void prep_redo __ARGS((int regname, long, int, int, int, int, int));
static int checkclearop __ARGS((oparg_T *oap)); 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 linenr_T redo_VIsual_line_count; /* number of lines */
static colnr_T redo_VIsual_vcol; /* number of cols or end column */ static colnr_T redo_VIsual_vcol; /* number of cols or end column */
static long redo_VIsual_count; /* count for Visual operator */ static long redo_VIsual_count; /* count for Visual operator */
static int redo_VIsual_arg; /* extra argument */
#ifdef FEAT_VIRTUALEDIT #ifdef FEAT_VIRTUALEDIT
int include_line_break = FALSE; int include_line_break = FALSE;
#endif #endif
@ -1699,6 +1699,7 @@ do_pending_operator(cap, old_col, gui_yank)
redo_VIsual_vcol = resel_VIsual_vcol; redo_VIsual_vcol = resel_VIsual_vcol;
redo_VIsual_line_count = resel_VIsual_line_count; redo_VIsual_line_count = resel_VIsual_line_count;
redo_VIsual_count = cap->count0; 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); oap->op_type == OP_FOLDDELREC, oap->is_VIsual);
break; break;
#endif #endif
case OP_NR_ADD:
case OP_NR_SUB:
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: default:
clearopbeep(oap); clearopbeep(oap);
} }
@ -3602,43 +3621,6 @@ find_ident_at_pos(wp, lnum, startcol, string, find_type)
return col; return col;
} }
/*
* 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);
AppendCharToRedobuff(' ');
}
}
AppendNumberToRedobuff(cap->count1);
}
/* /*
* Prepare for redo of a normal command. * Prepare for redo of a normal command.
*/ */
@ -4243,30 +4225,16 @@ nv_help(cap)
nv_addsub(cap) nv_addsub(cap)
cmdarg_T *cap; cmdarg_T *cap;
{ {
int visual = VIsual_active; if (!VIsual_active && cap->oap->op_type == OP_NOP)
if (cap->oap->op_type == OP_NOP
&& do_addsub((int)cap->cmdchar, cap->count1, cap->arg) == OK)
{ {
if (visual) cap->oap->op_type = cap->cmdchar == Ctrl_A ? OP_NR_ADD : OP_NR_SUB;
{ op_addsub(cap->oap, cap->count1, cap->arg);
prep_redo_visual(cap); cap->oap->op_type = OP_NOP;
if (cap->arg)
AppendCharToRedobuff('g');
AppendCharToRedobuff(cap->cmdchar);
} }
else if (VIsual_active)
nv_operator(cap);
else else
prep_redo_cmd(cap); clearop(cap->oap);
}
else
clearopbeep(cap->oap);
if (visual)
{
VIsual_active = FALSE;
redo_VIsual_busy = FALSE;
may_clear_cmdline();
redraw_later(INVERTED);
}
} }
/* /*
@ -7924,6 +7892,7 @@ nv_g_cmd(cap)
{ {
cap->arg = TRUE; cap->arg = TRUE;
cap->cmdchar = cap->nchar; cap->cmdchar = cap->nchar;
cap->nchar = NUL;
nv_addsub(cap); nv_addsub(cap);
} }
else else

303
src/ops.c
View File

@ -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)); static char_u *skip_comment __ARGS((char_u *line, int process, int include_space, int *is_comment));
#endif #endif
static void block_prep __ARGS((oparg_T *oap, struct block_def *, linenr_T, int)); 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) #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)); static void str_to_reg __ARGS((struct yankreg *y_ptr, int yank_type, char_u *str, long len, long blocklen, int str_list));
#endif #endif
@ -158,6 +159,8 @@ static char opchars[][3] =
{'z', 'D', TRUE}, /* OP_FOLDDELREC */ {'z', 'D', TRUE}, /* OP_FOLDDELREC */
{'g', 'w', TRUE}, /* OP_FORMAT2 */ {'g', 'w', TRUE}, /* OP_FORMAT2 */
{'g', '@', FALSE}, /* OP_FUNCTION */ {'g', '@', FALSE}, /* OP_FUNCTION */
{Ctrl_A, NUL, FALSE}, /* OP_NR_ADD */
{Ctrl_X, NUL, FALSE}, /* OP_NR_SUB */
}; };
/* /*
@ -175,6 +178,10 @@ get_op_type(char1, char2)
return OP_REPLACE; return OP_REPLACE;
if (char1 == '~') /* when tilde is an operator */ if (char1 == '~') /* when tilde is an operator */
return OP_TILDE; return OP_TILDE;
if (char1 == 'g' && char2 == Ctrl_A) /* add */
return OP_NR_ADD;
if (char1 == 'g' && char2 == Ctrl_X) /* subtract */
return OP_NR_SUB;
for (i = 0; ; ++i) for (i = 0; ; ++i)
if (opchars[i][0] == char1 && opchars[i][1] == char2) if (opchars[i][0] == char1 && opchars[i][1] == char2)
break; break;
@ -5340,16 +5347,131 @@ block_prep(oap, bdp, lnum, is_del)
} }
/* /*
* add or subtract 'Prenum1' from a number in a line * Handle the add/subtract operator.
* 'command' is CTRL-A for add, CTRL-X for subtract
*
* return FAIL for failure, OK otherwise
*/ */
int void
do_addsub(command, Prenum1, g_cmd) op_addsub(oap, Prenum1, g_cmd)
int command; oparg_T *oap;
linenr_T Prenum1; linenr_T Prenum1; /* Amount of add/subtract */
int g_cmd; /* was g<c-a>/g<c-x> */ int g_cmd; /* was g<c-a>/g<c-x> */
{
pos_T pos;
struct block_def bd;
int change_cnt = 0;
linenr_T amount = Prenum1;
if (!VIsual_active)
{
pos = curwin->w_cursor;
if (u_save_cursor() == FAIL)
return;
change_cnt = do_addsub(oap->op_type, &pos, 0, amount);
if (change_cnt)
changed_lines(pos.lnum, 0, pos.lnum + 1, 0L);
}
else
{
int one_change;
int length;
pos_T startpos;
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);
if (one_change)
{
/* Remember the start position of the first change. */
if (change_cnt == 0)
startpos = curbuf->b_op_start;
++change_cnt;
}
#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 (change_cnt)
changed_lines(oap->start.lnum, 0, oap->end.lnum + 1, 0L);
if (!change_cnt && oap->is_VIsual)
/* No change: need to remove the Visual selection */
redraw_curbuf_later(INVERTED);
/* Set '[ mark if something changed. Keep the last end
* position from do_addsub(). */
if (change_cnt > 0)
curbuf->b_op_start = startpos;
if (change_cnt > p_report)
{
if (change_cnt == 1)
MSG(_("1 line changed"));
else
smsg((char_u *)_("%ld lines changed"), change_cnt);
}
}
}
/*
* Add or subtract 'Prenum1' from a number in a line
* op_type is OP_NR_ADD or OP_NR_SUB
*
* Returns TRUE if some character was changed.
*/
static int
do_addsub(op_type, pos, length, Prenum1)
int op_type;
pos_T *pos;
int length;
linenr_T Prenum1;
{ {
int col; int col;
char_u *buf1; char_u *buf1;
@ -5357,11 +5479,9 @@ do_addsub(command, Prenum1, g_cmd)
int pre; /* 'X'/'x': hex; '0': octal; 'B'/'b': bin */ int pre; /* 'X'/'x': hex; '0': octal; 'B'/'b': bin */
static int hexupper = FALSE; /* 0xABC */ static int hexupper = FALSE; /* 0xABC */
unsigned long n; unsigned long n;
unsigned long offset = 0; /* line offset for Ctrl_V mode */
long_u oldn; long_u oldn;
char_u *ptr; char_u *ptr;
int c; int c;
int length = 0; /* character length of the number */
int todel; int todel;
int dohex; int dohex;
int dooct; int dooct;
@ -5372,16 +5492,9 @@ do_addsub(command, Prenum1, g_cmd)
int negative = FALSE; int negative = FALSE;
int was_positive = TRUE; int was_positive = TRUE;
int visual = VIsual_active; 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; int did_change = FALSE;
pos_T t = curwin->w_cursor; pos_T t = curwin->w_cursor;
int maxlen = 0; int maxlen = 0;
int pos = 0;
int bit = 0;
int bits = sizeof(unsigned long) * 8;
pos_T startpos; pos_T startpos;
pos_T endpos; pos_T endpos;
@ -5390,50 +5503,18 @@ do_addsub(command, Prenum1, g_cmd)
dobin = (vim_strchr(curbuf->b_p_nf, 'b') != NULL); /* "Bin" */ dobin = (vim_strchr(curbuf->b_p_nf, 'b') != NULL); /* "Bin" */
doalp = (vim_strchr(curbuf->b_p_nf, 'p') != NULL); /* "alPha" */ 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". * 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);
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();
if (dobin) if (dobin)
while (col > 0 && vim_isbdigit(ptr[col])) while (col > 0 && vim_isbdigit(ptr[col]))
--col; --col;
@ -5453,7 +5534,7 @@ do_addsub(command, Prenum1, g_cmd)
/* In case of binary/hexadecimal pattern overlap match, rescan */ /* In case of binary/hexadecimal pattern overlap match, rescan */
col = curwin->w_cursor.col; col = pos->col;
while (col > 0 && vim_isdigit(ptr[col])) while (col > 0 && vim_isdigit(ptr[col]))
col--; col--;
@ -5480,7 +5561,7 @@ do_addsub(command, Prenum1, g_cmd)
/* /*
* Search forward and then backward to find the start of number. * Search forward and then backward to find the start of number.
*/ */
col = curwin->w_cursor.col; col = pos->col;
while (ptr[col] != NUL while (ptr[col] != NUL
&& !vim_isdigit(ptr[col]) && !vim_isdigit(ptr[col])
@ -5494,64 +5575,40 @@ do_addsub(command, Prenum1, g_cmd)
} }
} }
for (i = lnum; i <= lnume; i++)
{
colnr_T stop = 0;
t = curwin->w_cursor;
curwin->w_cursor.lnum = i;
ptr = ml_get_curline();
if ((int)STRLEN(ptr) <= col)
/* try again on next line */
continue;
if (visual) if (visual)
{ {
if (VIsual_mode == 'v' while (ptr[col] != NUL && length > 0
&& i == lnume)
stop = curwin->w_cursor.col;
else if (VIsual_mode == Ctrl_V
&& curbuf->b_visual.vi_curswant != MAXCOL)
stop = curwin->w_cursor.col;
while (ptr[col] != NUL
&& !vim_isdigit(ptr[col]) && !vim_isdigit(ptr[col])
&& !(doalp && ASCII_ISALPHA(ptr[col]))) && !(doalp && ASCII_ISALPHA(ptr[col])))
{ {
if (col > 0 && col == stop)
break;
++col; ++col;
--length;
} }
if (col > startcol && ptr[col - 1] == '-') if (length == 0)
goto theend;
if (col > pos->col && ptr[col - 1] == '-')
{ {
negative = TRUE; negative = TRUE;
was_positive = FALSE; was_positive = FALSE;
} }
} }
/* /*
* If a number was found, and saving for undo works, replace the number. * If a number was found, and saving for undo works, replace the number.
*/ */
firstdigit = ptr[col]; firstdigit = ptr[col];
if ((!VIM_ISDIGIT(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit))) if (!VIM_ISDIGIT(firstdigit) && !(doalp && ASCII_ISALPHA(firstdigit)))
|| u_save_cursor() != OK)
{ {
if (lnum < lnume)
{
if (visual && VIsual_mode != Ctrl_V)
col = 0;
else
col = startcol;
/* Try again on next line */
continue;
}
beep_flush(); beep_flush();
return FAIL; goto theend;
} }
if (doalp && ASCII_ISALPHA(firstdigit)) if (doalp && ASCII_ISALPHA(firstdigit))
{ {
/* decrement or increment alphabetic character */ /* decrement or increment alphabetic character */
if (command == Ctrl_X) if (op_type == OP_NR_SUB)
{ {
if (CharOrd(firstdigit) < Prenum1) if (CharOrd(firstdigit) < Prenum1)
{ {
@ -5602,22 +5659,9 @@ do_addsub(command, Prenum1, g_cmd)
} }
/* get the number value (unsigned) */ /* get the number value (unsigned) */
if (visual && VIsual_mode != 'V') 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 maxlen = (curbuf->b_visual.vi_curswant == MAXCOL
? (int)STRLEN(ptr) - col ? (int)STRLEN(ptr) - col
: curwin->w_cursor.col - col + 1); : length);
}
vim_str2nr(ptr + col, &pre, &length, vim_str2nr(ptr + col, &pre, &length,
0 + (dobin ? STR2NR_BIN : 0) 0 + (dobin ? STR2NR_BIN : 0)
@ -5632,10 +5676,9 @@ do_addsub(command, Prenum1, g_cmd)
--length; --length;
negative = FALSE; negative = FALSE;
} }
/* add or subtract */ /* add or subtract */
subtract = FALSE; subtract = FALSE;
if (command == Ctrl_X) if (op_type == OP_NR_SUB)
subtract ^= TRUE; subtract ^= TRUE;
if (negative) if (negative)
subtract ^= TRUE; subtract ^= TRUE;
@ -5645,7 +5688,6 @@ do_addsub(command, Prenum1, g_cmd)
n -= (unsigned long)Prenum1; n -= (unsigned long)Prenum1;
else else
n += (unsigned long)Prenum1; n += (unsigned long)Prenum1;
/* handle wraparound for decimal numbers */ /* handle wraparound for decimal numbers */
if (!pre) if (!pre)
{ {
@ -5677,7 +5719,6 @@ do_addsub(command, Prenum1, g_cmd)
length++; length++;
} }
/* /*
* Delete the old number. * Delete the old number.
*/ */
@ -5687,7 +5728,6 @@ do_addsub(command, Prenum1, g_cmd)
did_change = TRUE; did_change = TRUE;
todel = length; todel = length;
c = gchar_cursor(); c = gchar_cursor();
/* /*
* Don't include the '-' in the length, only the length of the * Don't include the '-' in the length, only the length of the
* part after it is kept the same. * part after it is kept the same.
@ -5715,7 +5755,7 @@ do_addsub(command, Prenum1, g_cmd)
*/ */
buf1 = alloc((unsigned)length + NUMBUFLEN); buf1 = alloc((unsigned)length + NUMBUFLEN);
if (buf1 == NULL) if (buf1 == NULL)
return FAIL; goto theend;
ptr = buf1; ptr = buf1;
if (negative && (!visual || (visual && was_positive))) if (negative && (!visual || (visual && was_positive)))
{ {
@ -5738,14 +5778,18 @@ do_addsub(command, Prenum1, g_cmd)
*/ */
if (pre == 'b' || pre == 'B') if (pre == 'b' || pre == 'B')
{ {
int i;
int bit = 0;
int bits = sizeof(unsigned long) * 8;
/* leading zeros */ /* leading zeros */
for (bit = bits; bit > 0; bit--) for (bit = bits; bit > 0; bit--)
if ((n >> (bit - 1)) & 0x1) break; if ((n >> (bit - 1)) & 0x1) break;
for (pos = 0; bit > 0; bit--) for (i = 0; bit > 0; bit--)
buf2[pos++] = ((n >> (bit - 1)) & 0x1) ? '1' : '0'; buf2[i++] = ((n >> (bit - 1)) & 0x1) ? '1' : '0';
buf2[pos] = '\0'; buf2[i] = '\0';
} }
else if (pre == 0) else if (pre == 0)
sprintf((char *)buf2, "%lu", n); sprintf((char *)buf2, "%lu", n);
@ -5771,31 +5815,13 @@ do_addsub(command, Prenum1, g_cmd)
ins_str(buf1); /* insert the new number */ ins_str(buf1); /* insert the new number */
vim_free(buf1); vim_free(buf1);
endpos = curwin->w_cursor; endpos = curwin->w_cursor;
if (lnum < lnume) if (did_change && curwin->w_cursor.col)
curwin->w_cursor.col = t.col;
else if (did_change && curwin->w_cursor.col)
--curwin->w_cursor.col; --curwin->w_cursor.col;
} }
if (g_cmd) theend:
{
offset = (unsigned long)Prenum1;
g_cmd = 0;
}
/* reset */
subtract = FALSE;
negative = FALSE;
was_positive = TRUE;
if (visual && VIsual_mode == Ctrl_V)
col = startcol;
else
col = 0;
Prenum1 += offset;
curwin->w_set_curswant = TRUE;
}
if (visual) if (visual)
/* cursor at the top of the selection */ curwin->w_cursor = t;
curwin->w_cursor = VIsual;
if (did_change) if (did_change)
{ {
/* set the '[ and '] marks */ /* set the '[ and '] marks */
@ -5804,7 +5830,8 @@ do_addsub(command, Prenum1, g_cmd)
if (curbuf->b_op_end.col > 0) if (curbuf->b_op_end.col > 0)
--curbuf->b_op_end.col; --curbuf->b_op_end.col;
} }
return OK;
return did_change;
} }
#ifdef FEAT_VIMINFO #ifdef FEAT_VIMINFO

View File

@ -43,7 +43,7 @@ void op_formatexpr __ARGS((oparg_T *oap));
int fex_format __ARGS((linenr_T lnum, long count, int c)); int fex_format __ARGS((linenr_T lnum, long count, int c));
void format_lines __ARGS((linenr_T line_count, int avoid_fex)); void format_lines __ARGS((linenr_T line_count, int avoid_fex));
int paragraph_start __ARGS((linenr_T lnum)); 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)); int read_viminfo_register __ARGS((vir_T *virp, int force));
void write_viminfo_registers __ARGS((FILE *fp)); void write_viminfo_registers __ARGS((FILE *fp));
void x11_export_final_selection __ARGS((void)); void x11_export_final_selection __ARGS((void));

View File

@ -133,7 +133,7 @@ func Test_visual_increment_04()
exec "norm! vf-\<C-A>" exec "norm! vf-\<C-A>"
call assert_equal(["foobar-10"], getline(1, '$')) call assert_equal(["foobar-10"], getline(1, '$'))
" NOTE: I think this is correct behavior... " NOTE: I think this is correct behavior...
"call assert_equal([0, 1, 1, 0], getpos('.')) call assert_equal([0, 1, 1, 0], getpos('.'))
endfunc endfunc
" 5) g<Ctrl-A> on letter " 5) g<Ctrl-A> on letter
@ -576,7 +576,111 @@ func Test_visual_increment_27()
endif endif
endfunc endfunc
" 28) block-wise increment and dot-repeat " Tab code and linewise-visual inc/dec
func Test_visual_increment_28()
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_29()
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_30()
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_31()
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_32()
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_33()
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_34()
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_35()
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_36()
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, 1, 0], getpos('.'))
exec "norm! ..."
call assert_equal([" 123", "\<TAB>856789"], getline(1, '$'))
call assert_equal([0, 1, 1, 0], getpos('.'))
endfunc
" block-wise increment and dot-repeat
" Text: " Text:
" 1 23 " 1 23
" 4 56 " 4 56
@ -587,7 +691,7 @@ endfunc
" 4 59 " 4 59
" "
" Try with and without indent. " Try with and without indent.
func Test_visual_increment_28() func Test_visual_increment_37()
call setline(1, [" 1 23", " 4 56"]) call setline(1, [" 1 23", " 4 56"])
exec "norm! ggf2\<C-V>jl\<C-A>.." exec "norm! ggf2\<C-V>jl\<C-A>.."
call assert_equal([" 1 26", " 4 59"], getline(1, 2)) call assert_equal([" 1 26", " 4 59"], getline(1, 2))

View File

@ -741,6 +741,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
1087,
/**/ /**/
1086, 1086,
/**/ /**/

View File

@ -1457,6 +1457,10 @@ typedef UINT32_TYPEDEF UINT32_T;
#define OP_FOLDDELREC 25 /* "zD" delete folds recursively */ #define OP_FOLDDELREC 25 /* "zD" delete folds recursively */
#define OP_FORMAT2 26 /* "gw" format operator, keeps cursor pos */ #define OP_FORMAT2 26 /* "gw" format operator, keeps cursor pos */
#define OP_FUNCTION 27 /* "g@" call 'operatorfunc' */ #define OP_FUNCTION 27 /* "g@" call 'operatorfunc' */
#define OP_NR_ADD 28 /* "<C-A>" Add to the number or alphabetic
character (OP_ADD conflicts with Perl) */
#define OP_NR_SUB 29 /* "<C-X>" Subtract from the number or
alphabetic character */
/* /*
* Motion types, used for operators and for yank/delete registers. * Motion types, used for operators and for yank/delete registers.