Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit ad51de2

Browse filesBrowse files
author
Marien Zwart
committed
urwid frontend: handle long-running commands and lengthy output better.
Redrawing the screen is relatively slow, so rate-limiting it greatly speeds up inputs that result in a lot of output quickly. Also, scrolling to the bottom while waiting for a command to run out of output makes it more obvious we did not get stuck. Both issues reported by tos9 over irc.
1 parent 4188293 commit ad51de2
Copy full SHA for ad51de2

1 file changed

+45-3Lines changed: 45 additions & 3 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎bpython/urwid.py‎

Copy file name to clipboardExpand all lines: bpython/urwid.py
+45-3Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
import sys
3939
import os
40+
import time
4041
import locale
4142
import signal
4243
from types import ModuleType
@@ -438,9 +439,15 @@ def notify(self, s, n=10):
438439

439440
class URWIDRepl(repl.Repl):
440441

442+
_time_between_redraws = .05 # seconds
443+
441444
def __init__(self, event_loop, palette, interpreter, config):
442445
repl.Repl.__init__(self, interpreter, config)
443446

447+
self._redraw_handle = None
448+
self._redraw_pending = False
449+
self._redraw_time = 0
450+
444451
self.listbox = BPythonListBox(urwid.SimpleListWalker([]))
445452

446453
# String is straight from bpython.cli
@@ -485,6 +492,13 @@ def echo(self, orig_s):
485492
self.current_output = urwid.Text(('output', s))
486493
if self.edit is None:
487494
self.listbox.body.append(self.current_output)
495+
# Focus the widget we just added to force the
496+
# listbox to scroll. This causes output to scroll
497+
# if the user runs a blocking call that prints
498+
# more than a screenful, instead of staying
499+
# scrolled to the previous input line and then
500+
# jumping to the bottom when done.
501+
self.listbox.set_focus(len(self.listbox.body) - 1)
488502
else:
489503
self.listbox.body.insert(-1, self.current_output)
490504
# The edit widget should be focused and *stay* focused.
@@ -496,9 +510,37 @@ def echo(self, orig_s):
496510
('output', self.current_output.text + s))
497511
if orig_s.endswith('\n'):
498512
self.current_output = None
499-
# TODO: maybe do the redraw after a short delay
500-
# (for performance)
501-
self.main_loop.draw_screen()
513+
514+
# If we hit this repeatedly in a loop the redraw is rather
515+
# slow (testcase: pprint(__builtins__). So if we have recently
516+
# drawn the screen already schedule a call in the future.
517+
#
518+
# Unfortunately we may hit this function repeatedly through a
519+
# blocking call triggered by the user, in which case our
520+
# timeout will not run timely as we do not return to urwid's
521+
# eventloop. So we manually check if our timeout has long
522+
# since expired, and redraw synchronously if it has.
523+
if self._redraw_handle is None:
524+
self.main_loop.draw_screen()
525+
526+
def maybe_redraw(loop, self):
527+
if self._redraw_pending:
528+
loop.draw_screen()
529+
self._redraw_pending = False
530+
531+
self._redraw_handle = None
532+
533+
self._redraw_handle = self.main_loop.set_alarm_in(
534+
self._time_between_redraws, maybe_redraw, self)
535+
self._redraw_time = time.time()
536+
else:
537+
self._redraw_pending = True
538+
now = time.time()
539+
if now - self._redraw_time > 2 * self._time_between_redraws:
540+
# The timeout is well past expired, assume we're
541+
# blocked and redraw synchronously.
542+
self.main_loop.draw_screen()
543+
self._redraw_time = now
502544

503545
def current_line(self):
504546
"""Return the current line (the one the cursor is in)."""

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.