root / logilab.pylintinstaller / logilab / common / cli.py

Revision 202:d67e86292521, 7.0 kB (checked in by tziade@…, 9 months ago)

added logilab.pylintinstaller

Line 
1# Copyright (c) 2003-2008 LOGILAB S.A. (Paris, FRANCE).
2# http://www.logilab.fr/ -- mailto:contact@logilab.fr
3#
4# This program is free software; you can redistribute it and/or modify it under
5# the terms of the GNU General Public License as published by the Free Software
6# Foundation; either version 2 of the License, or (at your option) any later
7# version.
8#
9# This program is distributed in the hope that it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License along with
14# this program; if not, write to the Free Software Foundation, Inc.,
15# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16"""Command line interface helper classes.
17 
18 It provides some default commands, a help system, a default readline
19 configuration with completion and persistent history
20
21Exemple usage:
22
23    class BookShell(CLIHelper):
24
25        def __init__(self):
26            # quit and help are builtins
27            # CMD_MAP keys are commands, values are topics
28            self.CMD_MAP['pionce'] = _("Sommeil")
29            self.CMD_MAP['ronfle'] = _("Sommeil")
30            CLIHelper.__init__(self)
31
32        help_do_pionce = ("pionce", "pionce duree", _("met ton corps en veille"))
33        def do_pionce(self):
34            print 'nap is good'
35
36        help_do_ronfle = ("ronfle", "ronfle volume", _("met les autres en veille"))
37        def do_ronfle(self):
38            print 'fuuuuuuuuuuuu rhhhhhrhrhrrh'
39
40    cl = BookShell()
41
42:author:    Logilab
43:copyright: 2003-2008 LOGILAB S.A. (Paris, FRANCE)
44:contact:   http://www.logilab.fr/ -- mailto:python-projects@logilab.org
45"""
46
47
48import __builtin__
49if not hasattr(__builtin__, '_'):
50    __builtin__._ = str
51   
52
53def init_readline(complete_method, histfile=None):
54    """init the readline library if available"""
55    try:
56        import readline
57        readline.parse_and_bind("tab: complete")
58        readline.set_completer(complete_method)
59        string = readline.get_completer_delims().replace(':', '')
60        readline.set_completer_delims(string)
61        if histfile is not None:
62            try:
63                readline.read_history_file(histfile)
64            except IOError:
65                pass
66            import atexit
67            atexit.register(readline.write_history_file, histfile)
68    except:
69        print 'readline si not available :-('
70
71
72class Completer :
73    """readline completer"""
74   
75    def __init__(self, commands):
76        self.list = commands
77       
78    def complete(self, text, state):
79        """hook called by readline when <tab> is pressed"""
80        n = len(text)
81        matches = []
82        for cmd in self.list :
83            if cmd[:n] == text :
84                matches.append(cmd)
85        try:
86            return matches[state]
87        except IndexError:
88            return None
89
90
91class CLIHelper:
92    """ an abstract command line interface client which recognize commands
93    and provide an help system
94    """
95   
96    CMD_MAP = {'help' : _("Others"),
97               'quit' : _("Others"),
98               }
99    CMD_PREFIX = ''
100   
101    def __init__(self, histfile=None) :
102        self._topics = {}
103        self.commands = None
104        self._completer = Completer(self._register_commands())
105        init_readline(self._completer.complete, histfile)
106
107    def run(self):
108        """loop on user input, exit on EOF"""
109        while 1:
110            try:
111                line = raw_input('>>> ')
112            except EOFError:
113                print 
114                break
115            s_line = line.strip()
116            if not s_line:
117                continue
118            args = s_line.split()
119            if self.commands.has_key(args[0]):
120                try:
121                    cmd = 'do_%s' % self.commands[args[0]]
122                    getattr(self, cmd)(*args[1:])
123                except EOFError:
124                    break
125                except:
126                    import traceback
127                    traceback.print_exc()
128            else:
129                try:
130                    self.handle_line(s_line)
131                except:
132                    import traceback
133                    traceback.print_exc()
134
135    def handle_line(self, stripped_line):
136        """method to overload in the concrete class
137       
138        should handle lines wich are not command
139        """
140        raise NotImplementedError()
141
142
143    # private methods #########################################################
144   
145    def _register_commands(self):
146        """ register available commands method and return the list of
147        commands name
148        """
149        self.commands = {}
150        self._command_help = {}
151        commands = [attr[3:] for attr in dir(self) if attr[:3] == 'do_']
152        for command in commands:
153            topic = self.CMD_MAP[command]
154            help_method = getattr(self, 'help_do_%s' % command)
155            self._topics.setdefault(topic, []).append(help_method)
156            self.commands[self.CMD_PREFIX + command] = command
157            self._command_help[command] = help_method
158        return self.commands.keys()
159
160    def _print_help(self, cmd, syntax, explanation):
161        print _('Command %s') % cmd
162        print _('Syntax: %s') % syntax
163        print '\t', explanation
164        print
165
166
167    # predefined commands #####################################################
168   
169    def do_help(self, command=None) :
170        """base input of the help system"""
171        if self._command_help.has_key(command):
172            self._print_help(*self._command_help[command])
173        elif command is None or not self._topics.has_key(command):
174            print _("Use help <topic> or help <command>.")
175            print _("Available topics are:")
176            topics = self._topics.keys()
177            topics.sort()
178            for topic in topics:
179                print '\t', topic
180            print
181            print _("Available commands are:")
182            commands = self.commands.keys()
183            commands.sort()
184            for command in commands:
185                print '\t', command[len(self.CMD_PREFIX):]
186               
187        else:
188            print _('Available commands about %s:') % command
189            print
190            for command_help_method in self._topics[command]:
191                try:
192                    if callable(command_help_method):
193                        self._print_help(*command_help_method())
194                    else:
195                        self._print_help(*command_help_method)
196                except:
197                    import traceback
198                    traceback.print_exc()
199                    print 'ERROR in help method %s'% (
200                        command_help_method.func_name)
201               
202    help_do_help = ("help", "help [topic|command]",
203                    _("print help message for the given topic/command or \
204available topics when no argument"))
205
206    def do_quit(self):
207        """quit the CLI"""
208        raise EOFError()
209   
210    def help_do_quit(self):
211        return ("quit", "quit", _("quit the application"))
Note: See TracBrowser for help on using the browser.