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