Vega strike Python Modules doc  0.5.1
Documentation of the " Modules " folder of Vega strike
 All Data Structures Namespaces Files Functions Variables
cmd.py
Go to the documentation of this file.
1 """A generic class to build line-oriented command interpreters.
2 
3 Interpreters constructed with this class obey the following conventions:
4 
5 1. End of file on input is processed as the command 'EOF'.
6 2. A command is parsed out of each line by collecting the prefix composed
7  of characters in the identchars member.
8 3. A command `foo' is dispatched to a method 'do_foo()'; the do_ method
9  is passed a single argument consisting of the remainder of the line.
10 4. Typing an empty line repeats the last command. (Actually, it calls the
11  method `emptyline', which may be overridden in a subclass.)
12 5. There is a predefined `help' method. Given an argument `topic', it
13  calls the command `help_topic'. With no arguments, it lists all topics
14  with defined help_ functions, broken into up to three topics; documented
15  commands, miscellaneous help topics, and undocumented commands.
16 6. The command '?' is a synonym for `help'. The command '!' is a synonym
17  for `shell', if a do_shell method exists.
18 7. If completion is enabled, completing commands will be done automatically,
19  and completing of commands args is done by calling complete_foo() with
20  arguments text, line, begidx, endidx. text is string we are matching
21  against, all returned matches must begin with it. line is the current
22  input line (lstripped), begidx and endidx are the beginning and end
23  indexes of the text being matched, which could be used to provide
24  different completion depending upon which position the argument is in.
25 
26 The `default' method may be overridden to intercept commands for which there
27 is no do_ method.
28 
29 The `completedefault' method may be overridden to intercept completions for
30 commands that have no complete_ method.
31 
32 The data member `self.ruler' sets the character used to draw separator lines
33 in the help messages. If empty, no ruler line is drawn. It defaults to "=".
34 
35 If the value of `self.intro' is nonempty when the cmdloop method is called,
36 it is printed out on interpreter startup. This value may be overridden
37 via an optional argument to the cmdloop() method.
38 
39 The data members `self.doc_header', `self.misc_header', and
40 `self.undoc_header' set the headers used for the help function's
41 listings of documented functions, miscellaneous topics, and undocumented
42 functions respectively.
43 
44 These interpreters use raw_input; thus, if the readline module is loaded,
45 they automatically support Emacs-like command history and editing features.
46 """
47 
48 import string, sys
49 
50 __all__ = ["Cmd"]
51 
52 PROMPT = '(Cmd) '
53 IDENTCHARS = string.ascii_letters + string.digits + '_'
54 
55 class Cmd:
56  prompt = PROMPT
57  identchars = IDENTCHARS
58  ruler = '='
59  lastcmd = ''
60  cmdqueue = []
61  intro = None
62  doc_leader = ""
63  doc_header = "Documented commands (type help <topic>):"
64  misc_header = "Miscellaneous help topics:"
65  undoc_header = "Undocumented commands:"
66  nohelp = "*** No help on %s"
67  use_rawinput = 1
68 
69  def __init__(self, completekey='tab'):
70  if completekey:
71  try:
72  import readline
73  readline.set_completer(self.complete)
74  readline.parse_and_bind(completekey+": complete")
75  except ImportError:
76  pass
77 
78  def cmdloop(self, intro=None):
79  self.preloop()
80  if intro is not None:
81  self.intro = intro
82  if self.intro:
83  print self.intro
84  stop = None
85  while not stop:
86  if self.cmdqueue:
87  line = self.cmdqueue[0]
88  del self.cmdqueue[0]
89  else:
90  if self.use_rawinput:
91  try:
92  line = raw_input(self.prompt)
93  except EOFError:
94  line = 'EOF'
95  else:
96  sys.stdout.write(self.prompt)
97  sys.stdout.flush()
98  line = sys.stdin.readline()
99  if not len(line):
100  line = 'EOF'
101  else:
102  line = line[:-1] # chop \n
103  line = self.precmd(line)
104  stop = self.onecmd(line)
105  stop = self.postcmd(stop, line)
106  self.postloop()
107 
108  def precmd(self, line):
109  return line
110 
111  def postcmd(self, stop, line):
112  return stop
113 
114  def preloop(self):
115  pass
116 
117  def postloop(self):
118  pass
119 
120  def parseline(self, line):
121  line = line.strip()
122  if not line:
123  return None, None, line
124  elif line[0] == '?':
125  line = 'help ' + line[1:]
126  elif line[0] == '!':
127  if hasattr(self, 'do_shell'):
128  line = 'shell ' + line[1:]
129  else:
130  return None, None, line
131  i, n = 0, len(line)
132  while i < n and line[i] in self.identchars: i = i+1
133  cmd, arg = line[:i], line[i:].strip()
134  return cmd, arg, line
135 
136  def onecmd(self, line):
137  cmd, arg, line = self.parseline(line)
138  if not line:
139  return self.emptyline()
140  if cmd is None:
141  return self.default(line)
142  self.lastcmd = line
143  if cmd == '':
144  return self.default(line)
145  else:
146  try:
147  func = getattr(self, 'do_' + cmd)
148  except AttributeError:
149  return self.default(line)
150  return func(arg)
151 
152  def emptyline(self):
153  if self.lastcmd:
154  return self.onecmd(self.lastcmd)
155 
156  def default(self, line):
157  print '*** Unknown syntax:', line
158 
159  def completedefault(self, *ignored):
160  return []
161 
162  def completenames(self, text, *ignored):
163  dotext = 'do_'+text
164  return [a[3:] for a in self.get_names() if a.startswith(dotext)]
165 
166  def complete(self, text, state):
167  """Return the next possible completion for 'text'.
168 
169  If a command has not been entered, then complete against command list.
170  Otherwise try to call complete_<command> to get list of completions.
171  """
172  if state == 0:
173  import readline
174  origline = readline.get_line_buffer()
175  line = origline.lstrip()
176  stripped = len(origline) - len(line)
177  begidx = readline.get_begidx() - stripped
178  endidx = readline.get_endidx() - stripped
179  if begidx>0:
180  cmd, args, foo = self.parseline(line)
181  if cmd == '':
182  compfunc = self.completedefault
183  else:
184  try:
185  compfunc = getattr(self, 'complete_' + cmd)
186  except AttributeError:
187  compfunc = self.completedefault
188  else:
189  compfunc = self.completenames
190  self.completion_matches = compfunc(text, line, begidx, endidx)
191  try:
192  return self.completion_matches[state]
193  except IndexError:
194  return None
195 
196  def get_names(self):
197  # Inheritance says we have to look in class and
198  # base classes; order is not important.
199  names = []
200  classes = [self.__class__]
201  while classes:
202  aclass = classes[0]
203  if aclass.__bases__:
204  classes = classes + list(aclass.__bases__)
205  names = names + dir(aclass)
206  del classes[0]
207  return names
208 
209  def complete_help(self, *args):
210  return self.completenames(*args)
211 
212  def do_help(self, arg):
213  if arg:
214  # XXX check arg syntax
215  try:
216  func = getattr(self, 'help_' + arg)
217  except:
218  try:
219  doc=getattr(self, 'do_' + arg).__doc__
220  if doc:
221  print doc
222  return
223  except:
224  pass
225  print self.nohelp % (arg,)
226  return
227  func()
228  else:
229  names = self.get_names()
230  cmds_doc = []
231  cmds_undoc = []
232  help = {}
233  for name in names:
234  if name[:5] == 'help_':
235  help[name[5:]]=1
236  names.sort()
237  # There can be duplicates if routines overridden
238  prevname = ''
239  for name in names:
240  if name[:3] == 'do_':
241  if name == prevname:
242  continue
243  prevname = name
244  cmd=name[3:]
245  if help.has_key(cmd):
246  cmds_doc.append(cmd)
247  del help[cmd]
248  elif getattr(self, name).__doc__:
249  cmds_doc.append(cmd)
250  else:
251  cmds_undoc.append(cmd)
252  print self.doc_leader
253  self.print_topics(self.doc_header, cmds_doc, 15,80)
254  self.print_topics(self.misc_header, help.keys(),15,80)
255  self.print_topics(self.undoc_header, cmds_undoc, 15,80)
256 
257  def print_topics(self, header, cmds, cmdlen, maxcol):
258  if cmds:
259  print header
260  if self.ruler:
261  print self.ruler * len(header)
262  (cmds_per_line,junk)=divmod(maxcol,cmdlen)
263  col=cmds_per_line
264  for cmd in cmds:
265  if col==0: print
266  print (("%-"+`cmdlen`+"s") % cmd),
267  col = (col+1) % cmds_per_line
268  print "\n"