vim-patch:7.4.734

Problem:    ml_get error when using "p" in a Visual selection in the last
            line.
Solution:   Change the behavior at the last line. (Yukihiro Nakadaira)

d009e86826
This commit is contained in:
watiko
2016-02-07 09:58:52 +09:00
parent 84281bf675
commit 4a0e10fb2c
4 changed files with 187 additions and 57 deletions

View File

@@ -1538,9 +1538,11 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
curbuf->b_visual_mode_eval = VIsual_mode; curbuf->b_visual_mode_eval = VIsual_mode;
} }
/* In Select mode, a linewise selection is operated upon like a // In Select mode, a linewise selection is operated upon like a
* characterwise selection. */ // characterwise selection.
if (VIsual_select && VIsual_mode == 'V') { // Special case: gH<Del> deletes the last line.
if (VIsual_select && VIsual_mode == 'V'
&& cap->oap->op_type != OP_DELETE) {
if (lt(VIsual, curwin->w_cursor)) { if (lt(VIsual, curwin->w_cursor)) {
VIsual.col = 0; VIsual.col = 0;
curwin->w_cursor.col = curwin->w_cursor.col =
@@ -1676,20 +1678,15 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
&& (include_line_break || !virtual_op) && (include_line_break || !virtual_op)
) { ) {
oap->inclusive = false; oap->inclusive = false;
/* Try to include the newline, unless it's an operator // Try to include the newline, unless it's an operator
* that works on lines only. */ // that works on lines only.
if (*p_sel != 'o' && !op_on_lines(oap->op_type)) { if (*p_sel != 'o'
if (oap->end.lnum < curbuf->b_ml.ml_line_count) { && !op_on_lines(oap->op_type)
++oap->end.lnum; && oap->end.lnum < curbuf->b_ml.ml_line_count) {
oap->end.lnum++;
oap->end.col = 0; oap->end.col = 0;
oap->end.coladd = 0; oap->end.coladd = 0;
++oap->line_count; oap->line_count++;
} else {
/* Cannot move below the last line, make the op
* inclusive to tell the operation to include the
* line break. */
oap->inclusive = true;
}
} }
} }
} }

View File

@@ -1555,55 +1555,31 @@ int op_delete(oparg_T *oap)
if (gchar_cursor() != NUL) if (gchar_cursor() != NUL)
curwin->w_cursor.coladd = 0; curwin->w_cursor.coladd = 0;
} }
if (oap->op_type == OP_DELETE
&& oap->inclusive (void)del_bytes((long)n, !virtual_op,
&& oap->end.lnum == curbuf->b_ml.ml_line_count oap->op_type == OP_DELETE && !oap->is_VIsual);
&& n > (int)STRLEN(ml_get(oap->end.lnum))) {
/* Special case: gH<Del> deletes the last line. */
del_lines(1L, FALSE);
} else { } else {
(void)del_bytes((long)n, !virtual_op, oap->op_type == OP_DELETE // delete characters between lines
&& !oap->is_VIsual
);
}
} else { /* delete characters between lines */
pos_T curpos; pos_T curpos;
int delete_last_line;
/* save deleted and changed lines for undo */ /* save deleted and changed lines for undo */
if (u_save((linenr_T)(curwin->w_cursor.lnum - 1), if (u_save((linenr_T)(curwin->w_cursor.lnum - 1),
(linenr_T)(curwin->w_cursor.lnum + oap->line_count)) == FAIL) (linenr_T)(curwin->w_cursor.lnum + oap->line_count)) == FAIL)
return FAIL; return FAIL;
delete_last_line = (oap->end.lnum == curbuf->b_ml.ml_line_count); truncate_line(true); // delete from cursor to end of line
truncate_line(TRUE); /* delete from cursor to end of line */
curpos = curwin->w_cursor; /* remember curwin->w_cursor */ curpos = curwin->w_cursor; // remember curwin->w_cursor
++curwin->w_cursor.lnum; curwin->w_cursor.lnum++;
del_lines(oap->line_count - 2, FALSE); del_lines(oap->line_count - 2, false);
if (delete_last_line)
oap->end.lnum = curbuf->b_ml.ml_line_count;
// delete from start of line until op_end
n = (oap->end.col + 1 - !oap->inclusive); n = (oap->end.col + 1 - !oap->inclusive);
if (oap->inclusive && delete_last_line
&& n > (int)STRLEN(ml_get(oap->end.lnum))) {
/* Special case: gH<Del> deletes the last line. */
del_lines(1L, FALSE);
curwin->w_cursor = curpos; /* restore curwin->w_cursor */
if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
} else {
/* delete from start of line until op_end */
curwin->w_cursor.col = 0; curwin->w_cursor.col = 0;
(void)del_bytes((long)n, !virtual_op, oap->op_type == OP_DELETE (void)del_bytes((long)n, !virtual_op,
&& !oap->is_VIsual oap->op_type == OP_DELETE && !oap->is_VIsual);
); curwin->w_cursor = curpos; // restore curwin->w_cursor
curwin->w_cursor = curpos; /* restore curwin->w_cursor */ (void)do_join(2, false, false, false, false);
}
if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
do_join(2, FALSE, FALSE, FALSE, false);
}
} }
} }

View File

@@ -554,7 +554,7 @@ static int included_patches[] = {
737, 737,
736, 736,
// 735 NA // 735 NA
// 734, 734,
// 733, // 733,
732, 732,
// 731 NA // 731 NA

View File

@@ -24,6 +24,20 @@ local function source_user_functions()
]]) ]])
end end
local function put_abc()
source([[
$put ='a'
$put ='b'
$put ='c']])
end
local function define_select_mode_maps()
source([[
snoremap <lt>End> <End>
snoremap <lt>Down> <Down>
snoremap <lt>Del> <Del>]])
end
describe('Visual mode and operator', function() describe('Visual mode and operator', function()
before_each(function() before_each(function()
clear() clear()
@@ -150,4 +164,147 @@ describe('Visual mode and operator', function()
ok ok
ok]]) ok]])
end) end)
describe('characterwise visual mode:', function()
it('replace last line', function()
source([[
$put ='a'
let @" = 'x']])
feed('v$p')
expect([[
x]])
end)
it('delete middle line', function()
put_abc()
feed('kkv$d')
expect([[
b
c]])
end)
it('delete middle two line', function()
put_abc()
feed('kkvj$d')
expect([[
c]])
end)
it('delete last line', function()
put_abc()
feed('v$d')
expect([[
a
b
]])
end)
it('delete last two line', function()
put_abc()
feed('kvj$d')
expect([[
a
]])
end)
end)
describe('characterwise select mode:', function()
before_each(function()
define_select_mode_maps()
end)
it('delete middle line', function()
put_abc()
feed('kkgh<End><Del>')
expect([[
b
c]])
end)
it('delete middle two line', function()
put_abc()
feed('kkgh<Down><End><Del>')
expect([[
c]])
end)
it('delete last line', function()
put_abc()
feed('gh<End><Del>')
expect([[
a
b
]])
end)
it('delete last two line', function()
put_abc()
feed('kgh<Down><End><Del>')
expect([[
a
]])
end)
end)
describe('linewise select mode:', function()
before_each(function()
define_select_mode_maps()
end)
it('delete middle line', function()
put_abc()
feed(' kkgH<Del> ')
expect([[
b
c]])
end)
it('delete middle two line', function()
put_abc()
feed('kkgH<Down><Del>')
expect([[
c]])
end)
it('delete last line', function()
put_abc()
feed('gH<Del>')
expect([[
a
b]])
end)
it('delete last two line', function()
put_abc()
feed('kgH<Down><Del>')
expect([[
a]])
end)
end)
end) end)