| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- # 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"))
|