Index | Thread | Search

From:
Dante Catalfamo <dante@lambda.cx>
Subject:
mg: Add *Messages* buffer
To:
"tech@openbsd.org" <tech@openbsd.org>
Date:
Fri, 19 Jun 2026 16:41:59 -0400

Download raw body.

Thread
  • Dante Catalfamo:

    mg: Add *Messages* buffer

Hello tech,
I was trying to debug an issue in mg and noticed that it doesn't keep 
track of minibuffer messages like Emacs does. I use that feature pretty 
often in cases where the message I want to read gets replaced by another 
before I get a change to see it.
I wrote a diff that adds the *Messages* buffer and populates it when any 
messages are displayed. The exception is that it doesn't log user input 
prompts, also like Emacs. It's a pretty small patch, hopefully it's 
acceptable.
Thanks, Dante


diff --git usr.bin/mg/echo.c usr.bin/mg/echo.c
index ec178d3c859..95fa27a0ee4 100644
--- usr.bin/mg/echo.c
+++ usr.bin/mg/echo.c
@@ -22,6 +22,8 @@
  #include "key.h"
  #include "macro.h"
  
+#define NOEBUF 512
+
  static char	*veread(const char *, char *, size_t, int, va_list)
  			__attribute__((__format__ (printf, 1, 0)));
  static int	 complt(int, int, char *, size_t, int, int *);
@@ -32,10 +34,15 @@ static void	 eputi(int, int);
  static void	 eputl(long, int);
  static void	 eputs(const char *);
  static void	 eputc(char);
+static void	 eflush(void);
  static struct list	*copy_list(struct list *);
  
  int		epresf = FALSE;		/* stuff in echo line flag */
  
+char		ebuf[NOEBUF];		/* *Messages* output buffer */
+int		noebuf = 0;		/* Buffer count */
+int		einread = FALSE;	/* Currently in a read prompt */
+
  /*
   * Erase the echo line.
   */
@@ -177,9 +184,11 @@ eread(const char *fmt, char *buf, size_t nbuf, int flag, ...)
  	va_list	 ap;
  	char	*rep;
  
+	einread = TRUE;
  	va_start(ap, flag);
  	rep = veread(fmt, buf, nbuf, flag, ap);
  	va_end(ap);
+	einread = FALSE;
  	return (rep);
  }
  
@@ -835,6 +844,7 @@ ewprintf(const char *fmt, ...)
  	va_end(ap);
  	tteeol();
  	ttflush();
+	eflush();
  	epresf = TRUE;
  }
  
@@ -979,8 +989,40 @@ eputc(char c)
  		ttputc(c);
  		++ttcol;
  	}
+
+	if (einread == FALSE) {
+		ebuf[noebuf++] = c;
+		if (noebuf >= NOEBUF-1) {
+			eflush();
+		}
+	}
  }
  
+/*
+ * Flush the message line to the *Messages* buffer
+ */
+static void eflush(void) {
+	struct buffer	*buf;
+	struct mgwin	*win;
+
+	if (noebuf == 0) {
+		return;
+	}
+
+	ebuf[noebuf] = '\0';
+	buf = bfind("*Messages*", TRUE);
+	buf->b_flag |= BFREADONLY;
+	addlinef(buf, "%s", ebuf);
+	noebuf = 0;
+
+	for (win = wheadp; win != NULL; win = win->w_wndp) {
+		if (win->w_bufp == buf) {
+			win->w_rflag |= WFFULL;
+		}
+	}
+}
+
+
  void
  free_file_list(struct list *lp)
  {