Author: Armin Rigo <[email protected]>
Branch:
Changeset: r76163:b37ef838fa61
Date: 2015-02-27 17:14 +0100
http://bitbucket.org/pypy/pypy/changeset/b37ef838fa61/
Log: issue #1986: auto-indent support in "backspace" and "enter"
diff --git a/lib_pypy/pyrepl/readline.py b/lib_pypy/pyrepl/readline.py
--- a/lib_pypy/pyrepl/readline.py
+++ b/lib_pypy/pyrepl/readline.py
@@ -73,7 +73,6 @@
assume_immutable_completions = False
use_brackets = False
sort_in_column = True
- tab_insert_spaces_if_stem_is_empty = False
def error(self, msg="none"):
pass # don't show error messages by default
@@ -87,7 +86,7 @@
return ''.join(b[p+1:self.pos])
def get_completions(self, stem):
- if len(stem) == 0 and self.tab_insert_spaces_if_stem_is_empty:
+ if len(stem) == 0 and self.more_lines is not None:
b = self.buffer
p = self.pos
while p > 0 and b[p - 1] != '\n':
@@ -141,12 +140,16 @@
def collect_keymap(self):
return super(ReadlineAlikeReader, self).collect_keymap() + (
- (r'\n', 'maybe-accept'),)
+ (r'\n', 'maybe-accept'),
+ (r'\<backspace>', 'backspace-dedent'),
+ )
def __init__(self, console):
super(ReadlineAlikeReader, self).__init__(console)
self.commands['maybe_accept'] = maybe_accept
self.commands['maybe-accept'] = maybe_accept
+ self.commands['backspace_dedent'] = backspace_dedent
+ self.commands['backspace-dedent'] = backspace_dedent
def after_command(self, cmd):
super(ReadlineAlikeReader, self).after_command(cmd)
@@ -164,6 +167,28 @@
if self.pos > len(self.buffer):
self.pos = len(self.buffer)
+def _get_this_line_indent(buffer, pos):
+ indent = 0
+ while pos > 0 and buffer[pos - 1] in " \t":
+ indent += 1
+ pos -= 1
+ if pos > 0 and buffer[pos - 1] == "\n":
+ return indent
+ return 0
+
+def _get_previous_line_indent(buffer, pos):
+ prevlinestart = pos
+ while prevlinestart > 0 and buffer[prevlinestart - 1] != "\n":
+ prevlinestart -= 1
+ prevlinetext = prevlinestart
+ while prevlinetext < pos and buffer[prevlinetext] in " \t":
+ prevlinetext += 1
+ if prevlinetext == pos:
+ indent = None
+ else:
+ indent = prevlinetext - prevlinestart
+ return prevlinestart, indent
+
class maybe_accept(commands.Command):
def do(self):
r = self.reader
@@ -172,13 +197,39 @@
# if there are already several lines and the cursor
# is not on the last one, always insert a new \n.
text = r.get_unicode()
- if "\n" in r.buffer[r.pos:]:
+ if ("\n" in r.buffer[r.pos:] or
+ (r.more_lines is not None and r.more_lines(text))):
+ #
+ # auto-indent the next line like the previous line
+ prevlinestart, indent = _get_previous_line_indent(r.buffer, r.pos)
r.insert("\n")
- elif r.more_lines is not None and r.more_lines(text):
- r.insert("\n")
+ if indent:
+ for i in range(prevlinestart, prevlinestart + indent):
+ r.insert(r.buffer[i])
else:
self.finish = 1
+class backspace_dedent(commands.Command):
+ def do(self):
+ r = self.reader
+ b = r.buffer
+ if r.pos > 0:
+ repeat = 1
+ if b[r.pos - 1] != "\n":
+ indent = _get_this_line_indent(b, r.pos)
+ if indent > 0:
+ ls = r.pos - indent
+ while ls > 0:
+ ls, pi = _get_previous_line_indent(b, ls - 1)
+ if pi is not None and pi < indent:
+ repeat = indent - pi
+ break
+ r.pos -= repeat
+ del b[r.pos:r.pos + repeat]
+ r.dirty = 1
+ else:
+ self.reader.error("can't backspace at start")
+
# ____________________________________________________________
class _ReadlineWrapper(object):
@@ -212,15 +263,14 @@
boolean value is true.
"""
reader = self.get_reader()
- saved = reader.more_lines, reader.tab_insert_spaces_if_stem_is_empty
+ saved = reader.more_lines
try:
reader.more_lines = more_lines
reader.ps1 = reader.ps2 = ps1
reader.ps3 = reader.ps4 = ps2
- reader.tab_insert_spaces_if_stem_is_empty = True
return reader.readline(returns_unicode=returns_unicode)
finally:
- reader.more_lines, reader.tab_insert_spaces_if_stem_is_empty =
saved
+ reader.more_lines = saved
def parse_and_bind(self, string):
pass # XXX we don't support parsing GNU-readline-style init files
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit