mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	UI/nvim_ui_attach(): add override option
				
					
				
			Before now, Nvim always degrades UI capabilities to the lowest-common
denominator. For example, if any connected UI has `ext_messages=false`
then `ext_messages=true` requested by any other connected UI is ignored.
Now `nvim_ui_attach()` supports `override=true`, which flips the
behavior: if any UI requests an `ext_*` UI capability then the
capability is enabled (and the legacy behavior is disabled).
Legacy UIs will be broken while a `override=true` UI is connected, but
it's useful for debugging: you can type into the TUI and observe the UI
events from another connected (UI) client. And the legacy UI will
"recover" after the `override=true` UI disconnects.
Example using pynvim:
    >>> n.ui_attach(2048, 2048, rgb=True, override=True, ext_multigrid=True, ext_messages=True, ext_popupmenu=True)
    >>> while True: n.next_message();
			
			
This commit is contained in:
		| @@ -108,7 +108,7 @@ line numbers.  Double-click one of the lines and the Find Source dialog will | ||||
| appear.  Navigate to the directory where the Vim source is (if you have it.) | ||||
|  | ||||
| If you don't know how to debug this any further, follow the instructions | ||||
| at ":help bug-reports".  Paste the call stack into the bug report. | ||||
| at ":help bug-report".  Paste the call stack into the bug report. | ||||
|  | ||||
| If you have a non-free version of Visual Studio, you can save a minidump via | ||||
| the Debug menu and send it with the bug report.  A minidump is a small file | ||||
|   | ||||
| @@ -68,10 +68,8 @@ Options ~ | ||||
| *'viminfofile'*		Deprecated alias to 'shadafile' option. | ||||
|  | ||||
| UI extensions~ | ||||
| *ui-wildmenu*		Use `ext_cmdline` and `ext_popupmenu` instead. | ||||
| 			Enabled by `ext_wildmenu` |ui-options|. | ||||
| 			If `ext_wildmenu` is set, these events are emitted for | ||||
| 			backwards-compatibility: | ||||
| *ui-wildmenu*		Use |ui-cmdline| with |ui-popupmenu| instead. Enabled | ||||
| 			by `ext_wildmenu` |ui-options|. Emits these events: | ||||
| 				["wildmenu_show", items] | ||||
| 				["wildmenu_select", selected] | ||||
| 				["wildmenu_hide"] | ||||
|   | ||||
| @@ -58,7 +58,7 @@ For more information try one of these: | ||||
| ============================================================================== | ||||
| Nvim on the interwebs					*internet* | ||||
|  | ||||
| 			*www* *WWW*  *faq* *FAQ* *distribution* *download* | ||||
| 			*www* *faq* *distribution* *download* | ||||
|  | ||||
| 	Nvim home page:	  https://neovim.io/ | ||||
| 	Nvim FAQ:	  https://github.com/neovim/neovim/wiki/FAQ | ||||
| @@ -67,9 +67,10 @@ Nvim on the interwebs					*internet* | ||||
| 	Vim home page:	  https://www.vim.org/ | ||||
|  | ||||
|  | ||||
| Bug reports:				*bugs* *bug-reports* *bugreport.vim* | ||||
| 			*bugs* *bug-report* *bugreport.vim* *feature-request*  | ||||
|  | ||||
| Report bugs on GitHub: https://github.com/neovim/neovim/issues | ||||
| Report bugs and request features here: | ||||
| https://github.com/neovim/neovim/issues | ||||
|  | ||||
| Be brief, yet complete.  Always give a reproducible example and try to find | ||||
| out which settings or other things trigger the bug. | ||||
|   | ||||
| @@ -25,13 +25,20 @@ done by an embedder, see |ui-startup| below for details, but an UI can also | ||||
| connect to a running nvim instance and invoke this method. `options` must be | ||||
| a dictionary with these (optional) keys: | ||||
| 	`rgb`			Decides the color format. *ui-rgb* | ||||
| 				Set true (default) for 24-bit RGB colors. | ||||
| 				Set false for terminal colors (max of 256). | ||||
| 				true:	(default) 24-bit RGB colors | ||||
| 				false:	Terminal colors (8-bit, max 256) | ||||
| 	`override`		Decides how UI capabilities are resolved. | ||||
| 				true:	Enable requested UI capabilities, even | ||||
| 					if not supported by all connected UIs | ||||
| 					(including |TUI|). | ||||
| 				false:	(default) Disable UI capabilities not | ||||
| 					supported by all connected UIs | ||||
| 					(including TUI). | ||||
| 							      *ui-ext-options* | ||||
| 	`ext_popupmenu`		Externalize the popupmenu. |ui-popupmenu| | ||||
| 	`ext_popupmenu`		Externalize |popupmenu-completion| and | ||||
| 				'wildmenu'. |ui-popupmenu| | ||||
| 	`ext_tabline`		Externalize the tabline. |ui-tabline| | ||||
| 	`ext_cmdline`		Externalize the cmdline. |ui-cmdline| | ||||
| 	`ext_wildmenu`		Externalize the wildmenu (deprecated). |ui-wildmenu| | ||||
| 	`ext_messages`		Externalize messages. |ui-messages| | ||||
| 	`ext_linegrid`		Use new revision of the grid events. |ui-linegrid| | ||||
| 	`ext_multigrid`		Use per-window grid based events. |ui-multigrid| | ||||
| @@ -245,9 +252,9 @@ numerical highlight ids to the actual attributes. | ||||
| 	implementation, where using the terminal builtin ("ANSI") defaults | ||||
| 	are expected. | ||||
|  | ||||
| 	Note: unlike the corresponding events in the first revision, the | ||||
| 	screen is not always cleared after sending this event. The GUI has to | ||||
| 	repaint the screen with changed background color itself. | ||||
| 	Note: Unlike the corresponding |ui-grid-old| events, the screen is not | ||||
| 	always cleared after sending this event. The UI must repaint the | ||||
| 	screen with changed background color itself. | ||||
|  | ||||
| 							*ui-event-hl_attr_define* | ||||
| ["hl_attr_define", id, rgb_attr, cterm_attr, info] | ||||
| @@ -554,6 +561,7 @@ See |nvim_input_mouse| for sending mouse events to Nvim. | ||||
| Popupmenu Events						 *ui-popupmenu* | ||||
|  | ||||
| Only sent if `ext_popupmenu` option is set in |ui-options|. | ||||
| Events for |popupmenu-completion| and command-line 'wildmenu'. | ||||
|  | ||||
| ["popupmenu_show", items, selected, row, col, grid] | ||||
| 	Show |popupmenu-completion|. `items` is an array of completion items | ||||
| @@ -590,9 +598,7 @@ Only sent if `ext_tabline` option is set in |ui-options| | ||||
| Cmdline Events							   *ui-cmdline* | ||||
|  | ||||
| Only sent if `ext_cmdline` option is set in |ui-options|. To handle | ||||
| command-line completion (wildmenu), use |ui-popupmenu| events activated by | ||||
| |ext_popupmenu| option. (The `ext_wildmenu` option only exists for backwards | ||||
| compatibility). | ||||
| command-line 'wildmenu', enable |ui-popupmenu| and handle its events. | ||||
|  | ||||
| ["cmdline_show", content, pos, firstc, prompt, indent, level] | ||||
|         content: List of [attrs, string] | ||||
| @@ -650,18 +656,18 @@ compatibility). | ||||
| ============================================================================== | ||||
| Message Events							   *ui-messages* | ||||
|  | ||||
| Only sent if `ext_messages` option is set in |ui-options|. This option implies | ||||
| `ext_linegrid` and `ext_cmdline` also being set. |ui-linegrid| and |ui-cmdline| events | ||||
| will thus also be sent. | ||||
| Only sent if `ext_messages` option is set in |ui-options|. This option | ||||
| implicitly enables `ext_linegrid` and `ext_cmdline`. |ui-linegrid| and | ||||
| |ui-cmdline| events will thus also be sent. | ||||
|  | ||||
| This extension allows the UI to control the display of messages that otherwise | ||||
| would have been displayed in the message/cmdline area in the bottom of the | ||||
| screen. | ||||
|  | ||||
| Activating this extension means that Nvim will allocate no screen space for | ||||
| the cmdline or messages, and 'cmdheight' will be set to zero.  Attempting to | ||||
| change 'cmdheight' will silently be ignored. |ui-cmdline| events will be used | ||||
| to represent the state of the cmdline. | ||||
| Activating this extension means that Nvim will not allocate screen space for | ||||
| the cmdline or messages, 'cmdheight' will be zero.  Attempting to change | ||||
| 'cmdheight' will be silently ignored. |ui-cmdline| events represent the state | ||||
| of the cmdline. | ||||
|  | ||||
| ["msg_show", kind, content, replace_last] | ||||
| 	Display a message to the user. | ||||
|   | ||||
| @@ -110,6 +110,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, | ||||
|   ui->width = (int)width; | ||||
|   ui->height = (int)height; | ||||
|   ui->rgb = true; | ||||
|   ui->override = false; | ||||
|   ui->grid_resize = remote_ui_grid_resize; | ||||
|   ui->grid_clear = remote_ui_grid_clear; | ||||
|   ui->grid_cursor_goto = remote_ui_grid_cursor_goto; | ||||
| @@ -236,6 +237,15 @@ void nvim_ui_set_option(uint64_t channel_id, String name, | ||||
| static void ui_set_option(UI *ui, bool init, String name, Object value, | ||||
|                           Error *error) | ||||
| { | ||||
|   if (strequal(name.data, "override")) { | ||||
|     if (value.type != kObjectTypeBoolean) { | ||||
|       api_set_error(error, kErrorTypeValidation, "override must be a Boolean"); | ||||
|       return; | ||||
|     } | ||||
|     ui->override = value.data.boolean; | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   if (strequal(name.data, "rgb")) { | ||||
|     if (value.type != kObjectTypeBoolean) { | ||||
|       api_set_error(error, kErrorTypeValidation, "rgb must be a Boolean"); | ||||
|   | ||||
| @@ -141,6 +141,17 @@ bool ui_rgb_attached(void) | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| /// Returns true if any UI requested `override=true`. | ||||
| bool ui_override(void) | ||||
| { | ||||
|   for (size_t i = 1; i < ui_count; i++) { | ||||
|     if (uis[i]->override) { | ||||
|       return true; | ||||
|     } | ||||
|   } | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| bool ui_active(void) | ||||
| { | ||||
|   return ui_count > 1; | ||||
| @@ -173,12 +184,13 @@ void ui_refresh(void) | ||||
|     ext_widgets[i] = true; | ||||
|   } | ||||
|  | ||||
|   bool inclusive = ui_override(); | ||||
|   for (size_t i = 0; i < ui_count; i++) { | ||||
|     UI *ui = uis[i]; | ||||
|     width = MIN(ui->width, width); | ||||
|     height = MIN(ui->height, height); | ||||
|     for (UIExtension j = 0; (int)j < kUIExtCount; j++) { | ||||
|       ext_widgets[j] &= ui->ui_ext[j]; | ||||
|       ext_widgets[j] &= (ui->ui_ext[j] || inclusive); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -431,6 +443,7 @@ Array ui_array(void) | ||||
|     PUT(info, "width", INTEGER_OBJ(ui->width)); | ||||
|     PUT(info, "height", INTEGER_OBJ(ui->height)); | ||||
|     PUT(info, "rgb", BOOLEAN_OBJ(ui->rgb)); | ||||
|     PUT(info, "override", BOOLEAN_OBJ(ui->override)); | ||||
|     for (UIExtension j = 0; j < kUIExtCount; j++) { | ||||
|       if (ui_ext_names[j][0] != '_' || ui->ui_ext[j]) { | ||||
|         PUT(info, ui_ext_names[j], BOOLEAN_OBJ(ui->ui_ext[j])); | ||||
|   | ||||
| @@ -48,9 +48,11 @@ typedef int LineFlags; | ||||
|  | ||||
| struct ui_t { | ||||
|   bool rgb; | ||||
|   bool override;  ///< Force highest-requested UI capabilities. | ||||
|   bool composed; | ||||
|   bool ui_ext[kUIExtCount];  ///< Externalized widgets | ||||
|   int width, height; | ||||
|   bool ui_ext[kUIExtCount];  ///< Externalized UI capabilities. | ||||
|   int width; | ||||
|   int height; | ||||
|   void *data; | ||||
|  | ||||
| #ifdef INCLUDE_GENERATED_DECLARATIONS | ||||
|   | ||||
| @@ -1284,7 +1284,7 @@ describe('API', function() | ||||
|     end) | ||||
|     it('returns attached UIs', function() | ||||
|       local screen = Screen.new(20, 4) | ||||
|       screen:attach() | ||||
|       screen:attach({override=true}) | ||||
|       local expected = { | ||||
|         { | ||||
|           chan = 1, | ||||
| @@ -1299,6 +1299,7 @@ describe('API', function() | ||||
|           ext_messages = false, | ||||
|           height = 4, | ||||
|           rgb = true, | ||||
|           override = true, | ||||
|           width = 20, | ||||
|         } | ||||
|       } | ||||
| @@ -1308,6 +1309,7 @@ describe('API', function() | ||||
|       screen = Screen.new(44, 99) | ||||
|       screen:attach({ rgb = false }) | ||||
|       expected[1].rgb = false | ||||
|       expected[1].override = false | ||||
|       expected[1].width = 44 | ||||
|       expected[1].height = 99 | ||||
|       eq(expected, nvim("list_uis")) | ||||
|   | ||||
| @@ -255,14 +255,14 @@ describe('TUI', function() | ||||
|     ]]) | ||||
|   end) | ||||
|  | ||||
|   it('shows up in nvim_list_uis', function() | ||||
|   it('is included in nvim_list_uis()', function() | ||||
|     feed_data(':echo map(nvim_list_uis(), {k,v -> sort(items(filter(v, {k,v -> k[:3] !=# "ext_" })))})\013') | ||||
|     screen:expect([=[ | ||||
|                                                         | | ||||
|       {4:~                                                 }| | ||||
|       {5:                                                  }| | ||||
|       [[['height', 6], ['rgb', v:false], ['width', 50]]]| | ||||
|                                                         | | ||||
|       [[['height', 6], ['override', v:false], ['rgb', v:| | ||||
|       false], ['width', 50]]]                           | | ||||
|       {10:Press ENTER or type command to continue}{1: }          | | ||||
|       {3:-- TERMINAL --}                                    | | ||||
|     ]=]) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Justin M. Keyes
					Justin M. Keyes