Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

debugger: leave output screen with single key press #674

Closed
wants to merge 9 commits into from
11 changes: 8 additions & 3 deletions pudb/debugger.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

import urwid

from pudb.lowlevel import decode_lines, ui_log
from pudb.lowlevel import decode_lines, NonBufferedConsole, ui_log
from pudb.settings import get_save_config_path, load_config, save_config


Expand Down Expand Up @@ -769,10 +769,15 @@ def __init__(self, screen):

def __enter__(self):
self.screen.stop()
return self

def __exit__(self, exc_type, exc_value, exc_traceback):
self.screen.start()

def press_key_to_return(self):
with NonBufferedConsole() as nbc:
key = nbc.get_data()


class DebuggerUI(FrameVarInfoKeeper):
# {{{ constructor
Expand Down Expand Up @@ -2082,8 +2087,8 @@ def shrink_sidebar(w, size, key):
# {{{ top-level listeners

def show_output(w, size, key):
with StoppedScreen(self.screen):
input("Hit Enter to return:")
with StoppedScreen(self.screen) as s:
s.press_key_to_return()

def reload_breakpoints_and_redisplay():
reload_breakpoints()
Expand Down
69 changes: 69 additions & 0 deletions pudb/lowlevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,4 +283,73 @@ def decode_lines(lines):

# }}}


# {{{ non-buffered console

# Local platform dependent helper to get single key presses from a
# terminal in unbuffered mode. Eliminates the necessity to press ENTER
# before other input also becomes available. Also avoids the accumulation
# of prompts on the screen as was the case with Python's input() call.
# Is used in situations where urwid is disabled and curses calls are
# not available.
inducer marked this conversation as resolved.
Show resolved Hide resolved

_nbc_use_input = True
_nbc_use_getch = False
_nbc_use_select = False
inducer marked this conversation as resolved.
Show resolved Hide resolved
if sys.platform in ("emscripten", "wasi"):
pass
elif sys.platform in ("win32",):
import msvcrt
_nbc_use_input = False
_nbc_use_getch = True
else:
import select
import termios
import tty
_nbc_use_input = False
_nbc_use_select = True


class NonBufferedConsole(object):
inducer marked this conversation as resolved.
Show resolved Hide resolved

def __init__(self):
pass

inducer marked this conversation as resolved.
Show resolved Hide resolved
def __enter__(self):
if _nbc_use_select:
self.prev_settings = termios.tcgetattr(sys.stdin)
tty.setcbreak(sys.stdin.fileno())
return self

def __exit__(self, type, value, traceback):
if _nbc_use_select:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, self.prev_settings)

def get_data(self):
inducer marked this conversation as resolved.
Show resolved Hide resolved
if _nbc_use_getch:
c = msvcrt.getch()
if c in ('\x00', '\xe0'):
inducer marked this conversation as resolved.
Show resolved Hide resolved
c = msvcrt.getch()
return c

if _nbc_use_select:
rset, _, _ = select.select([sys.stdin], [], [], None)
if sys.stdin in rset:
return sys.stdin.read(1)
return None
inducer marked this conversation as resolved.
Show resolved Hide resolved

# Strictly speaking putting the fallback here which requires
# pressing ENTER is not correct, this is the "non buffered"
# console support code. But it simplifies call sites. And is
# easy to tell by users because a prompt is provided. This is
# the most portable approach, and backwards compatible with
# earlier PuDB releases. It's a most appropriate default for
# otherwise unsupported platforms. Or when users choose to
# not accept single key presses, or keys other than ENTER.
if _nbc_use_input:
input("Hit Enter to return:")
return None

# }}}

# vim: foldmethod=marker
Loading