1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
# Copyright 2000-2007 Michael Hudson-Doyle <micahel@gmail.com>
# Maciek Fijalkowski
#
# All Rights Reserved
#
#
# Permission to use, copy, modify, and distribute this software and
# its documentation for any purpose is hereby granted without fee,
# provided that the above copyright notice appear in all copies and
# that both that copyright notice and this permission notice appear in
# supporting documentation.
#
# THE AUTHOR MICHAEL HUDSON DISCLAIMS ALL WARRANTIES WITH REGARD TO
# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
# INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
"""Wedge pyrepl behaviour into cmd.Cmd-derived classes.
replize, when given a subclass of cmd.Cmd, returns a class that
behaves almost identically to the supplied class, except that it uses
pyrepl instead if raw_input.
It was designed to let you do this:
>>> import pdb
>>> from pyrepl import replize
>>> pdb.Pdb = replize(pdb.Pdb)
which is in fact done by the `pythoni' script that comes with
pyrepl."""
from __future__ import nested_scopes
from pyrepl import completing_reader as cr, reader, completer
from pyrepl.completing_reader import CompletingReader as CR
import cmd
class CmdReader(CR):
def collect_keymap(self):
return super(CmdReader, self).collect_keymap() + (
("\\M-\\n", "invalid-key"),
("\\n", "accept"))
CR_init = CR.__init__
def __init__(self, completions):
self.CR_init(self)
self.completions = completions
def get_completions(self, stem):
if len(stem) != self.pos:
return []
return cr.uniqify([s for s in self.completions
if s.startswith(stem)])
def replize(klass, history_across_invocations=1):
"""Return a subclass of the cmd.Cmd-derived klass that uses
pyrepl instead of readline.
Raises a ValueError if klass does not derive from cmd.Cmd.
The optional history_across_invocations parameter (default 1)
controls whether instances of the returned class share
histories."""
completions = [s[3:]
for s in completer.get_class_members(klass)
if s.startswith("do_")]
if not issubclass(klass, cmd.Cmd):
raise Exception
# if klass.cmdloop.im_class is not cmd.Cmd:
# print "this may not work"
class CmdRepl(klass):
k_init = klass.__init__
if history_across_invocations:
_CmdRepl__history = []
def __init__(self, *args, **kw):
self.k_init(*args, **kw)
self.__reader = CmdReader(completions)
self.__reader.history = CmdRepl._CmdRepl__history
self.__reader.historyi = len(CmdRepl._CmdRepl__history)
else:
def __init__(self, *args, **kw):
self.k_init(*args, **kw)
self.__reader = CmdReader(completions)
def cmdloop(self, intro=None):
self.preloop()
if intro is not None:
self.intro = intro
if self.intro:
print self.intro
stop = None
while not stop:
if self.cmdqueue:
line = self.cmdqueue[0]
del self.cmdqueue[0]
else:
try:
self.__reader.ps1 = self.prompt
line = self.__reader.readline()
except EOFError:
line = "EOF"
line = self.precmd(line)
stop = self.onecmd(line)
stop = self.postcmd(stop, line)
self.postloop()
CmdRepl.__name__ = "replize(%s.%s)"%(klass.__module__, klass.__name__)
return CmdRepl
|