mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	Merge pull request #9616 from chemzqm/completechange
add MenuPopupChanged autocmd
This commit is contained in:
		| @@ -354,6 +354,7 @@ Name			triggered by ~ | ||||
| |SessionLoadPost|	after loading a session file | ||||
|  | ||||
| |MenuPopup|		just before showing the popup menu | ||||
| |MenuPopupChanged|	after popup menu changed, not fired on popup menu hide | ||||
| |CompleteDone|		after Insert mode completion is done | ||||
|  | ||||
| |User|			to be used in combination with ":doautocmd" | ||||
| @@ -852,6 +853,22 @@ MenuPopup			Just before showing the popup menu (under the | ||||
| 					o	Operator-pending | ||||
| 					i	Insert | ||||
| 					c	Command line | ||||
| MenuPopupChanged 					*MenuPopupChanged* | ||||
| 				After each time popup menu changed, not fired | ||||
| 				on popup menu hide, use |CompleteDone| for popup | ||||
| 				menu hide. | ||||
|  | ||||
| 				Sets these |v:event| keys: | ||||
| 				    completed_item | ||||
| 				    height | ||||
| 				    width | ||||
| 				    row | ||||
| 				    col | ||||
| 				    size | ||||
| 				    scrollbar | ||||
|  | ||||
| 				It is not allowed to change the text |textlock|. | ||||
|  | ||||
| 							*OptionSet* | ||||
| OptionSet			After setting an option.  The pattern is | ||||
| 				matched against the long option name. | ||||
|   | ||||
| @@ -1553,6 +1553,19 @@ v:event		Dictionary of event data for the current |autocommand|.  Valid | ||||
| 					operation. | ||||
| 			regtype		Type of register as returned by | ||||
| 					|getregtype()|. | ||||
| 			completed_item    Current selected complete item on | ||||
| 					|MenuPopupChanged|, Is `{}` when no complete | ||||
| 					item selected. | ||||
| 			height 		Height of popup menu on |MenuPopupChanged| | ||||
| 			width   	width of popup menu on |MenuPopupChanged| | ||||
| 			row  	 	Row count of popup menu on |MenuPopupChanged|, | ||||
| 					relative to screen. | ||||
| 			col  	 	Col count of popup menu on |MenuPopupChanged|, | ||||
| 					relative to screen. | ||||
| 			size 		Total number of completion items on | ||||
| 					|MenuPopupChanged|. | ||||
| 			scrollbar 	Is |v:true| if popup menu have scrollbar, or | ||||
| 					|v:false| if not. | ||||
|  | ||||
| 					*v:exception* *exception-variable* | ||||
| v:exception	The value of the exception most recently caught and not | ||||
|   | ||||
| @@ -66,6 +66,7 @@ return { | ||||
|     'InsertLeave',            -- when leaving Insert mode | ||||
|     'JobActivity',            -- when job sent some data | ||||
|     'MenuPopup',              -- just before popup menu is displayed | ||||
|     'MenuPopupChanged',       -- after popup menu changed | ||||
|     'OptionSet',              -- after setting any option | ||||
|     'QuickFixCmdPost',        -- after :make, :grep etc. | ||||
|     'QuickFixCmdPre',         -- before :make, :grep etc. | ||||
|   | ||||
| @@ -2658,6 +2658,23 @@ void ins_compl_show_pum(void) | ||||
|   pum_selected_item = cur; | ||||
|   pum_display(compl_match_array, compl_match_arraysize, cur, array_changed); | ||||
|   curwin->w_cursor.col = col; | ||||
|  | ||||
|   if (!has_event(EVENT_MENUPOPUPCHANGED)) { | ||||
|     return; | ||||
|   } | ||||
|   dict_T *dict = get_vim_var_dict(VV_EVENT); | ||||
|   if (cur < 0) { | ||||
|     tv_dict_add_dict(dict, S_LEN("completed_item"), tv_dict_alloc()); | ||||
|   } else { | ||||
|     dict_T *item = ins_compl_dict_alloc(compl_curr_match); | ||||
|     tv_dict_add_dict(dict, S_LEN("completed_item"), item); | ||||
|   } | ||||
|   pum_set_boundings(dict); | ||||
|   tv_dict_set_keys_readonly(dict); | ||||
|   textlock++; | ||||
|   apply_autocmds(EVENT_MENUPOPUPCHANGED, NULL, NULL, false, curbuf); | ||||
|   textlock--; | ||||
|   tv_dict_clear(dict); | ||||
| } | ||||
|  | ||||
| #define DICT_FIRST      (1)     /* use just first element in "dict" */ | ||||
| @@ -4097,33 +4114,39 @@ static void ins_compl_insert(int in_compl_func) | ||||
|   else | ||||
|     compl_used_match = TRUE; | ||||
|  | ||||
|   // Set completed item. | ||||
|   // { word, abbr, menu, kind, info } | ||||
|   dict_T *dict = tv_dict_alloc(); | ||||
|   tv_dict_add_str( | ||||
|       dict, S_LEN("word"), | ||||
|       (const char *)EMPTY_IF_NULL(compl_shown_match->cp_str)); | ||||
|   tv_dict_add_str( | ||||
|       dict, S_LEN("abbr"), | ||||
|       (const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_ABBR])); | ||||
|   tv_dict_add_str( | ||||
|       dict, S_LEN("menu"), | ||||
|       (const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_MENU])); | ||||
|   tv_dict_add_str( | ||||
|       dict, S_LEN("kind"), | ||||
|       (const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_KIND])); | ||||
|   tv_dict_add_str( | ||||
|       dict, S_LEN("info"), | ||||
|       (const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_INFO])); | ||||
|   tv_dict_add_str( | ||||
|       dict, S_LEN("user_data"), | ||||
|       (const char *)EMPTY_IF_NULL(compl_shown_match->cp_text[CPT_USER_DATA])); | ||||
|   dict_T *dict = ins_compl_dict_alloc(compl_shown_match); | ||||
|   set_vim_var_dict(VV_COMPLETED_ITEM, dict); | ||||
|   if (!in_compl_func) { | ||||
|     compl_curr_match = compl_shown_match; | ||||
|   } | ||||
| } | ||||
|  | ||||
| // Convert to complete item dict | ||||
| static dict_T *ins_compl_dict_alloc(compl_T *match) | ||||
| { | ||||
|   // { word, abbr, menu, kind, info } | ||||
|   dict_T *dict = tv_dict_alloc(); | ||||
|   tv_dict_add_str( | ||||
|       dict, S_LEN("word"), | ||||
|       (const char *)EMPTY_IF_NULL(match->cp_str)); | ||||
|   tv_dict_add_str( | ||||
|       dict, S_LEN("abbr"), | ||||
|       (const char *)EMPTY_IF_NULL(match->cp_text[CPT_ABBR])); | ||||
|   tv_dict_add_str( | ||||
|       dict, S_LEN("menu"), | ||||
|       (const char *)EMPTY_IF_NULL(match->cp_text[CPT_MENU])); | ||||
|   tv_dict_add_str( | ||||
|       dict, S_LEN("kind"), | ||||
|       (const char *)EMPTY_IF_NULL(match->cp_text[CPT_KIND])); | ||||
|   tv_dict_add_str( | ||||
|       dict, S_LEN("info"), | ||||
|       (const char *)EMPTY_IF_NULL(match->cp_text[CPT_INFO])); | ||||
|   tv_dict_add_str( | ||||
|       dict, S_LEN("user_data"), | ||||
|       (const char *)EMPTY_IF_NULL(match->cp_text[CPT_USER_DATA])); | ||||
|   return dict; | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Fill in the next completion in the current direction. | ||||
|  * If "allow_get_expansion" is TRUE, then we may call ins_compl_get_exp() to | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
| #include "nvim/vim.h" | ||||
| #include "nvim/api/private/helpers.h" | ||||
| #include "nvim/ascii.h" | ||||
| #include "nvim/eval/typval.h" | ||||
| #include "nvim/popupmnu.h" | ||||
| #include "nvim/charset.h" | ||||
| #include "nvim/ex_cmds.h" | ||||
| @@ -841,3 +842,17 @@ int pum_get_height(void) | ||||
| { | ||||
|   return pum_height; | ||||
| } | ||||
|  | ||||
| void pum_set_boundings(dict_T *dict) | ||||
| { | ||||
|   if (!pum_visible()) { | ||||
|     return; | ||||
|   } | ||||
|   tv_dict_add_nr(dict, S_LEN("height"), pum_height); | ||||
|   tv_dict_add_nr(dict, S_LEN("width"), pum_width); | ||||
|   tv_dict_add_nr(dict, S_LEN("row"), pum_row); | ||||
|   tv_dict_add_nr(dict, S_LEN("col"), pum_col); | ||||
|   tv_dict_add_nr(dict, S_LEN("size"), pum_size); | ||||
|   tv_dict_add_special(dict, S_LEN("scrollbar"), | ||||
|                       pum_scrollbar ? kSpecialVarTrue : kSpecialVarFalse); | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| #ifndef NVIM_POPUPMNU_H | ||||
| #define NVIM_POPUPMNU_H | ||||
|  | ||||
| #include "nvim/vim.h" | ||||
| #include "nvim/macros.h" | ||||
| #include "nvim/grid_defs.h" | ||||
| #include "nvim/types.h" | ||||
|   | ||||
| @@ -1072,4 +1072,83 @@ describe('completion', function() | ||||
|       set complete&vim completeopt&vim | ||||
|     ]]) | ||||
|   end) | ||||
|  | ||||
|   it('MenuPopupChanged autocommand', function() | ||||
|     curbufmeths.set_lines(0, 1, false, { 'foo', 'bar', 'foobar', ''}) | ||||
|     source([[ | ||||
|       set complete=. completeopt=noinsert,noselect,menuone | ||||
|       function! OnPumChange() | ||||
|         let g:event = copy(v:event) | ||||
|         let g:item = get(v:event, 'completed_item', {}) | ||||
|         let g:word = get(g:item, 'word', v:null) | ||||
|       endfunction | ||||
|       autocmd! MenuPopupChanged * :call OnPumChange() | ||||
|       call cursor(4, 1) | ||||
|     ]]) | ||||
|  | ||||
|     feed('Sf<C-N>') | ||||
|     screen:expect([[ | ||||
|       foo                                                         | | ||||
|       bar                                                         | | ||||
|       foobar                                                      | | ||||
|       f^                                                           | | ||||
|       {1:foo            }{0:                                             }| | ||||
|       {1:foobar         }{0:                                             }| | ||||
|       {0:~                                                           }| | ||||
|       {3:-- Keyword completion (^N^P) }{5:Back at original}               | | ||||
|     ]]) | ||||
|     eq({completed_item = {}, width = 15, | ||||
|       height = 2, size = 2, | ||||
|       col = 0, row = 4, scrollbar = false}, | ||||
|       eval('g:event')) | ||||
|     feed('<C-N>') | ||||
|     screen:expect([[ | ||||
|       foo                                                         | | ||||
|       bar                                                         | | ||||
|       foobar                                                      | | ||||
|       foo^                                                         | | ||||
|       {2:foo            }{0:                                             }| | ||||
|       {1:foobar         }{0:                                             }| | ||||
|       {0:~                                                           }| | ||||
|       {3:-- Keyword completion (^N^P) }{4:match 1 of 2}                   | | ||||
|     ]]) | ||||
|     eq('foo', eval('g:word')) | ||||
|     feed('<C-N>') | ||||
|     screen:expect([[ | ||||
|       foo                                                         | | ||||
|       bar                                                         | | ||||
|       foobar                                                      | | ||||
|       foobar^                                                      | | ||||
|       {1:foo            }{0:                                             }| | ||||
|       {2:foobar         }{0:                                             }| | ||||
|       {0:~                                                           }| | ||||
|       {3:-- Keyword completion (^N^P) }{4:match 2 of 2}                   | | ||||
|     ]]) | ||||
|     eq('foobar', eval('g:word')) | ||||
|     feed('<up>') | ||||
|     screen:expect([[ | ||||
|       foo                                                         | | ||||
|       bar                                                         | | ||||
|       foobar                                                      | | ||||
|       foobar^                                                      | | ||||
|       {2:foo            }{0:                                             }| | ||||
|       {1:foobar         }{0:                                             }| | ||||
|       {0:~                                                           }| | ||||
|       {3:-- Keyword completion (^N^P) }{4:match 1 of 2}                   | | ||||
|     ]]) | ||||
|     eq('foo', eval('g:word')) | ||||
|     feed('<down>') | ||||
|     screen:expect([[ | ||||
|       foo                                                         | | ||||
|       bar                                                         | | ||||
|       foobar                                                      | | ||||
|       foobar^                                                      | | ||||
|       {1:foo            }{0:                                             }| | ||||
|       {2:foobar         }{0:                                             }| | ||||
|       {0:~                                                           }| | ||||
|       {3:-- Keyword completion (^N^P) }{4:match 2 of 2}                   | | ||||
|     ]]) | ||||
|     eq('foobar', eval('g:word')) | ||||
|     feed('<esc>') | ||||
|   end) | ||||
| end) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Björn Linse
					Björn Linse