diff options
-rw-r--r-- | src/nvim/message.c | 64 | ||||
-rw-r--r-- | src/nvim/message_defs.h | 1 | ||||
-rw-r--r-- | test/functional/ui/messages_spec.lua | 42 |
3 files changed, 100 insertions, 7 deletions
diff --git a/src/nvim/message.c b/src/nvim/message.c index 49bad3c994..a8635f1a61 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -96,6 +96,7 @@ static char *confirm_buttons; // ":confirm" buttons sent to cmdlin MessageHistoryEntry *msg_hist_last = NULL; // Last message (extern for unittest) static MessageHistoryEntry *msg_hist_first = NULL; // First message +static MessageHistoryEntry *msg_hist_temp = NULL; // First potentially temporary message static int msg_hist_len = 0; static int msg_hist_max = 500; // The default max value is 500 @@ -1039,7 +1040,9 @@ static void msg_hist_add_multihl(HlMessage msg, bool temp) // Allocate an entry and add the message at the end of the history. MessageHistoryEntry *entry = xmalloc(sizeof(MessageHistoryEntry)); entry->msg = msg; + entry->temp = temp; entry->kind = msg_ext_kind; + entry->prev = msg_hist_last; entry->next = NULL; if (msg_hist_first == NULL) { @@ -1048,6 +1051,9 @@ static void msg_hist_add_multihl(HlMessage msg, bool temp) if (msg_hist_last != NULL) { msg_hist_last->next = entry; } + if (msg_hist_temp == NULL) { + msg_hist_temp = entry; + } msg_hist_len += !temp; msg_hist_last = entry; @@ -1058,9 +1064,18 @@ static void msg_hist_add_multihl(HlMessage msg, bool temp) static void msg_hist_free_msg(MessageHistoryEntry *entry) { if (entry->next == NULL) { - msg_hist_last = NULL; + msg_hist_last = entry->prev; + } else { + entry->next->prev = entry->prev; + } + if (entry->prev == NULL) { + msg_hist_first = entry->next; + } else { + entry->prev->next = entry->next; + } + if (entry == msg_hist_temp) { + msg_hist_temp = entry->next; } - msg_hist_first = entry->next; hl_msg_free(entry->msg); xfree(entry); } @@ -1069,11 +1084,22 @@ static void msg_hist_free_msg(MessageHistoryEntry *entry) void msg_hist_clear(int keep) { while (msg_hist_len > keep || (keep == 0 && msg_hist_first != NULL)) { - msg_hist_len--; + msg_hist_len -= !msg_hist_first->temp; msg_hist_free_msg(msg_hist_first); } } +void msg_hist_clear_temp(void) +{ + while (msg_hist_temp != NULL) { + MessageHistoryEntry *next = msg_hist_temp->next; + if (msg_hist_temp->temp) { + msg_hist_free_msg(msg_hist_temp); + } + msg_hist_temp = next; + } +} + int messagesopt_changed(void) { int messages_flags_new = 0; @@ -1151,11 +1177,11 @@ void ex_messages(exarg_T *eap) } Array entries = ARRAY_DICT_INIT; - MessageHistoryEntry *p = msg_hist_first; + MessageHistoryEntry *p = eap->skip ? msg_hist_temp : msg_hist_first; int skip = eap->addr_count ? (msg_hist_len - eap->line2) : 0; while (p != NULL) { - if (skip-- > 0) { - // Skipping over messages. + if ((p->temp && !eap->skip) || skip-- > 0) { + // Skipping over count or temporary "g<" messages. } else if (ui_has(kUIMessages)) { Array entry = ARRAY_DICT_INIT; ADD(entry, CSTR_TO_OBJ(p->kind)); @@ -2179,6 +2205,8 @@ static void msg_ext_emit_chunk(void) ADD(*msg_ext_chunks, ARRAY_OBJ(chunk)); } +static bool do_clear_hist_temp = true; + /// The display part of msg_puts_len(). /// May be called recursively to display scroll-back text. static void msg_puts_display(const char *str, int maxlen, int hl_id, int recurse) @@ -2207,6 +2235,10 @@ static void msg_puts_display(const char *str, int maxlen, int hl_id, int recurse int col = (int)(maxlen < 0 ? mb_string2cells(p) : mb_string2cells_len(p, (size_t)(maxlen))); msg_col = (lastline ? 0 : msg_col) + col; + if (do_clear_hist_temp && !strequal(msg_ext_kind, "return_prompt")) { + msg_hist_clear_temp(); + do_clear_hist_temp = false; + } return; } @@ -2573,6 +2605,7 @@ static void store_sb_text(const char **sb_str, const char *s, int hl_id, int *sb void may_clear_sb_text(void) { do_clear_sb_text = SB_CLEAR_ALL; + do_clear_hist_temp = true; } /// Starting to edit the command line: do not clear messages now. @@ -2645,6 +2678,11 @@ void clear_sb_text(bool all) /// "g<" command. void show_sb_text(void) { + if (ui_has(kUIMessages)) { + exarg_T ea = { .arg = "", .skip = true }; + ex_messages(&ea); + return; + } // Only show something if there is more than one line, otherwise it looks // weird, typing a command without output results in one line. msgchunk_T *mp = msg_sb_start(last_msgchunk); @@ -3125,7 +3163,19 @@ void msg_ext_ui_flush(void) if (msg_ext_chunks->size > 0) { Array *tofree = msg_ext_init_chunks(); ui_call_msg_show(cstr_as_string(msg_ext_kind), *tofree, msg_ext_overwrite, msg_ext_history); - api_free_array(*tofree); + if (msg_ext_history || strequal(msg_ext_kind, "return_prompt")) { + api_free_array(*tofree); + } else { + // Add to history as temporary message for "g<". + HlMessage msg = KV_INITIAL_VALUE; + for (size_t i = 0; i < kv_size(*tofree); i++) { + Object *chunk = kv_A(*tofree, i).data.array.items; + kv_push(msg, ((HlMessageChunk){ chunk[1].data.string, (int)chunk[2].data.integer })); + xfree(chunk); + } + xfree(tofree->items); + msg_hist_add_multihl(msg, true); + } xfree(tofree); if (!msg_ext_overwrite) { msg_ext_visible++; diff --git a/src/nvim/message_defs.h b/src/nvim/message_defs.h index addb80fc25..a65f0cd97a 100644 --- a/src/nvim/message_defs.h +++ b/src/nvim/message_defs.h @@ -17,4 +17,5 @@ typedef struct msg_hist { struct msg_hist *prev; ///< Previous message. HlMessage msg; ///< Highlighted message. const char *kind; ///< Message kind (for msg_ext) + bool temp; ///< Temporary message since last command ("g<") } MessageHistoryEntry; diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua index 4770c5e143..a6577f3ca0 100644 --- a/test/functional/ui/messages_spec.lua +++ b/test/functional/ui/messages_spec.lua @@ -1571,6 +1571,48 @@ stack traceback: end, }) end) + + it('g< mapping shows recent messages', function() + command('echo "foo" | echo "bar"') + local s1 = [[ + ^ | + {1:~ }|*4 + ]] + screen:expect({ + grid = s1, + messages = { + { + content = { { 'bar' } }, + history = false, + kind = 'echo', + }, + }, + }) + feed(':messages<CR>g<lt>') + screen:expect({ + grid = [[ + ^ | + {1:~ }|*4 + ]], + messages = { + { + content = { { 'Press ENTER or type command to continue', 6, 18 } }, + history = false, + kind = 'return_prompt', + }, + }, + msg_history = { + { + content = { { 'foo' } }, + kind = 'echo', + }, + { + content = { { 'bar' } }, + kind = 'echo', + }, + }, + }) + end) end) describe('ui/builtin messages', function() |