Hello! 

I propose patch, that makes readline aware of ansi terminal codes. Also,
I attach program with which I tested my changes.

Problem, that address this patch can be seen on screenshots at my
ftp server.

  [1] ftp://kaction.name/readline/

Happy New Year!

-- 
Best regards, Dmitry Bogatov <[email protected]>,
Free Software supporter, esperantisto and netiquette guardian.
        git://kaction.name/rc-files.git
        GPG: 54B7F00D
>From 9fb1dd2f5a09ea239f27ec7d790088421f7dfdc5 Mon Sep 17 00:00:00 2001
From: Dmitry Bogatov <[email protected]>
Date: Tue, 31 Dec 2013 17:48:02 -0600
Subject: [PATCH] Fix display issue with ansi-codes in prompt

Signed-off-by: Dmitry Bogatov <[email protected]>
---
 display.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/display.c b/display.c
index e4105ee..fe94826 100644
--- a/display.c
+++ b/display.c
@@ -232,6 +232,34 @@ static int saved_local_length;
 static int saved_invis_chars_first_line;
 static int saved_physical_chars;
 
+
+/* If STR actually starts with ANSI terminal code, return pointer to last
+ character in this code. For this function, ansi code started by ESC, followed
+ by by '[' and finished by letter. If ESC is not followed by '[', ESC itself
+ is considererd invisible, but characters after are not.
+ Actual behavior of terminals is more compicated.
+
+ If STR do not starts with ANSI terminal code, return NULL. */
+
+static const char *
+maybe_skip_ansi_code(const char *str)
+{
+  if (*str != ESC)
+    return NULL;
+
+  if (str[1] == '[')
+    {
+      const char *p = str + 2;
+      while (*p && !isalpha(*p))
+	++p;
+      return p;
+    }
+  else
+    {
+      return str;
+    }
+}
+
 /* Expand the prompt string S and return the number of visible
    characters in *LP, if LP is not null.  This is currently more-or-less
    a placeholder for expansion.  LIP, if non-null is a place to store the
@@ -256,7 +284,9 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
   int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
 
   /* Short-circuit if we can. */
-  if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
+  if ((MB_CUR_MAX <= 1 || rl_byte_oriented) &&
+      strchr (pmt, RL_PROMPT_START_IGNORE) == 0 &&
+      strchr (pmt, ESC) == 0)
     {
       r = savestring (pmt);
       if (lp)
@@ -296,6 +326,18 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
 	}
       else
 	{
+	  const char *ansi_code_end = maybe_skip_ansi_code(p);
+	  if (ansi_code_end)
+	    {
+	      last = r - ansi_code_end;
+	      rl += ansi_code_end - p;
+	      while (*p && p <= ansi_code_end)
+		*r++ = *p++;
+
+	      if (!*p)
+		break;
+	    }
+
 #if defined (HANDLE_MULTIBYTE)
 	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
 	    {
-- 
Recipients list generated via git-blame. Tell me, if you object.

#include <readline/readline.h>

int
main(int argc, char *argv[])
{
  const char *pattern = "\e[31m*\e[0m* ";
  char buffer[600] = {0};
  for (int i = 0; i != 8; ++i)
    strcat(buffer, pattern);

  readline(buffer);
  return 0;
}
_______________________________________________
Bug-readline mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/bug-readline

Reply via email to