Hi Urtica!
On Mo, 29 Jun 2015, Urtica dioica wrote:
> > 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.
>
> I'm going from this patch. I've triggered a couple bugs where I couldn't
> figure out how to repeat them. I'll have to keep trying.
>
> 1. The cursor should really end at the top-left, probably at `< (maybe '< for
> line visual, I don't know). This is what you expect from most visual mode
> commands, and it's much more useful for dot-repeat.
>
> This should act on the same area both times, but instead:
Yes, as I said before, the visual region was not correctly restored in
the redo buffer. Should be fixed with the attached patch.
>
> 1
> 1
> --- <C-V>j<C-A>.
> 2
> 3
>
> This should act on the next column over:
>
> 1 1
> 1 1
> --- <C-V>j<C-A>w.
> 2 1
> 2 2
>
> Some of the cursor positions right now are especially silly. Here I insert to
> the end of the line:
>
> 1
> 1
> --- Vj<C-A>ia<Esc>
> 2
> 2a
>
> Or you can crash vim:
>
> 1
> --- YpxVk<C-A>a!
> segmentation fault
>
> Or like this:
>
> 10
> 10
> 10
> --- Vj<C-X>a!
> segmentation fault
Fixed.
>
> 2. The new dot repeat area is glitchy.
>
> You expect visual mode dot repeats to act on a 1v area. This dot repeat
> shrinks the visual area:
See above. Should work now.
>
> 1
> 1
> 1
> 1
> --- Vjj<C-A>gv<C-A>{.gv<C-A>
> 5
> 5
> 3
> 1
>
> It's different in the other visual modes:
>
> 1
> 1
> 1
> --- vjj<C-A>(.
> 3
> 2
> 2
>
> 3. Octal detection in decimal numbers is annoying. I'm not sure I'd call this
> a bug, but it's weird:
>
> 107
> --- lvl<C-A>
> 1010
>
> A real bug, even weirder:
>
> 101
> --- lv<C-A>
> 1011
Yes, that was a bug. Should be fixed now.
>
> 4. It's very picky now about not affecting digits right of the visual area...
> unless hex is detected.
>
> A funny example where the column changed is different in each row, and the
> hex row changes outside of the visual area:
>
> 0x1
> 001
> aaa
> --- :se nf+=alpha<CR><C-V>jjl<C-A>
> 0x2
> 011
> baa
should work now.
>
> 5. It's impossible to increment a series of right-aligned numbers.
>
> 1
> 19
> 119
> --- :%ri3<CR>{<C-V>3e<C-A>
> 1
> 19
> 120
Should work now.
>
> The way I'd expect it to work, it would look for the left-most incrementable
> number in each line, assuming it's inside the visual area. As it is, it
> ignores any line where there's not a number *exactly* aligned to the left
> side.
>
> These numbers are both in the visual area, but only the left-aligned one is
> recognized:
>
> 1=
> =1
> --- <C-V>jl<C-A>
> 2=
> =1
Should work now.
>
> 6. The position of the cursor within identical visual areas still matters.
>
> Similar to the one above:
>
> 1
> 19
> 119
> --- :%ri3<CR>{$<C-V>G<C-A>
> 1
> 19
> 219
Should work now.
> 7. The entire screen is redrawn every time, even for single-line edits that
> affect zero or one characters.
Not sure what you mean. Since one starts visual mode, one needs to
redraw after visual mode ended.
Best,
Christian
--
Hallo Liftbenutzer!
--
--
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 */
@@ -1860,10 +1862,12 @@ vim_str2nr(start, hexp, len, dooct, dohe
}
/* Recognize hex and octal. */
- if (ptr[0] == '0' && ptr[1] != '8' && ptr[1] != '9')
+ if (ptr[0] == '0' && ptr[1] != '8' && ptr[1] != '9' &&
+ (strlen == 0 || strlen > 1))
{
hex = ptr[1];
- if (dohex && (hex == 'X' || hex == 'x') && vim_isxdigit(ptr[2]))
+ if (dohex && (hex == 'X' || hex == 'x') && vim_isxdigit(ptr[2]) &&
+ (strlen == 0 || strlen > 2))
ptr += 2; /* hexadecimal */
else
{
@@ -1880,6 +1884,8 @@ vim_str2nr(start, hexp, len, dooct, dohe
}
if (ptr[n] >= '0')
hex = '0'; /* assume octal */
+ if (n == strlen)
+ break;
}
}
}
@@ -1888,6 +1894,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 +1902,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 +1913,8 @@ vim_str2nr(start, hexp, len, dooct, dohe
{
un = 16 * un + (unsigned long)hex2nr(*ptr);
++ptr;
+ if (n++ == strlen)
+ break;
}
}
else
@@ -1913,6 +1924,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
@@ -1615,7 +1615,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;
@@ -5128,7 +5128,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)
{
@@ -18233,7 +18233,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;
}
@@ -21039,7 +21039,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
@@ -40,6 +40,7 @@ static void find_start_of_word __ARGS((p
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));
@@ -3612,6 +3613,39 @@ find_ident_at_pos(wp, lnum, startcol, st
return col;
}
+/* Add commands to reselect visual mode to redo buffer */
+ static void
+prep_redo_visual(cap)
+ cmdarg_T *cap;
+{
+ ResetRedobuff();
+ AppendCharToRedobuff(VIsual_mode);
+ if (VIsual_mode == 'V')
+ {
+ AppendNumberToRedobuff(curbuf->b_visual.vi_end.lnum -
+ curbuf->b_visual.vi_start.lnum);
+ AppendCharToRedobuff('j');
+ }
+ else
+ {
+ /* 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_end.col == 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.
*/
@@ -4207,14 +4241,7 @@ nv_addsub(cap)
{
if (visual)
{
- ResetRedobuff();
- AppendCharToRedobuff(VIsual_mode);
- if (VIsual_mode == 'V')
- {
- AppendNumberToRedobuff(cap->oap->line_count);
- AppendCharToRedobuff('j');
- }
- AppendNumberToRedobuff(cap->count1);
+ prep_redo_visual(cap);
if (cap->nchar != NUL)
AppendCharToRedobuff(cap->nchar);
AppendCharToRedobuff(cap->cmdchar);
diff --git a/src/ops.c b/src/ops.c
--- a/src/ops.c
+++ b/src/ops.c
@@ -5403,7 +5403,8 @@ do_addsub(command, Prenum1, g_cmd)
int i;
int lnum = curwin->w_cursor.lnum;
int lnume = curwin->w_cursor.lnum;
- int startcol;
+ int startcol = 0;
+ pos_T t = curwin->w_cursor;
dohex = (vim_strchr(curbuf->b_p_nf, 'x') != NULL); /* "heX" */
dooct = (vim_strchr(curbuf->b_p_nf, 'o') != NULL); /* "Octal" */
@@ -5417,16 +5418,24 @@ 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);
+ }
+ 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;
@@ -5481,29 +5490,54 @@ 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();
+ RLADDSUBFIX(ptr);
if ((int)STRLEN(ptr) <= col)
/* try again on next line */
continue;
+ if (visual)
+ {
+ if (doalp) /* search for ascii chars */
+ {
+ while (!ASCII_ISALPHA(ptr[col]) && ptr[col])
+ col++;
+ }
+ /* skip to first digit, but allow for leading '-' */
+ else if (dohex)
+ {
+ while (!(vim_isxdigit(ptr[col]) || (ptr[col] == '-' && vim_isxdigit(ptr[col+1]))) && ptr[col])
+ col++;
+ }
+ else /* decimal */
+ {
+ while (!(vim_isdigit(ptr[col]) || (ptr[col] == '-' && vim_isdigit(ptr[col+1]))) && ptr[col])
+ col++;
+ }
+ }
if (visual && ptr[col] == '-')
{
negative = TRUE;
was_positive = FALSE;
col++;
}
- RLADDSUBFIX(ptr);
/*
* If a number was found, and saving for undo works, replace the number.
*/
firstdigit = ptr[col];
- RLADDSUBFIX(ptr);
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();
return FAIL;
}
@@ -5560,7 +5594,11 @@ do_addsub(command, Prenum1, g_cmd)
}
/* get the number value (unsigned) */
- vim_str2nr(ptr + col, &hex, &length, dooct, dohex, NULL, &n);
+ if (!visual || VIsual_mode == 'V' || (VIsual_mode == 'v' && i > lnum && i < lnume))
+ vim_str2nr(ptr + col, &hex, &length, dooct, dohex, NULL, &n, 0);
+ else
+ vim_str2nr(ptr + col, &hex, &length, dooct, dohex, NULL, &n,
+ curwin->w_cursor.col - startcol + 1);
/* ignore leading '-' for hex and octal numbers */
if (hex && negative)
@@ -5607,7 +5645,7 @@ do_addsub(command, Prenum1, g_cmd)
negative = FALSE;
}
- if (visual && !was_positive && !negative)
+ if (visual && !was_positive && !negative && col > 0)
{
/* need to remove the '-' */
col--;
@@ -5692,6 +5730,10 @@ 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;
}
if (g_cmd)
@@ -5702,6 +5744,7 @@ do_addsub(command, Prenum1, g_cmd)
/* reset */
subtract = FALSE;
negative = FALSE;
+ was_positive = TRUE;
if (visual && VIsual_mode == Ctrl_V)
col = startcol;
else
@@ -5713,7 +5756,9 @@ do_addsub(command, Prenum1, g_cmd)
RLADDSUBFIX(ptr);
#endif
}
- --curwin->w_cursor.col;
+ if (visual)
+ /* cursor at the top of the selection */
+ curwin->w_cursor = VIsual;
return OK;
}
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
@@ -185,6 +185,52 @@ 0 0
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
+
+
STARTTEST
:so small.vim
:"
@@ -200,16 +246,16 @@ f1v$:/^E1=/+4put a
f-v$:/^E1=/+5put a
f1v$
-:" Test 22
+:" Test 2
:/^S2=/+,/^E2=/-y a
:/^E2=/+put a
-V3k$:.+put a
+V3k$3j:.+put a
V3k$
:" Test 3
:/^S3=/+,/^E3=/-y a
:/^E3=/+put a
-V6k2g:.+put a
+V6k2g6j:.+put a
V6k2g
:" Test 4
@@ -229,21 +275,22 @@ v3kg
v3kg
:" Test 7
+:set nrformats&vim
:/^S7=/+,/^E7=/-y a
:/^E7=/+put a
-V4k:.+put a
+V4k4j:.+put a
V4k
:" Test 8
:/^S8=/+,/^E8=/-y a
:/^E8=/+put a
-kj$:.+put a
+kj$j:.+put a
k$+
:" Test 9
:/^S9=/+,/^E9=/-y a
:/^E9=/+put a
-5kVj22j.
+5kVj23j.
:" Test 10
:/^S10=/+,/^E10=/-y a
@@ -260,6 +307,27 @@ 3kf13jg
:/^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
+
:" Save the report
:/^# Test 1/,$w! test.out
:qa!
@@ -384,9 +452,38 @@ 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====
+
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
@@ -184,9 +184,52 @@ 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
ENDTEST