aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/ui.txt8
-rw-r--r--src/nvim/api/ui.c1
-rw-r--r--src/nvim/api/ui_events.in.h2
-rw-r--r--src/nvim/ex_docmd.c21
-rw-r--r--src/nvim/highlight.c20
-rw-r--r--src/nvim/highlight_defs.h1
-rw-r--r--src/nvim/ops.c12
-rw-r--r--src/nvim/syntax.c7
-rw-r--r--test/functional/ui/highlight_spec.lua32
-rw-r--r--test/functional/ui/screen.lua33
-rw-r--r--third-party/cmake/BuildLuarocks.cmake2
11 files changed, 107 insertions, 32 deletions
diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt
index c56f9467a3..1440e2ac78 100644
--- a/runtime/doc/ui.txt
+++ b/runtime/doc/ui.txt
@@ -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
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 4f28ea5af3..20ed77afad 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -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;
diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h
index a1d25766fe..41bf0af65b 100644
--- a/src/nvim/api/ui_events.in.h
+++ b/src/nvim/api/ui_events.in.h
@@ -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)
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index acd6db4d95..072f2fab40 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -8453,24 +8453,23 @@ static void ex_tag_cmd(exarg_T *eap, char_u *name)
int cmd;
switch (name[1]) {
- case 'j': cmd = DT_JUMP; /* ":tjump" */
+ case 'j': cmd = DT_JUMP; // ":tjump"
break;
- case 's': cmd = DT_SELECT; /* ":tselect" */
+ case 's': cmd = DT_SELECT; // ":tselect"
break;
- case 'p': cmd = DT_PREV; /* ":tprevious" */
+ case 'p': // ":tprevious"
+ case 'N': cmd = DT_PREV; // ":tNext"
break;
- case 'N': cmd = DT_PREV; /* ":tNext" */
+ case 'n': cmd = DT_NEXT; // ":tnext"
break;
- case 'n': cmd = DT_NEXT; /* ":tnext" */
+ case 'o': cmd = DT_POP; // ":pop"
break;
- case 'o': cmd = DT_POP; /* ":pop" */
+ case 'f': // ":tfirst"
+ case 'r': cmd = DT_FIRST; // ":trewind"
break;
- case 'f': /* ":tfirst" */
- case 'r': cmd = DT_FIRST; /* ":trewind" */
+ case 'l': cmd = DT_LAST; // ":tlast"
break;
- case 'l': cmd = DT_LAST; /* ":tlast" */
- break;
- default: /* ":tag" */
+ default: // ":tag"
if (p_cst && *eap->arg != NUL) {
ex_cstag(eap);
return;
diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c
index e5cbb4f944..f11880cb2b 100644
--- a/src/nvim/highlight.c
+++ b/src/nvim/highlight.c
@@ -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();
diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h
index 25d859c55d..afccf9e6f6 100644
--- a/src/nvim/highlight_defs.h
+++ b/src/nvim/highlight_defs.h
@@ -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);
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index e07e93060a..5fbcd54a19 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -1471,7 +1471,8 @@ int op_delete(oparg_T *oap)
// copy up to deleted part
memmove(newp, oldp, (size_t)bd.textcol);
// insert spaces
- memset(newp + bd.textcol, ' ', (size_t)(bd.startspaces + bd.endspaces));
+ memset(newp + bd.textcol, ' ', (size_t)bd.startspaces +
+ (size_t)bd.endspaces);
// copy the part after the deleted part
oldp += bd.textcol + bd.textlen;
STRMOVE(newp + bd.textcol + bd.startspaces + bd.endspaces, oldp);
@@ -1743,7 +1744,7 @@ int op_replace(oparg_T *oap, int c)
oldp = get_cursor_line_ptr();
oldlen = (int)STRLEN(oldp);
- size_t newp_size = (size_t)(bd.textcol + bd.startspaces);
+ size_t newp_size = (size_t)bd.textcol + (size_t)bd.startspaces;
if (had_ctrl_v_cr || (c != '\r' && c != '\n')) {
newp_size += (size_t)numc;
if (!bd.is_short) {
@@ -1760,6 +1761,8 @@ int op_replace(oparg_T *oap, int c)
// insert replacement chars CHECK FOR ALLOCATED SPACE
// REPLACE_CR_NCHAR/REPLACE_NL_NCHAR is used for entering CR literally.
size_t after_p_len = 0;
+ int col = oldlen - bd.textcol - bd.textlen + 1;
+ assert(col >= 0);
if (had_ctrl_v_cr || (c != '\r' && c != '\n')) {
// strlen(newp) at this point
int newp_len = bd.textcol + bd.startspaces;
@@ -1771,12 +1774,11 @@ int op_replace(oparg_T *oap, int c)
memset(newp + newp_len, ' ', (size_t)bd.endspaces);
newp_len += bd.endspaces;
// copy the part after the changed part
- memmove(newp + newp_len, oldp,
- (size_t)(oldlen - bd.textcol - bd.textlen + 1));
+ memmove(newp + newp_len, oldp, (size_t)col);
}
} else {
// Replacing with \r or \n means splitting the line.
- after_p_len = (size_t)(oldlen - bd.textcol - bd.textlen + 1);
+ after_p_len = (size_t)col;
after_p = (char_u *)xmalloc(after_p_len);
memmove(after_p, oldp, after_p_len);
}
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 470c77eb93..84392680c5 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -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"
@@ -7508,6 +7509,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
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 85b5aed2f8..08566fe493 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -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()
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
index 31669f5578..eb059c38ee 100644
--- a/test/functional/ui/screen.lua
+++ b/test/functional/ui/screen.lua
@@ -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
diff --git a/third-party/cmake/BuildLuarocks.cmake b/third-party/cmake/BuildLuarocks.cmake
index 7f038c732d..87e2946c96 100644
--- a/third-party/cmake/BuildLuarocks.cmake
+++ b/third-party/cmake/BuildLuarocks.cmake
@@ -163,7 +163,7 @@ if(USE_BUNDLED_BUSTED)
endif()
add_custom_command(OUTPUT ${BUSTED_EXE}
COMMAND ${LUAROCKS_BINARY}
- ARGS build busted 2.0.rc13-0 ${LUAROCKS_BUILDARGS}
+ ARGS build busted 2.0.0 ${LUAROCKS_BUILDARGS}
DEPENDS penlight)
add_custom_target(busted DEPENDS ${BUSTED_EXE})