Skip to content

Commit

Permalink
Handle -1 from wcwidth (e.g. newline) (#402)
Browse files Browse the repository at this point in the history
- Only try to find width of last line of prompt.
- Handle -1 from wcwidth by returning number of bytes in prompt.
- Does not handle newline inside of escape characters.

Addresses #394

- Add tests for control characters in prompt

See #402 (comment) and
#394 (comment) for
discussion.
  • Loading branch information
jyn514 authored and andychu committed Jul 6, 2019
1 parent d455d2d commit 97808b2
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 2 deletions.
9 changes: 7 additions & 2 deletions core/comp_ui.py
Expand Up @@ -32,7 +32,8 @@
def _PromptLen(prompt_str):
"""Ignore all characters between \x01 and \x02 and handle unicode characters.
In particular, the display width of a string may be different from either the
number of bytes or the number of unicode characters."""
number of bytes or the number of unicode characters.
Additionally, if there are multiple lines in the prompt, only give the length of the last line."""
escaped = False
display_str = ""
for c in prompt_str:
Expand All @@ -42,11 +43,15 @@ def _PromptLen(prompt_str):
escaped = False
elif not escaped:
display_str += c
last_line = display_str.split('\n')[-1]
try:
return libc.wcswidth(display_str)
width = libc.wcswidth(last_line)
# en_US.UTF-8 locale missing, just return the number of bytes
except (SystemError, UnicodeError):
return len(display_str)
if width == -1:
return len(display_str)
return width


class PromptState(object):
Expand Down
8 changes: 8 additions & 0 deletions core/comp_ui_test.py
Expand Up @@ -165,6 +165,14 @@ def testValidEscapes(self):
comp_ui._PromptLen("\x01\x02 hi \x01hi\x02 \x01\x02 hello"),
len(" hi hello"))

def testNewline(self):
self.assertEqual(comp_ui._PromptLen("\n"), 0)
self.assertEqual(comp_ui._PromptLen("abc\ndef"), 3)
self.assertEqual(comp_ui._PromptLen(""), 0)

def testControlCharacters(self):
self.assertEqual(comp_ui._PromptLen("\xef"), 1)
self.assertEqual(comp_ui._PromptLen("\x03\x05"), 2)

if __name__ == '__main__':
unittest.main()
1 change: 1 addition & 0 deletions native/libc_test.py
Expand Up @@ -193,6 +193,7 @@ def testGetTerminalWidth(self):
def testWcsWidth(self):
self.assertEqual(1, libc.wcswidth("▶️"))
self.assertEqual(28, libc.wcswidth("(osh) ~/.../unchanged/oil ▶️ "))
self.assertEqual(2, libc.wcswidth("→ "))
self.assertRaises(UnicodeError, libc.wcswidth, "\xfe")

if __name__ == '__main__':
Expand Down

0 comments on commit 97808b2

Please sign in to comment.