4848import math
4949import re
5050import time
51+ import functools
5152
5253import struct
5354if platform .system () != 'Windows' :
@@ -116,18 +117,31 @@ def calculate_screen_lines(tokens, width, cursor=0):
116117 pos %= width
117118 return lines
118119
120+ def forward_if_not_current (func ):
121+ @functools .wraps (func )
122+ def newfunc (self , * args , ** kwargs ):
123+ dest = self .get_dest ()
124+ if self is dest :
125+ return func (self , * args , ** kwargs )
126+ else :
127+ return getattr (self .get_dest (), newfunc .__name__ )(* args , ** kwargs )
128+ return newfunc
129+
119130
120131class FakeStream (object ):
121132 """Provide a fake file object which calls functions on the interface
122133 provided."""
123134
124- def __init__ (self , interface ):
135+ def __init__ (self , interface , get_dest ):
125136 self .encoding = getpreferredencoding ()
126137 self .interface = interface
138+ self .get_dest = get_dest
127139
140+ @forward_if_not_current
128141 def write (self , s ):
129142 self .interface .write (s )
130143
144+ @forward_if_not_current
131145 def writelines (self , l ):
132146 for s in l :
133147 self .write (s )
@@ -998,6 +1012,9 @@ def p_key(self, key):
9981012 self .do_exit = True
9991013 return None
10001014
1015+ elif key == '\x18 ' :
1016+ return self .send_current_line_to_editor ()
1017+
10011018 elif key [0 :3 ] == 'PAD' and not key in ('PAD0' , 'PADSTOP' ):
10021019 pad_keys = {
10031020 'PADMINUS' : '-' ,
@@ -1111,10 +1128,10 @@ def repl(self):
11111128 self .push ('from bpython._internal import _help as help\n ' , False )
11121129
11131130 self .iy , self .ix = self .scr .getyx ()
1114- more = False
1131+ self . more = False
11151132 while not self .do_exit :
11161133 self .f_string = ''
1117- self .prompt (more )
1134+ self .prompt (self . more )
11181135 try :
11191136 inp = self .get_line ()
11201137 except KeyboardInterrupt :
@@ -1135,8 +1152,8 @@ def repl(self):
11351152 else :
11361153 self .stdout_hist += inp .encode (getpreferredencoding ()) + '\n '
11371154 stdout_position = len (self .stdout_hist )
1138- more = self .push (inp )
1139- if not more :
1155+ self . more = self .push (inp )
1156+ if not self . more :
11401157 self .prev_block_finished = stdout_position
11411158 self .s = ''
11421159 return self .exit_value
@@ -1206,8 +1223,8 @@ def reevaluate(self):
12061223 # I decided it was easier to just do this manually
12071224 # than to make the print_line and history stuff more flexible.
12081225 self .scr .addstr ('\n ' )
1209- more = self .push (line )
1210- self .prompt (more )
1226+ self . more = self .push (line )
1227+ self .prompt (self . more )
12111228 self .iy , self .ix = self .scr .getyx ()
12121229
12131230 self .cpos = 0
@@ -1508,6 +1525,46 @@ def yank_from_buffer(self):
15081525 self .addstr (self .cut_buffer )
15091526 self .print_line (self .s , clr = True )
15101527
1528+ def send_current_line_to_editor (self ):
1529+ lines = self .send_to_external_editor (self .s ).split ('\n ' )
1530+ self .s = ''
1531+ self .print_line (self .s )
1532+ while lines and not lines [- 1 ]:
1533+ lines .pop ()
1534+ if not lines :
1535+ return ''
1536+
1537+ self .f_string = ''
1538+ self .cpos = - 1 # Set cursor position to -1 to prevent paren matching
1539+
1540+ self .iy , self .ix = self .scr .getyx ()
1541+ self .evaluating = True
1542+ for line in lines :
1543+ if py3 :
1544+ self .stdout_hist += line + '\n '
1545+ else :
1546+ self .stdout_hist += line .encode (getpreferredencoding ()) + '\n '
1547+ self .history .append (line )
1548+ self .print_line (line )
1549+ self .s_hist [- 1 ] += self .f_string
1550+ self .scr .addstr ('\n ' )
1551+ self .more = self .push (line )
1552+ self .prompt (self .more )
1553+ self .iy , self .ix = self .scr .getyx ()
1554+ self .evaluating = False
1555+
1556+ self .cpos = 0
1557+ indent = repl .next_indentation (self .s , self .config .tab_length )
1558+ self .s = ''
1559+ self .scr .refresh ()
1560+
1561+ if self .buffer :
1562+ for _ in xrange (indent ):
1563+ self .tab ()
1564+
1565+ self .print_line (self .s )
1566+ self .scr .redrawwin ()
1567+ return ''
15111568
15121569class Statusbar (object ):
15131570 """This class provides the status bar at the bottom of the screen.
@@ -1876,11 +1933,11 @@ def main_curses(scr, args, config, interactive=True, locals_=None,
18761933 clirepl ._C = cols
18771934
18781935 sys .stdin = FakeStdin (clirepl )
1879- sys .stdout = FakeStream (clirepl )
1880- sys .stderr = FakeStream (clirepl )
1936+ sys .stdout = FakeStream (clirepl , lambda : sys . stdout )
1937+ sys .stderr = FakeStream (clirepl , lambda : sys . stderr )
18811938
18821939 if args :
1883- exit_value = 0
1940+ exit_value = ()
18841941 try :
18851942 bpython .args .exec_code (interpreter , args )
18861943 except SystemExit , e :
@@ -1899,6 +1956,9 @@ def main_curses(scr, args, config, interactive=True, locals_=None,
18991956 clirepl .write (banner )
19001957 clirepl .write ('\n ' )
19011958 exit_value = clirepl .repl ()
1959+ if hasattr (sys , 'exitfunc' ):
1960+ sys .exitfunc ()
1961+ delattr (sys , 'exitfunc' )
19021962
19031963 main_win .erase ()
19041964 main_win .refresh ()
0 commit comments