diff options
author | Luuk van Baal <luukvbaal@gmail.com> | 2024-03-08 14:44:58 +0100 |
---|---|---|
committer | Luuk van Baal <luukvbaal@gmail.com> | 2024-11-09 14:28:17 +0100 |
commit | 4f9260d06a48216862ebb34fc33744486b058f58 (patch) | |
tree | f69ecc9f6556e504af0f0b4aa04a72380f866162 | |
parent | 5cfa7a72f8c40cdcc0fa93693689915e913806f1 (diff) | |
download | rneovim-4f9260d06a48216862ebb34fc33744486b058f58.tar.gz rneovim-4f9260d06a48216862ebb34fc33744486b058f58.tar.bz2 rneovim-4f9260d06a48216862ebb34fc33744486b058f58.zip |
feat(ext_messages): add hl_id to ext_messages chunks
Problem: Ext_messages chunks only contain the highlight attr id, which
is not very useful for vim.ui_attach() consumers.
Solotion: Add highlight group id to message chunks, which can easily be
used to highlight text in the TUI through nvim_buf_set_extmark():
hl_group = synIDattr(id, "name").
-rw-r--r-- | runtime/doc/news.txt | 2 | ||||
-rw-r--r-- | runtime/doc/ui.txt | 9 | ||||
-rw-r--r-- | src/nvim/message.c | 5 | ||||
-rw-r--r-- | src/nvim/normal.c | 3 | ||||
-rw-r--r-- | src/nvim/statusline.c | 4 | ||||
-rw-r--r-- | test/functional/lua/ui_event_spec.lua | 6 | ||||
-rw-r--r-- | test/functional/ui/messages_spec.lua | 160 | ||||
-rw-r--r-- | test/functional/ui/screen.lua | 4 |
8 files changed, 112 insertions, 81 deletions
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index df794596b8..41b9d623a2 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -283,6 +283,8 @@ UI |hl-PmenuMatchSel| inherits highlights from both |hl-PmenuSel| and |hl-PmenuMatch|. +• |ui-messages| content chunks now also contain the highlight group ID. + ============================================================================== CHANGED FEATURES *news-changed* diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt index cb057a8fd2..4ee8121034 100644 --- a/runtime/doc/ui.txt +++ b/runtime/doc/ui.txt @@ -805,10 +805,11 @@ must handle. kinds as the empty kind. content - Array of `[attr_id, text_chunk]` tuples, building up the message - text of chunks of different highlights. No extra spacing should be - added between chunks, the `text_chunk` by itself contains any - necessary whitespace. Messages can contain line breaks "\n". + Array of `[attr_id, text_chunk, hl_id]` tuples, building up the + message text of chunks of different highlights. No extra spacing + should be added between chunks, the `text_chunk` by itself + contains any necessary whitespace. Messages can contain line + breaks "\n". replace_last Decides how multiple messages should be displayed: diff --git a/src/nvim/message.c b/src/nvim/message.c index dc9c7d0c37..977b37f8c3 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -139,6 +139,7 @@ static const char *msg_ext_kind = NULL; static Array *msg_ext_chunks = NULL; static garray_T msg_ext_last_chunk = GA_INIT(sizeof(char), 40); static sattr_T msg_ext_last_attr = -1; +static int msg_ext_hl_id; static size_t msg_ext_cur_len = 0; static bool msg_ext_overwrite = false; ///< will overwrite last message @@ -1088,12 +1089,14 @@ void ex_messages(exarg_T *eap) Array content_entry = ARRAY_DICT_INIT; ADD(content_entry, INTEGER_OBJ(chunk.hl_id ? syn_id2attr(chunk.hl_id) : 0)); ADD(content_entry, STRING_OBJ(copy_string(chunk.text, NULL))); + ADD(content_entry, INTEGER_OBJ(chunk.hl_id)); ADD(content, ARRAY_OBJ(content_entry)); } } else if (p->msg && p->msg[0]) { Array content_entry = ARRAY_DICT_INIT; ADD(content_entry, INTEGER_OBJ(p->hl_id ? syn_id2attr(p->hl_id) : 0)); ADD(content_entry, CSTR_TO_OBJ(p->msg)); + ADD(content_entry, INTEGER_OBJ(p->hl_id)); ADD(content, ARRAY_OBJ(content_entry)); } ADD(entry, ARRAY_OBJ(content)); @@ -2125,6 +2128,7 @@ static void msg_ext_emit_chunk(void) msg_ext_last_attr = -1; String text = ga_take_string(&msg_ext_last_chunk); ADD(chunk, STRING_OBJ(text)); + ADD(chunk, INTEGER_OBJ(msg_ext_hl_id)); ADD(*msg_ext_chunks, ARRAY_OBJ(chunk)); } @@ -2141,6 +2145,7 @@ static void msg_puts_display(const char *str, int maxlen, int hl_id, int recurse if (ui_has(kUIMessages)) { if (attr != msg_ext_last_attr) { + msg_ext_hl_id = hl_id; msg_ext_emit_chunk(); msg_ext_last_attr = attr; } diff --git a/src/nvim/normal.c b/src/nvim/normal.c index d0517d5e4f..d2716bf236 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -2081,11 +2081,12 @@ static void display_showcmd(void) if (ui_has(kUIMessages)) { MAXSIZE_TEMP_ARRAY(content, 1); - MAXSIZE_TEMP_ARRAY(chunk, 2); + MAXSIZE_TEMP_ARRAY(chunk, 3); if (!showcmd_is_clear) { // placeholder for future highlight support ADD_C(chunk, INTEGER_OBJ(0)); ADD_C(chunk, CSTR_AS_OBJ(showcmd_buf)); + ADD_C(chunk, INTEGER_OBJ(0)); ADD_C(content, ARRAY_OBJ(chunk)); } ui_call_msg_showcmd(content); diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 6b8f5e27a3..d9ac1aa347 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -582,9 +582,11 @@ void win_redr_ruler(win_T *wp) if (ui_has(kUIMessages) && !part_of_status) { MAXSIZE_TEMP_ARRAY(content, 1); - MAXSIZE_TEMP_ARRAY(chunk, 2); + MAXSIZE_TEMP_ARRAY(chunk, 3); ADD_C(chunk, INTEGER_OBJ(attr)); ADD_C(chunk, CSTR_AS_OBJ(buffer)); + ADD_C(chunk, INTEGER_OBJ(HLF_MSG + 1)); + assert(attr == HL_ATTR(HLF_MSG)); ADD_C(content, ARRAY_OBJ(chunk)); ui_call_msg_ruler(content); did_show_ext_ruler = true; diff --git a/test/functional/lua/ui_event_spec.lua b/test/functional/lua/ui_event_spec.lua index 0a6deaa41c..52045b76ff 100644 --- a/test/functional/lua/ui_event_spec.lua +++ b/test/functional/lua/ui_event_spec.lua @@ -151,9 +151,9 @@ describe('vim.ui_attach', function() { 'msg_history_show', { - { 'echomsg', { { 0, 'message1' } } }, - { '', { { 0, 'message2' } } }, - { 'echomsg', { { 0, 'message3' } } }, + { 'echomsg', { { 0, 'message1', 0 } } }, + { '', { { 0, 'message2', 0 } } }, + { 'echomsg', { { 0, 'message3', 0 } } }, }, }, }, actual, vim.inspect(actual)) diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index a3e5068e55..d48af589ea 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -50,7 +50,7 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { '\ntest\n[O]k: ', 6 } }, + content = { { '\ntest\n[O]k: ', 6, 11 } }, kind = 'confirm', }, }, @@ -78,7 +78,7 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { '\ntest\n[O]k: ', 6 } }, + content = { { '\ntest\n[O]k: ', 6, 11 } }, kind = 'confirm', }, }, @@ -92,7 +92,7 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { '\ntest\n[O]k: ', 6 } }, + content = { { '\ntest\n[O]k: ', 6, 11 } }, kind = 'confirm', }, { @@ -100,7 +100,7 @@ describe('ui/ext_messages', function() kind = 'echo', }, { - content = { { 'Press ENTER or type command to continue', 6 } }, + content = { { 'Press ENTER or type command to continue', 6, 19 } }, kind = 'return_prompt', }, }, @@ -117,7 +117,7 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { 'replace with X (y/n/a/q/l/^E/^Y)?', 6 } }, + content = { { 'replace with X (y/n/a/q/l/^E/^Y)?', 6, 19 } }, kind = 'confirm_sub', }, }, @@ -136,7 +136,7 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { 'W10: Warning: Changing a readonly file', 19 } }, + content = { { 'W10: Warning: Changing a readonly file', 19, 27 } }, kind = 'wmsg', }, }, @@ -152,7 +152,7 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { 'search hit BOTTOM, continuing at TOP', 19 } }, + content = { { 'search hit BOTTOM, continuing at TOP', 19, 27 } }, kind = 'wmsg', }, }, @@ -168,15 +168,15 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { 'Error detected while processing :', 9 } }, + content = { { 'Error detected while processing :', 9, 7 } }, kind = 'emsg', }, { - content = { { 'E605: Exception not caught: foo', 9 } }, + content = { { 'E605: Exception not caught: foo', 9, 7 } }, kind = '', }, { - content = { { 'Press ENTER or type command to continue', 6 } }, + content = { { 'Press ENTER or type command to continue', 6, 19 } }, kind = 'return_prompt', }, }, @@ -209,7 +209,7 @@ describe('ui/ext_messages', function() {1:~ }|*4 ]], messages = { { - content = { { 'raa', 9 } }, + content = { { 'raa', 9, 7 } }, kind = 'echoerr', } }, } @@ -236,15 +236,15 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { 'bork', 9 } }, + content = { { 'bork', 9, 7 } }, kind = 'echoerr', }, { - content = { { 'fail', 9 } }, + content = { { 'fail', 9, 7 } }, kind = 'echoerr', }, { - content = { { 'Press ENTER or type command to continue', 6 } }, + content = { { 'Press ENTER or type command to continue', 6, 19 } }, kind = 'return_prompt', }, }, @@ -258,19 +258,19 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { 'bork', 9 } }, + content = { { 'bork', 9, 7 } }, kind = 'echoerr', }, { - content = { { 'fail', 9 } }, + content = { { 'fail', 9, 7 } }, kind = 'echoerr', }, { - content = { { 'extrafail', 9 } }, + content = { { 'extrafail', 9, 7 } }, kind = 'echoerr', }, { - content = { { 'Press ENTER or type command to continue', 6 } }, + content = { { 'Press ENTER or type command to continue', 6, 19 } }, kind = 'return_prompt', }, }, @@ -292,7 +292,7 @@ describe('ui/ext_messages', function() {1:~ }|*4 ]], messages = { { - content = { { 'problem', 9 } }, + content = { { 'problem', 9, 7 } }, kind = 'echoerr', } }, cmdline = { @@ -320,15 +320,15 @@ describe('ui/ext_messages', function() {1:~ }|*4 ]], msg_history = { - { kind = 'echoerr', content = { { 'raa', 9 } } }, - { kind = 'echoerr', content = { { 'bork', 9 } } }, - { kind = 'echoerr', content = { { 'fail', 9 } } }, - { kind = 'echoerr', content = { { 'extrafail', 9 } } }, - { kind = 'echoerr', content = { { 'problem', 9 } } }, + { kind = 'echoerr', content = { { 'raa', 9, 7 } } }, + { kind = 'echoerr', content = { { 'bork', 9, 7 } } }, + { kind = 'echoerr', content = { { 'fail', 9, 7 } } }, + { kind = 'echoerr', content = { { 'extrafail', 9, 7 } } }, + { kind = 'echoerr', content = { { 'problem', 9, 7 } } }, }, messages = { { - content = { { 'Press ENTER or type command to continue', 6 } }, + content = { { 'Press ENTER or type command to continue', 6, 19 } }, kind = 'return_prompt', }, }, @@ -351,10 +351,12 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - messages = { { - content = { { 'bork\nfail', 9 } }, - kind = 'echoerr', - } }, + messages = { + { + content = { { 'bork\nfail', 9, 7 } }, + kind = 'echoerr', + }, + }, } feed(':messages<cr>') @@ -365,13 +367,13 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { 'Press ENTER or type command to continue', 6 } }, + content = { { 'Press ENTER or type command to continue', 6, 19 } }, kind = 'return_prompt', }, }, msg_history = { { - content = { { 'bork\nfail', 9 } }, + content = { { 'bork\nfail', 9, 7 } }, kind = 'echoerr', }, }, @@ -418,15 +420,15 @@ describe('ui/ext_messages', function() { content = { { '\nErrorMsg ' }, - { 'xxx', 9 }, + { 'xxx', 9, 0 }, { ' ' }, - { 'ctermfg=', 18 }, + { 'ctermfg=', 18, 0 }, { '15 ' }, - { 'ctermbg=', 18 }, + { 'ctermbg=', 18, 0 }, { '1 ' }, - { 'guifg=', 18 }, + { 'guifg=', 18, 0 }, { 'White ' }, - { 'guibg=', 18 }, + { 'guibg=', 18, 0 }, { 'Red' }, }, kind = '', @@ -446,7 +448,10 @@ describe('ui/ext_messages', function() messages = { { content = { { 'x #1' } }, kind = '' }, { content = { { 'y #2' } }, kind = '' }, - { content = { { 'Press ENTER or type command to continue', 6 } }, kind = 'return_prompt' }, + { + content = { { 'Press ENTER or type command to continue', 6, 19 } }, + kind = 'return_prompt', + }, }, } end) @@ -459,7 +464,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - showmode = { { '-- INSERT --', 5 } }, + showmode = { { '-- INSERT --', 5, 12 } }, } feed('alphpabet<cr>alphanum<cr>') @@ -470,7 +475,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*2 ]], - showmode = { { '-- INSERT --', 5 } }, + showmode = { { '-- INSERT --', 5, 12 } }, } feed('<c-x>') @@ -481,7 +486,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*2 ]], - showmode = { { '-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)', 5 } }, + showmode = { { '-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)', 5, 12 } }, } feed('<c-p>') @@ -497,7 +502,7 @@ describe('ui/ext_messages', function() items = { { 'alphpabet', '', '', '' }, { 'alphanum', '', '', '' } }, pos = 1, }, - showmode = { { '-- Keyword Local completion (^N^P) ', 5 }, { 'match 1 of 2', 6 } }, + showmode = { { '-- Keyword Local completion (^N^P) ', 5, 19 }, { 'match 1 of 2', 6, 19 } }, } -- echomsg and showmode don't overwrite each other, this is the same @@ -519,7 +524,7 @@ describe('ui/ext_messages', function() content = { { 'stuff' } }, kind = 'echomsg', } }, - showmode = { { '-- Keyword Local completion (^N^P) ', 5 }, { 'match 1 of 2', 6 } }, + showmode = { { '-- Keyword Local completion (^N^P) ', 5, 19 }, { 'match 1 of 2', 6, 19 } }, } feed('<c-p>') @@ -539,7 +544,7 @@ describe('ui/ext_messages', function() content = { { 'stuff' } }, kind = 'echomsg', } }, - showmode = { { '-- Keyword Local completion (^N^P) ', 5 }, { 'match 2 of 2', 6 } }, + showmode = { { '-- Keyword Local completion (^N^P) ', 5, 19 }, { 'match 2 of 2', 6, 19 } }, } feed('<esc>:messages<cr>') @@ -556,7 +561,7 @@ describe('ui/ext_messages', function() } }, messages = { { - content = { { 'Press ENTER or type command to continue', 6 } }, + content = { { 'Press ENTER or type command to continue', 6, 19 } }, kind = 'return_prompt', }, }, @@ -570,7 +575,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - showmode = { { 'recording @q', 5 } }, + showmode = { { 'recording @q', 5, 12 } }, } feed('i') @@ -579,7 +584,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - showmode = { { '-- INSERT --recording @q', 5 } }, + showmode = { { '-- INSERT --recording @q', 5, 12 } }, } feed('<esc>') @@ -588,7 +593,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - showmode = { { 'recording @q', 5 } }, + showmode = { { 'recording @q', 5, 12 } }, } feed('q') @@ -607,7 +612,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - showmode = { { 'recording @q', 5 } }, + showmode = { { 'recording @q', 5, 12 } }, mode = 'normal', } @@ -617,7 +622,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - showmode = { { 'recording @q', 5 } }, + showmode = { { 'recording @q', 5, 12 } }, mode = 'insert', } @@ -627,7 +632,7 @@ describe('ui/ext_messages', function() ^ | {1:~ }|*4 ]], - showmode = { { 'recording @q', 5 } }, + showmode = { { 'recording @q', 5, 12 } }, mode = 'normal', } @@ -643,20 +648,22 @@ describe('ui/ext_messages', function() it('supports &showcmd and &ruler', function() command('set showcmd ruler') - screen:expect { + command('hi link MsgArea ErrorMsg') + screen:expect({ grid = [[ - ^ | - {1:~ }|*4 - ]], - ruler = { { '0,0-1 All' } }, - } + ^ | + {1:~ }|*4 + ]], + ruler = { { '0,0-1 All', 9, 62 } }, + }) + command('hi clear MsgArea') feed('i') screen:expect { grid = [[ ^ | {1:~ }|*4 ]], - showmode = { { '-- INSERT --', 5 } }, + showmode = { { '-- INSERT --', 5, 12 } }, ruler = { { '0,1 All' } }, } feed('abcde<cr>12345<esc>') @@ -694,7 +701,7 @@ describe('ui/ext_messages', function() {17:123}45 | {1:~ }|*3 ]], - showmode = { { '-- VISUAL BLOCK --', 5 } }, + showmode = { { '-- VISUAL BLOCK --', 5, 12 } }, showcmd = { { '2x3' } }, ruler = { { '1,3 All' } }, }) @@ -775,7 +782,7 @@ describe('ui/ext_messages', function() {1:~ }|*4 ]], messages = { { - content = { { 'bork', 9 } }, + content = { { 'bork', 9, 7 } }, kind = 'echoerr', } }, } @@ -800,7 +807,7 @@ describe('ui/ext_messages', function() ]], messages = { { - content = { { 'E117: Unknown function: nosuchfunction', 9 } }, + content = { { 'E117: Unknown function: nosuchfunction', 9, 7 } }, kind = 'emsg', }, }, @@ -815,12 +822,12 @@ describe('ui/ext_messages', function() msg_history = { { kind = 'echomsg', content = { { 'howdy' } } }, { kind = '', content = { { 'Type :qa and press <Enter> to exit Nvim' } } }, - { kind = 'echoerr', content = { { 'bork', 9 } } }, - { kind = 'emsg', content = { { 'E117: Unknown function: nosuchfunction', 9 } } }, + { kind = 'echoerr', content = { { 'bork', 9, 7 } } }, + { kind = 'emsg', content = { { 'E117: Unknown function: nosuchfunction', 9, 7 } } }, }, messages = { { - content = { { 'Press ENTER or type command to continue', 6 } }, + content = { { 'Press ENTER or type command to continue', 6, 19 } }, kind = 'return_prompt', }, }, @@ -893,6 +900,7 @@ stack traceback: [C]: in function 'error' [string ":lua"]:1: in main chunk]], 9, + 7, }, }, kind = 'lua_error', @@ -912,7 +920,7 @@ stack traceback: messages = { { content = { - { "Error invoking 'test_method' on channel 1:\ncomplete\nerror\n\nmessage", 9 }, + { "Error invoking 'test_method' on channel 1:\ncomplete\nerror\n\nmessage", 9, 7 }, }, kind = 'rpc_error', }, @@ -937,7 +945,7 @@ stack traceback: { content = { { '\nn Q @@\nn Y y$\nn j ' }, - { '*', 18 }, + { '*', 18, 0 }, { ' k' }, }, kind = '', @@ -1035,7 +1043,10 @@ stack traceback: {1:~ }|*4 ]], messages = { - { content = { { 'wow, ', 10 }, { 'such\n\nvery ', 9 }, { 'color', 8 } }, kind = 'echomsg' }, + { + content = { { 'wow, ', 10, 7 }, { 'such\n\nvery ', 9, 13 }, { 'color', 8, 13 } }, + kind = 'echomsg', + }, }, } @@ -1057,10 +1068,16 @@ stack traceback: {1:~ }|*4 ]], messages = { - { content = { { 'Press ENTER or type command to continue', 6 } }, kind = 'return_prompt' }, + { + content = { { 'Press ENTER or type command to continue', 6, 19 } }, + kind = 'return_prompt', + }, }, msg_history = { - { content = { { 'wow, ', 10 }, { 'such\n\nvery ', 9 }, { 'color', 8 } }, kind = 'echomsg' }, + { + content = { { 'wow, ', 10, 9 }, { 'such\n\nvery ', 9, 7 }, { 'color', 8, 13 } }, + kind = 'echomsg', + }, }, } @@ -1678,7 +1695,7 @@ describe('ui/ext_messages', function() {1:~ }type :help iccf{18:<Enter>} for information {1: }| {1:~ }|*5 ]] - local showmode = { { '-- INSERT --', 5 } } + local showmode = { { '-- INSERT --', 5, 12 } } screen:expect(introscreen) -- <c-l> (same as :mode) does _not_ clear intro message @@ -1752,7 +1769,10 @@ describe('ui/ext_messages', function() |*5 ]], messages = { - { content = { { 'Press ENTER or type command to continue', 6 } }, kind = 'return_prompt' }, + { + content = { { 'Press ENTER or type command to continue', 6, 19 } }, + kind = 'return_prompt', + }, }, } diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index f1891b608e..358e54dc55 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -1524,7 +1524,7 @@ end function Screen:_chunks_repr(chunks, attr_state) local repr_chunks = {} for i, chunk in ipairs(chunks) do - local hl, text = unpack(chunk) + local hl, text, id = unpack(chunk) local attrs if self._options.ext_linegrid then attrs = self._attr_table[hl][1] @@ -1532,7 +1532,7 @@ function Screen:_chunks_repr(chunks, attr_state) attrs = hl end local attr_id = self:_get_attr_id(attr_state, attrs, hl) - repr_chunks[i] = { text, attr_id } + repr_chunks[i] = { text, attr_id, attr_id and id or nil } end return repr_chunks end |