[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

prompt with \[ \] corrupted by vi history search

From: Mike Stroyan
Subject: prompt with \[ \] corrupted by vi history search
Date: Fri, 3 Feb 2006 12:16:07 -0700
User-agent: Mutt/1.5.9i

Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' 
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I../bash -I../bash/include -I../bash/lib   -g -O2
uname output: Linux hpstryn6 2.6.12-1-amd64-k8-smp #1 SMP Wed Sep 28 02:57:49 
CEST 2005 x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 3.1
Patch Level: 0
Release Status: release

        The prompt is corrupted when using the vi Esc/ history search.
        This happens when the prompt contains non-printing characters
        marked by the \[ \] delimiters.

        Set the PS1 prompt to a string containing non-printing
        characters marked by \[ and \].  Use "set -o vi".
        Type Esc/ to start a history search.  The prompt will
        be partially overwritten or printed with junk characters
        after the prompt.  In this captured example there are
        junk characters covered up by backspaces.  Longer prompts
        tend to leave visible junk characters.

bash-3.1$ LANG=C bash-3.1/build-bash/bash --norc^M$
bash-3.1$ PS1="\[$(tput setf 2)\]\$\[$(tput sgr0)\] "^M$
^[[32m$^[[m^[(B ^[[Kset -o vi^M$
^[[32m$^[[m^[(B echo sample^M$
^[[32m$^[[m^[(B /address@hidden address@hidden sample^H^H^H^H^H^H^H^H^H^H^H^M$
^[[32m$^[[m^[(B exit^M$
bash-3.1$ LANG=C bash-3.1-fix/build-bash/bash --norc^M$
bash-3.1$ PS1="\[$(tput setf 2)\]\$\[$(tput sgr0)\] "^M$
^[[32m$^[[m^[(B ^[[Kset -o vi^M$
^[[32m$^[[m^[(B echo sample^M$
^[[32m$^[[m^[(B /ec^H^H^Hecho sample^H^H^H^H^H^H^H^H^H^H^H^M$
^[[32m$^[[m^[(B exit^M$

        The best fix seems to be in _rl_make_prompt_for_search in 

        _rl_nsearch_init does
          p = _rl_make_prompt_for_search (pchar ? pchar : ':');
          rl_message (p, 0, 0);

        _rl_make_prompt_for_search calls rl_save_prompt and then tests for
        a non-null saved_local_prompt, which rl_save_prompt just set.
        _rl_make_prompt_for_search returns a string based on the value
        of local_prompt which rl_save_prompt just copied.

        When _rl_nsearch_init passes that string to rl_message it does
        some formatting with it into msg_buf and does
          local_prompt = expand_prompt (msg_buf, &prompt_visible_length,

        The result is that expand_prompt is done twice on the prompt.
        The second time around the string is missing the \[ ]\ sequences
        that mark non-printing characters.  The printing and non-printing
        character counts become bad.

        Everything behaves better if _rl_make_prompt_for_search just uses the
        unexpanded rl_prompt string for composing its result.  Here is a patch
        that comments out the troublesome code.

# fix display of history search prompt with non-printing chars in vi edit mode

--- bash/lib/readline/display.c~        2005-09-16 23:35:04.000000000 -0600
+++ bash/lib/readline/display.c 2005-09-16 23:43:19.000000000 -0600
@@ -1950,7 +1950,14 @@

   rl_save_prompt ();

+#if 0
+  /* The rl_prompt should always be used so it has the non-printing
+   * character sequence marks in it.  The local_prompt does not have
+   * them.  This string is passed into rl_message, which passes it
+   * into expand_prompt.
+   */
   if (saved_local_prompt == 0)
       len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
       pmt = (char *)xmalloc (len + 2);
@@ -1959,6 +1966,7 @@
       pmt[len] = pchar;
       pmt[len+1] = '\0';
+#if 0
       len = *saved_local_prompt ? strlen (saved_local_prompt) : 0;
@@ -1971,6 +1979,7 @@
       prompt_last_invisible = saved_last_invisible;
       prompt_visible_length = saved_visible_length + 1;

   return pmt;

reply via email to

[Prev in Thread] Current Thread [Next in Thread]