patch 9.1.0908: not possible to configure :messages

Problem:  not possible to configure :messages
Solution: add the 'messagesopt' option (Shougo Matsushita)

closes: #16068

Co-authored-by: h_east <h.east.727@gmail.com>
Signed-off-by: Shougo Matsushita <Shougo.Matsu@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/message.c b/src/message.c
index 15eaaae..34a2692 100644
--- a/src/message.c
+++ b/src/message.c
@@ -16,6 +16,7 @@
 #include "vim.h"
 
 static void add_msg_hist(char_u *s, int len, int attr);
+static void check_msg_hist(void);
 static void hit_return_msg(void);
 static void msg_home_replace_attr(char_u *fname, int attr);
 static void msg_puts_attr_len(char *str, int maxlen, int attr);
@@ -51,6 +52,21 @@
 static struct msg_hist *first_msg_hist = NULL;
 static struct msg_hist *last_msg_hist = NULL;
 static int msg_hist_len = 0;
+static int msg_hist_max = 500;		// The default max value is 500
+
+// flags obtained from the 'messagesopt' option
+#define MESSAGES_HIT_ENTER	0x001
+#define MESSAGES_WAIT		0x002
+#define MESSAGES_HISTORY	0x004
+
+// 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 = MESSAGES_HIT_ENTER | MESSAGES_HISTORY;
+static int msg_wait = 0;
 
 static FILE *verbose_fd = NULL;
 static int  verbose_did_open = FALSE;
@@ -1060,14 +1076,76 @@
     return OK;
 }
 
-    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)
+{
+    char_u	*p;
+    int		messages_flags_new = 0;
+    int		messages_wait_new = 0;
+    int		messages_history_new = 0;
+
+    p = p_meo;
+    while (*p != NUL)
+    {
+	if (STRNCMP(p, MESSAGES_OPT_HIT_ENTER,
+	     STRLEN_LITERAL(MESSAGES_OPT_HIT_ENTER)) == 0)
+	{
+	    p += STRLEN_LITERAL(MESSAGES_OPT_HIT_ENTER);
+	    messages_flags_new |= MESSAGES_HIT_ENTER;
+	}
+	else if (STRNCMP(p, MESSAGES_OPT_WAIT,
+		  STRLEN_LITERAL(MESSAGES_OPT_WAIT)) == 0
+	    && VIM_ISDIGIT(p[STRLEN_LITERAL(MESSAGES_OPT_WAIT)]))
+	{
+	    p += STRLEN_LITERAL(MESSAGES_OPT_WAIT);
+	    messages_wait_new = getdigits(&p);
+	    messages_flags_new |= MESSAGES_WAIT;
+	}
+	else if (STRNCMP(p, MESSAGES_OPT_HISTORY,
+		  STRLEN_LITERAL(MESSAGES_OPT_HISTORY)) == 0
+	    && VIM_ISDIGIT(p[STRLEN_LITERAL(MESSAGES_OPT_HISTORY)]))
+	{
+	    p += STRLEN_LITERAL(MESSAGES_OPT_HISTORY);
+	    messages_history_new = getdigits(&p);
+	    messages_flags_new |= MESSAGES_HISTORY;
+	}
+
+	if (*p != ',' && *p != NUL)
+	    return FAIL;
+	if (*p == ',')
+	    ++p;
+    }
+
+    // Either "wait" or "hit-enter" is required
+    if (!(messages_flags_new & (MESSAGES_HIT_ENTER | MESSAGES_WAIT)))
+        return FAIL;
+
+    // "history" must be set
+    if (!(messages_flags_new & MESSAGES_HISTORY))
+        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.
  */
@@ -1228,118 +1306,127 @@
 	if (need_check_timestamps)
 	    check_timestamps(FALSE);
 
-	hit_return_msg();
-
-	do
+	if (msg_flags & MESSAGES_HIT_ENTER)
 	{
-	    // Remember "got_int", if it is set vgetc() probably returns a
-	    // CTRL-C, but we need to loop then.
-	    had_got_int = got_int;
+	    hit_return_msg();
 
-	    // Don't do mappings here, we put the character back in the
-	    // typeahead buffer.
-	    ++no_mapping;
-	    ++allow_keys;
+	    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;
 
-	    // Temporarily disable Recording. If Recording is active, the
-	    // character will be recorded later, since it will be added to the
-	    // typebuf after the loop
-	    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;
+		// 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
+		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;
 
 #ifdef FEAT_CLIPBOARD
-	    // Strange way to allow copying (yanking) a modeless selection at
-	    // the hit-enter prompt.  Use CTRL-Y, because the same is used in
-	    // Cmdline-mode and it's harmless when there is no selection.
-	    if (c == Ctrl_Y && clip_star.state == SELECT_DONE)
-	    {
-		clip_copy_modeless_selection(TRUE);
-		c = K_IGNORE;
-	    }
-#endif
-
-	    /*
-	     * 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 && !p_cp)
-	    {
-		if (c == 'b' || c == 'k' || c == 'u' || c == 'g'
-						|| c == K_UP || c == K_PAGEUP)
+		// Strange way to allow copying (yanking) a modeless selection at
+		// the hit-enter prompt.  Use CTRL-Y, because the same is used in
+		// Cmdline-mode and it's harmless when there is no selection.
+		if (c == Ctrl_Y && clip_star.state == SELECT_DONE)
 		{
-		    if (msg_scrolled > Rows)
-			// scroll back to show older messages
-			do_more_prompt(c);
-		    else
-		    {
-			msg_didout = FALSE;
-			c = K_IGNORE;
-			msg_col =
-#ifdef FEAT_RIGHTLEFT
-			    cmdmsg_rl ? Columns - 1 :
-#endif
-			    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();
-		    }
-		}
-		else if (msg_scrolled > Rows - 2
-			 && (c == 'j' || c == 'd' || c == 'f'
-					   || c == K_DOWN || c == K_PAGEDOWN))
+		    clip_copy_modeless_selection(TRUE);
 		    c = K_IGNORE;
-	    }
-	} while ((had_got_int && c == Ctrl_C)
-				|| c == K_IGNORE
-#ifdef FEAT_GUI
-				|| c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR
+		}
 #endif
-				|| 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
-				|| (!mouse_has(MOUSE_RETURN)
-				    && mouse_row < msg_row
-				    && (c == K_LEFTMOUSE
-					|| c == K_MIDDLEMOUSE
-					|| c == K_RIGHTMOUSE
-					|| c == K_X1MOUSE
-					|| c == K_X2MOUSE))
-				);
-	ui_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)
-	    (void)jump_to_mouse(MOUSE_SETPOS, NULL, 0);
-	else if (vim_strchr((char_u *)"\r\n ", c) == NULL && c != Ctrl_C)
+		/*
+		* 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 && !p_cp)
+		{
+		    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 =
+#ifdef FEAT_RIGHTLEFT
+				cmdmsg_rl ? Columns - 1 :
+#endif
+				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();
+			}
+		    }
+		    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
+#ifdef FEAT_GUI
+				    || c == K_VER_SCROLLBAR || c == K_HOR_SCROLLBAR
+#endif
+				    || 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
+				    || (!mouse_has(MOUSE_RETURN)
+					&& mouse_row < msg_row
+					&& (c == K_LEFTMOUSE
+					    || c == K_MIDDLEMOUSE
+					    || c == K_RIGHTMOUSE
+					    || c == K_X1MOUSE
+					    || c == K_X2MOUSE))
+				    );
+	    ui_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)
+		(void)jump_to_mouse(MOUSE_SETPOS, NULL, 0);
+	    else if (vim_strchr((char_u *)"\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);
+		do_redraw = TRUE;	    // need a redraw even though there is
+					// typeahead
+	    }
+	}
+	else
 	{
-	    // 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);
-	    do_redraw = TRUE;	    // need a redraw even though there is
-				    // typeahead
+	    c = CAR;
+	    // Wait to allow the user to verify the output.
+	    do_sleep(msg_wait, TRUE);
 	}
     }
     redir_off = FALSE;