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 */ -- -- 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 Wed Nov 13 23:54:13 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') @@ -1797,10 +1794,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),
diff -r 34a3b852ec05 src/search.c --- a/src/search.c Tue Nov 12 18:09:29 2013 +0100 +++ b/src/search.c Thu Nov 14 00:10:51 2013 +0100 @@ -4543,8 +4543,10 @@ /* Is the pattern is zero-width? */ one_char = is_one_char(spats[last_idx].pat); - if (one_char == -1) - return FAIL; /* invalid pattern */ + if (one_char == -1) { + p_ws = old_p_ws; + return FAIL; /* pattern not found */ + } /* * The trick is to first search backwards and then search forward again,