#!/usr/bin/python """This is ppr. Hi there.""" import sys, re r_hws = re.compile(r'[ \t]+') commands = {} def at(line): """Asserts that the length of the line is longer than 0.""" if line: return True return False commands['@'] = at def strip(line): """Strips the line of leading and trailing spaces and tabs.""" return line.strip(' \t') commands['strip'] = strip def reduce(line): """Reduces all horizontal whitespace to a single space.""" return r_hws.sub(' ', line) commands['reduce'] = reduce def get(line, arg=None): """Strip, reduce, split on space, and get the relevant index.""" if arg is not None: arg = int(arg.lstrip(' ')) else: arg = 0 line = strip(line) line = reduce(line) parts = line.split(' ') if (arg + 1) > len(parts): return '' else: return parts[arg] commands['get'] = get def quot(line): """Quote a string in the usual manner.""" return '"%s"' % line.replace('"', '\\"') commands['quot'] = quot def slice(line, arg=None): """Return a string slice.""" if arg: lower, higher = tuple(map(int, arg.split(':'))) else: lower, higher = 0, len(line) return line[lower:higher] commands['slice'] = slice def fro(line, arg=None): if arg is None: arg = '' i = line.find(arg) + len(arg) return line[i:] commands['from'] = fro def dest(line, arg=None): if arg is None: arg = '' i = line.find(arg) return line[:i] commands['to'] = dest r_name = re.compile(r'[a-z]+') class Engine(object): def __init__(self, inputs=None, outputs=None): if inputs is None: inputs = [sys.stdin] if outputs is None: outputs = [sys.stdout] self.inputs = inputs self.outputs = outputs self.commands = commands def __call__(self, command): self.doCommand(command) def write(self, s): for output in self.outputs: output.write(s) def error(self, msg): sys.stderr.write(msg) sys.exit(1) def doCommand(self, command): sepchars = ';, :|' if command: if command[0] in sepchars: sepchar = command[0] command = command[1:] else: sepchar = ';' t_bit = r'[^\%s\\]*(?:\\.[^\%s\\]*)*' % (sepchar, sepchar) r_bit = re.compile(t_bit) commands = [] while 1: m = r_bit.match(command) if m: bit = m.group(0) command = command[len(bit):] bit = bit.lstrip(' ') bit = bit.replace('\\%s' % sepchar, sepchar) if bit: commands.append(bit) if command.startswith(sepchar): command = command[1:] elif command: msg = 'Unknown seperator: %s\n' % command[0] self.error(msg) else: break else: break for input in self.inputs: while True: line = input.readline() if not line: break if line.endswith('\r\n'): line = line[:-2] elif line.endswith('\n'): line = line[:-1] else: self.error("Line doesn't end with nl: %r\n" % line) for command in commands: m = r_name.match(command) if m: fname = m.group(0) if command != fname: arg = command[len(fname):] if arg.startswith('(') and arg.endswith(')'): arg = arg[1:-1] args = (line, arg) else: args = (line,) if self.commands.has_key(fname): funct = self.commands[fname] else: self.error('Unknown command: %s\n' % command) elif command in ('@',): funct = self.commands[command] args = (line,) elif command.startswith('['): funct = self.commands['slice'] if command.endswith(']'): command = command[:-1] args = (line, command[1:]) else: self.error('Unknown command: %s\n' % command) result = funct(*args) if result is True: continue elif result is False: line = None break else: line = result if line is not None: self.write(line + '\n') def main(argv=None): if argv is None: argv = sys.argv[1:] if argv: inputs = [open(fn, 'r') for fn in argv[1:]] or None process = Engine(inputs=inputs) process(argv[0]) else: print __doc__ for key in commands.keys(): msg = commands[key].__doc__ or '@@ No documentation!' print '%s:\t%s' % (key, msg) if __name__=="__main__": main()