diff options
author | Jeff Quast <contact@jeffquast.com> | 2015-01-04 00:43:25 -0800 |
---|---|---|
committer | Jeff Quast <contact@jeffquast.com> | 2015-01-04 00:43:25 -0800 |
commit | beaa2907d1dceb9639a7e99d31bb2fd09f43317f (patch) | |
tree | 473b8abeb2779afab883e9590d9991a1d94d1a1f | |
parent | ecda1a296838ad696ec47dac0370e488c191c917 (diff) | |
parent | 8f264cee6c24f3405752652719f73f3d4369bd12 (diff) | |
download | blessings-beaa2907d1dceb9639a7e99d31bb2fd09f43317f.tar.gz |
Merge pull request #39 from jquast/break-really-long-words
break_long_words=True now supported by term.wrap
-rw-r--r-- | README.rst | 1 | ||||
-rw-r--r-- | blessed/sequences.py | 56 | ||||
-rw-r--r-- | blessed/tests/accessories.py | 32 | ||||
-rw-r--r-- | blessed/tests/test_wrap.py | 24 | ||||
-rw-r--r-- | docs/conf.py | 2 | ||||
-rwxr-xr-x | setup.py | 4 | ||||
-rw-r--r-- | tox.ini | 3 |
7 files changed, 89 insertions, 33 deletions
@@ -691,6 +691,7 @@ shares the same. See the LICENSE file. Version History =============== 1.9 + * enhancement: ``break_long_words=True`` now supported by ``term.wrap`` * workaround: ignore curses.error 'tparm() returned NULL', this occurs on win32 platforms using PDCurses_ where ``tparm()`` is not implemented. diff --git a/blessed/sequences.py b/blessed/sequences.py index 2862197..8f9ed95 100644 --- a/blessed/sequences.py +++ b/blessed/sequences.py @@ -103,7 +103,7 @@ def get_movement_sequence_patterns(term): re.escape(term.rc), # clear_screen: clear screen and home cursor re.escape(term.clear), - # cursor_up: Up one line + # enter/exit_fullscreen: switch to alternate screen buffer re.escape(term.enter_fullscreen), re.escape(term.exit_fullscreen), # forward cursor @@ -369,6 +369,60 @@ class SequenceTextWrapper(textwrap.TextWrapper): lines.append(indent + u''.join(cur_line)) return lines + def _handle_long_word(self, reversed_chunks, cur_line, cur_len, width): + """_handle_long_word(chunks : [string], + cur_line : [string], + cur_len : int, width : int) + + Handle a chunk of text (most likely a word, not whitespace) that + is too long to fit in any line. + """ + # Figure out when indent is larger than the specified width, and make + # sure at least one character is stripped off on every pass + if width < 1: + space_left = 1 + else: + space_left = width - cur_len + + # If we're allowed to break long words, then do so: put as much + # of the next chunk onto the current line as will fit. + if self.break_long_words: + term = self.term + chunk = reversed_chunks[-1] + if (space_left == 0 or + space_left == 1 and chunk == u' '): + idx = space_left + else: + nxt = 0 + for idx in range(0, len(chunk)): + if idx == nxt: + # at sequence, point beyond it, + nxt = idx + measure_length(chunk[idx:], term) + if nxt <= idx: + # point beyond next sequence, if any, + # otherwise point to next character + nxt = idx + measure_length(chunk[idx:], term) + 1 + if Sequence(chunk[:nxt], term).length() > space_left: + break + else: + idx = space_left + + cur_line.append(reversed_chunks[-1][:idx]) + reversed_chunks[-1] = reversed_chunks[-1][idx:] + + # Otherwise, we have to preserve the long word intact. Only add + # it to the current line if there's nothing already there -- + # that minimizes how much we violate the width constraint. + elif not cur_line: + cur_line.append(reversed_chunks.pop()) + + # If we're not allowed to break long words, and there's already + # text on the current line, do nothing. Next time through the + # main loop of _wrap_chunks(), we'll wind up here again, but + # cur_len will be zero, so the next line will be entirely + # devoted to the long word that we can't handle right now. + + SequenceTextWrapper.__doc__ = textwrap.TextWrapper.__doc__ diff --git a/blessed/tests/accessories.py b/blessed/tests/accessories.py index 9c06688..408d2e7 100644 --- a/blessed/tests/accessories.py +++ b/blessed/tests/accessories.py @@ -30,24 +30,24 @@ SEND_SEMAPHORE = SEMAPHORE = b'SEMAPHORE\n' RECV_SEMAPHORE = b'SEMAPHORE\r\n' all_xterms_params = ['xterm', 'xterm-256color'] many_lines_params = [30, 100] -many_columns_params = [1, 25, 50] +many_columns_params = [1, 10] from blessed._binterms import binary_terminals default_all_terms = ['screen', 'vt220', 'rxvt', 'cons25', 'linux', 'ansi'] -try: - available_terms = [ - _term.split(None, 1)[0].decode('ascii') for _term in - subprocess.Popen(["toe"], stdout=subprocess.PIPE, close_fds=True) - .communicate()[0].splitlines()] - if not os.environ.get('TEST_ALLTERMS'): - # we just pick 3 random terminal types, they're all as good as any so - # long as they're not in the binary_terminals list. - random.shuffle(available_terms) - available_terms = available_terms[:3] - all_terms_params = list(set(available_terms) - ( - set(binary_terminals) if not os.environ.get('TEST_BINTERMS') - else set())) or default_all_terms -except OSError: - all_terms_params = default_all_terms +if os.environ.get('TEST_ALLTERMS'): + try: + available_terms = [ + _term.split(None, 1)[0].decode('ascii') for _term in + subprocess.Popen(('toe', '-a'), + stdout=subprocess.PIPE, + close_fds=True) + .communicate()[0].splitlines()] + except OSError: + all_terms_params = default_all_terms +else: + available_terms = default_all_terms +all_terms_params = list(set(available_terms) - ( + set(binary_terminals) if not os.environ.get('TEST_BINTERMS') + else set())) or default_all_terms class as_subprocess(object): diff --git a/blessed/tests/test_wrap.py b/blessed/tests/test_wrap.py index dee3ebc..1e12060 100644 --- a/blessed/tests/test_wrap.py +++ b/blessed/tests/test_wrap.py @@ -48,18 +48,18 @@ def test_SequenceWrapper_invalid_width(): dict(break_long_words=False, drop_whitespace=True, subsequent_indent=' '), - # dict(break_long_words=True, - # drop_whitespace=False, - # subsequent_indent=''), - # dict(break_long_words=True, - # drop_whitespace=True, - # subsequent_indent=''), - # dict(break_long_words=True, - # drop_whitespace=False, - # subsequent_indent=' '), - # dict(break_long_words=True, - # drop_whitespace=True, - # subsequent_indent=' '), + dict(break_long_words=True, + drop_whitespace=False, + subsequent_indent=''), + dict(break_long_words=True, + drop_whitespace=True, + subsequent_indent=''), + dict(break_long_words=True, + drop_whitespace=False, + subsequent_indent=' '), + dict(break_long_words=True, + drop_whitespace=True, + subsequent_indent=' '), ]) def test_SequenceWrapper(all_terms, many_columns, kwargs): """Test that text wrapping matches internal extra options.""" diff --git a/docs/conf.py b/docs/conf.py index 4ab6f41..6975d7f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -53,7 +53,7 @@ copyright = u'2014 Jeff Quast, 2011 Erik Rose' # built documents. # # The short X.Y version. -version = '1.9.4' +version = '1.9.5' # The full version, including alpha/beta/rc tags. release = version @@ -17,7 +17,7 @@ class SetupDevelop(setuptools.command.develop.develop): # ensure a virtualenv is loaded, assert os.getenv('VIRTUAL_ENV'), 'You should be in a virtualenv' # ensure tox is installed - subprocess.check_call(('pip', 'install', 'tox')) + subprocess.check_call(('pip', 'install', 'tox', 'ipython')) # install development egg-link setuptools.command.develop.develop.run(self) @@ -38,7 +38,7 @@ def main(): setuptools.setup( name='blessed', - version='1.9.4', + version='1.9.5', description="A feature-filled fork of Erik Rose's blessings project", long_description=open(os.path.join(here, 'README.rst')).read(), author='Jeff Quast', @@ -20,7 +20,8 @@ deps = pytest-flakes commands = {envbindir}/py.test \ --strict --pep8 --flakes \ --junit-xml=results.{envname}.xml --verbose \ - --cov blessed blessed/tests {posargs} + --cov blessed blessed/tests --cov-report=term-missing \ + {posargs} /bin/mv {toxinidir}/.coverage {toxinidir}/.coverage.{envname} [testenv:static_analysis] |