summaryrefslogtreecommitdiff
path: root/cmd2.py
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 /cmd2.py
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.
Diffstat (limited to 'cmd2.py')
-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: