diff options
Diffstat (limited to 'src/nvim/message.c')
-rw-r--r-- | src/nvim/message.c | 242 |
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; } /* |