Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b0cddd3

Browse files
committed
Merge pull request ipython#8738 from asmeurer/invisible-characters
Be a little smarter about invisible characters in terminal prompts
2 parents d26d026 + 1da5de9 commit b0cddd3

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

IPython/core/prompts.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,14 @@ def _lenlastline(s):
257257
return len(s.splitlines()[-1])
258258

259259

260+
invisible_chars_re = re.compile('\001[^\001\002]*\002')
261+
def _invisible_characters(s):
262+
"""
263+
Get the number of invisible ANSI characters in s. Invisible characters
264+
must be delimited by \001 and \002.
265+
"""
266+
return _lenlastline(s) - _lenlastline(invisible_chars_re.sub('', s))
267+
260268
class UserNSFormatter(Formatter):
261269
"""A Formatter that falls back on a shell's user_ns and __builtins__ for name resolution"""
262270
def __init__(self, shell):
@@ -350,8 +358,7 @@ def update_prompt(self, name, new_template=None):
350358
self.templates[name] = multiple_replace(prompt_abbreviations, new_template)
351359
# We count invisible characters (colour escapes) on the last line of the
352360
# prompt, to calculate the width for lining up subsequent prompts.
353-
invis_chars = _lenlastline(self._render(name, color=True)) - \
354-
_lenlastline(self._render(name, color=False))
361+
invis_chars = _invisible_characters(self._render(name, color=True))
355362
self.invisible_chars[name] = invis_chars
356363

357364
def _update_prompt_trait(self, traitname, new_template):

IPython/core/tests/test_prompts.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import os
77

88
from IPython.testing import tools as tt, decorators as dec
9-
from IPython.core.prompts import PromptManager, LazyEvaluate
9+
from IPython.core.prompts import PromptManager, LazyEvaluate, _invisible_characters
1010
from IPython.testing.globalipapp import get_ipython
1111
from IPython.utils.tempdir import TemporaryWorkingDirectory
1212
from IPython.utils import py3compat
@@ -106,4 +106,24 @@ def test_cwd_x(self):
106106
self.assertEqual(p, '~')
107107
finally:
108108
os.chdir(save)
109-
109+
110+
def test_invisible_chars(self):
111+
self.assertEqual(_invisible_characters('abc'), 0)
112+
self.assertEqual(_invisible_characters('\001\033[1;37m\002'), 9)
113+
# Sequences must be between \001 and \002 to be counted
114+
self.assertEqual(_invisible_characters('\033[1;37m'), 0)
115+
# Test custom escape sequences
116+
self.assertEqual(_invisible_characters('\001\033]133;A\a\002'), 10)
117+
118+
def test_width(self):
119+
default_in = '\x01\x1b]133;A\x07\x02In [1]: \x01\x1b]133;B\x07\x02'
120+
self.pm.in_template = default_in
121+
self.pm.render('in')
122+
self.assertEqual(self.pm.width, 8)
123+
self.assertEqual(self.pm.txtwidth, 8)
124+
125+
# Test custom escape sequences
126+
self.pm.in_template = '\001\033]133;A\a\002' + default_in + '\001\033]133;B\a\002'
127+
self.pm.render('in')
128+
self.assertEqual(self.pm.width, 8)
129+
self.assertEqual(self.pm.txtwidth, 8)

0 commit comments

Comments
 (0)