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 import collections
49 if not hasattr(builtins, '_'):
50 builtins._ = str
51
52
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 is not available :-(')
70
71
73 """Readline completer."""
74
77
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
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
102 self._topics = {}
103 self.commands = None
104 self._completer = Completer(self._register_commands())
105 init_readline(self._completer.complete, histfile)
106
108 """loop on user input, exit on EOF"""
109 while True:
110 try:
111 line = 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 args[0] in self.commands:
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
136 """Method to overload in the concrete class (should handle
137 lines which are not commands).
138 """
139 raise NotImplementedError()
140
141
142
143
145 """ register available commands method and return the list of
146 commands name
147 """
148 self.commands = {}
149 self._command_help = {}
150 commands = [attr[3:] for attr in dir(self) if attr[:3] == 'do_']
151 for command in commands:
152 topic = self.CMD_MAP[command]
153 help_method = getattr(self, 'help_do_%s' % command)
154 self._topics.setdefault(topic, []).append(help_method)
155 self.commands[self.CMD_PREFIX + command] = command
156 self._command_help[command] = help_method
157 return list(self.commands.keys())
158
160 print(_('Command %s') % cmd)
161 print(_('Syntax: %s') % syntax)
162 print('\t', explanation)
163 print()
164
165
166
167
169 """base input of the help system"""
170 if command in self._command_help:
171 self._print_help(*self._command_help[command])
172 elif command is None or command not in self._topics:
173 print(_("Use help <topic> or help <command>."))
174 print(_("Available topics are:"))
175 topics = sorted(self._topics.keys())
176 for topic in topics:
177 print('\t', topic)
178 print()
179 print(_("Available commands are:"))
180 commands = list(self.commands.keys())
181 commands.sort()
182 for command in commands:
183 print('\t', command[len(self.CMD_PREFIX):])
184
185 else:
186 print(_('Available commands about %s:') % command)
187 print()
188 for command_help_method in self._topics[command]:
189 try:
190 if isinstance(command_help_method, collections.Callable):
191 self._print_help(*command_help_method())
192 else:
193 self._print_help(*command_help_method)
194 except:
195 import traceback
196 traceback.print_exc()
197 print('ERROR in help method %s'% (
198 command_help_method.__name__))
199
200 help_do_help = ("help", "help [topic|command]",
201 _("print help message for the given topic/command or \
202 available topics when no argument"))
203
205 """quit the CLI"""
206 raise EOFError()
207
209 return ("quit", "quit", _("quit the application"))
210