[Urwid] Rendering standout attribute across entire Columns widget

Ian Ward ian at excess.org
Fri Sep 2 10:33:23 EDT 2011

Jacob Courtneay wrote on 2011-09-02 02:04:
> Ian Ward <ian <at> excess.org> writes:
>> Interesting change.  I think that moving to a slightly more CSS-like
>> display attribute system might be clearer and easier to use though.
>> Also in this specific case you can't add strings to AttrSpec instances
>> (which sometimes are used as display attributes)
>> How about this:
>> 1. Canvases would start remembering the order that display attributes
>> were applied
>> eg:
>>     w1 = Text(('first', ('second', "Hello")))
>>     w2 = AttrMap(Text(('first', "Hello")), {'first':'second'})
>> would both be widgets with display attributes applied to the "Hello"
>> text in the order 'first', 'second'.
>> 2. Screen palette lookups would match tuples of display attributes in
>> order from last to first, stopping when no further match is found.
>> eg:
>>     palette = [('first', 'yellow', 'black'),
>>                ('second', light blue', 'black')]
>> would colour "Hello" light blue as it does now, but:
>>     palette = [('first', 'yellow', 'black'),
>>                ('second', light blue', 'black'),
>>                (('first', 'second'), 'dark green', 'black')]
>> would colour "Hello" dark green. Note that if there was another display
>> attribute applied earlier:
>>     w3 = Text(('zeroth', ('first', ('second', "Hello"))))
>> The "Hello" text would still be dark green because ('first', 'second')
>> is the last match found in the palette.
> So you just mean there doesn't need to be a full match in the palette, 
> right? It matches the longest possible chain. That would be pretty intuitive.

Yes, but the longest possible chain with matching endings.  Like a
regexp with a $.  This makes the matching dead-simple.

>> This should cleanly solve the common "in focus" case.
> I don't understand. If you mean it helps make focus attributes less special, 
> that sounds good. Having to pass a second dict into AttrMap is kind of 
> annoying, it seems like there could be a standard way of saying "this 
> display attribute when it's focused".

Yes, so one way to do that would be AttrMap(foo, {}, {'*': 'focus'})

>> It doesn't go as far as allowing arbitrary combinations like adding
>> standout to any display attribute.  You could do that with a list
>> comprehension in the palette definition, similar to the "prefix."+attr
>> case you site above.
> Forcing the user to resort to that seems sort of clumsy. Is adding an 
> attribute option (bold, standout, etc) to AttrSpec feasible? It looks tricky 
> but mostly in display_common.py. That file scares me.

Sure it's feasible, but except for standout it's pretty useless.  Many
terminals don't support bold or underline, so you can't add those and
expect anything to happen.  Also foregrounds and backgrounds can't
safely be changed independently.  You really need to have different
definitions for these display attribute changes and the best place for
that is in the palette.

Should there be a special consideration for standout?  I'm not sure.  It
would make highlighting text in the Edit widget again easier, certainly.
 It's not as flexible as switching to a different palette entry, though.

> Finally, would performance be an issue for large palettes? Currently palette 
> lookups with raw_display.Screen._pal_escape are fast dictionary lookups. Every 
> lookup would now be required to check the entire palette unless it finds an 
> exact match. Maybe this isn't a problem, I'm just speculating at this point.

It would increase lookups to a worst case of (longest chain match)+1.
Still a constant in any situation I can imagine, so I'm not worried.

> I like the idea, it's much simpler to use. As for the implementation, would 
> this involve CompositeCanvas.fill_attr_apply to remember attributes (similar 
> to what I've already done) or something else? I'm not likely to be much help 
> if the canvas changes are lower-level than that, but I can probably handle 
> the screen attribute lookups, at least in raw_display.

Yes, the change would be there and also in the Text markup processing.
Currently the innermost display attribute simply replaces the others.


More information about the Urwid mailing list