On Thursday, November 14, 2013 12:23:03 AM UTC+1, Christian Wellenbrock wrote:
> On Monday, August 12, 2013 9:22:21 PM UTC+2, Christian Brabandt wrote:
> > On Do, 08 Aug 2013, Dimitar DIMITROV wrote:
> >
> >
> >
> > > As per the subject :)
> >
> >
> >
> > Can you check, whether the attached patch fixes it for you?
> >
> >
> >
> > regards,
> >
> > Christian
> >
> > --
> >
> > Was die Welt in diesem Augenblick sucht, ist viel weniger ein
> >
> > Gleichgewicht als eine Sprache.
> >
> > -- Jean Giraudoux
>
> I'd like to bring this up again. I was surprised that `gUgn` wasn't
> repeatable and took a dive into the code. I solved it in a different way and
> found this topic while I wanted to submit my patch.
>
> I discovered that the `gn` command used the `redobuff` in a differend way [1]
> than most commands. The command `dgn` would write `gnd` to the `redobuff`
> instead of the more natuaral `dgn`. To make redo work, there was some special
> code [2] needed to read the `d` after `gn` to issue the deletion.
>
> This breaks when using two character operators. The command `gUgn` writes
> `gngU` to the stuffbuff. The `.` command would now only get one extra char
> after `gn`, leading to the repeated command `gng`, which does nothing.
>
> Getting another extra char in that case would probably work, but instead I
> tried to reverse the `redobuff`. Instead of `gngU` from [1] I wrote `gUgn` to
> the `stuffbuff` and suddenly everything worked. When repeated, the `gU`
> command pends, `gn` selects the next match and the pending operator makes it
> uppercase.
>
> After that I could remove the special behavior mentioned in [2].
>
> Here is a small test case to demonstrate the difference. The following vim
> invocation inserts "vim vim", searches for "vim", uppercases the first match,
> but fails to uppercase the second match upon repetition. Result: "VIM vim"
>
> ./vim -c ':exe "norm 2Ivim \<Esc>x#gUgn."'
>
> The same invocation with the attached `gugn_repeat.patch` applied, yields the
> expected "VIM VIM".
>
>
> Bonus: In the `gn` implementation `current_search` there is an early return
> [3] that doesn't restore the 'wrapscan' option. This happens when the search
> pattern cannot be found.
>
> So after you deleted all occurences of a pattern by repeating `dgn`, the
> 'nowrapscan' option will remain set. I fixed this by restoring 'wrapscan'
> before returning.
>
> Test case: Start vim with this invocation and execute the ex command `:set
> ws?` to verify that 'nowrapscan' is set.
>
> ./vim -c ':let @/="a"|norm "dgn"'
>
> The same invocation with the attached `gn_wrapscan.patch` applied, still has
> 'wrapscan' set as expected.
>
>
> @ Christian Brabandt: Was there any intention in the reversed `stuffbuff`
> order that I might have missed?
>
>
> [1] normal.c
> 1800 /* "gn" and "gN" are a bit different */
> 1801 prep_redo(oap->regname, 0L, NUL, cap->cmdchar,
> cap->nchar,
> 1802 get_op_char(oap->op_type),
> 1803 get_extra_op_char(oap->op_type));
>
> [2] normal.c
> 965 /* For "gn" from redo, need to get one more char to
> determine the
> 966 * operator */
> 967 if (ca.nchar == 'r' || ca.nchar == '\'' || ca.nchar == '`'
> 968 || ca.nchar ==
> Ctrl_BSL
> 969 || ((ca.nchar == 'n' || ca.nchar == 'N') &&
> !stuff_empty()))
>
> [3] search.c
> 4544 /* Is the pattern is zero-width? */
> 4545 one_char = is_one_char(spats[last_idx].pat);
> 4546 if (one_char == -1)
> 4547 return FAIL; /* invalid pattern */
Small update: There is some more special `gn` code [1] that can be removed
after changing the `stuffbuff` order. Find updated patch attached.
[1] normal.c
1091 else if ((ca.nchar == 'n' || ca.nchar == 'N') && ca.cmdchar ==
'g')
1092 ca.oap->op_type = get_op_type(*cp, NUL);
--
--
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/groups/opt_out.
diff -r 34a3b852ec05 src/normal.c
--- a/src/normal.c Tue Nov 12 18:09:29 2013 +0100
+++ b/src/normal.c Thu Nov 14 00:33:06 2013 +0100
@@ -962,11 +962,8 @@
#ifdef FEAT_CMDL_INFO
need_flushbuf |= add_to_showcmd(ca.nchar);
#endif
- /* For "gn" from redo, need to get one more char to determine the
- * operator */
if (ca.nchar == 'r' || ca.nchar == '\'' || ca.nchar == '`'
- || ca.nchar == Ctrl_BSL
- || ((ca.nchar == 'n' || ca.nchar == 'N') && !stuff_empty()))
+ || ca.nchar == Ctrl_BSL)
{
cp = &ca.extra_char; /* need to get a third character */
if (ca.nchar != 'r')
@@ -1088,8 +1085,6 @@
ca.nchar = ca.extra_char;
idx = find_command(ca.cmdchar);
}
- else if ((ca.nchar == 'n' || ca.nchar == 'N') && ca.cmdchar == 'g')
- ca.oap->op_type = get_op_type(*cp, NUL);
else if (*cp == Ctrl_BSL)
{
long towait = (p_ttm >= 0 ? p_ttm : p_tm);
@@ -1797,10 +1792,9 @@
* otherwise it might be the second char of the operator. */
if (cap->cmdchar == 'g' && (cap->nchar == 'n'
|| cap->nchar == 'N'))
- /* "gn" and "gN" are a bit different */
- prep_redo(oap->regname, 0L, NUL, cap->cmdchar, cap->nchar,
- get_op_char(oap->op_type),
- get_extra_op_char(oap->op_type));
+ prep_redo(oap->regname, cap->count0,
+ get_op_char(oap->op_type), get_extra_op_char(oap->op_type),
+ oap->motion_force, cap->cmdchar, cap->nchar);
else if (cap->cmdchar != ':')
prep_redo(oap->regname, 0L, NUL, 'v',
get_op_char(oap->op_type),