src/extras/pyrepl/cmdrepl.py
changeset 0 ca70ae20a155
equal deleted inserted replaced
-1:000000000000 0:ca70ae20a155
       
     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