diff options
-rw-r--r-- | runtime/doc/ui.txt | 8 | ||||
-rw-r--r-- | src/nvim/api/ui.c | 1 | ||||
-rw-r--r-- | src/nvim/api/ui_events.in.h | 2 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 21 | ||||
-rw-r--r-- | src/nvim/highlight.c | 20 | ||||
-rw-r--r-- | src/nvim/highlight_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/ops.c | 12 | ||||
-rw-r--r-- | src/nvim/syntax.c | 7 | ||||
-rw-r--r-- | test/functional/ui/highlight_spec.lua | 32 | ||||
-rw-r--r-- | test/functional/ui/screen.lua | 33 | ||||
-rw-r--r-- | third-party/cmake/BuildLuarocks.cmake | 2 |
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}) |