Index: third_party/logilab/common/cli.py
|
diff --git a/third_party/logilab/common/cli.py b/third_party/logilab/common/cli.py
|
new file mode 100644
|
index 0000000000000000000000000000000000000000..42837329020b30bc3405c6f93c036af59d238b7d
|
--- /dev/null
|
+++ b/third_party/logilab/common/cli.py
|
@@ -0,0 +1,208 @@
|
+# copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
|
+# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
|
+#
|
+# This file is part of logilab-common.
|
+#
|
+# logilab-common is free software: you can redistribute it and/or modify it under
|
+# the terms of the GNU Lesser General Public License as published by the Free
|
+# Software Foundation, either version 2.1 of the License, or (at your option) any
|
+# later version.
|
+#
|
+# logilab-common is distributed in the hope that it will be useful, but WITHOUT
|
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
+# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
+# details.
|
+#
|
+# You should have received a copy of the GNU Lesser General Public License along
|
+# with logilab-common. If not, see <http://www.gnu.org/licenses/>.
|
+"""Command line interface helper classes.
|
+
|
+It provides some default commands, a help system, a default readline
|
+configuration with completion and persistent history.
|
+
|
+Example::
|
+
|
+ class BookShell(CLIHelper):
|
+
|
+ def __init__(self):
|
+ # quit and help are builtins
|
+ # CMD_MAP keys are commands, values are topics
|
+ self.CMD_MAP['pionce'] = _("Sommeil")
|
+ self.CMD_MAP['ronfle'] = _("Sommeil")
|
+ CLIHelper.__init__(self)
|
+
|
+ help_do_pionce = ("pionce", "pionce duree", _("met ton corps en veille"))
|
+ def do_pionce(self):
|
+ print 'nap is good'
|
+
|
+ help_do_ronfle = ("ronfle", "ronfle volume", _("met les autres en veille"))
|
+ def do_ronfle(self):
|
+ print 'fuuuuuuuuuuuu rhhhhhrhrhrrh'
|
+
|
+ cl = BookShell()
|
+"""
|
+
|
+__docformat__ = "restructuredtext en"
|
+
|
+from logilab.common.compat import raw_input, builtins
|
+if not hasattr(builtins, '_'):
|
+ builtins._ = str
|
+
|
+
|
+def init_readline(complete_method, histfile=None):
|
+ """Init the readline library if available."""
|
+ try:
|
+ import readline
|
+ readline.parse_and_bind("tab: complete")
|
+ readline.set_completer(complete_method)
|
+ string = readline.get_completer_delims().replace(':', '')
|
+ readline.set_completer_delims(string)
|
+ if histfile is not None:
|
+ try:
|
+ readline.read_history_file(histfile)
|
+ except IOError:
|
+ pass
|
+ import atexit
|
+ atexit.register(readline.write_history_file, histfile)
|
+ except:
|
+ print 'readline is not available :-('
|
+
|
+
|
+class Completer :
|
+ """Readline completer."""
|
+
|
+ def __init__(self, commands):
|
+ self.list = commands
|
+
|
+ def complete(self, text, state):
|
+ """Hook called by readline when <tab> is pressed."""
|
+ n = len(text)
|
+ matches = []
|
+ for cmd in self.list :
|
+ if cmd[:n] == text :
|
+ matches.append(cmd)
|
+ try:
|
+ return matches[state]
|
+ except IndexError:
|
+ return None
|
+
|
+
|
+class CLIHelper:
|
+ """An abstract command line interface client which recognize commands
|
+ and provide an help system.
|
+ """
|
+
|
+ CMD_MAP = {'help': _("Others"),
|
+ 'quit': _("Others"),
|
+ }
|
+ CMD_PREFIX = ''
|
+
|
+ def __init__(self, histfile=None) :
|
+ self._topics = {}
|
+ self.commands = None
|
+ self._completer = Completer(self._register_commands())
|
+ init_readline(self._completer.complete, histfile)
|
+
|
+ def run(self):
|
+ """loop on user input, exit on EOF"""
|
+ while True:
|
+ try:
|
+ line = raw_input('>>> ')
|
+ except EOFError:
|
+ print
|
+ break
|
+ s_line = line.strip()
|
+ if not s_line:
|
+ continue
|
+ args = s_line.split()
|
+ if args[0] in self.commands:
|
+ try:
|
+ cmd = 'do_%s' % self.commands[args[0]]
|
+ getattr(self, cmd)(*args[1:])
|
+ except EOFError:
|
+ break
|
+ except:
|
+ import traceback
|
+ traceback.print_exc()
|
+ else:
|
+ try:
|
+ self.handle_line(s_line)
|
+ except:
|
+ import traceback
|
+ traceback.print_exc()
|
+
|
+ def handle_line(self, stripped_line):
|
+ """Method to overload in the concrete class (should handle
|
+ lines which are not commands).
|
+ """
|
+ raise NotImplementedError()
|
+
|
+
|
+ # private methods #########################################################
|
+
|
+ def _register_commands(self):
|
+ """ register available commands method and return the list of
|
+ commands name
|
+ """
|
+ self.commands = {}
|
+ self._command_help = {}
|
+ commands = [attr[3:] for attr in dir(self) if attr[:3] == 'do_']
|
+ for command in commands:
|
+ topic = self.CMD_MAP[command]
|
+ help_method = getattr(self, 'help_do_%s' % command)
|
+ self._topics.setdefault(topic, []).append(help_method)
|
+ self.commands[self.CMD_PREFIX + command] = command
|
+ self._command_help[command] = help_method
|
+ return self.commands.keys()
|
+
|
+ def _print_help(self, cmd, syntax, explanation):
|
+ print _('Command %s') % cmd
|
+ print _('Syntax: %s') % syntax
|
+ print '\t', explanation
|
+ print
|
+
|
+
|
+ # predefined commands #####################################################
|
+
|
+ def do_help(self, command=None) :
|
+ """base input of the help system"""
|
+ if command in self._command_help:
|
+ self._print_help(*self._command_help[command])
|
+ elif command is None or command not in self._topics:
|
+ print _("Use help <topic> or help <command>.")
|
+ print _("Available topics are:")
|
+ topics = sorted(self._topics.keys())
|
+ for topic in topics:
|
+ print '\t', topic
|
+ print
|
+ print _("Available commands are:")
|
+ commands = self.commands.keys()
|
+ commands.sort()
|
+ for command in commands:
|
+ print '\t', command[len(self.CMD_PREFIX):]
|
+
|
+ else:
|
+ print _('Available commands about %s:') % command
|
+ print
|
+ for command_help_method in self._topics[command]:
|
+ try:
|
+ if callable(command_help_method):
|
+ self._print_help(*command_help_method())
|
+ else:
|
+ self._print_help(*command_help_method)
|
+ except:
|
+ import traceback
|
+ traceback.print_exc()
|
+ print 'ERROR in help method %s'% (
|
+ command_help_method.func_name)
|
+
|
+ help_do_help = ("help", "help [topic|command]",
|
+ _("print help message for the given topic/command or \
|
+available topics when no argument"))
|
+
|
+ def do_quit(self):
|
+ """quit the CLI"""
|
+ raise EOFError()
|
+
|
+ def help_do_quit(self):
|
+ return ("quit", "quit", _("quit the application"))
|
|