Skip to content

Commit 46740f0

Browse files
committed
Merge
2 parents e097e14 + d4b967d commit 46740f0

File tree

2 files changed

+136
-103
lines changed

2 files changed

+136
-103
lines changed

bpython/cli.py

Lines changed: 77 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -171,49 +171,78 @@ def __init__(self, interface):
171171

172172
self.encoding = getpreferredencoding()
173173
self.interface = interface
174+
self.buffer = list()
175+
176+
def __iter__(self):
177+
return iter(self.readlines())
174178

175179
def isatty(self):
176180
return True
177181

178-
def readline(self):
182+
def readline(self, size=-1):
179183
"""I can't think of any reason why anything other than readline would
180184
be useful in the context of an interactive interpreter so this is the
181185
only one I've done anything with. The others are just there in case
182186
someone does something weird to stop it from blowing up."""
183187

188+
if not size:
189+
return ''
190+
elif self.buffer:
191+
buffer = self.buffer.pop(0)
192+
else:
193+
buffer = ''
194+
184195
curses.raw(True)
185-
buffer = ''
186196
try:
187-
while True:
197+
while not buffer.endswith('\n'):
188198
key = self.interface.get_key()
189199
if key in [curses.erasechar(), 'KEY_BACKSPACE']:
190200
y, x = self.interface.scr.getyx()
191201
if buffer:
192202
self.interface.scr.delch(y, x - 1)
193203
buffer = buffer[:-1]
194204
continue
205+
elif key == chr(4) and not buffer:
206+
# C-d
207+
return ''
195208
elif (key != '\n' and
196209
(len(key) > 1 or unicodedata.category(key) == 'Cc')):
197210
continue
198211
sys.stdout.write(key)
199212
# Include the \n in the buffer - raw_input() seems to deal with trailing
200213
# linebreaks and will break if it gets an empty string.
201214
buffer += key
202-
if key == '\n':
203-
break
204215
finally:
205216
curses.raw(False)
206217

218+
if size > 0:
219+
rest = buffer[size:]
220+
if rest:
221+
self.buffer.append(rest)
222+
buffer = buffer[:size]
223+
207224
if py3:
208225
return buffer
209226
else:
210227
return buffer.encode(getpreferredencoding())
211228

212-
def read(self, x):
213-
pass
229+
def read(self, size=None):
230+
if size == 0:
231+
return ''
214232

215-
def readlines(self, x):
216-
pass
233+
data = list()
234+
while size is None or size > 0:
235+
line = self.readline(size or -1)
236+
if not line:
237+
break
238+
if size is not None:
239+
size -= len(line)
240+
data.append(line)
241+
242+
return ''.join(data)
243+
244+
def readlines(self, size=-1):
245+
return list(iter(self.readline, ''))
217246

218247
OPTS = Struct()
219248
DO_RESIZE = False
@@ -514,7 +543,7 @@ def __init__(self, scr, interp, statusbar=None, idle=None):
514543
sys.stdin = FakeStdin(self)
515544
self.paste_mode = False
516545
self.last_key_press = time.time()
517-
self.paste_time = float(OPTS.paste_time)
546+
self.paste_time = OPTS.paste_time
518547
self.prev_block_finished = 0
519548
sys.path.insert(0, '.')
520549

@@ -798,6 +827,10 @@ def _complete(self, tab=False):
798827
else:
799828
matches = self.completer.matches
800829

830+
if not e and self.argspec:
831+
matches.extend(name + '=' for name in self.argspec[1][0]
832+
if name.startswith(cw))
833+
801834
if e or not matches:
802835
self.matches = []
803836
self.matches_iter.update()
@@ -1324,7 +1357,7 @@ def repl(self):
13241357
if inp:
13251358
self.rl_hist.append(inp + '\n')
13261359
stdout_position = len(self.stdout_hist)
1327-
more = self.push(inp) or self.paste_mode
1360+
more = self.push(inp)
13281361
if not more:
13291362
self.prev_block_finished = stdout_position
13301363
self.s = ''
@@ -1487,14 +1520,10 @@ def bs(self, delete_tabs=True):
14871520

14881521
n = 1
14891522

1490-
if x == 0:
1491-
y -= 1
1492-
x = gethw()[1]
1493-
14941523
# Delete following lines if the current string is greater than the
14951524
# screen width. Curses does not handle that on its own.
14961525
width = self.scr.getmaxyx()[1]
1497-
for y in xrange(self.iy + 1, self.iy + len(self.s) // width + 2):
1526+
for y in xrange(self.iy + 1, self.iy + len(self.s) // width + 1):
14981527
self.scr.move(y, 0)
14991528
self.scr.clrtoeol()
15001529

@@ -1549,7 +1578,7 @@ def clrtobol(self):
15491578
# It seems as if curses does not handle this on its own, which
15501579
# makes me sad.
15511580
width = self.scr.getmaxyx()[1]
1552-
for y in xrange(self.iy + 1, self.iy + len(self.s) // width + 2):
1581+
for y in xrange(self.iy + 1, self.iy + len(self.s) // width + 1):
15531582
self.scr.move(y, 0)
15541583
self.scr.clrtoeol()
15551584

@@ -1562,120 +1591,119 @@ def clrtobol(self):
15621591
self.scr.redrawwin()
15631592
self.scr.refresh()
15641593

1565-
def p_key(self):
1594+
def p_key(self, key):
15661595
"""Process a keypress"""
15671596

1568-
if self.c is None:
1597+
if key is None:
15691598
return ''
15701599

1571-
if self.c == chr(8): # C-Backspace (on my computer anyway!)
1600+
if key == chr(8): # C-Backspace (on my computer anyway!)
15721601
self.clrtobol()
1573-
self.c = '\n'
1602+
key = '\n'
15741603
# Don't return; let it get handled
1575-
if self.c == chr(27):
1604+
if key == chr(27):
15761605
return ''
15771606

1578-
if self.c in (chr(127), 'KEY_BACKSPACE'):
1607+
if key in (chr(127), 'KEY_BACKSPACE'):
15791608
self.bs()
15801609
self.complete()
15811610
return ''
15821611

1583-
elif self.c == 'KEY_DC': # Del
1612+
elif key == 'KEY_DC': # Del
15841613
self.delete()
15851614
self.complete()
15861615
# Redraw (as there might have been highlighted parens)
15871616
self.print_line(self.s)
15881617
return ''
15891618

1590-
elif self.c in key_dispatch[OPTS.undo_key]: # C-r
1619+
elif key in key_dispatch[OPTS.undo_key]: # C-r
15911620
self.undo()
15921621
return ''
15931622

1594-
elif self.c in ('KEY_UP', ) + key_dispatch[OPTS.up_one_line_key]: # Cursor Up/C-p
1623+
elif key in ('KEY_UP', ) + key_dispatch[OPTS.up_one_line_key]: # Cursor Up/C-p
15951624
self.back()
15961625
return ''
15971626

1598-
elif self.c in ('KEY_DOWN', ) + key_dispatch[OPTS.down_one_line_key]: # Cursor Down/C-n
1627+
elif key in ('KEY_DOWN', ) + key_dispatch[OPTS.down_one_line_key]: # Cursor Down/C-n
15991628
self.fwd()
16001629
return ''
16011630

1602-
elif self.c == 'KEY_LEFT': # Cursor Left
1631+
elif key == 'KEY_LEFT': # Cursor Left
16031632
self.mvc(1)
16041633
# Redraw (as there might have been highlighted parens)
16051634
self.print_line(self.s)
16061635

1607-
elif self.c == 'KEY_RIGHT': # Cursor Right
1636+
elif key == 'KEY_RIGHT': # Cursor Right
16081637
self.mvc(-1)
16091638
# Redraw (as there might have been highlighted parens)
16101639
self.print_line(self.s)
16111640

1612-
elif self.c in ("KEY_HOME", '^A', chr(1)): # home or ^A
1641+
elif key in ("KEY_HOME", '^A', chr(1)): # home or ^A
16131642
self.home()
16141643
# Redraw (as there might have been highlighted parens)
16151644
self.print_line(self.s)
16161645

1617-
elif self.c in ("KEY_END", '^E', chr(5)): # end or ^E
1646+
elif key in ("KEY_END", '^E', chr(5)): # end or ^E
16181647
self.end()
16191648
# Redraw (as there might have been highlighted parens)
16201649
self.print_line(self.s)
16211650

1622-
elif self.c in key_dispatch[OPTS.cut_to_buffer_key]: # cut to buffer
1651+
elif key in key_dispatch[OPTS.cut_to_buffer_key]: # cut to buffer
16231652
self.cut_to_buffer()
16241653
return ''
16251654

1626-
elif self.c in key_dispatch[OPTS.yank_from_buffer_key]: # yank from buffer
1655+
elif key in key_dispatch[OPTS.yank_from_buffer_key]: # yank from buffer
16271656
self.yank_from_buffer()
16281657
return ''
16291658

1630-
elif self.c in key_dispatch[OPTS.clear_word_key]:
1659+
elif key in key_dispatch[OPTS.clear_word_key]:
16311660
self.bs_word()
16321661
self.complete()
16331662
return ''
16341663

1635-
elif self.c in key_dispatch[OPTS.clear_line_key]:
1664+
elif key in key_dispatch[OPTS.clear_line_key]:
16361665
self.clrtobol()
16371666
return ''
16381667

1639-
elif self.c in key_dispatch[OPTS.clear_screen_key]:
1668+
elif key in key_dispatch[OPTS.clear_screen_key]:
16401669
self.s_hist = [self.s_hist[-1]]
16411670
self.highlighted_paren = None
16421671
self.redraw()
16431672
return ''
16441673

1645-
elif self.c in key_dispatch[OPTS.exit_key]:
1674+
elif key in key_dispatch[OPTS.exit_key]:
16461675
if not self.s:
16471676
self.do_exit = True
16481677
return None
16491678
else:
16501679
return ''
16511680

1652-
elif self.c in key_dispatch[OPTS.save_key]:
1681+
elif key in key_dispatch[OPTS.save_key]:
16531682
self.write2file()
16541683
return ''
16551684

1656-
elif self.c in key_dispatch[OPTS.pastebin_key]:
1685+
elif key in key_dispatch[OPTS.pastebin_key]:
16571686
self.pastebin()
16581687
return ''
16591688

1660-
elif self.c in key_dispatch[OPTS.last_output_key]:
1689+
elif key in key_dispatch[OPTS.last_output_key]:
16611690
page(self.stdout_hist[self.prev_block_finished:-4])
16621691
return ''
16631692

1664-
elif self.c == '\n':
1693+
elif key == '\n':
16651694
self.lf()
16661695
return None
16671696

1668-
elif self.c == '\t':
1697+
elif key == '\t':
16691698
return self.tab()
16701699

1671-
elif len(self.c) == 1 and not unicodedata.category(self.c) == 'Cc':
1672-
self.addstr(self.c)
1700+
elif len(key) == 1 and not unicodedata.category(key) == 'Cc':
1701+
self.addstr(key)
16731702
self.print_line(self.s)
16741703

16751704
else:
16761705
return ''
16771706

1678-
16791707
return True
16801708

16811709
def tab(self):
@@ -1924,19 +1952,16 @@ def get_line(self):
19241952

19251953
if not self.paste_mode:
19261954
for _ in range(indent_spaces // OPTS.tab_length):
1927-
self.c = '\t'
1928-
self.p_key()
1955+
self.p_key('\t')
19291956

19301957
if indent and not self.paste_mode:
1931-
self.c = '\t'
1932-
self.p_key()
1958+
self.p_key('\t')
19331959

1934-
self.c = None
19351960
self.cpos = 0
19361961

19371962
while True:
1938-
self.c = self.get_key()
1939-
if self.p_key() is None:
1963+
key = self.get_key()
1964+
if self.p_key(key) is None:
19401965
return self.s
19411966

19421967
def clear_current_line(self):

0 commit comments

Comments
 (0)