rendered paste body#!/usr/bin/env python2.5from re import compile as regCompilefrom types import ListTypefrom sys import argvfrom random import randintfrom os import getenv, spawnv, P_NOWAITfrom os.path import joinclass ConfigError (Exception): def __init__ (self, line = -1): self.line = linedef parseConfig (config): def splitArg (string): # Feature: a"b"c -> [a, b, c] def recsplit(string, result, pos): match = regCompile(' *\"[^"]+\" *').search(string, pos) if match: result += string[pos:match.start()].strip().split(' ') result.append(match.string[match.start():match.end()].strip()[1:-1]) return recsplit(string, result, pos + match.end()) return result if string.find('"') == -1: return string return recsplit(string, list(), 0) def parseArg (arg): split = splitArg(arg[1]) if type(split) <> ListType: split = split.split() return [arg[0]] + split count, lines = 1, list() for line in [x.strip() for x in config]: if line and not line.startswith('#'): groups, fields = list(), line.split(':') assert len(fields) == 3, ConfigError(line) assert fields[1].lower() in ('random', 'norandom'), ConfigError(line) fields[1] = fields[1].lower() == 'random' for group in fields[2].split(';'): groups.append([parseArg(z) for z in [y.split('=') for y in group.split(',')]]) fields[2] = groups fields.insert(0, count) lines.append(fields) count += 1 return linesclass XtermDict (dict): RANDOM, COMMAND = range(2) def __getitem__ (self, key): return dict.__getitem__(self, key)[XtermDict.COMMAND] def random (self): assert len(self) > 0 randoms = filter(lambda x: dict.__getitem__(self, x)[XtermDict.RANDOM], self) return self[randoms[randint(0, len(randoms)-1)]]class Xterm (object): class _Options: NO_ARGUMENT = 2**0 FOUND_ARGUMENT = 2**1 BOOLEAN_ARGUMENT = 2**2 SIMPLE_ARGUMENT = 2**3 CONCAT_ARGUMENT = 2**4 UNION_ARGUMENT = 2**5 MULTIPLE_ARGUMENT = 2**6 COMMAND = '/usr/X11R6/bin/xterm' DEFAULTS = [('132', BOOLEAN_ARGUMENT, None), ('C', NO_ARGUMENT, None), ('S', CONCAT_ARGUMENT, None), ('T', SIMPLE_ARGUMENT, None), ('ah', BOOLEAN_ARGUMENT, None), ('ai', BOOLEAN_ARGUMENT, None), ('aw', BOOLEAN_ARGUMENT, None), ('b', SIMPLE_ARGUMENT, None), ('bc', BOOLEAN_ARGUMENT, None), ('bcf', SIMPLE_ARGUMENT, None), ('bcn', SIMPLE_ARGUMENT, None), ('bd', SIMPLE_ARGUMENT, None), ('bdc', BOOLEAN_ARGUMENT, None), ('bg', SIMPLE_ARGUMENT, None), ('bw', SIMPLE_ARGUMENT, None), ('cb', BOOLEAN_ARGUMENT, None), ('cc', SIMPLE_ARGUMENT, None), ('cjk_width', BOOLEAN_ARGUMENT, None), ('class', SIMPLE_ARGUMENT, None), ('cm', BOOLEAN_ARGUMENT, None), ('cn', BOOLEAN_ARGUMENT, None), ('cr', SIMPLE_ARGUMENT, None), ('cu', BOOLEAN_ARGUMENT, None), ('dc', BOOLEAN_ARGUMENT, None), ('display', SIMPLE_ARGUMENT, None), ('e', SIMPLE_ARGUMENT|MULTIPLE_ARGUMENT, None), ('fa', SIMPLE_ARGUMENT, None), ('fb', SIMPLE_ARGUMENT, None), ('fbb', BOOLEAN_ARGUMENT, None), ('fbx', BOOLEAN_ARGUMENT, None), ('fd', SIMPLE_ARGUMENT, None), ('fg', SIMPLE_ARGUMENT, None), ('fi', SIMPLE_ARGUMENT, None), ('fn', SIMPLE_ARGUMENT, None), ('fs', SIMPLE_ARGUMENT, None), ('fw', SIMPLE_ARGUMENT, None), ('fwb', SIMPLE_ARGUMENT, None), ('fx', SIMPLE_ARGUMENT, None), ('%', UNION_ARGUMENT, None), ('#', UNION_ARGUMENT, None), ('geometry', SIMPLE_ARGUMENT, None), ('hc', SIMPLE_ARGUMENT, None), ('help', NO_ARGUMENT, None), # ;-) ('hold', BOOLEAN_ARGUMENT, None), ('iconic', NO_ARGUMENT, None), ('ie', BOOLEAN_ARGUMENT, None), ('im', BOOLEAN_ARGUMENT, None), ('into', SIMPLE_ARGUMENT, None), ('j', BOOLEAN_ARGUMENT, None), ('k8', BOOLEAN_ARGUMENT, None), ('kt', SIMPLE_ARGUMENT, None), ('l', BOOLEAN_ARGUMENT, None), ('lc', BOOLEAN_ARGUMENT, None), ('lcc', SIMPLE_ARGUMENT, None), ('leftbar', NO_ARGUMENT, None), ('lf', SIMPLE_ARGUMENT, None), ('ls', BOOLEAN_ARGUMENT, None), ('mb', BOOLEAN_ARGUMENT, None), ('mc', SIMPLE_ARGUMENT, None), ('mesg', BOOLEAN_ARGUMENT, None), ('mk_width', BOOLEAN_ARGUMENT, None), ('ms', SIMPLE_ARGUMENT, None), ('n', SIMPLE_ARGUMENT, None), ('name', SIMPLE_ARGUMENT, None), ('nb', SIMPLE_ARGUMENT, None), ('nul', BOOLEAN_ARGUMENT, None), ('pc', BOOLEAN_ARGUMENT, None), ('pob', BOOLEAN_ARGUMENT, None), ('rightbar', NO_ARGUMENT, None), ('rv', BOOLEAN_ARGUMENT, None), ('rvc', BOOLEAN_ARGUMENT, None), ('rw', BOOLEAN_ARGUMENT, None), ('s', BOOLEAN_ARGUMENT, None), ('samename', BOOLEAN_ARGUMENT, None), ('sb', BOOLEAN_ARGUMENT, None), ('sf', BOOLEAN_ARGUMENT, None), ('si', BOOLEAN_ARGUMENT, None), ('sk', BOOLEAN_ARGUMENT, None), ('sl', SIMPLE_ARGUMENT, None), ('sm', BOOLEAN_ARGUMENT, None), ('sp', BOOLEAN_ARGUMENT, None), ('t', BOOLEAN_ARGUMENT, None), ('ti', SIMPLE_ARGUMENT, None), ('title', SIMPLE_ARGUMENT, None), ('tm', SIMPLE_ARGUMENT, None), ('tn', SIMPLE_ARGUMENT, None), ('u8', BOOLEAN_ARGUMENT, None), ('ulc', BOOLEAN_ARGUMENT, None), ('ulit', BOOLEAN_ARGUMENT, None), ('ut', BOOLEAN_ARGUMENT, None), ('vb', BOOLEAN_ARGUMENT, None), ('version', NO_ARGUMENT, None), # ;-) ('wc', BOOLEAN_ARGUMENT, None), ('wf', BOOLEAN_ARGUMENT, None), ('xrm', SIMPLE_ARGUMENT, None), ('ziconbeep', SIMPLE_ARGUMENT, None)] class _Dict (dict): _MODE = 0 _ARGUMENT = 1 def __init__ (self, defaults): dict.__init__(self) for key, mode, arg in defaults: dict.__setitem__(self, key, (mode, arg)) def _mode(self, key): return dict.__getitem__(self, key)[Xterm._Dict._MODE] def _args(self, key): return dict.__getitem__(self, key)[Xterm._Dict._ARGUMENT] def __iter2__ (self): return filter(lambda x : self._mode(x) & Xterm._Options.FOUND_ARGUMENT, dict.iterkeys(self)) def __setitem__ (self, key, value): assert dict.has_key(self, key), ConfigError() mode = self._mode(key) dict.__setitem__(self, key, (mode | Xterm._Options.FOUND_ARGUMENT, value)) return self def __getitem__ (self, key): result = None assert dict.has_key(self, key) assert self._mode(key) & Xterm._Options.FOUND_ARGUMENT if self._mode(key) & Xterm._Options.NO_ARGUMENT: assert len(self._args(key)) == 0, ConfigError() result = ['-%s' % key] elif self._mode(key) & Xterm._Options.BOOLEAN_ARGUMENT: assert len(self._args(key)) == 0, ConfigError() result = ['%s%s' % ('-' if self._args(key) else '+', key)] elif self._mode(key) & Xterm._Options.SIMPLE_ARGUMENT: if self._mode(key) & Xterm._Options.MULTIPLE_ARGUMENT: assert len(self._args(key)) > 0, ConfigError() else: assert len(self._args(key)) == 1, ConfigError() result = ['-%s' % key] + self._args(key) elif self._mode(key) & Xterm._Options.UNION_ARGUMENT: assert len(self._args(key)) == 0, ConfigError() result = ['%s%s' % (key, self._args(key))] elif self._mode(key) & Xterm._Options.CONCAT_ARGUMENT: assert len(self._args(key) > 1, ConfigError()) result = ['-%s' % key] + self._args(key) else: assert False return result def has_key(self, key): return dict.has_key(self, key) and self._mode(key) & Xterm._Options.FOUND_ARGUMENT def __init__ (self, *args): self.dict = Xterm._Dict(Xterm._Options.DEFAULTS) for arg in args: option, value = arg[0], arg[1:] self.dict[option] = value def command (self): result = [Xterm._Options.COMMAND] for arg in self.dict.__iter2__(): if arg <> 'e': result += self.dict[arg] if self.dict.has_key('e'): result += self.dict['e'] return result def execute (self): cmd = self.command() + argv print cmd spawnv(P_NOWAIT, cmd[0], cmd)xtermDict = XtermDict()try: config = getenv('XT_CONFIG') config = config if config else join(getenv('HOME'), '.xt') for line, name, random, argGroup in parseConfig(open(config)): try: xterms = list() for args in argGroup: xterms.append(Xterm(*args)) xtermDict[name] = random, xterms except (AssertionError, ConfigError), e: raise ConfigError(line)except ConfigError, e: print 'Error at line ', e.line raise eargv = argv[1:]if not xtermDict: xtermDict['xterm'] = True, [Xterm()]print xtermDictif argv and xtermDict.has_key(argv[0]): xterms, argv = xtermDict[argv[0]], argv[1:]else: xterms = xtermDict.random()for x in xterms: x.execute()