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),