diff --git a/lib/readline/bind.c b/lib/readline/bind.c
index 8acf4ac..da6ae42 100644
--- a/lib/readline/bind.c
+++ b/lib/readline/bind.c
@@ -1573,6 +1573,12 @@ static int sv_histsize PARAMS((const char *));
 static int sv_isrchterm PARAMS((const char *));
 static int sv_keymap PARAMS((const char *));
 static int sv_seqtimeout PARAMS((const char *));
+static int sv_viinspromptprefix PARAMS((const char *));
+static int sv_viinspromptsuffix PARAMS((const char *));
+static int sv_vinormpromptprefix PARAMS((const char *));
+static int sv_vinormpromptsuffix PARAMS((const char *));
+static int sv_emacspromptprefix PARAMS((const char *));
+static int sv_emacspromptsuffix PARAMS((const char *));
 
 static const struct {
   const char * const name;
@@ -1589,6 +1595,12 @@ static const struct {
   { "isearch-terminators", V_STRING,	sv_isrchterm },
   { "keymap",		V_STRING,	sv_keymap },
   { "keyseq-timeout",	V_INT,		sv_seqtimeout },
+  { "prompt-prefix-vi-insert-mode", V_STRING, sv_viinspromptprefix },
+  { "prompt-suffix-vi-insert-mode", V_STRING, sv_viinspromptsuffix },
+  { "prompt-prefix-vi-normal-mode", V_STRING, sv_vinormpromptprefix },
+  { "prompt-suffix-vi-normal-mode", V_STRING, sv_vinormpromptsuffix },
+  { "prompt-prefix-emacs-mode", V_STRING, sv_emacspromptprefix },
+  { "prompt-suffix-emacs-mode", V_STRING, sv_emacspromptsuffix },
   { (char *)NULL,	0, (_rl_sv_func_t *)0 }
 };
 
@@ -1795,6 +1807,43 @@ sv_seqtimeout (value)
 }
 
 static int
+sv_viinspromptprefix (value)
+     const char *value;
+{
+    _rl_vi_ins_mode_prompt_prefix = strdup (value);
+}
+static int
+sv_viinspromptsuffix (value)
+     const char *value;
+{
+    _rl_vi_ins_mode_prompt_suffix = strdup (value);
+}
+static int
+sv_vinormpromptprefix (value)
+     const char *value;
+{
+  _rl_vi_norm_mode_prompt_prefix = strdup (value);
+}
+static int
+sv_vinormpromptsuffix (value)
+     const char *value;
+{
+  _rl_vi_norm_mode_prompt_suffix = strdup (value);
+}
+static int
+sv_emacspromptprefix (value)
+     const char *value;
+{
+  _rl_emacs_mode_prompt_prefix = strdup (value);
+}
+static int
+sv_emacspromptsuffix (value)
+     const char *value;
+{
+  _rl_emacs_mode_prompt_suffix = strdup (value);
+}
+
+static int
 sv_bell_style (value)
      const char *value;
 {
@@ -1811,6 +1860,8 @@ sv_bell_style (value)
   return 0;
 }
 
+
+
 static int
 sv_isrchterm (value)
      const char *value;
diff --git a/lib/readline/display.c b/lib/readline/display.c
index 4df1f73..ee29206 100644
--- a/lib/readline/display.c
+++ b/lib/readline/display.c
@@ -251,6 +251,40 @@ prompt_modechar ()
     return ':';		/* vi command mode */
 }
 
+static char *
+prompt_modechars_before ()
+{
+  if (rl_editing_mode == emacs_mode)
+    return _rl_emacs_mode_prompt_prefix != NULL
+      ? _rl_emacs_mode_prompt_prefix
+      : "@";
+  else if (_rl_keymap == vi_insertion_keymap)
+    return _rl_vi_ins_mode_prompt_prefix != NULL
+      ? _rl_vi_ins_mode_prompt_prefix
+      : "+";
+  else
+    return _rl_vi_norm_mode_prompt_prefix != NULL
+      ? _rl_vi_norm_mode_prompt_prefix
+      : ":";
+}
+
+static char *
+prompt_modechars_after ()
+{
+  if (rl_editing_mode == emacs_mode)
+    return _rl_emacs_mode_prompt_suffix != NULL
+      ? _rl_emacs_mode_prompt_suffix
+      : "";
+  else if (_rl_keymap == vi_insertion_keymap)
+    return _rl_vi_ins_mode_prompt_suffix != NULL
+      ? _rl_vi_ins_mode_prompt_suffix
+      : "";
+  else
+    return _rl_vi_norm_mode_prompt_prefix != NULL
+      ? _rl_vi_norm_mode_prompt_suffix
+      : "";
+}
+
 /* 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
@@ -271,8 +305,18 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
      char *pmt;
      int *lp, *lip, *niflp, *vlp;
 {
-  char *r, *ret, *p, *igstart;
-  int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
+  char *r, *ret, *p, *igstart, *before_prompt_chars, *after_prompt_chars,
+       *pmt_with_after_prompt_chars;
+  int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars,
+      before_prompt_num_chars, after_prompt_num_chars;
+
+  if (pmt == rl_prompt && _rl_show_mode_in_prompt)
+    {
+      before_prompt_chars = prompt_modechars_before ();
+      before_prompt_num_chars = strlen (before_prompt_chars);
+      after_prompt_chars = prompt_modechars_after ();
+      after_prompt_num_chars = strlen (after_prompt_chars);
+    }
 
   /* Short-circuit if we can. */
   if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
@@ -280,9 +324,10 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
       if (pmt == rl_prompt && _rl_show_mode_in_prompt)
         {
           l = strlen (pmt);
-          r = (char *)xmalloc (l + 2);
-          r[0] = prompt_modechar ();
-          strcpy (r + 1, pmt);
+          r = (char *)xmalloc (l + before_prompt_num_chars + after_prompt_num_chars + 1);
+          strcpy (r, before_prompt_chars);
+          strcpy (r + before_prompt_num_chars, pmt);
+          strcpy (r + before_prompt_num_chars + l, after_prompt_chars);
         }
       else
 	r = savestring (pmt);
@@ -299,20 +344,30 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
     }
 
   l = strlen (pmt);
-  r = ret = (char *)xmalloc (l + 2);
 
   rl = physchars = 0;	/* move up here so mode show can set them */
   if (pmt == rl_prompt && _rl_show_mode_in_prompt)
     {
-      *r++ = prompt_modechar ();
-      rl = physchars = 1;
+      r = ret = (char *)xmalloc (l + before_prompt_num_chars +
+              after_prompt_num_chars + 1);
+      strcpy(r, before_prompt_chars);
+      r += before_prompt_num_chars;
+      rl = physchars = before_prompt_num_chars;
+      pmt_with_after_prompt_chars = (char*)xmalloc (l + after_prompt_num_chars + 1);
+      strcpy (pmt_with_after_prompt_chars, pmt);
+      strcpy (pmt_with_after_prompt_chars + l, after_prompt_chars);
+    }
+  else
+    {
+      r = ret = (char *)xmalloc (l + 1);
+      pmt_with_after_prompt_chars = pmt;
     }
 
   invfl = 0;	/* invisible chars in first line of prompt */
   invflset = 0;	/* we only want to set invfl once */
 
   igstart = 0;
-  for (ignoring = last = ninvis = 0, p = pmt; p && *p; p++)
+  for (ignoring = last = ninvis = 0, p = pmt_with_after_prompt_chars; p && *p; p++)
     {
       /* This code strips the invisible character string markers
 	 RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
@@ -334,8 +389,9 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
 #if defined (HANDLE_MULTIBYTE)
 	  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
 	    {
-	      pind = p - pmt;
-	      ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO);
+	      pind = p - pmt_with_after_prompt_chars;
+	      ind = _rl_find_next_mbchar (
+                      pmt_with_after_prompt_chars, pind, 1, MB_FIND_NONZERO);
 	      l = ind - pind;
 	      while (l--)
 	        *r++ = *p++;
@@ -347,7 +403,8 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
 		     not be the same as the number of physical characters
 		     on the screen in the presence of multibyte characters */
 		  rl += ind - pind;
-		  physchars += _rl_col_width (pmt, pind, ind, 0);
+		  physchars += _rl_col_width (
+                          pmt_with_after_prompt_chars, pind, ind, 0);
 		}
 	      else
 		ninvis += ind - pind;
@@ -374,6 +431,9 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
 	}
     }
 
+  //if (pmt == rl_prompt && _rl_show_mode_in_prompt)
+  //  FREE(pmt_with_after_prompt_chars);
+
   if (rl < _rl_screenwidth)
     invfl = ninvis;
 
diff --git a/lib/readline/readline.c b/lib/readline/readline.c
index abb29a0..7c1be99 100644
--- a/lib/readline/readline.c
+++ b/lib/readline/readline.c
@@ -235,6 +235,24 @@ Keymap rl_executing_keymap;
 /* Keymap we're currently using to dispatch. */
 Keymap _rl_dispatching_keymap;
 
+/* String inserted before the prompt to indicate vi insert mode. */
+char *_rl_vi_ins_mode_prompt_prefix = NULL;
+
+/* String inserted after the prompt to indicate vi insert mode. */
+char *_rl_vi_ins_mode_prompt_suffix = NULL;
+
+/* String inserted before the prompt to indicate vi normal mode. */
+char *_rl_vi_norm_mode_prompt_prefix = NULL;
+
+/* String inserted after the prompt to indicate vi normal mode. */
+char *_rl_vi_norm_mode_prompt_suffix = NULL;
+
+/* String inserted before the prompt to indicate emacs mode. */
+char *_rl_emacs_mode_prompt_prefix = NULL;
+
+/* String inserted after the prompt to indicate emacs mode. */
+char *_rl_emacs_mode_prompt_suffix = NULL;
+
 /* Non-zero means to erase entire line, including prompt, on empty input lines. */
 int rl_erase_empty_line = 0;
 
diff --git a/lib/readline/rlprivate.h b/lib/readline/rlprivate.h
index 14a370d..4fc35da 100644
--- a/lib/readline/rlprivate.h
+++ b/lib/readline/rlprivate.h
@@ -485,6 +485,12 @@ extern int _rl_eof_char;
 extern procenv_t _rl_top_level;
 extern _rl_keyseq_cxt *_rl_kscxt;
 extern int _rl_keyseq_timeout;
+extern char *_rl_vi_ins_mode_prompt_prefix;
+extern char *_rl_vi_ins_mode_prompt_suffix;
+extern char *_rl_vi_norm_mode_prompt_prefix;
+extern char *_rl_vi_norm_mode_prompt_suffix;
+extern char *_rl_emacs_mode_prompt_prefix;
+extern char *_rl_emacs_mode_prompt_suffix;
 
 extern int _rl_executing_keyseq_size;
 
