|
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 |