aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/message.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/message.c')
-rw-r--r--src/nvim/message.c242
1 files changed, 165 insertions, 77 deletions
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 47f246fc76..6104adf2c7 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -19,10 +19,10 @@
#include "nvim/fileio.h"
#include "nvim/func_attr.h"
#include "nvim/getchar.h"
+#include "nvim/main.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/misc1.h"
-#include "nvim/misc2.h"
#include "nvim/keymap.h"
#include "nvim/garray.h"
#include "nvim/ops.h"
@@ -297,8 +297,22 @@ void trunc_string(char_u *s, char_u *buf, int room, int buflen)
len += n;
}
- /* Set the middle and copy the last part. */
- if (e + 3 < buflen) {
+ if (i <= e + 3) {
+ // text fits without truncating
+ if (s != buf) {
+ len = STRLEN(s);
+ if (len >= buflen) {
+ len = buflen - 1;
+ }
+ len = len - e + 1;
+ if (len < 1) {
+ buf[e - 1] = NUL;
+ } else {
+ memmove(buf + e, s + e, len);
+ }
+ }
+ } else if (e + 3 < buflen) {
+ // set the middle and copy the last part
memmove(buf + e, "...", (size_t)3);
len = (int)STRLEN(s + i) + 1;
if (len >= buflen - e - 3)
@@ -306,7 +320,8 @@ void trunc_string(char_u *s, char_u *buf, int room, int buflen)
memmove(buf + e + 3, s + i, len);
buf[e + 3 + len - 1] = NUL;
} else {
- buf[e - 1] = NUL; /* make sure it is truncated */
+ // can't fit in the "...", just truncate it
+ buf[e - 1] = NUL;
}
}
@@ -366,20 +381,17 @@ static int other_sourcing_name(void)
return FALSE;
}
-/*
- * Get the message about the source, as used for an error message.
- * Returns an allocated string with room for one more character.
- * Returns NULL when no message is to be given.
- */
+/// Get the message about the source, as used for an error message.
+/// Returns an allocated string with room for one more character.
+/// Returns NULL when no message is to be given.
static char_u *get_emsg_source(void)
{
- char_u *Buf, *p;
-
if (sourcing_name != NULL && other_sourcing_name()) {
- p = (char_u *)_("Error detected while processing %s:");
- Buf = xmalloc(STRLEN(sourcing_name) + STRLEN(p));
- sprintf((char *)Buf, (char *)p, sourcing_name);
- return Buf;
+ char_u *p = (char_u *)_("Error detected while processing %s:");
+ size_t len = STRLEN(sourcing_name) + STRLEN(p) + 1;
+ char_u *buf = xmalloc(len);
+ snprintf((char *)buf, len, (char *)p, sourcing_name);
+ return buf;
}
return NULL;
}
@@ -493,10 +505,11 @@ int emsg(char_u *s)
* when the message should be ignored completely (used for the
* interrupt message).
*/
- if (cause_errthrow(s, severe, &ignore) == TRUE) {
- if (!ignore)
- did_emsg = TRUE;
- return TRUE;
+ if (cause_errthrow(s, severe, &ignore) == true) {
+ if (!ignore) {
+ did_emsg = true;
+ }
+ return true;
}
// set "v:errmsg", also when using ":silent! cmd"
@@ -507,45 +520,49 @@ int emsg(char_u *s)
* But do write it to the redirection file.
*/
if (emsg_silent != 0) {
- msg_start();
- p = get_emsg_source();
- if (p != NULL) {
- STRCAT(p, "\n");
- redir_write(p, -1);
- xfree(p);
- }
- p = get_emsg_lnum();
- if (p != NULL) {
- STRCAT(p, "\n");
- redir_write(p, -1);
- xfree(p);
+ if (!emsg_noredir) {
+ msg_start();
+ p = get_emsg_source();
+ if (p != NULL) {
+ STRCAT(p, "\n");
+ redir_write(p, STRLEN(p));
+ xfree(p);
+ }
+ p = get_emsg_lnum();
+ if (p != NULL) {
+ STRCAT(p, "\n");
+ redir_write(p, STRLEN(p));
+ xfree(p);
+ }
+ redir_write(s, STRLEN(s));
}
- redir_write(s, -1);
- return TRUE;
+ return true;
}
- /* Reset msg_silent, an error causes messages to be switched back on. */
+ // Reset msg_silent, an error causes messages to be switched back on.
msg_silent = 0;
cmd_silent = FALSE;
- if (global_busy) /* break :global command */
- ++global_busy;
+ if (global_busy) { // break :global command
+ global_busy++;
+ }
- if (p_eb)
- beep_flush(); /* also includes flush_buffers() */
- else
- flush_buffers(FALSE); /* flush internal buffers */
- did_emsg = TRUE; /* flag for DoOneCmd() */
+ if (p_eb) {
+ beep_flush(); // also includes flush_buffers()
+ } else {
+ flush_buffers(false); // flush internal buffers
+ }
+ did_emsg = true; // flag for DoOneCmd()
}
- emsg_on_display = TRUE; /* remember there is an error message */
- ++msg_scroll; /* don't overwrite a previous message */
- attr = hl_attr(HLF_E); /* set highlight mode for error messages */
- if (msg_scrolled != 0)
- need_wait_return = TRUE; /* needed in case emsg() is called after
- * wait_return has reset need_wait_return
- * and a redraw is expected because
- * msg_scrolled is non-zero */
+ emsg_on_display = true; // remember there is an error message
+ msg_scroll++; // don't overwrite a previous message
+ attr = hl_attr(HLF_E); // set highlight mode for error messages
+ if (msg_scrolled != 0) {
+ need_wait_return = true; // needed in case emsg() is called after
+ } // wait_return has reset need_wait_return
+ // and a redraw is expected because
+ // msg_scrolled is non-zero
/*
* Display name and line number for the source of the error.
@@ -579,6 +596,24 @@ bool emsgf(const char *const fmt, ...)
return emsg(IObuff);
}
+static void msg_emsgf_event(void **argv)
+{
+ char *s = argv[0];
+ (void)emsg((char_u *)s);
+ xfree(s);
+}
+
+void msg_schedule_emsgf(const char *const fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vim_vsnprintf((char *)IObuff, IOSIZE, fmt, ap, NULL);
+ va_end(ap);
+
+ char *s = xstrdup((char *)IObuff);
+ loop_schedule(&main_loop, event_create(1, msg_emsgf_event, 1, s));
+}
+
/*
* Like msg(), but truncate to a single line if p_shm contains 't', or when
* "force" is TRUE. This truncates in another way as for normal messages.
@@ -699,21 +734,47 @@ int delete_first_msg(void)
void ex_messages(exarg_T *eap)
{
struct msg_hist *p;
- const char *s;
+ int c = 0;
- msg_hist_off = TRUE;
+ if (STRCMP(eap->arg, "clear") == 0) {
+ int keep = eap->addr_count == 0 ? 0 : eap->line2;
- s = os_getenv("LANG");
- if (s)
- msg_attr((char_u *)
- _("Messages maintainer: Bram Moolenaar <Bram@vim.org>"),
- hl_attr(HLF_T));
+ while (msg_hist_len > keep) {
+ (void)delete_first_msg();
+ }
+ return;
+ }
+
+ if (*eap->arg != NUL) {
+ EMSG(_(e_invarg));
+ return;
+ }
+
+ msg_hist_off = true;
+
+ p = first_msg_hist;
+
+ if (eap->addr_count != 0) {
+ // Count total messages
+ for (; p != NULL && !got_int; p = p->next) {
+ c++;
+ }
+
+ c -= eap->line2;
+
+ // Skip without number of messages specified
+ for (p = first_msg_hist; p != NULL && !got_int && c > 0; p = p->next, c--) {
+ }
+ }
- for (p = first_msg_hist; p != NULL && !got_int; p = p->next)
- if (p->msg != NULL)
+ // Display what was not skipped.
+ for (; p != NULL && !got_int; p = p->next) {
+ if (p->msg != NULL) {
msg_attr(p->msg, p->attr);
+ }
+ }
- msg_hist_off = FALSE;
+ msg_hist_off = false;
}
/*
@@ -785,11 +846,13 @@ void wait_return(int redraw)
State = HITRETURN;
setmouse();
- /* Avoid the sequence that the user types ":" at the hit-return prompt
- * to start an Ex command, but the file-changed dialog gets in the
- * way. */
- if (need_check_timestamps)
- check_timestamps(FALSE);
+ cmdline_row = msg_row;
+ // Avoid the sequence that the user types ":" at the hit-return prompt
+ // to start an Ex command, but the file-changed dialog gets in the
+ // way.
+ if (need_check_timestamps) {
+ check_timestamps(false);
+ }
hit_return_msg();
@@ -1970,6 +2033,7 @@ static void msg_puts_printf(char *str, int maxlen)
*/
static int do_more_prompt(int typed_char)
{
+ static bool entered = false;
int used_typed_char = typed_char;
int oldState = State;
int c;
@@ -1979,6 +2043,14 @@ static int do_more_prompt(int typed_char)
msgchunk_T *mp;
int i;
+ // We get called recursively when a timer callback outputs a message. In
+ // that case don't show another prompt. Also when at the hit-Enter prompt
+ // and nothing was typed.
+ if (entered || (State == HITRETURN && typed_char == 0)) {
+ return false;
+ }
+ entered = true;
+
if (typed_char == 'G') {
/* "g<": Find first line on the last page. */
mp_last = msg_sb_start(last_msgchunk);
@@ -2153,9 +2225,11 @@ static int do_more_prompt(int typed_char)
if (quit_more) {
msg_row = Rows - 1;
msg_col = 0;
- } else if (cmdmsg_rl)
+ } else if (cmdmsg_rl) {
msg_col = Columns - 1;
+ }
+ entered = false;
return retval;
}
@@ -2377,6 +2451,10 @@ static void redir_write(char_u *str, int maxlen)
char_u *s = str;
static int cur_col = 0;
+ if (maxlen == 0) {
+ return;
+ }
+
/* Don't do anything for displaying prompts and the like. */
if (redir_off)
return;
@@ -2389,26 +2467,37 @@ static void redir_write(char_u *str, int maxlen)
/* If the string doesn't start with CR or NL, go to msg_col */
if (*s != '\n' && *s != '\r') {
while (cur_col < msg_col) {
- if (redir_reg)
- write_reg_contents(redir_reg, (char_u *)" ", -1, TRUE);
- else if (redir_vname)
+ if (capture_ga) {
+ ga_concat_len(capture_ga, " ", 1);
+ }
+ if (redir_reg) {
+ write_reg_contents(redir_reg, (char_u *)" ", 1, true);
+ } else if (redir_vname) {
var_redir_str((char_u *)" ", -1);
- else if (redir_fd != NULL)
+ } else if (redir_fd != NULL) {
fputs(" ", redir_fd);
- if (verbose_fd != NULL)
+ }
+ if (verbose_fd != NULL) {
fputs(" ", verbose_fd);
- ++cur_col;
+ }
+ cur_col++;
}
}
- if (redir_reg)
- write_reg_contents(redir_reg, s, maxlen, TRUE);
- if (redir_vname)
+ size_t len = maxlen == -1 ? STRLEN(s) : (size_t)maxlen;
+ if (capture_ga) {
+ ga_concat_len(capture_ga, (const char *)str, len);
+ }
+ if (redir_reg) {
+ write_reg_contents(redir_reg, s, len, true);
+ }
+ if (redir_vname) {
var_redir_str(s, maxlen);
+ }
/* Write and adjust the current column. */
while (*s != NUL && (maxlen < 0 || (int)(s - str) < maxlen)) {
- if (!redir_reg && !redir_vname)
+ if (!redir_reg && !redir_vname && !capture_ga)
if (redir_fd != NULL)
putc(*s, redir_fd);
if (verbose_fd != NULL)
@@ -2430,8 +2519,7 @@ static void redir_write(char_u *str, int maxlen)
int redirecting(void)
{
return redir_fd != NULL || *p_vfile != NUL
- || redir_reg || redir_vname
- ;
+ || redir_reg || redir_vname || capture_ga != NULL;
}
/*