Skip to content

Commit

Permalink
Merge pull request #155 from nicoddemus/terminal-chars-per-line-count
Browse files Browse the repository at this point in the history
add TerminalWriter.chars_on_current_line read-only property
  • Loading branch information
RonnyPfannschmidt committed Nov 10, 2017
2 parents e5f9547 + d4cf79b commit aa56ef0
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
- turn iniconfig and apipkg into vendored packages and ease de-vendoring for distributions
- fix #68 remove invalid py.test.ensuretemp references
- fix #25 - deprecate path.listdir(sort=callable)
- add ``TerminalWriter.chars_on_current_line`` read-only property that tracks how many characters
have been written to the current line.

1.4.34
====================================================================
Expand Down
27 changes: 27 additions & 0 deletions py/_io/terminalwriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ def __init__(self, file=None, stringio=False, encoding=None):
self._file = file
self.hasmarkup = should_do_markup(file)
self._lastlen = 0
self._chars_on_current_line = 0

@property
def fullwidth(self):
Expand All @@ -150,6 +151,19 @@ def fullwidth(self):
def fullwidth(self, value):
self._terminal_width = value

@property
def chars_on_current_line(self):
"""Return the number of characters written so far in the current line.
Please note that this count does not produce correct results after a reline() call,
see #164.
.. versionadded:: 1.5.0
:rtype: int
"""
return self._chars_on_current_line

def _escaped(self, text, esc):
if esc and self.hasmarkup:
text = (''.join(['\x1b[%sm' % cod for cod in esc]) +
Expand Down Expand Up @@ -200,12 +214,22 @@ def write(self, msg, **kw):
if msg:
if not isinstance(msg, (bytes, text)):
msg = text(msg)

self._update_chars_on_current_line(msg)

if self.hasmarkup and kw:
markupmsg = self.markup(msg, **kw)
else:
markupmsg = msg
write_out(self._file, markupmsg)

def _update_chars_on_current_line(self, text):
fields = text.rsplit('\n', 1)
if '\n' in text:
self._chars_on_current_line = len(fields[-1])
else:
self._chars_on_current_line += len(fields[-1])

def line(self, s='', **kw):
self.write(s, **kw)
self._checkfill(s)
Expand All @@ -229,6 +253,9 @@ def write(self, msg, **kw):
if msg:
if not isinstance(msg, (bytes, text)):
msg = text(msg)

self._update_chars_on_current_line(msg)

oldcolors = None
if self.hasmarkup and kw:
handle = GetStdHandle(STD_OUTPUT_HANDLE)
Expand Down
21 changes: 21 additions & 0 deletions testing/io_/test_terminalwriter.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,27 @@ class fil:
assert l == set(["2"])


def test_chars_on_current_line():
tw = py.io.TerminalWriter(stringio=True)

written = []

def write_and_check(s, expected):
tw.write(s, bold=True)
written.append(s)
assert tw.chars_on_current_line == expected
assert tw.stringio.getvalue() == ''.join(written)

write_and_check('foo', 3)
write_and_check('bar', 6)
write_and_check('\n', 0)
write_and_check('\n', 0)
write_and_check('\n\n\n', 0)
write_and_check('\nfoo', 3)
write_and_check('\nfbar\nhello', 5)
write_and_check('10', 7)


@pytest.mark.skipif(sys.platform == "win32", reason="win32 has no native ansi")
def test_attr_hasmarkup():
tw = py.io.TerminalWriter(stringio=True)
Expand Down

0 comments on commit aa56ef0

Please sign in to comment.