mirror of
				https://github.com/vim/vim.git
				synced 2025-10-30 09:47:20 -04: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
						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,22 +4935,62 @@ get_register_completion(void) | ||||
|  | ||||
| 	reg = (yankreg_T *)reg_ptr; | ||||
|  | ||||
| 	if (compl_status_adding()) | ||||
| 	{ | ||||
| 	    for (int j = 0; j < reg->y_size; j++) | ||||
| 	    { | ||||
| 		char_u *str = reg->y_array[j].string; | ||||
| 		if (str == NULL) | ||||
| 		    continue; | ||||
|  | ||||
| 	    char_u *p = str; | ||||
| 	    while (*p != NUL) | ||||
| 		int str_len = (int)STRLEN(str); | ||||
| 		if (str_len == 0) | ||||
| 		    continue; | ||||
|  | ||||
| 		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(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; | ||||
|  | ||||
| 		// 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 == NUL) | ||||
| 		    if (p >= str_end || *p == NUL) | ||||
| 			break; | ||||
|  | ||||
| 		    char_u *word_end = find_word_end(p); | ||||
|  | ||||
| 		// Add the word to the completion list | ||||
| 		    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, | ||||
| @@ -4964,6 +5004,14 @@ get_register_completion(void) | ||||
| 		    } | ||||
|  | ||||
| 		    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