Skip to content

Commit b41d20a

Browse files
clean up curtsies.repl.Repl and implement weak rewind
weak rewind is cli.py-style rewind, where a new interpreter isn't used. This is useful when bpython REPL was initialized with locals, or was run as -i.
1 parent 2b8d8a4 commit b41d20a

File tree

2 files changed

+42
-34
lines changed

2 files changed

+42
-34
lines changed

bpython/curtsies.py

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import absolute_import
22

33
import sys
4-
import os
4+
import code
55
from optparse import Option
66

77
import curtsies
@@ -28,14 +28,37 @@ def main(args=None, locals_=None, banner=None):
2828
import logging
2929
logging.basicConfig(filename='scroll.log', level=logging.DEBUG)
3030

31-
# do parsing before doing any frontend stuff
31+
interp = None
32+
paste = None
33+
if exec_args:
34+
assert options, "don't pass in exec_args without options"
35+
exit_value = 0
36+
if options.type:
37+
paste = curtsies.events.PasteEvent()
38+
sourcecode = open(exec_args[0]).read()
39+
paste.events.extend(sourcecode)
40+
else:
41+
try:
42+
interp = code.InteractiveInterpreter(locals=locals_)
43+
bpargs.exec_code(interp, exec_args)
44+
except SystemExit, e:
45+
exit_value = e.args
46+
if not options.interactive:
47+
raise SystemExit(exit_value)
48+
else:
49+
sys.path.insert(0, '') # expected for interactive sessions (python does it)
50+
51+
mainloop(config, locals_, banner, interp, paste)
52+
53+
def mainloop(config, locals_, banner, interp=None, paste=None):
3254
with Terminal(paste_mode=True) as tc:
3355
with Window(tc, keep_last_line=True, hide_cursor=False) as term:
3456
#TODO why need to make repl first
3557
with Repl(config=config,
3658
locals_=locals_,
3759
stuff_a_refresh_request=tc.stuff_a_refresh_request,
38-
banner=banner) as repl:
60+
banner=banner,
61+
interp=interp) as repl:
3962
rows, columns = tc.get_screen_size()
4063
repl.width = columns
4164
repl.height = rows
@@ -58,34 +81,12 @@ def process_event(e):
5881
# Could this be calculated in the repl, avoiding this
5982
# two-way communication?
6083

61-
exit_value = 0
62-
if exec_args:
63-
assert options, "don't pass in exec_args without options"
64-
if options.type:
65-
repl.process_event(tc.get_event()) #first event will always be a window size set
66-
paste = curtsies.events.PasteEvent()
67-
old_argv, sys.argv = sys.argv, exec_args
68-
paste.events.extend(open(exec_args[0]).read())
69-
sys.path.insert(0, os.path.abspath(os.path.dirname(exec_args[0])))
70-
process_event(paste)
71-
else:
72-
try:
73-
# THIS IS NORMAL PYTHON
74-
#TODO replace this so that stdout is properly harvested for display and rewind works
75-
bpargs.exec_code(repl.interp, exec_args)
76-
except SystemExit, e:
77-
exit_value = e.args
78-
if not options.interactive:
79-
#TODO treat this properly: no prompt should ever display, but stdout should!
80-
array, cursor_pos = repl.paint(about_to_exit=True)
81-
term.render_to_terminal(array, cursor_pos)
82-
raise SystemExit(exit_value)
83-
else:
84-
sys.path.insert(0, '') # expected for interactive sessions (python does it)
84+
if paste:
85+
repl.process_event(tc.get_event()) #first event will always be a window size set
86+
process_event(paste)
8587

8688
while True:
8789
process_event(tc.get_event())
8890

89-
9091
if __name__ == '__main__':
9192
sys.exit(main())

bpython/curtsiesfrontend/repl.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,18 @@ class Repl(BpythonRepl):
125125
"""
126126

127127
## initialization, cleanup
128-
def __init__(self, locals_=None, config=None, stuff_a_refresh_request=lambda: None, banner=None):
128+
def __init__(self, locals_=None, config=None, stuff_a_refresh_request=lambda: None, banner=None, interp=None):
129129
logging.debug("starting init")
130130

131131
if config is None:
132132
config = Struct()
133133
loadini(config, default_config_path())
134134

135-
interp = code.InteractiveInterpreter(locals=locals_)
135+
self.weak_rewind = bool(locals_ or interp)
136+
137+
if interp is None:
138+
interp = code.InteractiveInterpreter(locals=locals_)
139+
136140

137141
if banner is None:
138142
banner = _('welcome to bpython')
@@ -822,10 +826,13 @@ def reevaluate(self, insert_into_history=False):
822826
self.display_lines = []
823827

824828
self.done = True # this keeps the first prompt correct
825-
self.interp = code.InteractiveInterpreter()
826-
self.coderunner.interp = self.interp
827-
self.completer = Autocomplete(self.interp.locals, self.config)
828-
self.completer.autocomplete_mode = 'simple'
829+
830+
if not self.weak_rewind:
831+
self.interp = code.InteractiveInterpreter()
832+
self.coderunner.interp = self.interp
833+
self.completer = Autocomplete(self.interp.locals, self.config)
834+
self.completer.autocomplete_mode = 'simple'
835+
829836
self.buffer = []
830837
self.display_buffer = []
831838
self.highlighted_paren = None

0 commit comments

Comments
 (0)