Show More
@@ -257,6 +257,14 b' def _lenlastline(s):' | |||
|
257 | 257 | return len(s.splitlines()[-1]) |
|
258 | 258 | |
|
259 | 259 | |
|
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 | ||
|
260 | 268 | class UserNSFormatter(Formatter): |
|
261 | 269 | """A Formatter that falls back on a shell's user_ns and __builtins__ for name resolution""" |
|
262 | 270 | def __init__(self, shell): |
@@ -350,8 +358,7 b' class PromptManager(Configurable):' | |||
|
350 | 358 | self.templates[name] = multiple_replace(prompt_abbreviations, new_template) |
|
351 | 359 | # We count invisible characters (colour escapes) on the last line of the |
|
352 | 360 | # prompt, to calculate the width for lining up subsequent prompts. |
|
353 |
invis_chars = _ |
|
|
354 | _lenlastline(self._render(name, color=False)) | |
|
361 | invis_chars = _invisible_characters(self._render(name, color=True)) | |
|
355 | 362 | self.invisible_chars[name] = invis_chars |
|
356 | 363 | |
|
357 | 364 | def _update_prompt_trait(self, traitname, new_template): |
@@ -6,7 +6,7 b' import unittest' | |||
|
6 | 6 | import os |
|
7 | 7 | |
|
8 | 8 | 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 | |
|
10 | 10 | from IPython.testing.globalipapp import get_ipython |
|
11 | 11 | from IPython.utils.tempdir import TemporaryWorkingDirectory |
|
12 | 12 | from IPython.utils import py3compat |
@@ -107,3 +107,23 b' class PromptTests(unittest.TestCase):' | |||
|
107 | 107 | finally: |
|
108 | 108 | 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 [\\#]: \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) |
General Comments 0
You need to be logged in to leave comments.
Login now