def attr_triple(value): """ Check that interprets the value as `urwid.AttrSpec` triple for the colour modes 1,16 and 256. It assumes a <6 tuple of attribute strings for mono foreground, mono background, 16c fg, 16c bg, 256 fg and 256 bg respectively. If any of these are missing, we downgrade to the next lower available pair, defaulting to 'default'. :raises: VdtValueTooLongError, VdtTypeError :rtype: triple of `urwid.AttrSpec` """ keys = ['dfg', 'dbg', '1fg', '1bg', '16fg', '16bg', '256fg', '256bg'] acc = {} if not isinstance(value, (list, tuple)): value = value, if len(value) > 6: raise VdtValueTooLongError(value) # ensure we have exactly 6 attribute strings attrstrings = (value + (6 - len(value)) * [None])[:6] # add fallbacks for the empty list attrstrings = (2 * ['default']) + attrstrings for i, value in enumerate(attrstrings): if value: acc[keys[i]] = value else: acc[keys[i]] = acc[keys[i - 2]] try: mono = AttrSpec(acc['1fg'], acc['1bg'], 1) normal = AttrSpec(acc['16fg'], acc['16bg'], 16) high = AttrSpec(acc['256fg'], acc['256bg'], 256) except AttrSpecError as e: raise ValidateError(str(e)) return mono, normal, high
def __init__(self, edit_text, strike=False, new=False): self.strikethrough = strike self.new_expan = new # Spacing strings self.leading_space = ' ' self.leading_char = '- ' self.leading_STRIKE = 'x ' # Default color specs self.text_attr = AttrSpec('h6', '') self.text_STRIKE = AttrSpec('h6, strikethrough', '') self.focus_attr = AttrSpec('h6, bold', '') self.focus_STRIKE = AttrSpec('h6, bold, strikethrough', '') if not self.strikethrough: caption = self.leading_space + self.leading_char attr = self.text_attr attr_focus = self.focus_attr else: caption = self.leading_space + self.leading_STRIKE attr = self.text_STRIKE attr_focus = self.focus_STRIKE self.edit = Edit(caption, edit_text, wrap='clip') self.map = AttrMap(self.edit, attr_map=attr, focus_map=attr_focus) self.fill = Filler(self.map) super().__init__(self.map)
def __init__(self, list_data=None): self.is_editing = False self.tasks = [] self.name = None self.group = None self.id = None if list_data: # Parse the data. self.parse_data(list_data) else: # Must be a new list self.name = 'untitled' self.group = 'none' self.id = uuid.uuid4().hex # AttrSpecs self.attr_spec = AttrSpec('', '') self.focus_nav = AttrSpec('h12', '') self.focus_ins = AttrSpec('h160', '') # Build widget stack self.title = TitleBar(self.name) self.group_foot = GroupFoot(self.group) self.body = urwid.SimpleFocusListWalker(self.tasks) self.list_box = ListBox(self.body) self.list_frame = Frame(self.list_box, header=self.title, footer=self.group_foot) self.line_box = LineBox(self.list_frame) self.line_attr = AttrMap(self.line_box, self.attr_spec, self.focus_nav) super().__init__(self.line_attr)
def test_regex_symbol_is_correct(self): # Match 4th level quote self.assertEqual(parse_quotes('Aaa A'), AttrSpec('#401', '#402')) self.assertIsNone(parse_quotes('One symbol at the end <>!b')) self.assertEqual(parse_quotes('Aa<>tb Ah, so much fun'), AttrSpec('#401', '#402')) self.assertEqual(parse_quotes('> A symbol at the begining'), AttrSpec('#201', '#202')) self.assertEqual(parse_quotes('A A symbols every> where>>! >>'), AttrSpec('#201', '#202')) self.assertEqual(parse_quotes('A>A or A<A ?'), AttrSpec('#301', '#302'))
def compute_color(entry: Entry) -> AttrSpec: rating = entry.rating if entry.parent and entry.parent.unexplored: rating = 0.5 bold = False unimportant = False if not entry.readable: color = theme.forbidden elif rating < 0.05: color = theme.unused else: if rating >= 0.6: bold = True elif rating < 0.2: unimportant = True if entry.is_dir: color = theme.directory elif entry.is_link: color = theme.symlink elif entry.executable: color = theme.executable else: color = theme.file if unimportant: color = theme.unimportant[color] if bold: color = color + ',bold' return AttrSpec(color, '', colors=16)
def check_color(string): try: attrspec = AttrSpec(string, 'default') except AttrSpecError: raise ValueError(string) else: return max(16, attrspec.colors)
def _parse_attributes(self, c): """ parse a (previously validated) valid theme file into urwid AttrSpec attributes for internal use. :param c: config object for theme file :type c: `configobj.ConfigObj` :raises: `ConfigError` """ attributes = {} for sec in c.sections: try: colours = int(sec) except ValueError: err_msg = 'section name %s is not a valid colour mode' raise ConfigError(err_msg % sec) attributes[colours] = {} for mode in c[sec].sections: attributes[colours][mode] = {} for themable in c[sec][mode].sections: block = c[sec][mode][themable] fg = block['fg'] if colours == 1: bg = 'default' else: bg = block['bg'] if colours == 256: fg = fg or c['16'][mode][themable][fg] bg = bg or c['16'][mode][themable][bg] try: att = AttrSpec(fg, bg, colours) except AttrSpecError, e: raise ConfigError(e) attributes[colours][mode][themable] = att
def show_error(message: str, duration: float = 1.5) -> None: """ Triggers a notification :param message: the error to display :param duration: if set to 0, the message is displayed until another call to 'show' or 'clear' """ show((AttrSpec(theme.forbidden + ',bold', '', colors=16), message), duration)
def handle_keypress(self, size, key): try: self.calculate_sizes(size) handled = False if self.filter.active: self.filter.keypress(self.filter_size, key) handled = True elif self.active_action: handled = self.active_action.__call__(key=key) if not handled: if not self.handle_key_individually(key): for action in self.action_map.values(): if action.handle(key): break except PermissionError: notify.show((AttrSpec(theme.forbidden + ',bold', '', colors=16), "PERMISSION DENIED")) except FileNotFoundError: notify.show((AttrSpec(theme.forbidden + ',bold', '', colors=16), "FILE NOT FOUND"))
def resolve_att(a, fallback): """ replace '' and 'default' by fallback values """ if a is None: return fallback if a.background in ['default', '']: bg = fallback.background else: bg = a.background if a.foreground in ['default', '']: fg = fallback.foreground else: fg = a.foreground return AttrSpec(fg, bg)
def render(self, size, focus=False): key = " " if self.entry.key.value == "" else self.entry.key.value caption = " " + key + " " text = self.entry.name display = caption + text if focus and viewmodel.global_mode in viewmodel.ANY_ASSIGN_MODE: color = AttrSpec(self.color.foreground + ',standout', self.color.background, colors=16) else: color = self.color self.entry_text.set_text((color, display)) self.entry_edit.set_caption((color, caption)) return super().render(size, focus=focus)
def __init__(self, tag_index, tag_text, new=False): self.new_tag = new op_char = tag_text[0] if op_char == 'o': self.strikethrough = False elif op_char == 'x': self.strikethrough = True tag_text = tag_text.lstrip(op_char) self.tag_index = tag_index self.tag_text = tag_text # Default color specs self.index_attr = AttrSpec('h11', '') self.index_STRIKE = AttrSpec('h11, strikethrough', '') self.text_attr = AttrSpec('', '') self.text_STRIKE = AttrSpec(', strikethrough', '') self.focus_attr = AttrSpec(', bold', '') self.focus_STRIKE = AttrSpec(', bold, strikethrough', '') # Build widget stack self.edit = Edit( caption=self.build_caption(), edit_text=self.tag_text, multiline=False, wrap ='clip') if not self.strikethrough: self.tag_map = AttrMap( self.edit, attr_map=self.text_attr, focus_map=self.focus_attr) else: self.tag_map = AttrMap( self.edit, attr_map=self.text_STRIKE, focus_map=self.focus_STRIKE) self.tag_fill = Filler(self.tag_map, 'top') super().__init__(self.tag_map)
def build_stack(self, obj=None): pack = self.group.pack()[0] length = pack if pack else 1 self.padding = urwid.Padding(self.group, 'center', length) self.map = AttrMap(self.padding, AttrSpec('', 'black')) self.holder.original_widget = self.map
def test_quote_level_get_equals_corresponding_attribute(self): self.assertEqual(parse_quotes('> >>'), AttrSpec('#301', '#302')) self.assertEqual(parse_quotes('>> >> >> >'), AttrSpec('#701', '#702')) # Higest level quote possible matched self.assertEqual(parse_quotes('>> >> >> >>'), AttrSpec('#701', '#702'))