summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Leonhardt <todd.leonhardt@gmail.com>2017-05-11 21:41:36 -0400
committerTodd Leonhardt <todd.leonhardt@gmail.com>2017-05-11 21:41:36 -0400
commit2bd17dbc34ce88a4cd5375dadb0406b891a1fdb6 (patch)
treee80135780402ed18a7c0c4a788782f9326169b3e
parentecf5a11315fc0bcab575182820f8c06e348813d2 (diff)
downloadcmd2-git-2bd17dbc34ce88a4cd5375dadb0406b891a1fdb6.tar.gz
Added code to protect against GNU Readline bug
GNU Readline has a bug in calculating prompt length when ANSI escape codes are present in the prompt. It requires you to escape the escape codes to tell it where sections of invisible characters begin and end. So before calling input(), cmd2 now makes the prompt safe by escaping any ANSI escape codes present.
-rwxr-xr-xcmd2.py28
1 files changed, 27 insertions, 1 deletions
diff --git a/cmd2.py b/cmd2.py
index ab16472c..b5dbcfbd 100755
--- a/cmd2.py
+++ b/cmd2.py
@@ -34,6 +34,7 @@ import optparse
import os
import platform
import re
+import readline
import shlex
import six
import subprocess
@@ -1096,12 +1097,37 @@ class Cmd(cmd.Cmd):
return False
+ @staticmethod
+ def _surround_ansi_escapes(prompt, start="\x01", end="\x02"):
+ """Overcome bug in GNU Readline in relation to calculation of prompt length in presence of ASNI escape codes.
+
+ :param prompt: str - original prompt
+ :param start: str - start code to tell GNU Readline about beginning of invisible characters
+ :param end: str - end code to tell GNU Readline about end of invisible characters
+ :return: str - prompt safe to pass to GNU Readline
+ """
+ escaped = False
+ result = ""
+
+ for c in prompt:
+ if c == "\x1b" and not escaped:
+ result += start + c
+ escaped = True
+ elif c.isalpha() and escaped:
+ result += c + end
+ escaped = False
+ else:
+ result += c
+
+ return result
+
def pseudo_raw_input(self, prompt):
"""copied from cmd's cmdloop; like raw_input, but accounts for changed stdin, stdout"""
if self.use_rawinput:
+ safe_prompt = self._surround_ansi_escapes(prompt)
try:
- line = sm.input(prompt)
+ line = sm.input(safe_prompt)
except EOFError:
line = 'EOF'
else: