mirror of
https://github.com/neovim/neovim.git
synced 2025-10-17 23:31:51 +00:00
vim-patch:9.1.0908: not possible to configure :messages (#31492)
Problem: not possible to configure :messages
Solution: add the 'messagesopt' option (Shougo Matsushita)
closes: vim/vim#16068
51d4d84d6a
Co-authored-by: Shougo Matsushita <Shougo.Matsu@gmail.com>
Co-authored-by: h_east <h.east.727@gmail.com>
This commit is contained in:
@@ -6101,12 +6101,18 @@ static void ex_sleep(exarg_T *eap)
|
||||
default:
|
||||
semsg(_(e_invarg2), eap->arg); return;
|
||||
}
|
||||
do_sleep(len);
|
||||
do_sleep(len, false);
|
||||
}
|
||||
|
||||
/// Sleep for "msec" milliseconds, but return early on CTRL-C.
|
||||
void do_sleep(int64_t msec)
|
||||
///
|
||||
/// @param hide_cursor hide the cursor if true
|
||||
void do_sleep(int64_t msec, bool hide_cursor)
|
||||
{
|
||||
if (hide_cursor) {
|
||||
ui_busy_start();
|
||||
}
|
||||
|
||||
ui_flush(); // flush before waiting
|
||||
LOOP_PROCESS_EVENTS_UNTIL(&main_loop, main_loop.events, msec, got_int);
|
||||
|
||||
@@ -6115,6 +6121,10 @@ void do_sleep(int64_t msec)
|
||||
if (got_int) {
|
||||
vpeekc();
|
||||
}
|
||||
|
||||
if (hide_cursor) {
|
||||
ui_busy_stop();
|
||||
}
|
||||
}
|
||||
|
||||
/// ":winsize" command (obsolete).
|
||||
|
@@ -47,7 +47,9 @@ end
|
||||
--- @param s string
|
||||
--- @return string
|
||||
local lowercase_to_titlecase = function(s)
|
||||
return s:sub(1, 1):upper() .. s:sub(2)
|
||||
return table.concat(vim.tbl_map(function(word) --- @param word string
|
||||
return word:sub(1, 1):upper() .. word:sub(2)
|
||||
end, vim.split(s, '[-_]')))
|
||||
end
|
||||
|
||||
-- Generate options enum file
|
||||
@@ -177,7 +179,7 @@ for _, option in ipairs(options_meta) do
|
||||
vars_w(
|
||||
(' kOpt%sFlag%s = 0x%02x,'):format(
|
||||
opt_name,
|
||||
lowercase_to_titlecase(flag_name),
|
||||
lowercase_to_titlecase(flag_name:gsub(':$', '')),
|
||||
enum_values[flag_name]
|
||||
)
|
||||
)
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "nvim/event/loop.h"
|
||||
#include "nvim/event/multiqueue.h"
|
||||
#include "nvim/ex_cmds_defs.h"
|
||||
#include "nvim/ex_docmd.h"
|
||||
#include "nvim/ex_eval.h"
|
||||
#include "nvim/fileio.h"
|
||||
#include "nvim/garray.h"
|
||||
@@ -94,6 +95,16 @@ static char *confirm_msg_tail; // tail of confirm_msg
|
||||
MessageHistoryEntry *first_msg_hist = NULL;
|
||||
MessageHistoryEntry *last_msg_hist = NULL;
|
||||
static int msg_hist_len = 0;
|
||||
static int msg_hist_max = 500; // The default max value is 500
|
||||
|
||||
// args in 'messagesopt' option
|
||||
#define MESSAGES_OPT_HIT_ENTER "hit-enter"
|
||||
#define MESSAGES_OPT_WAIT "wait:"
|
||||
#define MESSAGES_OPT_HISTORY "history:"
|
||||
|
||||
// The default is "hit-enter,history:500"
|
||||
static int msg_flags = kOptMoptFlagHitEnter | kOptMoptFlagHistory;
|
||||
static int msg_wait = 0;
|
||||
|
||||
static FILE *verbose_fd = NULL;
|
||||
static bool verbose_did_open = false;
|
||||
@@ -1038,14 +1049,69 @@ int delete_first_msg(void)
|
||||
return OK;
|
||||
}
|
||||
|
||||
void check_msg_hist(void)
|
||||
static void check_msg_hist(void)
|
||||
{
|
||||
// Don't let the message history get too big
|
||||
while (msg_hist_len > 0 && msg_hist_len > p_mhi) {
|
||||
while (msg_hist_len > 0 && msg_hist_len > msg_hist_max) {
|
||||
(void)delete_first_msg();
|
||||
}
|
||||
}
|
||||
|
||||
int messagesopt_changed(void)
|
||||
{
|
||||
int messages_flags_new = 0;
|
||||
int messages_wait_new = 0;
|
||||
int messages_history_new = 0;
|
||||
|
||||
char *p = p_meo;
|
||||
while (*p != NUL) {
|
||||
if (strnequal(p, S_LEN(MESSAGES_OPT_HIT_ENTER))) {
|
||||
p += STRLEN_LITERAL(MESSAGES_OPT_HIT_ENTER);
|
||||
messages_flags_new |= kOptMoptFlagHitEnter;
|
||||
} else if (strnequal(p, S_LEN(MESSAGES_OPT_WAIT))
|
||||
&& ascii_isdigit(p[STRLEN_LITERAL(MESSAGES_OPT_WAIT)])) {
|
||||
p += STRLEN_LITERAL(MESSAGES_OPT_WAIT);
|
||||
messages_wait_new = getdigits_int(&p, false, INT_MAX);
|
||||
messages_flags_new |= kOptMoptFlagWait;
|
||||
} else if (strnequal(p, S_LEN(MESSAGES_OPT_HISTORY))
|
||||
&& ascii_isdigit(p[STRLEN_LITERAL(MESSAGES_OPT_HISTORY)])) {
|
||||
p += STRLEN_LITERAL(MESSAGES_OPT_HISTORY);
|
||||
messages_history_new = getdigits_int(&p, false, INT_MAX);
|
||||
messages_flags_new |= kOptMoptFlagHistory;
|
||||
}
|
||||
|
||||
if (*p != ',' && *p != NUL) {
|
||||
return FAIL;
|
||||
}
|
||||
if (*p == ',') {
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
// Either "wait" or "hit-enter" is required
|
||||
if (!(messages_flags_new & (kOptMoptFlagHitEnter | kOptMoptFlagWait))) {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
// "history" must be set
|
||||
if (!(messages_flags_new & kOptMoptFlagHistory)) {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
// "history" must be <= 10000
|
||||
if (messages_history_new > 10000) {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
msg_flags = messages_flags_new;
|
||||
msg_wait = messages_wait_new;
|
||||
|
||||
msg_hist_max = messages_history_new;
|
||||
check_msg_hist();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/// :messages command implementation
|
||||
void ex_messages(exarg_T *eap)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
@@ -1209,83 +1275,88 @@ void wait_return(int redraw)
|
||||
cmdline_row = Rows - 1;
|
||||
}
|
||||
|
||||
hit_return_msg(true);
|
||||
if (msg_flags & kOptMoptFlagHitEnter) {
|
||||
hit_return_msg(true);
|
||||
|
||||
do {
|
||||
// Remember "got_int", if it is set vgetc() probably returns a
|
||||
// CTRL-C, but we need to loop then.
|
||||
had_got_int = got_int;
|
||||
do {
|
||||
// Remember "got_int", if it is set vgetc() probably returns a
|
||||
// CTRL-C, but we need to loop then.
|
||||
had_got_int = got_int;
|
||||
|
||||
// Don't do mappings here, we put the character back in the
|
||||
// typeahead buffer.
|
||||
no_mapping++;
|
||||
allow_keys++;
|
||||
// Don't do mappings here, we put the character back in the
|
||||
// typeahead buffer.
|
||||
no_mapping++;
|
||||
allow_keys++;
|
||||
|
||||
// Temporarily disable Recording. If Recording is active, the
|
||||
// character will be recorded later, since it will be added to the
|
||||
// typebuf after the loop
|
||||
const int save_reg_recording = reg_recording;
|
||||
save_scriptout = scriptout;
|
||||
reg_recording = 0;
|
||||
scriptout = NULL;
|
||||
c = safe_vgetc();
|
||||
if (had_got_int && !global_busy) {
|
||||
got_int = false;
|
||||
}
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
reg_recording = save_reg_recording;
|
||||
scriptout = save_scriptout;
|
||||
|
||||
// Allow scrolling back in the messages.
|
||||
// Also accept scroll-down commands when messages fill the screen,
|
||||
// to avoid that typing one 'j' too many makes the messages
|
||||
// disappear.
|
||||
if (p_more) {
|
||||
if (c == 'b' || c == 'k' || c == 'u' || c == 'g'
|
||||
|| c == K_UP || c == K_PAGEUP) {
|
||||
if (msg_scrolled > Rows) {
|
||||
// scroll back to show older messages
|
||||
do_more_prompt(c);
|
||||
} else {
|
||||
msg_didout = false;
|
||||
c = K_IGNORE;
|
||||
msg_col = 0;
|
||||
}
|
||||
if (quit_more) {
|
||||
c = CAR; // just pretend CR was hit
|
||||
quit_more = false;
|
||||
got_int = false;
|
||||
} else if (c != K_IGNORE) {
|
||||
c = K_IGNORE;
|
||||
hit_return_msg(false);
|
||||
}
|
||||
} else if (msg_scrolled > Rows - 2
|
||||
&& (c == 'j' || c == 'd' || c == 'f'
|
||||
|| c == K_DOWN || c == K_PAGEDOWN)) {
|
||||
c = K_IGNORE;
|
||||
// Temporarily disable Recording. If Recording is active, the
|
||||
// character will be recorded later, since it will be added to the
|
||||
// typebuf after the loop
|
||||
const int save_reg_recording = reg_recording;
|
||||
save_scriptout = scriptout;
|
||||
reg_recording = 0;
|
||||
scriptout = NULL;
|
||||
c = safe_vgetc();
|
||||
if (had_got_int && !global_busy) {
|
||||
got_int = false;
|
||||
}
|
||||
}
|
||||
} while ((had_got_int && c == Ctrl_C)
|
||||
|| c == K_IGNORE
|
||||
|| c == K_LEFTDRAG || c == K_LEFTRELEASE
|
||||
|| c == K_MIDDLEDRAG || c == K_MIDDLERELEASE
|
||||
|| c == K_RIGHTDRAG || c == K_RIGHTRELEASE
|
||||
|| c == K_MOUSELEFT || c == K_MOUSERIGHT
|
||||
|| c == K_MOUSEDOWN || c == K_MOUSEUP
|
||||
|| c == K_MOUSEMOVE);
|
||||
os_breakcheck();
|
||||
no_mapping--;
|
||||
allow_keys--;
|
||||
reg_recording = save_reg_recording;
|
||||
scriptout = save_scriptout;
|
||||
|
||||
// Avoid that the mouse-up event causes visual mode to start.
|
||||
if (c == K_LEFTMOUSE || c == K_MIDDLEMOUSE || c == K_RIGHTMOUSE
|
||||
|| c == K_X1MOUSE || c == K_X2MOUSE) {
|
||||
jump_to_mouse(MOUSE_SETPOS, NULL, 0);
|
||||
} else if (vim_strchr("\r\n ", c) == NULL && c != Ctrl_C) {
|
||||
// Put the character back in the typeahead buffer. Don't use the
|
||||
// stuff buffer, because lmaps wouldn't work.
|
||||
ins_char_typebuf(vgetc_char, vgetc_mod_mask, true);
|
||||
do_redraw = true; // need a redraw even though there is
|
||||
// typeahead
|
||||
// Allow scrolling back in the messages.
|
||||
// Also accept scroll-down commands when messages fill the screen,
|
||||
// to avoid that typing one 'j' too many makes the messages
|
||||
// disappear.
|
||||
if (p_more) {
|
||||
if (c == 'b' || c == 'k' || c == 'u' || c == 'g'
|
||||
|| c == K_UP || c == K_PAGEUP) {
|
||||
if (msg_scrolled > Rows) {
|
||||
// scroll back to show older messages
|
||||
do_more_prompt(c);
|
||||
} else {
|
||||
msg_didout = false;
|
||||
c = K_IGNORE;
|
||||
msg_col = 0;
|
||||
}
|
||||
if (quit_more) {
|
||||
c = CAR; // just pretend CR was hit
|
||||
quit_more = false;
|
||||
got_int = false;
|
||||
} else if (c != K_IGNORE) {
|
||||
c = K_IGNORE;
|
||||
hit_return_msg(false);
|
||||
}
|
||||
} else if (msg_scrolled > Rows - 2
|
||||
&& (c == 'j' || c == 'd' || c == 'f'
|
||||
|| c == K_DOWN || c == K_PAGEDOWN)) {
|
||||
c = K_IGNORE;
|
||||
}
|
||||
}
|
||||
} while ((had_got_int && c == Ctrl_C)
|
||||
|| c == K_IGNORE
|
||||
|| c == K_LEFTDRAG || c == K_LEFTRELEASE
|
||||
|| c == K_MIDDLEDRAG || c == K_MIDDLERELEASE
|
||||
|| c == K_RIGHTDRAG || c == K_RIGHTRELEASE
|
||||
|| c == K_MOUSELEFT || c == K_MOUSERIGHT
|
||||
|| c == K_MOUSEDOWN || c == K_MOUSEUP
|
||||
|| c == K_MOUSEMOVE);
|
||||
os_breakcheck();
|
||||
|
||||
// Avoid that the mouse-up event causes visual mode to start.
|
||||
if (c == K_LEFTMOUSE || c == K_MIDDLEMOUSE || c == K_RIGHTMOUSE
|
||||
|| c == K_X1MOUSE || c == K_X2MOUSE) {
|
||||
jump_to_mouse(MOUSE_SETPOS, NULL, 0);
|
||||
} else if (vim_strchr("\r\n ", c) == NULL && c != Ctrl_C) {
|
||||
// Put the character back in the typeahead buffer. Don't use the
|
||||
// stuff buffer, because lmaps wouldn't work.
|
||||
ins_char_typebuf(vgetc_char, vgetc_mod_mask, true);
|
||||
do_redraw = true; // need a redraw even though there is typeahead
|
||||
}
|
||||
} else {
|
||||
c = CAR;
|
||||
// Wait to allow the user to verify the output.
|
||||
do_sleep(msg_wait, true);
|
||||
}
|
||||
}
|
||||
redir_off = false;
|
||||
|
@@ -812,7 +812,7 @@ static void normal_get_additional_char(NormalState *s)
|
||||
// There is a busy wait here when typing "f<C-\>" and then
|
||||
// something different from CTRL-N. Can't be avoided.
|
||||
while ((s->c = vpeekc()) <= 0 && towait > 0) {
|
||||
do_sleep(towait > 50 ? 50 : towait);
|
||||
do_sleep(towait > 50 ? 50 : towait, false);
|
||||
towait -= 50;
|
||||
}
|
||||
if (s->c > 0) {
|
||||
@@ -5561,7 +5561,7 @@ static void nv_g_cmd(cmdarg_T *cap)
|
||||
|
||||
// "gs": Goto sleep.
|
||||
case 's':
|
||||
do_sleep(cap->count1 * 1000);
|
||||
do_sleep(cap->count1 * 1000, false);
|
||||
break;
|
||||
|
||||
// "ga": Display the ascii value of the character under the
|
||||
|
@@ -2199,13 +2199,6 @@ static const char *did_set_modified(optset_T *args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Process the updated 'msghistory' option value.
|
||||
static const char *did_set_msghistory(optset_T *args FUNC_ATTR_UNUSED)
|
||||
{
|
||||
check_msg_hist();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Process the updated 'number' or 'relativenumber' option value.
|
||||
static const char *did_set_number_relativenumber(optset_T *args)
|
||||
{
|
||||
@@ -2886,13 +2879,6 @@ static const char *validate_num_option(OptIndex opt_idx, OptInt *newval, char *e
|
||||
return e_invarg;
|
||||
}
|
||||
break;
|
||||
case kOptMsghistory:
|
||||
if (value < 0) {
|
||||
return e_positive;
|
||||
} else if (value > 10000) {
|
||||
return e_invarg;
|
||||
}
|
||||
break;
|
||||
case kOptPyxversion:
|
||||
if (value == 0) {
|
||||
*newval = 3;
|
||||
|
@@ -448,6 +448,7 @@ EXTERN OptInt p_mfd; ///< 'maxfuncdepth'
|
||||
EXTERN OptInt p_mmd; ///< 'maxmapdepth'
|
||||
EXTERN OptInt p_mmp; ///< 'maxmempattern'
|
||||
EXTERN OptInt p_mis; ///< 'menuitems'
|
||||
EXTERN char *p_meo; ///< 'messagesopt'
|
||||
EXTERN char *p_msm; ///< 'mkspellmem'
|
||||
EXTERN int p_ml; ///< 'modeline'
|
||||
EXTERN int p_mle; ///< 'modelineexpr'
|
||||
@@ -464,7 +465,6 @@ EXTERN OptInt p_mousescroll_vert INIT( = MOUSESCROLL_VERT_DFLT);
|
||||
EXTERN OptInt p_mousescroll_hor INIT( = MOUSESCROLL_HOR_DFLT);
|
||||
EXTERN OptInt p_mouset; ///< 'mousetime'
|
||||
EXTERN int p_more; ///< 'more'
|
||||
EXTERN OptInt p_mhi; ///< 'msghistory'
|
||||
EXTERN char *p_nf; ///< 'nrformats'
|
||||
EXTERN char *p_opfunc; ///< 'operatorfunc'
|
||||
EXTERN char *p_para; ///< 'paragraphs'
|
||||
|
@@ -4094,7 +4094,7 @@ return {
|
||||
desc = [=[
|
||||
A history of ":" commands, and a history of previous search patterns
|
||||
is remembered. This option decides how many entries may be stored in
|
||||
each of these histories (see |cmdline-editing| and 'msghistory' for
|
||||
each of these histories (see |cmdline-editing| and 'messagesopt' for
|
||||
the number of messages to remember).
|
||||
The maximum value is 10000.
|
||||
]=],
|
||||
@@ -5448,6 +5448,38 @@ return {
|
||||
type = 'number',
|
||||
varname = 'p_mis',
|
||||
},
|
||||
{
|
||||
abbreviation = 'mopt',
|
||||
cb = 'did_set_messagesopt',
|
||||
defaults = { if_true = 'hit-enter,history:500' },
|
||||
values = { 'hit-enter', 'wait:', 'history:' },
|
||||
flags = true,
|
||||
deny_duplicates = true,
|
||||
desc = [=[
|
||||
Option settings when outputting messages. It can consist of the
|
||||
following items. Items must be separated by a comma.
|
||||
|
||||
hit-enter Use |hit-enter| prompt when the message is longer than
|
||||
'cmdheight' size.
|
||||
|
||||
wait:{n} Ignored when "hit-enter" is present. Instead of using
|
||||
|hit-enter| prompt, will simply wait for {n}
|
||||
milliseconds so the user has a chance to read the
|
||||
message, use 0 to disable sleep (but then the user may
|
||||
miss an important message).
|
||||
|
||||
history:{n} Determines how many entries are remembered in the
|
||||
|:messages| history. The maximum value is 10000.
|
||||
Setting it to zero clears the message history.
|
||||
]=],
|
||||
expand_cb = 'expand_set_messagesopt',
|
||||
full_name = 'messagesopt',
|
||||
list = 'onecommacolon',
|
||||
scope = { 'global' },
|
||||
short_desc = N_('options for outputting messages'),
|
||||
type = 'string',
|
||||
varname = 'p_meo',
|
||||
},
|
||||
{
|
||||
abbreviation = 'msm',
|
||||
cb = 'did_set_mkspellmem',
|
||||
@@ -5892,21 +5924,6 @@ return {
|
||||
type = 'number',
|
||||
varname = 'p_mouset',
|
||||
},
|
||||
{
|
||||
abbreviation = 'mhi',
|
||||
cb = 'did_set_msghistory',
|
||||
defaults = { if_true = 500 },
|
||||
desc = [=[
|
||||
Determines how many entries are remembered in the |:messages| history.
|
||||
The maximum value is 10000.
|
||||
Setting it to zero clears the message history.
|
||||
]=],
|
||||
full_name = 'msghistory',
|
||||
scope = { 'global' },
|
||||
short_desc = N_('how many messages are remembered'),
|
||||
type = 'number',
|
||||
varname = 'p_mhi',
|
||||
},
|
||||
{
|
||||
abbreviation = 'nf',
|
||||
cb = 'did_set_nrformats',
|
||||
|
@@ -1682,6 +1682,24 @@ const char *did_set_matchpairs(optset_T *args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Process the updated 'messagesopt' option value.
|
||||
const char *did_set_messagesopt(optset_T *args FUNC_ATTR_UNUSED)
|
||||
{
|
||||
if (messagesopt_changed() == FAIL) {
|
||||
return e_invarg;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int expand_set_messagesopt(optexpand_T *args, int *numMatches, char ***matches)
|
||||
{
|
||||
return expand_set_opt_string(args,
|
||||
opt_mopt_values,
|
||||
ARRAY_SIZE(opt_mopt_values) - 1,
|
||||
numMatches,
|
||||
matches);
|
||||
}
|
||||
|
||||
/// The 'mkspellmem' option is changed.
|
||||
const char *did_set_mkspellmem(optset_T *args FUNC_ATTR_UNUSED)
|
||||
{
|
||||
|
Reference in New Issue
Block a user