1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """Command line interface helper classes.
19
20 It provides some default commands, a help system, a default readline
21 configuration with completion and persistent history.
22
23 Example::
24
25 class BookShell(CLIHelper):
26
27 def __init__(self):
28 # quit and help are builtins
29 # CMD_MAP keys are commands, values are topics
30 self.CMD_MAP['pionce'] = _("Sommeil")
31 self.CMD_MAP['ronfle'] = _("Sommeil")
32 CLIHelper.__init__(self)
33
34 help_do_pionce = ("pionce", "pionce duree", _("met ton corps en veille"))
35 def do_pionce(self):
36 print 'nap is good'
37
38 help_do_ronfle = ("ronfle", "ronfle volume", _("met les autres en veille"))
39 def do_ronfle(self):
40 print 'fuuuuuuuuuuuu rhhhhhrhrhrrh'
41
42 cl = BookShell()
43 """
44
45 __docformat__ = "restructuredtext en"
46
47 from logilab.common.compat import raw_input, builtins
48 if not hasattr(builtins, '_'):
49 builtins._ = str
50
51
53 """Init the readline library if available."""
54 try:
55 import readline
56 readline.parse_and_bind("tab: complete")
57 readline.set_completer(complete_method)
58 string = readline.get_completer_delims().replace(':', '')
59 readline.set_completer_delims(string)
60 if histfile is not None:
61 try:
62 readline.read_history_file(histfile)
63 except IOError:
64 pass
65 import atexit
66 atexit.register(readline.write_history_file, histfile)
67 except:
68 print 'readline is not available :-('
69
70
72 """Readline completer."""
73
76
78 """Hook called by readline when <tab> is pressed."""
79 n = len(text)
80 matches = []
81 for cmd in self.list :
82 if cmd[:n] == text :
83 matches.append(cmd)
84 try:
85 return matches[state]
86 except IndexError:
87 return None
88
89
91 """An abstract command line interface client which recognize commands
92 and provide an help system.
93 """
94
95 CMD_MAP = {'help': _("Others"),
96 'quit': _("Others"),
97 }
98 CMD_PREFIX = ''
99
101 self._topics = {}
102 self.commands = None
103 self._completer = Completer(self._register_commands())
104 init_readline(self._completer.complete, histfile)
105
107 """loop on user input, exit on EOF"""
108 while True:
109 try:
110 line = raw_input('>>> ')
111 except EOFError:
112 print
113 break
114 s_line = line.strip()
115 if not s_line:
116 continue
117 args = s_line.split()
118 if args[0] in self.commands:
119 try:
120 cmd = 'do_%s' % self.commands[args[0]]
121 getattr(self, cmd)(*args[1:])
122 except EOFError:
123 break
124 except:
125 import traceback
126 traceback.print_exc()
127 else:
128 try:
129 self.handle_line(s_line)
130 except:
131 import traceback
132 traceback.print_exc()
133
135 """Method to overload in the concrete class (should handle
136 lines which are not commands).
137 """
138 raise NotImplementedError()
139
140
141
142
144 """ register available commands method and return the list of
145 commands name
146 """
147 self.commands = {}
148 self._command_help = {}
149 commands = [attr[3:] for attr in dir(self) if attr[:3] == 'do_']
150 for command in commands:
151 topic = self.CMD_MAP[command]
152 help_method = getattr(self, 'help_do_%s' % command)
153 self._topics.setdefault(topic, []).append(help_method)
154 self.commands[self.CMD_PREFIX + command] = command
155 self._command_help[command] = help_method
156 return self.commands.keys()
157
159 print _('Command %s') % cmd
160 print _('Syntax: %s') % syntax
161 print '\t', explanation
162 print
163
164
165
166
168 """base input of the help system"""
169 if command in self._command_help:
170 self._print_help(*self._command_help[command])
171 elif command is None or command not in self._topics:
172 print _("Use help <topic> or help <command>.")
173 print _("Available topics are:")
174 topics = sorted(self._topics.keys())
175 for topic in topics:
176 print '\t', topic
177 print
178 print _("Available commands are:")
179 commands = self.commands.keys()
180 commands.sort()
181 for command in commands:
182 print '\t', command[len(self.CMD_PREFIX):]
183
184 else:
185 print _('Available commands about %s:') % command
186 print
187 for command_help_method in self._topics[command]:
188 try:
189 if callable(command_help_method):
190 self._print_help(*command_help_method())
191 else:
192 self._print_help(*command_help_method)
193 except:
194 import traceback
195 traceback.print_exc()
196 print 'ERROR in help method %s'% (
197 command_help_method.func_name)
198
199 help_do_help = ("help", "help [topic|command]",
200 _("print help message for the given topic/command or \
201 available topics when no argument"))
202
204 """quit the CLI"""
205 raise EOFError()
206
208 return ("quit", "quit", _("quit the application"))
209