git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] winansi: support ESC [ K (erase in line)

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Mar 10, 2009, 00:41 UTC
Message-ID
<e2b19f6c7c50e5b0a652c40b0d8e4947134ed669.1236639280u.git.johannes.schindelin@gmx.de>
In-Reply-To
<cover.1236639280u.git.johannes.schindelin@gmx.de>
To make use of it during a fetch, write() needs to be overridden, too.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
	This fixes the last bit of msysGit issue 124 for me:
		http://code.google.com/p/msysgit/issues/detail?id=124
	which annoyed me one time to many today.
	I had an earlier version which was smaller, but pretty hacky, in 
	that it checked if fprintf is #define'd in xwrite(), and had 
	special handling for that case.
	This patch is only slightly hacky, in that it assumes that you do 
	not try to output something that ends in an incomplete ESC [
	sequence.
 compat/mingw.h   |    2 ++
 compat/winansi.c |   51 +++++++++++++++++++++++++++++++++++++++------------
 2 files changed, 41 insertions(+), 12 deletions(-)
diff --git a/compat/mingw.h b/compat/mingw.h
index b82903c..9aac4e1 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -192,9 +192,11 @@ sig_handler_t mingw_signal(int sig, sig_handler_t handler);
 int winansi_fputs(const char *str, FILE *stream);
 int winansi_printf(const char *format, ...) __attribute__((format (printf, 1, 2)));
 int winansi_fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3)));
+int winansi_write(int fd, const void *buf, size_t len);
 #define fputs winansi_fputs
 #define printf(...) winansi_printf(__VA_ARGS__)
 #define fprintf(...) winansi_fprintf(__VA_ARGS__)
+#define write winansi_write
 
 /*
  * git specific compatibility
diff --git a/compat/winansi.c b/compat/winansi.c
index e2d96df..a9d981c 100644
--- a/compat/winansi.c
+++ b/compat/winansi.c
@@ -11,15 +11,13 @@
 #undef printf
 #undef fprintf
 #undef fputs
-/* TODO: write */
+#undef write
 
 /*
  ANSI codes used by git: m, K
 
  This file is git-specific. Therefore, this file does not attempt
  to implement any codes that are not used by git.
-
- TODO: K
 */
 
 static HANDLE console;
@@ -79,6 +77,20 @@ static void set_console_attr(void)
 	SetConsoleTextAttribute(console, attributes);
 }
 
+static void erase_in_line(void)
+{
+	CONSOLE_SCREEN_BUFFER_INFO sbi;
+
+	if (!console)
+		return;
+
+	GetConsoleScreenBufferInfo(console, &sbi);
+	FillConsoleOutputCharacterA(console, ' ',
+		sbi.dwSize.X - sbi.dwCursorPosition.X, sbi.dwCursorPosition,
+		NULL);
+}
+
+
 static const char *set_attr(const char *str)
 {
 	const char *func;
@@ -218,7 +230,7 @@ static const char *set_attr(const char *str)
 		set_console_attr();
 		break;
 	case 'K':
-		/* TODO */
+		erase_in_line();
 		break;
 	default:
 		/* Unsupported code */
@@ -228,13 +240,16 @@ static const char *set_attr(const char *str)
 	return func + 1;
 }
 
-static int ansi_emulate(const char *str, FILE *stream)
+static int ansi_emulate(const char *str, ssize_t len, FILE *stream)
 {
 	int rv = 0;
 	const char *pos = str;
 
-	while (*pos) {
-		pos = strstr(str, "\033[");
+	if (len < 0)
+		len = strlen(str);
+
+	while (rv < len) {
+		pos = memmem(str, len - rv, "\033[", 2);
 		if (pos) {
 			size_t len = pos - str;
 
@@ -254,10 +269,11 @@ static int ansi_emulate(const char *str, FILE *stream)
 			rv += pos - str;
 			str = pos;
 		} else {
-			rv += strlen(str);
-			fputs(str, stream);
-			return rv;
+			fwrite(str, len - rv, 1, stream);
+			return len;
 		}
+		if (rv > len)
+			die ("Invalid use of ESC [ sequence detected");
 	}
 	return rv;
 }
@@ -274,7 +290,7 @@ int winansi_fputs(const char *str, FILE *stream)
 	if (!console)
 		return fputs(str, stream);
 
-	rv = ansi_emulate(str, stream);
+	rv = ansi_emulate(str, -1, stream);
 
 	if (rv >= 0)
 		return 0;
@@ -309,7 +325,7 @@ static int winansi_vfprintf(FILE *stream, const char *format, va_list list)
 		len = vsnprintf(buf, len + 1, format, list);
 	}
 
-	rv = ansi_emulate(buf, stream);
+	rv = ansi_emulate(buf, -1, stream);
 
 	if (buf != small_buf)
 		free(buf);
@@ -343,3 +359,14 @@ int winansi_printf(const char *format, ...)
 
 	return rv;
 }
+
+int winansi_write(int fd, const void *buf, size_t len)
+{
+	if (isatty(fd)) {
+		init();
+		if (console)
+			return ansi_emulate((const char *)buf, len,
+					fd == 2 ? stderr : stdout);
+	}
+	return write(fd, buf, len);
+}
-- 
1.6.2.240.g23c7
Next: Johannes Sixt
Message 1 of 26 in “winansi: support ESC [ K (erase in line)”
  1. winansi: support ESC [ K (erase in line)Johannes Schindelin, Mar 10, 2009
  2. Johannes SixtMar 10, 2009
  3. recv_sideband: Band #2 always goes to stderrJohannes Sixt, Mar 10, 2009
  4. Johannes SchindelinMar 10, 2009
  5. Johannes SixtMar 10, 2009
  6. Johannes SixtMar 10, 2009
  7. Johannes SchindelinMar 10, 2009
  8. Johannes SixtMar 10, 2009
  9. Johannes SchindelinMar 10, 2009
  10. Johannes SixtMar 10, 2009
  11. Shawn O. PearceMar 10, 2009
  12. Johannes SchindelinMar 10, 2009
  13. Junio C HamanoMar 10, 2009
  14. Shawn O. PearceMar 10, 2009
  15. Johannes SixtMar 10, 2009
  16. Johannes SchindelinMar 10, 2009
  17. Johannes SixtMar 10, 2009
  18. Nicolas PitreMar 10, 2009
  19. Jay SoffianMar 10, 2009
  20. Nicolas PitreMar 10, 2009
  21. 1/2 recv_sideband: Bands #2 and #3 always go to stderrJohannes Sixt, Mar 10, 2009
  22. 2/2 winansi: support ESC [ K (erase in line)Johannes Sixt, Mar 10, 2009
  23. Johannes SchindelinMar 11, 2009
  24. Johannes SchindelinMar 10, 2009
  25. Peter HarrisMar 10, 2009
  26. Johannes SchindelinMar 10, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.