Skip to content

Commit 2bd17db

Browse files
committed
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.
1 parent ecf5a11 commit 2bd17db

File tree

1 file changed

+27
-1
lines changed

1 file changed

+27
-1
lines changed

cmd2.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import os
3535
import platform
3636
import re
37+
import readline
3738
import shlex
3839
import six
3940
import subprocess
@@ -1096,12 +1097,37 @@ def _default(self, statement):
10961097

10971098
return False
10981099

1100+
@staticmethod
1101+
def _surround_ansi_escapes(prompt, start="\x01", end="\x02"):
1102+
"""Overcome bug in GNU Readline in relation to calculation of prompt length in presence of ASNI escape codes.
1103+
1104+
:param prompt: str - original prompt
1105+
:param start: str - start code to tell GNU Readline about beginning of invisible characters
1106+
:param end: str - end code to tell GNU Readline about end of invisible characters
1107+
:return: str - prompt safe to pass to GNU Readline
1108+
"""
1109+
escaped = False
1110+
result = ""
1111+
1112+
for c in prompt:
1113+
if c == "\x1b" and not escaped:
1114+
result += start + c
1115+
escaped = True
1116+
elif c.isalpha() and escaped:
1117+
result += c + end
1118+
escaped = False
1119+
else:
1120+
result += c
1121+
1122+
return result
1123+
10991124
def pseudo_raw_input(self, prompt):
11001125
"""copied from cmd's cmdloop; like raw_input, but accounts for changed stdin, stdout"""
11011126

11021127
if self.use_rawinput:
1128+
safe_prompt = self._surround_ansi_escapes(prompt)
11031129
try:
1104-
line = sm.input(prompt)
1130+
line = sm.input(safe_prompt)
11051131
except EOFError:
11061132
line = 'EOF'
11071133
else:

0 commit comments

Comments
 (0)