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 vim_dev+unsubscr...@googlegroups.com.
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),

Raspunde prin e-mail lui