comparison cmd2.py @ 76:dcd5d13e5603

fixed problem with interpreting terminators
author catherine@Elli.myhome.westell.com
date Sat, 28 Jun 2008 10:31:12 -0400
parents 8b2603d1acc1
children bb44928c3856
comparison
equal deleted inserted replaced
75:8b2603d1acc1 76:dcd5d13e5603
127 def getPasteBuffer(): 127 def getPasteBuffer():
128 raise OSError, pastebufferr % ('xclip', 'On Debian/Ubuntu, install with "sudo apt-get install xclip"') 128 raise OSError, pastebufferr % ('xclip', 'On Debian/Ubuntu, install with "sudo apt-get install xclip"')
129 setPasteBuffer = getPasteBuffer 129 setPasteBuffer = getPasteBuffer
130 130
131 pyparsing.ParserElement.setDefaultWhitespaceChars(' \t') # see http://pyparsing.wikispaces.com/message/view/home/1352689 131 pyparsing.ParserElement.setDefaultWhitespaceChars(' \t') # see http://pyparsing.wikispaces.com/message/view/home/1352689
132 132
133 class Arguments(str):
134 def __new__(cls, s, parent):
135 result = str.__new__(cls, s)
136 result.parent = parent
137 return result
138
133 class UserCommand(str): 139 class UserCommand(str):
134 def __new__(cls, s, app): 140 def __new__(cls, s, app):
135 return str.__new__(cls, s) 141 return str.__new__(cls, s)
136 def __init__(self, s, app): 142 def __init__(self, s, app):
137 self.terminator = None 143 self.terminator = None
138 self.terminator_suffix = None 144 self.terminator_suffix = None
145 s = s.strip()
146 shortcut = app.shortcuts.get(s[0])
147 if shortcut and hasattr(app, 'do_%s' % shortcut):
148 s = '%s %s' % (shortcut, s[1:])
139 self.searchable = self.asEntered = s 149 self.searchable = self.asEntered = s
140 self.app = app 150 self.app = app
141 self.output_destination_pattern = self.punctuationPattern(['>>', '>']) 151 self.output_destination_pattern = self.punctuationPattern(['>>', '>'])
142 self.input_source_pattern = self.punctuationPattern(['<']) 152 self.input_source_pattern = self.punctuationPattern(['<'])
143 self.pipe_destination_pattern = self.punctuationPattern(['|']) 153 self.pipe_destination_pattern = self.punctuationPattern(['|'])
148 processed = reduce(lambda x, y: x ^ y, processed) 158 processed = reduce(lambda x, y: x ^ y, processed)
149 processed.ignore(pyparsing.sglQuotedString) 159 processed.ignore(pyparsing.sglQuotedString)
150 processed.ignore(pyparsing.dblQuotedString) 160 processed.ignore(pyparsing.dblQuotedString)
151 pattern = pyparsing.SkipTo(processed) + processed + pyparsing.restOfLine 161 pattern = pyparsing.SkipTo(processed) + processed + pyparsing.restOfLine
152 return pattern 162 return pattern
153 def find_punctuation(self): 163 def parse(self):
154 punctuators = ['|','>','>>','<'] 164 punctuators = ['|','>','>>','<']
155 punctuators.extend(self.app.terminators) 165 punctuators.extend(self.app.terminators)
156 punctuated = self.punctuationPattern(punctuators).searchString(self.asEntered) 166 punctuated = self.punctuationPattern(punctuators).searchString(self.asEntered)
157 if punctuated: 167 if punctuated:
158 self.executable, self.searchable = punctuated[0][0], self.asEntered[len(punctuated[0][0]):] 168 self.executable, self.searchable = punctuated[0][0], self.asEntered[len(punctuated[0][0]):]
159 else: 169 else:
160 self.executable, self.searchable = self.asEntered, '' 170 self.executable, self.searchable = self.asEntered, ''
171 self.executable = self.executable.strip()
172 try:
173 self.cmd, self.arg = (pyparsing.Word(self.app.identchars)+pyparsing.restOfLine).parseString(self.executable)
174 self.arg = Arguments(self.arg, self)
175 except pyparsing.ParseException:
176 self.cmd, self.arg = None, None
177
161 def complete(self): 178 def complete(self):
162 terminator_finder = self.punctuationPattern(self.app.terminators) 179 terminator_finder = self.punctuationPattern(self.app.terminators)
163 result = terminator_finder.searchString(self.asEntered) 180 result = terminator_finder.searchString(self.asEntered)
164 while not result: 181 while not result:
165 inp = self.app.pseudo_raw_input(self.app.continuationPrompt) 182 inp = self.app.pseudo_raw_input(self.app.continuationPrompt)
166 self.asEntered = '%s\n%s' % (self.asEntered, inp) 183 self.asEntered = '%s\n%s' % (self.asEntered, inp)
167 result = terminator_finder.searchString(self.asEntered) 184 result = terminator_finder.searchString(self.asEntered)
168 try: 185 self.terminator = result[0][1]
169 self.terminator = result[0][1][0] 186 if len(result[0]) > 3:
170 self.terminator_suffix = result[0][1][1] 187 self.terminator_suffix = result[0][2]
171 except IndexError: 188 else:
172 self.terminator = result[0][1]
173 self.terminator_suffix = None 189 self.terminator_suffix = None
174 def redirectedInput(self): 190 def redirectedInput(self):
175 inputFrom = self.input_source_pattern.searchString(self.searchable) 191 inputFrom = self.input_source_pattern.searchString(self.searchable)
176 if inputFrom: 192 if inputFrom:
177 if inputFrom[0][-1].strip(): 193 if inputFrom[0][-1].strip():
193 mode = 'a' 209 mode = 'a'
194 else: 210 else:
195 mode = 'w' 211 mode = 'w'
196 return dest, mode 212 return dest, mode
197 return None, None 213 return None, None
198
199
200
201 """
202 Produces a string parser based on a list of targets to search for.
203 Output is a parser function.
204 Parser's output is a tuple: (before the target, [elements of the target], after the target)
205 >>> p = punctuationParser([';', 'EOF'])
206 >>> p('is terminated;')
207 ('is terminated', [';'], '')
208 >>> p('is terminated EOF after the end')
209 ('is terminated', ['EOF'], 'after the end')
210 >>> p('is not terminated')
211 >>> pattern1 = pyparsing.Literal(';') + pyparsing.Optional(pyparsing.Word(pyparsing.nums))
212 >>> p2 = punctuationParser([pattern1, 'EOF'])
213 >>> p2('the quick brown fox;4')
214 ('the quick brown fox', [';', '4'], '')
215 >>> p2('the quick brown foxEOF')
216 ('the quick brown fox', ['EOF'], '')
217 >>> p2('nothing')
218 """
219 214
220 class Cmd(cmd.Cmd): 215 class Cmd(cmd.Cmd):
221 caseInsensitive = True 216 caseInsensitive = True
222 multilineCommands = [] # commands that need a terminator to be finished 217 multilineCommands = [] # commands that need a terminator to be finished
223 terminators = [';', pyparsing.LineEnd() + pyparsing.LineEnd()] 218 terminators = [';', pyparsing.LineEnd() + pyparsing.LineEnd()]
298 command, args = self.extractCommand(line) 293 command, args = self.extractCommand(line)
299 originalStatement = ' '.join([command, args]) 294 originalStatement = ' '.join([command, args])
300 statement = UserCommand(originalStatement, self) 295 statement = UserCommand(originalStatement, self)
301 if (not assumeComplete) and (command in self.multilineCommands): 296 if (not assumeComplete) and (command in self.multilineCommands):
302 statement.complete() 297 statement.complete()
303 statement.find_punctuation() 298 statement.parse()
304 statement.redirectedInput() 299 statement.redirectedInput()
305 pipeTo = statement.pipeDestination() 300 pipeTo = statement.pipeDestination()
306 if pipeTo: 301 if pipeTo:
307 statekeeper = Statekeeper(self, ('stdout',)) 302 statekeeper = Statekeeper(self, ('stdout',))
308 dest = subprocess.Popen(pipeTo, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE) 303 dest = subprocess.Popen(pipeTo, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
316 else: 311 else:
317 self.stdout = tempfile.TemporaryFile() 312 self.stdout = tempfile.TemporaryFile()
318 if outputMode == 'a': 313 if outputMode == 'a':
319 self.stdout.write(getPasteBuffer()) 314 self.stdout.write(getPasteBuffer())
320 315
321 stop = cmd.Cmd.onecmd(self, statement.executable) 316 stop = cmd.Cmd.onecmd(self, statement)
322 try: 317 try:
323 if command not in self.excludeFromHistory: 318 if command not in self.excludeFromHistory:
324 self.history.append(originalStatement) 319 self.history.append(originalStatement)
325 finally: 320 finally:
326 if statekeeper: 321 if statekeeper:
409 def parseline(self, line): 404 def parseline(self, line):
410 """Parse the line into a command name and a string containing 405 """Parse the line into a command name and a string containing
411 the arguments. Returns a tuple containing (command, args, line). 406 the arguments. Returns a tuple containing (command, args, line).
412 'command' and 'args' may be None if the line couldn't be parsed. 407 'command' and 'args' may be None if the line couldn't be parsed.
413 """ 408 """
414 line = line.strip() 409 if not line.executable:
415 if not line:
416 return None, None, line 410 return None, None, line
417 shortcut = self.shortcuts.get(line[0]) 411 return line.cmd, line.arg, line.executable
418 if shortcut and hasattr(self, 'do_%s' % shortcut):
419 line = '%s %s' % (shortcut, line[1:])
420 i, n = 0, len(line)
421 while i < n and line[i] in self.identchars: i = i+1
422 cmd, arg = line[:i], line[i:].strip()
423 return cmd, arg, line
424
425 def showParam(self, param): 412 def showParam(self, param):
426 param = self.clean(param) 413 param = self.clean(param)
427 if param in self.settable: 414 if param in self.settable:
428 val = getattr(self, param) 415 val = getattr(self, param)
429 self.stdout.write('%s: %s\n' % (param, str(getattr(self, param)))) 416 self.stdout.write('%s: %s\n' % (param, str(getattr(self, param))))