Merge pull request #10504 from bfredl/hl_def

highlight: expose builtin highlight groups using hl_group_set event
This commit is contained in:
Björn Linse 2019-07-16 10:17:29 +02:00 committed by GitHub
commit 8a3f8589a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 89 additions and 15 deletions

View File

@ -316,6 +316,14 @@ numerical highlight ids to the actual attributes.
`info` is an empty array by default, and will be used by the `info` is an empty array by default, and will be used by the
|ui-hlstate| extension explained below. |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* *ui-event-grid_line*
["grid_line", grid, row, col_start, cells] ["grid_line", grid, row, col_start, cells]
Redraw a continuous part of a `row` on a `grid`, starting at the column Redraw a continuous part of a `row` on a `grid`, starting at the column

View File

@ -123,6 +123,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
ui->mode_change = remote_ui_mode_change; ui->mode_change = remote_ui_mode_change;
ui->grid_scroll = remote_ui_grid_scroll; ui->grid_scroll = remote_ui_grid_scroll;
ui->hl_attr_define = remote_ui_hl_attr_define; 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->raw_line = remote_ui_raw_line;
ui->bell = remote_ui_bell; ui->bell = remote_ui_bell;
ui->visual_bell = remote_ui_visual_bell; ui->visual_bell = remote_ui_visual_bell;

View File

@ -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, void hl_attr_define(Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs,
Array info) Array info)
FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_BRIDGE_IMPL; 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) void grid_resize(Integer grid, Integer width, Integer height)
FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_COMPOSITOR_IMPL; FUNC_API_SINCE(5) FUNC_API_REMOTE_IMPL FUNC_API_COMPOSITOR_IMPL;
void grid_clear(Integer grid) void grid_clear(Integer grid)

View File

@ -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. /// When a UI connects, we need to send it the table of highlights used so far.
void ui_send_all_hls(UI *ui) void ui_send_all_hls(UI *ui)
{ {
if (!ui->hl_attr_define) { if (ui->hl_attr_define) {
return; 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++) { if (ui->hl_group_set) {
Array inspect = hl_inspect((int)i); for (size_t hlf = 0; hlf < HLF_COUNT; hlf++) {
ui->hl_attr_define(ui, (Integer)i, kv_A(attr_entries, i).attr, ui->hl_group_set(ui, cstr_as_string((char *)hlf_names[hlf]),
kv_A(attr_entries, i).attr, inspect); highlight_attr[hlf]);
api_free_array(inspect); }
} }
} }
@ -251,6 +256,7 @@ void clear_hl_tables(bool reinit)
map_clear(int, int)(combine_attr_entries); map_clear(int, int)(combine_attr_entries);
map_clear(int, int)(blend_attr_entries); map_clear(int, int)(blend_attr_entries);
map_clear(int, int)(blendthrough_attr_entries); map_clear(int, int)(blendthrough_attr_entries);
memset(highlight_attr_last, -1, sizeof(highlight_attr_last));
highlight_attr_set_all(); highlight_attr_set_all();
highlight_changed(); highlight_changed();
screen_invalidate_highlights(); screen_invalidate_highlights();

View File

@ -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[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_user[9]; // User[1-9] attributes
EXTERN int highlight_stlnc[9]; // On top of user EXTERN int highlight_stlnc[9]; // On top of user
EXTERN int cterm_normal_fg_color INIT(= 0); EXTERN int cterm_normal_fg_color INIT(= 0);

View File

@ -14,6 +14,7 @@
#include "nvim/vim.h" #include "nvim/vim.h"
#include "nvim/ascii.h" #include "nvim/ascii.h"
#include "nvim/api/private/helpers.h"
#include "nvim/syntax.h" #include "nvim/syntax.h"
#include "nvim/charset.h" #include "nvim/charset.h"
#include "nvim/cursor_shape.h" #include "nvim/cursor_shape.h"
@ -7504,6 +7505,12 @@ void highlight_changed(void)
highlight_attr[hlf] = hl_get_ui_attr(hlf, final_id, highlight_attr[hlf] = hl_get_ui_attr(hlf, final_id,
hlf == (int)HLF_INACTIVE); 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 /* Setup the user highlights

View File

@ -311,6 +311,38 @@ describe('highlight defaults', function()
[1] = {foreground=Screen.colors.Blue}, [1] = {foreground=Screen.colors.Blue},
}) })
end) 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) end)
describe('highlight', function() describe('highlight', function()

View File

@ -165,6 +165,7 @@ function Screen.new(width, height)
showmode = {}, showmode = {},
showcmd = {}, showcmd = {},
ruler = {}, ruler = {},
hl_groups = {},
_default_attr_ids = nil, _default_attr_ids = nil,
_default_attr_ignore = nil, _default_attr_ignore = nil,
_mouse_enabled = true, _mouse_enabled = true,
@ -322,7 +323,7 @@ function Screen:expect(expected, attr_ids, attr_ignore)
assert(not (attr_ids ~= nil or attr_ignore ~= nil)) assert(not (attr_ids ~= nil or attr_ignore ~= nil))
local is_key = {grid=true, attr_ids=true, attr_ignore=true, condition=true, local is_key = {grid=true, attr_ids=true, attr_ignore=true, condition=true,
any=true, mode=true, unchanged=true, intermediate=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 for _, v in ipairs(ext_keys) do
is_key[v] = true is_key[v] = true
end end
@ -418,9 +419,10 @@ screen:redraw_debug() to show all intermediate screen states. ]])
-- (e.g. no external cmdline visible). Some extensions require -- (e.g. no external cmdline visible). Some extensions require
-- preprocessing to represent highlights in a reproducible way. -- preprocessing to represent highlights in a reproducible way.
local extstate = self:_extstate_repr(attr_state) local extstate = self:_extstate_repr(attr_state)
if expected['mode'] ~= nil then if expected.mode ~= nil then
extstate['mode'] = self.mode extstate.mode = self.mode
end end
-- Convert assertion errors into invalid screen state descriptions. -- Convert assertion errors into invalid screen state descriptions.
for _, k in ipairs(concat_tables(ext_keys, {'mode'})) do for _, k in ipairs(concat_tables(ext_keys, {'mode'})) do
-- Empty states are considered the default and need not be mentioned. -- 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 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, expected)
end end
@ -836,6 +849,10 @@ function Screen:_handle_hl_attr_define(id, rgb_attrs, cterm_attrs, info)
self._new_attrs = true self._new_attrs = true
end end
function Screen:_handle_hl_group_set(name, id)
self.hl_groups[name] = id
end
function Screen:get_hl(val) function Screen:get_hl(val)
if self._options.ext_newgrid then if self._options.ext_newgrid then
return self._attr_table[val][1] return self._attr_table[val][1]
@ -1411,17 +1428,17 @@ function Screen:_get_attr_id(attr_state, attrs, hl_id)
end end
return "UNEXPECTED "..self:_pprint_attrs(self._attr_table[hl_id][1]) return "UNEXPECTED "..self:_pprint_attrs(self._attr_table[hl_id][1])
else 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 if self:_equal_attrs(attrs, {}) or
attr_state.ignore == true or attr_state.ignore == true or
self:_attr_index(attr_state.ignore, attrs) ~= nil then self:_attr_index(attr_state.ignore, attrs) ~= nil then
-- ignore this attrs -- ignore this attrs
return nil return nil
end 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 if attr_state.mutable then
table.insert(attr_state.ids, attrs) table.insert(attr_state.ids, attrs)
attr_state.modified = true attr_state.modified = true