Author: Ronny Pfannschmidt <[email protected]>
Branch: commands-as-functions
Changeset: r216:c1f83654d126
Date: 2013-01-15 11:38 +0100
http://bitbucket.org/pypy/pyrepl/changeset/c1f83654d126/
Log: turn most commands into functions
diff --git a/pyrepl/commands.py b/pyrepl/commands.py
--- a/pyrepl/commands.py
+++ b/pyrepl/commands.py
@@ -19,7 +19,8 @@
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-import sys, os
+import os
+import signal
# Catgories of actions:
# killing
@@ -30,6 +31,7 @@
# finishing
# [completion]
+
class Command(object):
finish = 0
kills_digit_arg = 1
@@ -42,137 +44,168 @@
def do(self):
pass
+ @classmethod
+ def usereader(cls, func):
+ is_method = 'self' in func.__code__.co_varnames
+
+ def wrap(f):
+ if is_method:
+ return f
+ else:
+ return staticmethod(f)
+
+ class ReaderCommand(cls):
+ do_reader = wrap(func)
+
+ def do(self):
+ self.do_reader(self.reader)
+
+ ReaderCommand.__name__ = func.__name__
+ return ReaderCommand
+
+
+def kill_range(reader, start, end):
+ if start == end:
+ return
+ r = reader
+ b = reader.buffer
+ text = b[start:end]
+ del b[start:end]
+ if is_kill(r.last_command):
+ if start < r.pos:
+ r.kill_ring[-1] = text + r.kill_ring[-1]
+ else:
+ r.kill_ring[-1] = r.kill_ring[-1] + text
+ else:
+ r.kill_ring.append(text)
+ r.pos = start
+ r.dirty = 1
+
+
class KillCommand(Command):
- def kill_range(self, start, end):
- if start == end:
- return
- r = self.reader
- b = r.buffer
- text = b[start:end]
- del b[start:end]
- if is_kill(r.last_command):
- if start < r.pos:
- r.kill_ring[-1] = text + r.kill_ring[-1]
- else:
- r.kill_ring[-1] = r.kill_ring[-1] + text
- else:
- r.kill_ring.append(text)
- r.pos = start
- r.dirty = 1
+ pass
+
class YankCommand(Command):
pass
+
class MotionCommand(Command):
pass
+
class EditCommand(Command):
pass
+
class FinishCommand(Command):
finish = 1
- pass
+
def is_kill(command):
return command and issubclass(command, KillCommand)
+
def is_yank(command):
return command and issubclass(command, YankCommand)
# etc
+
class digit_arg(Command):
kills_digit_arg = 0
+
def do(self):
r = self.reader
c = self.event[-1]
if c == "-":
- if r.arg is not None:
+ if r.arg is None:
+ r.arg = -1
+ else:
r.arg = -r.arg
- else:
- r.arg = -1
else:
d = int(c)
if r.arg is None:
r.arg = d
else:
if r.arg < 0:
- r.arg = 10*r.arg - d
+ r.arg = 10 * r.arg - d
else:
- r.arg = 10*r.arg + d
+ r.arg = 10 * r.arg + d
r.dirty = 1
-class clear_screen(Command):
- def do(self):
- r = self.reader
- r.console.clear()
- r.dirty = 1
-class refresh(Command):
- def do(self):
- self.reader.dirty = 1
[email protected]
+def clear_screen(r):
+ r.console.clear()
+ r.dirty = 1
-class repaint(Command):
- def do(self):
- self.reader.dirty = 1
- self.reader.console.repaint_prep()
-class kill_line(KillCommand):
- def do(self):
- r = self.reader
- b = r.buffer
- eol = r.eol()
- for c in b[r.pos:eol]:
- if not c.isspace():
- self.kill_range(r.pos, eol)
- return
- else:
- self.kill_range(r.pos, eol+1)
[email protected]
+def refresh(reader):
+ reader.dirty = 1
-class unix_line_discard(KillCommand):
- def do(self):
- r = self.reader
- self.kill_range(r.bol(), r.pos)
+
[email protected]
+def repaint(self):
+ self.reader.dirty = 1
+ self.reader.console.repaint_prep()
+
+
[email protected]
+def kill_line(r):
+ b = r.buffer
+ eol = r.eol()
+ for c in b[r.pos:eol]:
+ if not c.isspace():
+ kill_range(r, r.pos, eol)
+ return
+ else:
+ kill_range(r, r.pos, eol + 1)
+
+
[email protected]
+def unix_line_discard(r):
+ kill_range(r, r.bol(), r.pos)
# XXX unix_word_rubout and backward_kill_word should actually
# do different things...
-class unix_word_rubout(KillCommand):
- def do(self):
- r = self.reader
- for i in range(r.get_arg()):
- self.kill_range(r.bow(), r.pos)
-class kill_word(KillCommand):
- def do(self):
- r = self.reader
- for i in range(r.get_arg()):
- self.kill_range(r.pos, r.eow())
[email protected]
+def unix_word_rubout(r):
+ for i in range(r.get_arg()):
+ kill_range(r, r.bow(), r.pos)
-class backward_kill_word(KillCommand):
- def do(self):
- r = self.reader
- for i in range(r.get_arg()):
- self.kill_range(r.bow(), r.pos)
-class yank(YankCommand):
- def do(self):
- r = self.reader
- if not r.kill_ring:
- r.error("nothing to yank")
- return
[email protected]
+def kill_word(r):
+ for i in range(r.get_arg()):
+ kill_range(r, r.pos, r.eow())
+
+
[email protected]
+def backward_kill_word(r):
+ for i in range(r.get_arg()):
+ kill_range(r, r.bow(), r.pos)
+
+
[email protected]
+def yank(r):
+ if r.kill_ring:
r.insert(r.kill_ring[-1])
+ else:
+ r.error("nothing to yank")
-class yank_pop(YankCommand):
- def do(self):
- r = self.reader
+
[email protected]
+def yank_pop(r):
+ if not r.kill_ring:
+ r.error("nothing to yank")
+ elif not is_yank(r.last_command):
+ r.error("previous command was not a yank")
+ else:
b = r.buffer
- if not r.kill_ring:
- r.error("nothing to yank")
- return
- if not is_yank(r.last_command):
- r.error("previous command was not a yank")
- return
repl = len(r.kill_ring[-1])
r.kill_ring.insert(0, r.kill_ring.pop())
t = r.kill_ring[-1]
@@ -180,208 +213,209 @@
r.pos = r.pos - repl + len(t)
r.dirty = 1
-class interrupt(FinishCommand):
- def do(self):
- import signal
- self.reader.console.finish()
- os.kill(os.getpid(), signal.SIGINT)
-class suspend(Command):
- def do(self):
- import signal
- r = self.reader
- p = r.pos
[email protected]
+def interrupt(r):
+ r.console.finish()
+ os.kill(os.getpid(), signal.SIGINT)
+
+
[email protected]
+def suspend(r):
+ p = r.pos
+ r.console.finish()
+ os.kill(os.getpid(), signal.SIGSTOP)
+ ## this should probably be done
+ ## in a handler for SIGCONT?
+ r.console.prepare()
+ r.pos = p
+ r.posxy = 0, 0
+ r.dirty = 1
+ r.console.screen = []
+
+
[email protected]
+def up(r):
+ for i in range(r.get_arg()):
+ bol1 = r.bol()
+ if bol1 == 0:
+ if r.historyi > 0:
+ r.select_item(r.historyi - 1)
+ return
+ r.pos = 0
+ r.error("start of buffer")
+ return
+ bol2 = r.bol(bol1 - 1)
+ line_pos = r.pos - bol1
+ if line_pos > bol1 - bol2 - 1:
+ r.sticky_y = line_pos
+ r.pos = bol1 - 1
+ else:
+ r.pos = bol2 + line_pos
+
+
[email protected]
+def down(r):
+ b = r.buffer
+ for i in range(r.get_arg()):
+ bol1 = r.bol()
+ eol1 = r.eol()
+ if eol1 == len(b):
+ if r.historyi < len(r.history):
+ r.select_item(r.historyi + 1)
+ r.pos = r.eol(0)
+ return
+ r.pos = len(b)
+ r.error("end of buffer")
+ return
+ eol2 = r.eol(eol1 + 1)
+ if r.pos - bol1 > eol2 - eol1 - 1:
+ r.pos = eol2
+ else:
+ r.pos = eol1 + (r.pos - bol1) + 1
+
+
[email protected]
+def left(r):
+ new_pos = r.pos - r.get_arg()
+ r.pos = max(0, new_pos)
+ if new_pos < 0:
+ r.error("start of buffer")
+
+
[email protected]
+def right(r):
+ new_pos = r.pos + r.get_arg()
+ buffsize = len(r.buffer)
+ r.pos = min(new_pos, buffsize)
+ if new_pos > buffsize:
+ r.error("end of buffer")
+
+
[email protected]
+def beginning_of_line(r):
+ r.pos = r.bol()
+
+
[email protected]
+def end_of_line(r):
+ r.pos = r.eol()
+
+
[email protected]
+def home(r):
+ r.pos = 0
+
+
[email protected]
+def end(r):
+ r.pos = len(r.buffer)
+
+
[email protected]
+def forward_word(r):
+ for i in range(r.get_arg()):
+ r.pos = r.eow()
+
+
[email protected]
+def backward_word(r):
+ for i in range(r.get_arg()):
+ r.pos = r.bow()
+
+
[email protected]
+def self_insert(self, r):
+ r.insert(self.event * r.get_arg())
+
+
[email protected]
+def insert_nl(r):
+ r.insert("\n" * r.get_arg())
+
+
[email protected]
+def transpose_characters(r):
+ b = r.buffer
+ s = r.pos - 1
+ if s < 0:
+ r.error("cannot transpose at start of buffer")
+ else:
+ if s == len(b):
+ s -= 1
+ t = min(s + r.get_arg(), len(b) - 1)
+ c = b[s]
+ del b[s]
+ b.insert(t, c)
+ r.pos = t
+ r.dirty = 1
+
+
[email protected]
+def backspace(r):
+ b = r.buffer
+ for i in range(r.get_arg()):
+ if r.pos > 0:
+ r.pos -= 1
+ del b[r.pos]
+ r.dirty = 1
+ else:
+ r.error("can't backspace at start")
+
+
[email protected]
+def delete(self, r):
+ b = r.buffer
+ if r.pos == 0 and not b and self.event[-1] == "\004":
+ r.update_screen()
r.console.finish()
- os.kill(os.getpid(), signal.SIGSTOP)
- ## this should probably be done
- ## in a handler for SIGCONT?
- r.console.prepare()
- r.pos = p
- r.posxy = 0, 0
- r.dirty = 1
- r.console.screen = []
+ raise EOFError
+ for i in range(r.get_arg()):
+ if r.pos != len(b):
+ del b[r.pos]
+ r.dirty = 1
+ else:
+ r.error("end of buffer")
-class up(MotionCommand):
- def do(self):
- r = self.reader
- for i in range(r.get_arg()):
- bol1 = r.bol()
- if bol1 == 0:
- if r.historyi > 0:
- r.select_item(r.historyi - 1)
- return
- r.pos = 0
- r.error("start of buffer")
- return
- bol2 = r.bol(bol1-1)
- line_pos = r.pos - bol1
- if line_pos > bol1 - bol2 - 1:
- r.sticky_y = line_pos
- r.pos = bol1 - 1
- else:
- r.pos = bol2 + line_pos
-
-class down(MotionCommand):
- def do(self):
- r = self.reader
- b = r.buffer
- for i in range(r.get_arg()):
- bol1 = r.bol()
- eol1 = r.eol()
- if eol1 == len(b):
- if r.historyi < len(r.history):
- r.select_item(r.historyi + 1)
- r.pos = r.eol(0)
- return
- r.pos = len(b)
- r.error("end of buffer")
- return
- eol2 = r.eol(eol1+1)
- if r.pos - bol1 > eol2 - eol1 - 1:
- r.pos = eol2
- else:
- r.pos = eol1 + (r.pos - bol1) + 1
-
-class left(MotionCommand):
- def do(self):
- r = self.reader
- for i in range(r.get_arg()):
- p = r.pos - 1
- if p >= 0:
- r.pos = p
- else:
- self.reader.error("start of buffer")
-
-class right(MotionCommand):
- def do(self):
- r = self.reader
- b = r.buffer
- for i in range(r.get_arg()):
- p = r.pos + 1
- if p <= len(b):
- r.pos = p
- else:
- self.reader.error("end of buffer")
-
-class beginning_of_line(MotionCommand):
- def do(self):
- self.reader.pos = self.reader.bol()
-
-class end_of_line(MotionCommand):
- def do(self):
- r = self.reader
- self.reader.pos = self.reader.eol()
-
-class home(MotionCommand):
- def do(self):
- self.reader.pos = 0
-
-class end(MotionCommand):
- def do(self):
- self.reader.pos = len(self.reader.buffer)
-
-class forward_word(MotionCommand):
- def do(self):
- r = self.reader
- for i in range(r.get_arg()):
- r.pos = r.eow()
-
-class backward_word(MotionCommand):
- def do(self):
- r = self.reader
- for i in range(r.get_arg()):
- r.pos = r.bow()
-
-class self_insert(EditCommand):
- def do(self):
- r = self.reader
- r.insert(self.event * r.get_arg())
-
-class insert_nl(EditCommand):
- def do(self):
- r = self.reader
- r.insert("\n" * r.get_arg())
-
-class transpose_characters(EditCommand):
- def do(self):
- r = self.reader
- b = r.buffer
- s = r.pos - 1
- if s < 0:
- r.error("cannot transpose at start of buffer")
- else:
- if s == len(b):
- s -= 1
- t = min(s + r.get_arg(), len(b) - 1)
- c = b[s]
- del b[s]
- b.insert(t, c)
- r.pos = t
- r.dirty = 1
-
-class backspace(EditCommand):
- def do(self):
- r = self.reader
- b = r.buffer
- for i in range(r.get_arg()):
- if r.pos > 0:
- r.pos -= 1
- del b[r.pos]
- r.dirty = 1
- else:
- self.reader.error("can't backspace at start")
-
-class delete(EditCommand):
- def do(self):
- r = self.reader
- b = r.buffer
- if ( r.pos == 0 and len(b) == 0 # this is something of a hack
- and self.event[-1] == "\004"):
- r.update_screen()
- r.console.finish()
- raise EOFError
- for i in range(r.get_arg()):
- if r.pos != len(b):
- del b[r.pos]
- r.dirty = 1
- else:
- self.reader.error("end of buffer")
class accept(FinishCommand):
- def do(self):
- pass
+ pass
-class help(Command):
- def do(self):
- self.reader.msg = self.reader.help_text
- self.reader.dirty = 1
-class invalid_key(Command):
- def do(self):
- pending = self.reader.console.getpending()
- s = ''.join(self.event) + pending.data
- self.reader.error("`%r' not bound"%s)
[email protected]
+def help(reader):
+ reader.msg = reader.help_text
+ reader.dirty = 1
-class invalid_command(Command):
- def do(self):
- s = self.event_name
- self.reader.error("command `%s' not known"%s)
-class qIHelp(Command):
- def do(self):
- r = self.reader
- r.insert((self.event + r.console.getpending().data) * r.get_arg())
- r.pop_input_trans()
[email protected]
+def invalid_key(self, reader):
+ pending = reader.console.getpending()
+ s = ''.join(self.event) + pending.data
+ reader.error("`%r' not bound" % s)
-from pyrepl import input
+
[email protected]
+def invalid_command(self, reader):
+ reader.error("command `%s' not known" % self.event_name)
+
+
[email protected]
+def qIHelp(self, r):
+ r.insert((self.event + r.console.getpending().data) * r.get_arg())
+ r.pop_input_trans()
+
class QITrans(object):
def push(self, evt):
self.evt = evt
+
def get(self):
return ('qIHelp', self.evt.raw)
+
class quoted_insert(Command):
kills_digit_arg = 0
+
def do(self):
self.reader.push_input_trans(QITrans())
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit