Skip to content

Commit 96bf950

Browse files
hacker external pager (hardcoded to less) added for bpython-curtsies
1 parent 63cbf14 commit 96bf950

File tree

3 files changed

+44
-7
lines changed

3 files changed

+44
-7
lines changed

bpython/curtsies.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ def event_or_refresh(timeout=None):
7676
get_cursor_vertical_diff=window.get_cursor_vertical_diff,
7777
banner=banner,
7878
interp=interp,
79-
interactive=interactive) as repl:
79+
interactive=interactive,
80+
orig_tcattrs=input_generator.original_stty) as repl:
8081
repl.height, repl.width = window.t.height, window.t.width
8182
sys.repl = repl
8283

bpython/curtsiesfrontend/repl.py

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import os
77
import re
88
import signal
9+
import subprocess
910
import sys
11+
import tempfile
1012
import threading
1113
import unicodedata
1214

@@ -15,13 +17,15 @@
1517
from bpython.config import Struct, loadini, default_config_path
1618
from bpython.formatter import BPythonFormatter
1719
from pygments import format
20+
from pygments.lexers import PythonLexer
21+
from pygments.formatters import TerminalFormatter
1822
from bpython import importcompletion
1923
from bpython import translations
2024
translations.init()
2125
from bpython.translations import _
2226
from bpython._py3compat import py3
2327

24-
from curtsies import FSArray, fmtstr, FmtStr
28+
from curtsies import FSArray, fmtstr, FmtStr, Termmode
2529
from curtsies.bpythonparse import parse as bpythonparse
2630
from curtsies.bpythonparse import func_for_letter, color_for_letter
2731
from curtsies import fmtfuncs
@@ -152,7 +156,8 @@ class Repl(BpythonRepl):
152156
## initialization, cleanup
153157
def __init__(self, locals_=None, config=None,
154158
request_refresh=lambda: None, get_term_hw=lambda:(50, 10),
155-
get_cursor_vertical_diff=lambda: 0, banner=None, interp=None, interactive=True):
159+
get_cursor_vertical_diff=lambda: 0, banner=None, interp=None, interactive=True,
160+
orig_tcattrs=None):
156161
"""
157162
locals_ is a mapping of locals to pass into the interpreter
158163
config is a bpython config.Struct with config attributes
@@ -223,6 +228,7 @@ def smarter_request_refresh():
223228
self.scroll_offset = 0 # how many times display has been scrolled down
224229
# because there wasn't room to display everything
225230
self.cursor_offset = 0 # from the left, 0 means first char
231+
self.orig_tcattrs = orig_tcattrs # useful for shelling out with normal terminal
226232

227233
self.coderunner = CodeRunner(self.interp, self.request_refresh)
228234
self.stdout = FakeOutput(self.coderunner, self.send_to_stdout)
@@ -360,8 +366,17 @@ def process_event(self, e):
360366
self.request_paint_to_clear_screen = True
361367
elif e in key_dispatch[self.config.last_output_key]: #TODO Not Implemented
362368
pass
363-
elif e in key_dispatch[self.config.show_source_key]: #TODO Not Implemented
364-
pass
369+
elif e in ('\x1f',) + key_dispatch[self.config.show_source_key]: #TODO Not Implemented
370+
source = self.get_source_of_current_name()
371+
if source is None:
372+
self.status_bar.message('whoops!')
373+
else:
374+
if self.config.highlight_show_source:
375+
source = format(PythonLexer().get_tokens(source), TerminalFormatter())
376+
with tempfile.NamedTemporaryFile() as tmp:
377+
tmp.write(source)
378+
tmp.flush()
379+
self.focus_on_subprocess(['less', '-R', tmp.name])
365380
elif e in key_dispatch[self.config.suspend_key]:
366381
raise SystemExit()
367382
elif e in ("",) + key_dispatch[self.config.exit_key]:
@@ -937,6 +952,27 @@ def getstdout(self):
937952
) if lines else ''
938953
return s
939954

955+
def focus_on_subprocess(self, args):
956+
import blessings
957+
prev_sigwinch_handler = signal.getsignal(signal.SIGWINCH)
958+
try:
959+
signal.signal(signal.SIGWINCH, self.orig_sigwinch_handler)
960+
with Termmode(self.orig_stdin, self.orig_tcattrs):
961+
terminal = blessings.Terminal(stream=sys.__stdout__)
962+
with terminal.fullscreen():
963+
sys.__stdout__.write(terminal.save)
964+
sys.__stdout__.write(terminal.move(0, 0))
965+
sys.__stdout__.flush()
966+
p = subprocess.Popen(args,
967+
stdin=self.orig_stdin,
968+
stderr=sys.__stderr__,
969+
stdout=sys.__stdout__)
970+
p.wait()
971+
sys.__stdout__.write(terminal.restore)
972+
sys.__stdout__.flush()
973+
finally:
974+
signal.signal(signal.SIGWINCH, prev_sigwinch_handler)
975+
940976
def is_nop(char):
941977
return unicodedata.category(unicode(char)) == 'Cc'
942978

bpython/test/test_autocomplete.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ class TestSimpleComplete(unittest.TestCase):
99
complete = partial(autocomplete.complete,
1010
namespace={'zabcdef':1, 'zabcqwe':2, 'ze':3},
1111
config=simple_config)
12-
kwargs = {locals_={'zabcdef':1, 'zabcqwe':2, 'ze':3},
13-
argspec=inspect.getargspec(lambda x: x),
12+
kwargs = {locals_:{'zabcdef':1, 'zabcqwe':2, 'ze':3},
13+
argspec:inspect.getargspec(lambda x: x),
1414

1515
def test_simple_completion(self):
1616
self.assertEqual(self.complete('zab'), ['zabcdef', 'zabcqwe'])

0 commit comments

Comments
 (0)