Thu, 21 Dec 2017 12:27:16 +0200
Added ldconfig.ldr support
#!/usr/bin/env python3 class Colour: ''' Colour interface. Supports LDConfig colours and direct colours. For LDConfig colours to work, load_colours must be called first. ''' def __init__(self, index): if not isinstance(index, int): index = int(index, 0) self.index = index def __str__(self): if self.is_direct_colour: # write direct colours with hex codes return '0x%07X' % self.index else: return str(self.index) def __repr__(self): try: return 'colours.' + colours_inverse_dict[self.index] except KeyError: return str.format('Colour({!r})', self.index) @property def is_direct_colour(self): return self.index >= 0x2000000 @property def is_ldconfig_colour(self): return self.index in ldconfig_colour_data @property def name(self): if self.is_ldconfig_colour: return ldconfig_colour_data[self.index]['name'] else: return str(self) @property def face_colour(self): if self.is_ldconfig_colour: return ldconfig_colour_data[self.index]['value'] elif self.is_direct_colour: return '#%06X' % (self.index & 0xffffff) else: return '#000000' @property def is_valid(self): return self.is_ldconfig_colour or self.is_direct_colour def __eq__(self, other): return self.index == other.index def __lt__(self, other): return self.index < other.index def __le__(self, other): return self.index <= other.index def __gt__(self, other): return self.index > other.index def __ge__(self, other): return self.index >= other.index def parse_ldconfig_ldr_line(line): ''' Parses a single LDConfig.ldr line. Returns: · a dict for a successful parsed colour. · None for empty lines and comments. Raises an error for invalid lines. ''' line = line.strip() import re def parse_tag(tag): match = re.search(tag + r'\s+([^ ]+)', line) if match: return match.group(1) else: raise KeyError(str.format('Tag {} not found', tag)) # parse 0 !COLOUR and get the name match = re.search(r'^0\s+!COLOUR\s([^ ]+)', line) if not match: # failed, check if it's an empty line or comment: if not line or line.startswith('0'): return None else: # failed too, thus the line is bad raise ValueError('Bad LDConfig.ldr line') # replace underscores for readability name = match.group(1).replace('_', ' ') # parse tags code = int(parse_tag('CODE')) value = parse_tag('VALUE') edge = parse_tag('EDGE') return { 'name': name, 'code': code, 'value': value, 'edge': edge, } def parse_ldconfig_ldr(ldconfig_ldr): ''' Parses LDConfig.ldr and returns pairs ''' for line in ldconfig_ldr: colour = parse_ldconfig_ldr_line(line) if colour: yield (colour['code'], colour) class colours: ''' LDConfig colour namespace, exists for interactive mode and for Colour.__repr__ to return something pretty. ''' pass # LDConfig lookup tables colours_inverse_dict = {} ldconfig_colour_data = {} def load_colours(ldconfig_ldr): ''' Loads colours. Expects a file pointer to LDConfig.ldr as the parameter. ''' global ldconfig_colour_data ldconfig_colour_data = dict(parse_ldconfig_ldr(ldconfig_ldr)) for index, colour in ldconfig_colour_data.items(): identifier = colour['name'].replace(' ', '_').lower() setattr(colours, identifier, Colour(index)) colours_inverse_dict[index] = identifier # Interactive mode support (pass LDConfig.ldr path as a command-line argument) if __name__ == '__main__': from sys import argv with open(argv[1]) as ldconfig_ldr: load_colours(ldconfig_ldr)