vim-patch:8.1.0971: failure to select quoted text obj moves cursor #9658

closes #9640

Problem:    Failure for selecting quoted text object moves cursor.
Solution:   Restore the Visual selection on failure. (Christian Brabandt,
            closes vim/vim#4024)
55d3bdbbe2
This commit is contained in:
Pierre 2019-03-03 11:04:32 +01:00 committed by Justin M. Keyes
parent 7a6da502b9
commit 14c53e4cbe
2 changed files with 67 additions and 21 deletions

View File

@ -3687,11 +3687,12 @@ current_quote(
int col_end; int col_end;
int col_start = curwin->w_cursor.col; int col_start = curwin->w_cursor.col;
bool inclusive = false; bool inclusive = false;
int vis_empty = TRUE; /* Visual selection <= 1 char */ int vis_empty = true; // Visual selection <= 1 char
int vis_bef_curs = FALSE; /* Visual starts before cursor */ int vis_bef_curs = false; // Visual starts before cursor
int inside_quotes = FALSE; /* Looks like "i'" done before */ int inside_quotes = false; // Looks like "i'" done before
int selected_quote = FALSE; /* Has quote inside selection */ int selected_quote = false; // Has quote inside selection
int i; int i;
int restore_vis_bef = false; // resotre VIsual on abort
// Correct cursor when 'selection' is "exclusive". // Correct cursor when 'selection' is "exclusive".
if (VIsual_active) { if (VIsual_active) {
@ -3709,6 +3710,7 @@ current_quote(
curwin->w_cursor = VIsual; curwin->w_cursor = VIsual;
VIsual = t; VIsual = t;
vis_bef_curs = true; vis_bef_curs = true;
restore_vis_bef = true;
} }
dec_cursor(); dec_cursor();
} }
@ -3749,8 +3751,9 @@ current_quote(
/* Assume we are on a closing quote: move to after the next /* Assume we are on a closing quote: move to after the next
* opening quote. */ * opening quote. */
col_start = find_next_quote(line, col_start + 1, quotechar, NULL); col_start = find_next_quote(line, col_start + 1, quotechar, NULL);
if (col_start < 0) if (col_start < 0) {
return FALSE; goto abort_search;
}
col_end = find_next_quote(line, col_start + 1, quotechar, col_end = find_next_quote(line, col_start + 1, quotechar,
curbuf->b_p_qe); curbuf->b_p_qe);
if (col_end < 0) { if (col_end < 0) {
@ -3760,8 +3763,9 @@ current_quote(
} }
} else { } else {
col_end = find_prev_quote(line, col_start, quotechar, NULL); col_end = find_prev_quote(line, col_start, quotechar, NULL);
if (line[col_end] != quotechar) if (line[col_end] != quotechar) {
return FALSE; goto abort_search;
}
col_start = find_prev_quote(line, col_end, quotechar, col_start = find_prev_quote(line, col_end, quotechar,
curbuf->b_p_qe); curbuf->b_p_qe);
if (line[col_start] != quotechar) { if (line[col_start] != quotechar) {
@ -3789,17 +3793,20 @@ current_quote(
for (;; ) { for (;; ) {
/* Find open quote character. */ /* Find open quote character. */
col_start = find_next_quote(line, col_start, quotechar, NULL); col_start = find_next_quote(line, col_start, quotechar, NULL);
if (col_start < 0 || col_start > first_col) if (col_start < 0 || col_start > first_col) {
return FALSE; goto abort_search;
/* Find close quote character. */ }
// Find close quote character.
col_end = find_next_quote(line, col_start + 1, quotechar, col_end = find_next_quote(line, col_start + 1, quotechar,
curbuf->b_p_qe); curbuf->b_p_qe);
if (col_end < 0) if (col_end < 0) {
return FALSE; goto abort_search;
/* If is cursor between start and end quote character, it is }
* target text object. */ // If is cursor between start and end quote character, it is
if (col_start <= first_col && first_col <= col_end) // target text object.
if (col_start <= first_col && first_col <= col_end) {
break; break;
}
col_start = col_end + 1; col_start = col_end + 1;
} }
} else { } else {
@ -3808,15 +3815,17 @@ current_quote(
if (line[col_start] != quotechar) { if (line[col_start] != quotechar) {
/* No quote before the cursor, look after the cursor. */ /* No quote before the cursor, look after the cursor. */
col_start = find_next_quote(line, col_start, quotechar, NULL); col_start = find_next_quote(line, col_start, quotechar, NULL);
if (col_start < 0) if (col_start < 0) {
return FALSE; goto abort_search;
}
} }
/* Find close quote character. */ /* Find close quote character. */
col_end = find_next_quote(line, col_start + 1, quotechar, col_end = find_next_quote(line, col_start + 1, quotechar,
curbuf->b_p_qe); curbuf->b_p_qe);
if (col_end < 0) if (col_end < 0) {
return FALSE; goto abort_search;
}
} }
/* When "include" is TRUE, include spaces after closing quote or before /* When "include" is TRUE, include spaces after closing quote or before
@ -3893,6 +3902,18 @@ current_quote(
} }
return OK; return OK;
abort_search:
if (VIsual_active && *p_sel == 'e') {
inc_cursor();
if (restore_vis_bef) {
pos_T t = curwin->w_cursor;
curwin->w_cursor = VIsual;
VIsual = t;
}
}
return FALSE;
} }

View File

@ -52,6 +52,31 @@ func Test_quote_selection_selection_exclusive()
bw! bw!
endfunc endfunc
func Test_quote_selection_selection_exclusive_abort()
new
set selection=exclusive
call setline(1, "'abzzc'")
let exp_curs = [0, 1, 6, 0]
call cursor(1,1)
exe 'norm! fcdvi"'
" make sure to end visual mode to have a clear state
exe "norm! \<esc>"
call assert_equal(exp_curs, getpos('.'))
call cursor(1,1)
exe 'norm! fcvi"'
exe "norm! \<esc>"
call assert_equal(exp_curs, getpos('.'))
call cursor(1,2)
exe 'norm! vfcoi"'
exe "norm! \<esc>"
let exp_curs = [0, 1, 2, 0]
let exp_visu = [0, 1, 7, 0]
call assert_equal(exp_curs, getpos('.'))
call assert_equal(exp_visu, getpos("'>"))
set selection&vim
bw!
endfunc
" Tests for string and html text objects " Tests for string and html text objects
func Test_string_html_objects() func Test_string_html_objects()
enew! enew!