mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	Merge pull request #10504 from bfredl/hl_def
highlight: expose builtin highlight groups using hl_group_set event
This commit is contained in:
		| @@ -316,6 +316,14 @@ numerical highlight ids to the actual attributes. | ||||
| 	`info` is an empty array by default, and will be used by the | ||||
| 	|ui-hlstate| extension explained below. | ||||
|  | ||||
| ["hl_group_set", name, hl_id] | ||||
| 	The bulitin highlight group `name` was set to use the attributes `hl_id` | ||||
| 	defined by a previous `hl_attr_define` call. This event is not needed | ||||
| 	to render the grids which use attribute ids directly, but is useful | ||||
| 	for an UI who want to render its own elements with consistent | ||||
| 	highlighting. For instance an UI using |ui-popupmenu| events, might | ||||
| 	use the |hl-Pmenu| family of builtin highlights. | ||||
|  | ||||
| 							    *ui-event-grid_line* | ||||
| ["grid_line", grid, row, col_start, cells] | ||||
| 	Redraw a continuous part of a `row` on a `grid`, starting at the column | ||||
|   | ||||
| @@ -123,6 +123,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, | ||||
|   ui->mode_change = remote_ui_mode_change; | ||||
|   ui->grid_scroll = remote_ui_grid_scroll; | ||||
|   ui->hl_attr_define = remote_ui_hl_attr_define; | ||||
|   ui->hl_group_set = remote_ui_hl_group_set; | ||||
|   ui->raw_line = remote_ui_raw_line; | ||||
|   ui->bell = remote_ui_bell; | ||||
|   ui->visual_bell = remote_ui_visual_bell; | ||||
|   | ||||
| @@ -73,6 +73,8 @@ void default_colors_set(Integer rgb_fg, Integer rgb_bg, Integer rgb_sp, | ||||
| void hl_attr_define(Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs, | ||||
|                     Array info) | ||||
|   FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_BRIDGE_IMPL; | ||||
| void hl_group_set(String name, Integer id) | ||||
|   FUNC_API_SINCE(6) FUNC_API_BRIDGE_IMPL; | ||||
| void grid_resize(Integer grid, Integer width, Integer height) | ||||
|   FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_COMPOSITOR_IMPL; | ||||
| void grid_clear(Integer grid) | ||||
|   | ||||
| @@ -106,14 +106,19 @@ static int get_attr_entry(HlEntry entry) | ||||
| /// When a UI connects, we need to send it the table of highlights used so far. | ||||
| void ui_send_all_hls(UI *ui) | ||||
| { | ||||
|   if (!ui->hl_attr_define) { | ||||
|     return; | ||||
|   if (ui->hl_attr_define) { | ||||
|     for (size_t i = 1; i < kv_size(attr_entries); i++) { | ||||
|       Array inspect = hl_inspect((int)i); | ||||
|       ui->hl_attr_define(ui, (Integer)i, kv_A(attr_entries, i).attr, | ||||
|                          kv_A(attr_entries, i).attr, inspect); | ||||
|       api_free_array(inspect); | ||||
|     } | ||||
|   } | ||||
|   for (size_t i = 1; i < kv_size(attr_entries); i++) { | ||||
|     Array inspect = hl_inspect((int)i); | ||||
|     ui->hl_attr_define(ui, (Integer)i, kv_A(attr_entries, i).attr, | ||||
|                        kv_A(attr_entries, i).attr, inspect); | ||||
|     api_free_array(inspect); | ||||
|   if (ui->hl_group_set) { | ||||
|     for (size_t hlf = 0; hlf < HLF_COUNT; hlf++) { | ||||
|       ui->hl_group_set(ui, cstr_as_string((char *)hlf_names[hlf]), | ||||
|                        highlight_attr[hlf]); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -251,6 +256,7 @@ void clear_hl_tables(bool reinit) | ||||
|     map_clear(int, int)(combine_attr_entries); | ||||
|     map_clear(int, int)(blend_attr_entries); | ||||
|     map_clear(int, int)(blendthrough_attr_entries); | ||||
|     memset(highlight_attr_last, -1, sizeof(highlight_attr_last)); | ||||
|     highlight_attr_set_all(); | ||||
|     highlight_changed(); | ||||
|     screen_invalidate_highlights(); | ||||
|   | ||||
| @@ -150,6 +150,7 @@ EXTERN const char *hlf_names[] INIT(= { | ||||
|  | ||||
|  | ||||
| EXTERN int highlight_attr[HLF_COUNT];       // Highl. attr for each context. | ||||
| EXTERN int highlight_attr_last[HLF_COUNT];  // copy for detecting changed groups | ||||
| EXTERN int highlight_user[9];                   // User[1-9] attributes | ||||
| EXTERN int highlight_stlnc[9];                  // On top of user | ||||
| EXTERN int cterm_normal_fg_color INIT(= 0); | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
|  | ||||
| #include "nvim/vim.h" | ||||
| #include "nvim/ascii.h" | ||||
| #include "nvim/api/private/helpers.h" | ||||
| #include "nvim/syntax.h" | ||||
| #include "nvim/charset.h" | ||||
| #include "nvim/cursor_shape.h" | ||||
| @@ -7504,6 +7505,12 @@ void highlight_changed(void) | ||||
|  | ||||
|     highlight_attr[hlf] = hl_get_ui_attr(hlf, final_id, | ||||
|                                          hlf == (int)HLF_INACTIVE); | ||||
|  | ||||
|     if (highlight_attr[hlf] != highlight_attr_last[hlf]) { | ||||
|       ui_call_hl_group_set(cstr_as_string((char *)hlf_names[hlf]), | ||||
|                            highlight_attr[hlf]); | ||||
|       highlight_attr_last[hlf] = highlight_attr[hlf]; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* Setup the user highlights | ||||
|   | ||||
| @@ -311,6 +311,38 @@ describe('highlight defaults', function() | ||||
|       [1] = {foreground=Screen.colors.Blue}, | ||||
|     }) | ||||
|   end) | ||||
|  | ||||
|   it('are sent to UIs', function() | ||||
|     screen:try_resize(53, 4) | ||||
|     screen:set_default_attr_ids({ | ||||
|       [0] = {}, | ||||
|       [1] = {bold = true, foreground = Screen.colors.Blue1}, | ||||
|       [2] = {bold = true, reverse = true}, | ||||
|       [3] = {italic=true} | ||||
|     }) | ||||
|     screen:expect{grid=[[ | ||||
|       ^                                                     | | ||||
|       {1:~                                                    }| | ||||
|       {1:~                                                    }| | ||||
|                                                            | | ||||
|     ]], hl_groups={EndOfBuffer=1, MsgSeparator=2}} | ||||
|  | ||||
|     command('highlight EndOfBuffer gui=italic') | ||||
|     screen:expect{grid=[[ | ||||
|       ^                                                     | | ||||
|       {3:~                                                    }| | ||||
|       {3:~                                                    }| | ||||
|                                                            | | ||||
|     ]], hl_groups={EndOfBuffer=3, MsgSeparator=2}} | ||||
|  | ||||
|     command('highlight clear EndOfBuffer') | ||||
|     screen:expect{grid=[[ | ||||
|       ^                                                     | | ||||
|       ~                                                    | | ||||
|       ~                                                    | | ||||
|                                                            | | ||||
|     ]], hl_groups={EndOfBuffer=0, MsgSeparator=2}} | ||||
|   end) | ||||
| end) | ||||
|  | ||||
| describe('highlight', function() | ||||
|   | ||||
| @@ -165,6 +165,7 @@ function Screen.new(width, height) | ||||
|     showmode = {}, | ||||
|     showcmd = {}, | ||||
|     ruler = {}, | ||||
|     hl_groups = {}, | ||||
|     _default_attr_ids = nil, | ||||
|     _default_attr_ignore = nil, | ||||
|     _mouse_enabled = true, | ||||
| @@ -322,7 +323,7 @@ function Screen:expect(expected, attr_ids, attr_ignore) | ||||
|     assert(not (attr_ids ~= nil or attr_ignore ~= nil)) | ||||
|     local is_key = {grid=true, attr_ids=true, attr_ignore=true, condition=true, | ||||
|                     any=true, mode=true, unchanged=true, intermediate=true, | ||||
|                     reset=true, timeout=true, request_cb=true} | ||||
|                     reset=true, timeout=true, request_cb=true, hl_groups=true} | ||||
|     for _, v in ipairs(ext_keys) do | ||||
|       is_key[v] = true | ||||
|     end | ||||
| @@ -418,9 +419,10 @@ screen:redraw_debug() to show all intermediate screen states.  ]]) | ||||
|     -- (e.g. no external cmdline visible). Some extensions require | ||||
|     -- preprocessing to represent highlights in a reproducible way. | ||||
|     local extstate = self:_extstate_repr(attr_state) | ||||
|     if expected['mode'] ~= nil then | ||||
|       extstate['mode'] = self.mode | ||||
|     if expected.mode ~= nil then | ||||
|       extstate.mode = self.mode | ||||
|     end | ||||
|  | ||||
|     -- Convert assertion errors into invalid screen state descriptions. | ||||
|     for _, k in ipairs(concat_tables(ext_keys, {'mode'})) do | ||||
|       -- Empty states are considered the default and need not be mentioned. | ||||
| @@ -431,6 +433,17 @@ screen:redraw_debug() to show all intermediate screen states.  ]]) | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|  | ||||
|     if expected.hl_groups ~= nil then | ||||
|       for name, id in pairs(expected.hl_groups) do | ||||
|         local expected_hl = attr_state.ids[id] | ||||
|         local actual_hl = self._attr_table[self.hl_groups[name]][(self._options.rgb and 1) or 2] | ||||
|         local status, res = pcall(eq, expected_hl, actual_hl, "highlight "..name) | ||||
|         if not status then | ||||
|           return tostring(res) | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|   end, expected) | ||||
| end | ||||
|  | ||||
| @@ -836,6 +849,10 @@ function Screen:_handle_hl_attr_define(id, rgb_attrs, cterm_attrs, info) | ||||
|   self._new_attrs = true | ||||
| end | ||||
|  | ||||
| function Screen:_handle_hl_group_set(name, id) | ||||
|   self.hl_groups[name] = id | ||||
| end | ||||
|  | ||||
| function Screen:get_hl(val) | ||||
|   if self._options.ext_newgrid then | ||||
|     return self._attr_table[val][1] | ||||
| @@ -1411,17 +1428,17 @@ function Screen:_get_attr_id(attr_state, attrs, hl_id) | ||||
|     end | ||||
|     return "UNEXPECTED "..self:_pprint_attrs(self._attr_table[hl_id][1]) | ||||
|   else | ||||
|     for id, a in pairs(attr_state.ids) do | ||||
|       if self:_equal_attrs(a, attrs) then | ||||
|          return id | ||||
|        end | ||||
|     end | ||||
|     if self:_equal_attrs(attrs, {}) or | ||||
|         attr_state.ignore == true or | ||||
|         self:_attr_index(attr_state.ignore, attrs) ~= nil then | ||||
|       -- ignore this attrs | ||||
|       return nil | ||||
|     end | ||||
|     for id, a in pairs(attr_state.ids) do | ||||
|       if self:_equal_attrs(a, attrs) then | ||||
|          return id | ||||
|        end | ||||
|     end | ||||
|     if attr_state.mutable then | ||||
|       table.insert(attr_state.ids, attrs) | ||||
|       attr_state.modified = true | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Björn Linse
					Björn Linse