aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/message.c64
-rw-r--r--src/nvim/message_defs.h1
-rw-r--r--test/functional/ui/messages_spec.lua42
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()