mirror of
https://github.com/vim/vim
synced 2025-07-15 16:51:57 +00:00
patch 9.1.1426: completion: register contents not completed
Problem: CTRL-X CTRL-R only completes individual words from registers, making it difficult to insert complete register content. Solution: Add consecutive CTRL-X CTRL-R support - first press completes words, second press completes full register lines, similar to CTRL-X CTRL-L and CTRL-X CTRL-P behavior (glepnir). closes: #17395 Signed-off-by: glepnir <glephunter@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
3993cd619a
commit
d5fdfa5c9c
@ -1,4 +1,4 @@
|
||||
*index.txt* For Vim version 9.1. Last change: 2025 May 26
|
||||
*index.txt* For Vim version 9.1. Last change: 2025 Jun 02
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@ -163,7 +163,7 @@ commands in CTRL-X submode *i_CTRL-X_index*
|
||||
|i_CTRL-X_CTRL-N| CTRL-X CTRL-N next completion
|
||||
|i_CTRL-X_CTRL-O| CTRL-X CTRL-O omni completion
|
||||
|i_CTRL-X_CTRL-P| CTRL-X CTRL-P previous completion
|
||||
|i_CTRL-X_CTRL-R| CTRL-X CTRL-R complete words from registers
|
||||
|i_CTRL-X_CTRL-R| CTRL-X CTRL-R complete contents from registers
|
||||
|i_CTRL-X_CTRL-S| CTRL-X CTRL-S spelling suggestions
|
||||
|i_CTRL-X_CTRL-T| CTRL-X CTRL-T complete identifiers from thesaurus
|
||||
|i_CTRL-X_CTRL-Y| CTRL-X CTRL-Y scroll down
|
||||
|
@ -1,4 +1,4 @@
|
||||
*insert.txt* For Vim version 9.1. Last change: 2025 May 26
|
||||
*insert.txt* For Vim version 9.1. Last change: 2025 Jun 02
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@ -649,7 +649,7 @@ Completion can be done for:
|
||||
11. omni completion |i_CTRL-X_CTRL-O|
|
||||
12. Spelling suggestions |i_CTRL-X_s|
|
||||
13. keywords in 'complete' |i_CTRL-N| |i_CTRL-P|
|
||||
14. words from registers |i_CTRL-X_CTRL-R|
|
||||
14. contents from registers |i_CTRL-X_CTRL-R|
|
||||
|
||||
Additionally, |i_CTRL-X_CTRL-Z| stops completion without changing the text.
|
||||
|
||||
@ -1021,7 +1021,7 @@ CTRL-X CTRL-V Guess what kind of item is in front of the cursor and
|
||||
:imap <Tab> <C-X><C-V>
|
||||
|
||||
|
||||
Completing words from registers *compl-register-words*
|
||||
Completing contents from registers *compl-register-words*
|
||||
*i_CTRL-X_CTRL-R*
|
||||
CTRL-X CTRL-R Guess what kind of item is in front of the cursor from
|
||||
all registers and find the first match for it.
|
||||
@ -1035,6 +1035,11 @@ CTRL-X CTRL-R Guess what kind of item is in front of the cursor from
|
||||
CTRL-P Search backwards for previous match. This match
|
||||
replaces the previous one.
|
||||
|
||||
CTRL-X CTRL-R Further use of CTRL-X CTRL-R will copy the line
|
||||
following the previous expansion in other contexts
|
||||
unless a double CTRL-X is used (e.g. this switches
|
||||
from completing register words to register contents).
|
||||
|
||||
User defined completion *compl-function*
|
||||
|
||||
Completion is done by a function that can be defined by the user with the
|
||||
|
@ -1,4 +1,4 @@
|
||||
*usr_24.txt* For Vim version 9.1. Last change: 2018 Mar 18
|
||||
*usr_24.txt* For Vim version 9.1. Last change: 2025 Jun 02
|
||||
|
||||
VIM USER MANUAL - by Bram Moolenaar
|
||||
|
||||
@ -187,7 +187,7 @@ with a certain type of item:
|
||||
CTRL-X CTRL-D macro definitions (also in included files)
|
||||
CTRL-X CTRL-I current and included files
|
||||
CTRL-X CTRL-K words from a dictionary
|
||||
CTRL-X CTRL-R words from registers
|
||||
CTRL-X CTRL-R contents from registers
|
||||
CTRL-X CTRL-T words from a thesaurus
|
||||
CTRL-X CTRL-] tags
|
||||
CTRL-X CTRL-V Vim command line
|
||||
|
@ -1,4 +1,4 @@
|
||||
*vi_diff.txt* For Vim version 9.1. Last change: 2025 Mar 28
|
||||
*vi_diff.txt* For Vim version 9.1. Last change: 2025 Jun 02
|
||||
|
||||
|
||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||
@ -338,7 +338,7 @@ Insert-mode completion. |ins-completion|
|
||||
|i_CTRL-X_CTRL-D| definitions or macros
|
||||
|i_CTRL-X_CTRL-O| Omni completion: clever completion
|
||||
specifically for a file type
|
||||
|i_CTRL-X_CTRL-R| words from registers
|
||||
|i_CTRL-X_CTRL-R| contents from registers
|
||||
etc.
|
||||
|
||||
Long line support. |'wrap'| |'linebreak'|
|
||||
|
@ -4935,35 +4935,83 @@ get_register_completion(void)
|
||||
|
||||
reg = (yankreg_T *)reg_ptr;
|
||||
|
||||
for (int j = 0; j < reg->y_size; j++)
|
||||
if (compl_status_adding())
|
||||
{
|
||||
char_u *str = reg->y_array[j].string;
|
||||
if (str == NULL)
|
||||
continue;
|
||||
|
||||
char_u *p = str;
|
||||
while (*p != NUL)
|
||||
for (int j = 0; j < reg->y_size; j++)
|
||||
{
|
||||
p = find_word_start(p);
|
||||
if (*p == NUL)
|
||||
break;
|
||||
char_u *str = reg->y_array[j].string;
|
||||
if (str == NULL)
|
||||
continue;
|
||||
|
||||
char_u *word_end = find_word_end(p);
|
||||
int str_len = (int)STRLEN(str);
|
||||
if (str_len == 0)
|
||||
continue;
|
||||
|
||||
// Add the word to the completion list
|
||||
int len = (int)(word_end - p);
|
||||
if (len > 0 && (!compl_orig_text.string
|
||||
|| (p_ic ? STRNICMP(p, compl_orig_text.string,
|
||||
compl_orig_text.length) == 0
|
||||
: STRNCMP(p, compl_orig_text.string,
|
||||
compl_orig_text.length) == 0)))
|
||||
if (!compl_orig_text.string
|
||||
|| (p_ic ? STRNICMP(str, compl_orig_text.string,
|
||||
compl_orig_text.length) == 0
|
||||
: STRNCMP(str, compl_orig_text.string,
|
||||
compl_orig_text.length) == 0))
|
||||
{
|
||||
if (ins_compl_add_infercase(p, len, p_ic, NULL,
|
||||
dir, FALSE, 0) == OK)
|
||||
if (ins_compl_add_infercase(str, str_len, p_ic, NULL, dir, FALSE, 0) == OK)
|
||||
dir = FORWARD;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < reg->y_size; j++)
|
||||
{
|
||||
char_u *str = reg->y_array[j].string;
|
||||
if (str == NULL)
|
||||
continue;
|
||||
|
||||
p = word_end;
|
||||
// Calculate the safe end of string to avoid null byte issues
|
||||
char_u *str_end = str + STRLEN(str);
|
||||
char_u *p = str;
|
||||
|
||||
// Safely iterate through the string
|
||||
while (p < str_end && *p != NUL)
|
||||
{
|
||||
char_u *old_p = p;
|
||||
p = find_word_start(p);
|
||||
if (p >= str_end || *p == NUL)
|
||||
break;
|
||||
|
||||
char_u *word_end = find_word_end(p);
|
||||
|
||||
if (word_end <= p)
|
||||
{
|
||||
if (has_mbyte)
|
||||
word_end = p + (*mb_ptr2len)(p);
|
||||
else
|
||||
word_end = p + 1;
|
||||
}
|
||||
|
||||
if (word_end > str_end)
|
||||
word_end = str_end;
|
||||
|
||||
int len = (int)(word_end - p);
|
||||
if (len > 0 && (!compl_orig_text.string
|
||||
|| (p_ic ? STRNICMP(p, compl_orig_text.string,
|
||||
compl_orig_text.length) == 0
|
||||
: STRNCMP(p, compl_orig_text.string,
|
||||
compl_orig_text.length) == 0)))
|
||||
{
|
||||
if (ins_compl_add_infercase(p, len, p_ic, NULL,
|
||||
dir, FALSE, 0) == OK)
|
||||
dir = FORWARD;
|
||||
}
|
||||
|
||||
p = word_end;
|
||||
|
||||
if (p <= old_p)
|
||||
{
|
||||
p = old_p + 1;
|
||||
if (has_mbyte && p < str_end)
|
||||
p = old_p + (*mb_ptr2len)(old_p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6379,7 +6427,7 @@ get_spell_compl_info(int startcol UNUSED, colnr_T curs_col UNUSED)
|
||||
static int
|
||||
compl_get_info(char_u *line, int startcol, colnr_T curs_col, int *line_invalid)
|
||||
{
|
||||
if (ctrl_x_mode_normal()
|
||||
if (ctrl_x_mode_normal() || ctrl_x_mode_register()
|
||||
|| (ctrl_x_mode & CTRL_X_WANT_IDENT
|
||||
&& !thesaurus_func_complete(ctrl_x_mode)))
|
||||
{
|
||||
@ -6410,10 +6458,6 @@ compl_get_info(char_u *line, int startcol, colnr_T curs_col, int *line_invalid)
|
||||
return FAIL;
|
||||
*line_invalid = TRUE; // "line" may have become invalid
|
||||
}
|
||||
else if (ctrl_x_mode_register())
|
||||
{
|
||||
return get_normal_compl_info(line, startcol, curs_col);
|
||||
}
|
||||
else
|
||||
{
|
||||
internal_error("ins_complete()");
|
||||
@ -6480,7 +6524,7 @@ ins_compl_continue_search(char_u *line)
|
||||
if (compl_length < 1)
|
||||
compl_cont_status &= CONT_LOCAL;
|
||||
}
|
||||
else if (ctrl_x_mode_line_or_eval())
|
||||
else if (ctrl_x_mode_line_or_eval() || ctrl_x_mode_register())
|
||||
compl_cont_status = CONT_ADDING | CONT_N_ADDS;
|
||||
else
|
||||
compl_cont_status = 0;
|
||||
|
@ -4670,6 +4670,27 @@ func Test_register_completion()
|
||||
call feedkeys("Sze\<C-X>\<C-R>\<C-R>=string(complete_info(['mode']))\<CR>\<ESC>", "tx")
|
||||
call assert_equal("zero{'mode': 'register'}", getline(1))
|
||||
|
||||
" Test consecutive CTRL-X CTRL-R (adding mode)
|
||||
" First CTRL-X CTRL-R should split into words, second should use full content
|
||||
let @f = "hello world test complete"
|
||||
call setline(1, "hel")
|
||||
call cursor(1, 3)
|
||||
call feedkeys("a\<C-X>\<C-R>\<C-N>\<Esc>", 'tx')
|
||||
call assert_equal("hello", getline(1))
|
||||
|
||||
" Second consecutive CTRL-X CTRL-R should complete with full content
|
||||
call setline(1, "hello")
|
||||
call cursor(1, 5)
|
||||
call feedkeys("a\<C-X>\<C-R>\<C-X>\<C-R>\<Esc>", 'tx')
|
||||
call assert_equal("hello world test complete", getline(1))
|
||||
|
||||
" Test consecutive completion with multi-line register
|
||||
let @g = "first line content\nsecond line here\nthird line data"
|
||||
call setline(1, "first")
|
||||
call cursor(1, 5)
|
||||
call feedkeys("a\<C-X>\<C-R>\<C-X>\<C-R>\<Esc>", 'tx')
|
||||
call assert_equal("first line content", getline(1))
|
||||
|
||||
" Clean up
|
||||
bwipe!
|
||||
delfunc GetItems
|
||||
|
@ -709,6 +709,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1426,
|
||||
/**/
|
||||
1425,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user