Here is another update, that fixes the problem, that vim_str2nr always
checks all available chars for numbers, making it impossible to select
less numbers.
Best,
Christian
--
"Was nun die Menschen gesetzt haben, das will nicht passen, es
mag recht oder unrecht sein; was aber die Götter setzen, das ist
immer am Platz, recht oder unrecht."
-- Goethe, Maximen und Reflektionen, Nr. 104
--
--
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/charset.c b/src/charset.c
--- a/src/charset.c
+++ b/src/charset.c
@@ -1835,9 +1835,10 @@ vim_isblankline(lbuf)
* octal number.
* If "dohex" is non-zero recognize hex numbers, when > 1 always assume
* hex number.
+ * If strlen > 0, check at a maximum strlen chars
*/
void
-vim_str2nr(start, hexp, len, dooct, dohex, nptr, unptr)
+vim_str2nr(start, hexp, len, dooct, dohex, nptr, unptr, strlen)
char_u *start;
int *hexp; /* return: type of number 0 = decimal, 'x'
or 'X' is hex, '0' = octal */
@@ -1846,6 +1847,7 @@ vim_str2nr(start, hexp, len, dooct, dohe
int dohex; /* recognize hex number */
long *nptr; /* return: signed result */
unsigned long *unptr; /* return: unsigned result */
+ int strlen; /* length of string to check */
{
char_u *ptr = start;
int hex = 0; /* default is decimal */
@@ -1880,6 +1882,8 @@ vim_str2nr(start, hexp, len, dooct, dohe
}
if (ptr[n] >= '0')
hex = '0'; /* assume octal */
+ if (n == strlen)
+ break;
}
}
}
@@ -1888,6 +1892,7 @@ vim_str2nr(start, hexp, len, dooct, dohe
/*
* Do the string-to-numeric conversion "manually" to avoid sscanf quirks.
*/
+ n = 1;
if (hex == '0' || dooct > 1)
{
/* octal */
@@ -1895,6 +1900,8 @@ vim_str2nr(start, hexp, len, dooct, dohe
{
un = 8 * un + (unsigned long)(*ptr - '0');
++ptr;
+ if (n++ == strlen)
+ break;
}
}
else if (hex != 0 || dohex > 1)
@@ -1904,6 +1911,8 @@ vim_str2nr(start, hexp, len, dooct, dohe
{
un = 16 * un + (unsigned long)hex2nr(*ptr);
++ptr;
+ if (n++ == strlen)
+ break;
}
}
else
@@ -1913,6 +1922,8 @@ vim_str2nr(start, hexp, len, dooct, dohe
{
un = 10 * un + (unsigned long)(*ptr - '0');
++ptr;
+ if (n++ == strlen)
+ break;
}
}
diff --git a/src/eval.c b/src/eval.c
--- a/src/eval.c
+++ b/src/eval.c
@@ -1612,7 +1612,7 @@ call_vim_function(func, argc, argv, safe
len = 0;
else
/* Recognize a number argument, the others must be strings. */
- vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL);
+ vim_str2nr(argv[i], NULL, &len, TRUE, TRUE, &n, NULL, 0);
if (len != 0 && len == (int)STRLEN(argv[i]))
{
argvars[i].v_type = VAR_NUMBER;
@@ -5125,7 +5125,7 @@ eval7(arg, rettv, evaluate, want_string)
else
#endif
{
- vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL);
+ vim_str2nr(*arg, NULL, &len, TRUE, TRUE, &n, NULL, 0);
*arg += len;
if (evaluate)
{
@@ -18230,7 +18230,7 @@ f_str2nr(argvars, rettv)
p = skipwhite(get_tv_string(&argvars[0]));
if (*p == '+')
p = skipwhite(p + 1);
- vim_str2nr(p, NULL, NULL, base == 8 ? 2 : 0, base == 16 ? 2 : 0, &n, NULL);
+ vim_str2nr(p, NULL, NULL, base == 8 ? 2 : 0, base == 16 ? 2 : 0, &n, NULL, 0);
rettv->vval.v_number = n;
}
@@ -21007,7 +21007,7 @@ get_tv_number_chk(varp, denote)
case VAR_STRING:
if (varp->vval.v_string != NULL)
vim_str2nr(varp->vval.v_string, NULL, NULL,
- TRUE, TRUE, &n, NULL);
+ TRUE, TRUE, &n, NULL, 0);
return n;
case VAR_LIST:
EMSG(_("E745: Using a List as a Number"));
diff --git a/src/ex_cmds.c b/src/ex_cmds.c
--- a/src/ex_cmds.c
+++ b/src/ex_cmds.c
@@ -500,7 +500,7 @@ ex_sort(eap)
nrs[lnum - eap->line1].start_col_nr = -MAXLNUM;
else
vim_str2nr(s, NULL, NULL, sort_oct, sort_hex,
- &nrs[lnum - eap->line1].start_col_nr, NULL);
+ &nrs[lnum - eap->line1].start_col_nr, NULL, 0);
*s2 = c;
}
else
diff --git a/src/ex_getln.c b/src/ex_getln.c
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -5917,7 +5917,7 @@ get_list_range(str, num1, num2)
*str = skipwhite(*str);
if (**str == '-' || vim_isdigit(**str)) /* parse "from" part of range */
{
- vim_str2nr(*str, NULL, &len, FALSE, FALSE, &num, NULL);
+ vim_str2nr(*str, NULL, &len, FALSE, FALSE, &num, NULL, 0);
*str += len;
*num1 = (int)num;
first = TRUE;
@@ -5926,7 +5926,7 @@ get_list_range(str, num1, num2)
if (**str == ',') /* parse "to" part of range */
{
*str = skipwhite(*str + 1);
- vim_str2nr(*str, NULL, &len, FALSE, FALSE, &num, NULL);
+ vim_str2nr(*str, NULL, &len, FALSE, FALSE, &num, NULL, 0);
if (len > 0)
{
*num2 = (int)num;
diff --git a/src/misc2.c b/src/misc2.c
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -2813,7 +2813,7 @@ find_special_key(srcp, modp, keycode, ke
bp += 3; /* skip t_xx, xx may be '-' or '>' */
else if (STRNICMP(bp, "char-", 5) == 0)
{
- vim_str2nr(bp + 5, NULL, &l, TRUE, TRUE, NULL, NULL);
+ vim_str2nr(bp + 5, NULL, &l, TRUE, TRUE, NULL, NULL, 0);
bp += l + 5;
break;
}
@@ -2845,7 +2845,7 @@ find_special_key(srcp, modp, keycode, ke
&& VIM_ISDIGIT(last_dash[6]))
{
/* <Char-123> or <Char-033> or <Char-0x33> */
- vim_str2nr(last_dash + 6, NULL, NULL, TRUE, TRUE, NULL, &n);
+ vim_str2nr(last_dash + 6, NULL, NULL, TRUE, TRUE, NULL, &n, 0);
key = (int)n;
}
else
diff --git a/src/normal.c b/src/normal.c
--- a/src/normal.c
+++ b/src/normal.c
@@ -4204,7 +4204,24 @@ nv_addsub(cap)
int visual = VIsual_active;
if (cap->oap->op_type == OP_NOP
&& do_addsub((int)cap->cmdchar, cap->count1, cap->arg) == OK)
- prep_redo_cmd(cap);
+ {
+ if (visual)
+ {
+ ResetRedobuff();
+ AppendCharToRedobuff(VIsual_mode);
+ if (VIsual_mode == 'V')
+ {
+ AppendNumberToRedobuff(cap->oap->line_count);
+ AppendCharToRedobuff('j');
+ }
+ AppendNumberToRedobuff(cap->count1);
+ if (cap->nchar != NUL)
+ AppendCharToRedobuff(cap->nchar);
+ AppendCharToRedobuff(cap->cmdchar);
+ }
+ else
+ prep_redo_cmd(cap);
+ }
else
clearopbeep(cap->oap);
if (visual)
diff --git a/src/ops.c b/src/ops.c
--- a/src/ops.c
+++ b/src/ops.c
@@ -5386,7 +5386,7 @@ do_addsub(command, Prenum1, g_cmd)
int hex; /* 'X' or 'x': hex; '0': octal */
static int hexupper = FALSE; /* 0xABC */
unsigned long n;
- long offset = 0; /* line offset for Ctrl_V mode */
+ unsigned long offset = 0; /* line offset for Ctrl_V mode */
long_u oldn;
char_u *ptr;
int c;
@@ -5398,10 +5398,13 @@ do_addsub(command, Prenum1, g_cmd)
int firstdigit;
int subtract;
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;
+ pos_T t;
dohex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL); /* "heX" */
dooct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL); /* "Octal" */
@@ -5415,30 +5418,32 @@ do_addsub(command, Prenum1, g_cmd)
{
if (lt(curwin->w_cursor, VIsual))
{
- pos_T t;
t = curwin->w_cursor;
curwin->w_cursor = VIsual;
VIsual = t;
}
- if (VIsual_mode == 'V')
- VIsual.col = 0;
-
ptr = ml_get(VIsual.lnum);
RLADDSUBFIX(ptr);
+ if (VIsual_mode == 'V')
+ {
+ VIsual.col = 0;
+ curwin->w_cursor.col = STRLEN(ptr);
+ }
+
/* 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;
- col = VIsual.col;
+ 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;
- if (ptr[col] == '-')
- {
- negative = TRUE;
- col++;
- }
}
else
{
@@ -5479,11 +5484,19 @@ do_addsub(command, Prenum1, g_cmd)
for (i = lnum; i <= lnume; i++)
{
+ 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 && ptr[col] == '-')
+ {
+ negative = TRUE;
+ was_positive = FALSE;
+ col++;
+ }
RLADDSUBFIX(ptr);
- if ((int)STRLEN(ptr) <= col)
- col = 0;
/*
* If a number was found, and saving for undo works, replace the number.
*/
@@ -5551,7 +5564,8 @@ do_addsub(command, Prenum1, g_cmd)
}
/* get the number value (unsigned) */
- vim_str2nr(ptr + col, &hex, &length, dooct, dohex, NULL, &n);
+ vim_str2nr(ptr + col, &hex, &length, dooct, dohex, NULL, &n,
+ visual ? curwin->w_cursor.col - startcol + 1 : 0);
/* ignore leading '-' for hex and octal numbers */
if (hex && negative)
@@ -5598,6 +5612,14 @@ do_addsub(command, Prenum1, g_cmd)
negative = FALSE;
}
+ if (visual && !was_positive && !negative)
+ {
+ /* need to remove the '-' */
+ col--;
+ length++;
+ }
+
+
/*
* Delete the old number.
*/
@@ -5634,8 +5656,7 @@ do_addsub(command, Prenum1, g_cmd)
if (buf1 == NULL)
return FAIL;
ptr = buf1;
- /* do not add leading '-' for visual mode */
- if (negative && !visual)
+ if (negative && (!visual || (visual && was_positive)))
{
*ptr++ = '-';
}
@@ -5654,23 +5675,15 @@ do_addsub(command, Prenum1, g_cmd)
* Put the number characters in buf2[].
*/
if (hex == 0)
- sprintf((char *)buf2, "%lu", n + offset);
+ sprintf((char *)buf2, "%lu", n);
else if (hex == '0')
- sprintf((char *)buf2, "%lo", n + offset);
+ sprintf((char *)buf2, "%lo", n);
else if (hex && hexupper)
- sprintf((char *)buf2, "%lX", n + offset);
+ sprintf((char *)buf2, "%lX", n);
else
- sprintf((char *)buf2, "%lx", n + offset);
+ sprintf((char *)buf2, "%lx", n);
length -= (int)STRLEN(buf2);
- if (g_cmd)
- {
- if (subtract)
- offset -= (unsigned long)Prenum1;
- else
- offset += (unsigned long)Prenum1;
- }
-
/*
* Adjust number of zeros to the new number of digits, so the
* total length of the number remains the same.
@@ -5684,8 +5697,25 @@ do_addsub(command, Prenum1, g_cmd)
STRCAT(buf1, buf2);
ins_str(buf1); /* insert the new number */
vim_free(buf1);
+ if (lnum < lnume)
+ curwin->w_cursor.col = t.col;
+ else
+ --curwin->w_cursor.col;
}
- --curwin->w_cursor.col;
+
+ if (g_cmd)
+ {
+ offset = (unsigned long)Prenum1;
+ g_cmd = 0;
+ }
+ /* reset */
+ subtract = FALSE;
+ negative = FALSE;
+ if (visual && VIsual_mode != Ctrl_V)
+ col = 0;
+ else
+ col = startcol;
+ Prenum1 += offset;
curwin->w_set_curswant = TRUE;
#ifdef FEAT_RIGHTLEFT
ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE);
diff --git a/src/option.c b/src/option.c
--- a/src/option.c
+++ b/src/option.c
@@ -4561,7 +4561,7 @@ do_set(arg, opt_flags)
{
/* Allow negative (for 'undolevels'), octal and
* hex numbers. */
- vim_str2nr(arg, NULL, &i, TRUE, TRUE, &value, NULL);
+ vim_str2nr(arg, NULL, &i, TRUE, TRUE, &value, NULL, 0);
if (arg[i] != NUL && !vim_iswhite(arg[i]))
{
errmsg = e_invarg;
diff --git a/src/proto/charset.pro b/src/proto/charset.pro
--- a/src/proto/charset.pro
+++ b/src/proto/charset.pro
@@ -49,7 +49,7 @@ char_u *skiptowhite __ARGS((char_u *p));
char_u *skiptowhite_esc __ARGS((char_u *p));
long getdigits __ARGS((char_u **pp));
int vim_isblankline __ARGS((char_u *lbuf));
-void vim_str2nr __ARGS((char_u *start, int *hexp, int *len, int dooct, int dohex, long *nptr, unsigned long *unptr));
+void vim_str2nr __ARGS((char_u *start, int *hexp, int *len, int dooct, int dohex, long *nptr, unsigned long *unptr, int strlen));
int hex2nr __ARGS((int c));
int hexhex2nr __ARGS((char_u *p));
int rem_backslash __ARGS((char_u *str));
diff --git a/src/testdir/test_increment.in b/src/testdir/test_increment.in
--- a/src/testdir/test_increment.in
+++ b/src/testdir/test_increment.in
@@ -6,6 +6,7 @@ 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":
@@ -24,6 +25,7 @@ 20
30
40
+ Expected:
1) Ctrl-A on visually selected lines:
11
21
@@ -46,6 +48,7 @@ 30
40
+ Expected:
1) 2 g Ctrl-A on visually selected lines:
12
@@ -66,24 +69,155 @@ 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
+
STARTTEST
:so small.vim
:" 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
+:/^E1=/+put a
+:/^E1=/+2put a
+f-v$:/^E1=/+3put a
+f1v$:/^E1=/+4put a
+f-v$:/^E1=/+5put a
f1v$
:" Test 22
:/^S2=/+,/^E2=/-y a
-:/^E2/+put a
+:/^E2=/+put a
V3k$:.+put a
V3k$
@@ -98,6 +232,55 @@ V6k2g
:/^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
+:/^S7=/+,/^E7=/-y a
+:/^E7=/+put a
+V4k:.+put a
+V4k
+
+:" Test 8
+:/^S8=/+,/^E8=/-y a
+:/^E8=/+put a
+kj$:.+put a
+k$+
+
+:" Test 9
+:/^S9=/+,/^E9=/-y a
+:/^E9=/+put a
+5kVj22j.
+
+:" 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
+3kf1l2j:.+put a
+3kf1l2j
+
:" Save the report
:/^# Test 1/,$w! test.out
:qa!
@@ -139,5 +322,100 @@ 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====
+
+
+
+
+
+
ENDTEST
diff --git a/src/testdir/test_increment.ok b/src/testdir/test_increment.ok
--- a/src/testdir/test_increment.ok
+++ b/src/testdir/test_increment.ok
@@ -62,5 +62,147 @@ 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
+
+
+
+
+
ENDTEST