On Mo, 12 Feb 2018, Bram Moolenaar wrote:
>
> Christian Brabandt wrote:
>
> > this example throws ml_get errors:
> > ,----
> > | set bs=2
> > | exe "normal a\nabcdefghi\njk\tlmn\n opq rst\n\<C-D>uvwxyz"
> > | call cursor(1,1)
> > | exe "normal gR0\<del> 1\nA\nBCDEFGHIJ\n\tKL\nMNO\nPQR"
> > `----
> >
> > Problem is, that once a linebreak is deleted in virtual replace mode,
> > orig_lines_count is not correctly reset.
> >
> > Here is a patch that fixes that issue and includes a test.
> >
> > diff --git a/src/edit.c b/src/edit.c
> > index 47227d34b..10bfd08a1 100644
> > --- a/src/edit.c
> > +++ b/src/edit.c
> > @@ -8927,7 +8927,17 @@ ins_del(void)
> > || do_join(2, FALSE, TRUE, FALSE, FALSE) == FAIL)
> > vim_beep(BO_BS);
> > else
> > + {
> > curwin->w_cursor.col = temp;
> > +#ifdef FEAT_VREPLACE
> > + if (State & VREPLACE_FLAG)
> > + {
> > + orig_line_count = curbuf->b_ml.ml_line_count;
> > + if (vr_lines_changed > 1)
> > + vr_lines_changed--;
> > + }
> > +#endif
>
> Hmm, I suspect this needs a check whether the cursor is in the first
> changed line or not.
Why would that matter? If the line count changes we need to adjust
orig_line_count or else open_line will throw an error later if adding
new lines (which this patch was trying to fix).
> Compare with the do_join() in ins_bs(), it doesn't adjust vr_lines_changed or
> orig_line_count there.
Wait a second. You are talking about this part here, right:
,----[ ins_bs() ]-
| #ifdef FEAT_VREPLACE
| if (!(State & VREPLACE_FLAG)
| || curwin->w_cursor.lnum >
orig_line_count)
| #endif
| {
| temp = gchar_cursor(); /* remember current char */
| --curwin->w_cursor.lnum;
|
| /* When "aw" is in 'formatoptions' we must delete the space
at
| * the end of the line, otherwise the line will be broken
| * again when auto-formatting. */
| if (has_format_option(FO_AUTO)
| &&
has_format_option(FO_WHITE_PAR))
| {
| char_u *ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum,
|
TRUE);
| int len;
|
| len = (int)STRLEN(ptr);
| if (len > 0 && ptr[len - 1] == ' ')
| ptr[len - 1] = NUL;
| }
|
| (void)do_join(2, FALSE, FALSE, FALSE, FALSE);
| if (temp == NUL && gchar_cursor() != NUL)
| inc_cursor();
| }
| #ifdef FEAT_VREPLACE
| else
| dec_cursor();
| #endif
`----
If I am reading that correctly, this is only done when not in virtual
replace mode (or the current cursor is below orig_line_count, which I
think can only happen if we add lines in virtual replace mode).
So that means, in virtual replace mode pressing <BS> at the beginning of
a line, will only move the cursor (the else part at the bottom).
And indeed this is what happens, it doesn't actually delete the newline,
only if a newline has been added before and the cursor is below the
original line count it will be removed
Take this example, [vim --clean]:
abcd
efgh
ijkl
Now put the cursor on 'e', press gR type 1234\n5<BS><BS><BS>, you will be at:
abcd
123h
ijkl
Note, the new line has not been deleted.
However with this:
abcd
efgh
ijkl
Put the cursor on 'e', press gR type 1234\n\n56<BS><BS><BS>
abcd
1234
ijkl
Note: the second newline has actually been deleted.
> It is used to decide whether or not to save the next line for undo.
> this is in open_line(). Perhaps you can make a test case that enters NL
> in virtual replace mode, then DEL to join the next line, then enters NL
> again, check if undo still works as expected.
That sounds like a good idea. Will amend the test and I should also add
the test case from above (about deleting lines in virtual replace
mode....)
Best,
Christian
--
Der Scharfsinn verlässt geistreiche Männer am wenigsten, wenn
sie unrecht haben.
-- Goethe, Maximen und Reflektionen, Nr. 766
--
--
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.