root/palette_test.py

Revision 277:1de61bc52bc6, 9.3 KB (checked in by Ian Ward, 10 months ago)

add licence and docstring for palette_test example

  • Property exe set to *
Line 
1#!/usr/bin/python
2#
3# Urwid Palette Test.  Showing off highcolor support
4#    Copyright (C) 2004-2009  Ian Ward
5#
6#    This library is free software; you can redistribute it and/or
7#    modify it under the terms of the GNU Lesser General Public
8#    License as published by the Free Software Foundation; either
9#    version 2.1 of the License, or (at your option) any later version.
10#
11#    This library is distributed in the hope that it will be useful,
12#    but WITHOUT ANY WARRANTY; without even the implied warranty of
13#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14#    Lesser General Public License for more details.
15#
16#    You should have received a copy of the GNU Lesser General Public
17#    License along with this library; if not, write to the Free Software
18#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19#
20# Urwid web site: http://excess.org/urwid/
21
22"""
23Palette test.  Shows the available foreground and background settings
24in monochrome, 16 color, 88 color and 256 color modes.
25"""
26
27import re
28import sys
29
30import urwid
31import urwid.raw_display
32
33CHART_256 = """
34brown__   dark_red_   dark_magenta_   dark_blue_   dark_cyan_   dark_green_
35yellow_   light_red   light_magenta   light_blue   light_cyan   light_green
36
37              #00f#06f#08f#0af#0df#0ff        black_______    dark_gray___   
38            #60f#00d#06d#08d#0ad#0dd#0fd        light_gray__    white_______
39          #80f#60d#00a#06a#08a#0aa#0da#0fa       
40        #a0f#80d#60a#008#068#088#0a8#0d8#0f8       
41      #d0f#a0d#80d#608#006#066#086#0a6#0d6#0f6
42    #f0f#d0d#a0a#808#606#000#060#080#0a0#0d0#0f0#0f6#0f8#0fa#0fd#0ff
43      #f0d#d0a#a08#806#600#660#680#6a0#6d0#6f0#6f6#6f8#6fa#6fd#6ff#0df
44        #f0a#d08#a06#800#860#880#8a0#8d0#8f0#8f6#8f8#8fa#8fd#8ff#6df#0af
45          #f08#d06#a00#a60#a80#aa0#ad0#af0#af6#af8#afa#afd#aff#8df#6af#08f
46            #f06#d00#d60#d80#da0#dd0#df0#df6#df8#dfa#dfd#dff#adf#8af#68f#06f
47              #f00#f60#f80#fa0#fd0#ff0#ff6#ff8#ffa#ffd#fff#ddf#aaf#88f#66f#00f
48                                    #fd0#fd6#fd8#fda#fdd#fdf#daf#a8f#86f#60f
49      #66d#68d#6ad#6dd                #fa0#fa6#fa8#faa#fad#faf#d8f#a6f#80f
50    #86d#66a#68a#6aa#6da                #f80#f86#f88#f8a#f8d#f8f#d6f#a0f
51  #a6d#86a#668#688#6a8#6d8                #f60#f66#f68#f6a#f6d#f6f#d0f
52#d6d#a6a#868#666#686#6a6#6d6#6d8#6da#6dd    #f00#f06#f08#f0a#f0d#f0f
53  #d6a#a68#866#886#8a6#8d6#8d8#8da#8dd#6ad       
54    #d68#a66#a86#aa6#ad6#ad8#ada#add#8ad#68d   
55      #d66#d86#da6#dd6#dd8#dda#ddd#aad#88d#66d        g78_g82_g85_g89_g93_g100 
56                    #da6#da8#daa#dad#a8d#86d        g52_g58_g62_g66_g70_g74_
57      #88a#8aa        #d86#d88#d8a#d8d#a6d        g27_g31_g35_g38_g42_g46_g50_
58    #a8a#888#8a8#8aa    #d66#d68#d6a#d6d        g0__g3__g7__g11_g15_g19_g23_
59      #a88#aa8#aaa#88a                       
60            #a88#a8a
61"""                   
62
63CHART_88 = """
64brown__   dark_red_   dark_magenta_   dark_blue_   dark_cyan_   dark_green_
65yellow_   light_red   light_magenta   light_blue   light_cyan   light_green
66
67      #00f#08f#0cf#0ff            black_______    dark_gray___             
68    #80f#00c#08c#0cc#0fc            light_gray__    white_______           
69  #c0f#80c#008#088#0c8#0f8
70#f0f#c0c#808#000#080#0c0#0f0#0f8#0fc#0ff            #88c#8cc       
71  #f0c#c08#800#880#8c0#8f0#8f8#8fc#8ff#0cf        #c8c#888#8c8#8cc   
72    #f08#c00#c80#cc0#cf0#cf8#cfc#cff#8cf#08f        #c88#cc8#ccc#88c
73      #f00#f80#fc0#ff0#ff8#ffc#fff#ccf#88f#00f            #c88#c8c       
74                    #fc0#fc8#fcc#fcf#c8f#80f   
75                      #f80#f88#f8c#f8f#c0f        g62_g74_g82_g89_g100 
76                        #f00#f08#f0c#f0f        g0__g19_g35_g46_g52
77"""
78
79CHART_16 = """
80brown__   dark_red_   dark_magenta_   dark_blue_   dark_cyan_   dark_green_
81yellow_   light_red   light_magenta   light_blue   light_cyan   light_green
82
83black_______    dark_gray___    light_gray__    white_______           
84"""
85
86ATTR_RE = re.compile("(?P<whitespace>[ \n]*)(?P<entry>[^ \n]+)")
87SHORT_ATTR = 4 # length of short high-colour descriptions which may
88# be packed one after the next
89
90def parse_chart(chart, convert):
91    """
92    Convert string chart into text markup with the correct attributes.
93
94    chart -- palette chart as a string
95    convert -- function that converts a single palette entry to an
96        (attr, text) tuple, or None if no match is found
97    """
98    out = []
99    for match in re.finditer(ATTR_RE, chart):
100        if match.group('whitespace'):
101            out.append(match.group('whitespace'))
102        entry = match.group('entry')
103        entry = entry.replace("_", " ")
104        while entry:
105            # try the first four characters
106            attrtext = convert(entry[:SHORT_ATTR])
107            if attrtext:
108                elen = SHORT_ATTR
109                entry = entry[SHORT_ATTR:].strip()
110            else: # try the whole thing
111                attrtext = convert(entry.strip())
112                assert attrtext, "Invalid palette entry: %r" % entry
113                elen = len(entry)
114                entry = ""
115            attr, text = attrtext
116            out.append((attr, text.ljust(elen)))
117    return out
118           
119def foreground_chart(chart, background, colors):
120    """
121    Create text markup for a foreground colour chart
122
123    chart -- palette chart as string
124    background -- colour to use for background of chart
125    colors -- number of colors (88 or 256)
126    """
127    def convert_foreground(entry):
128        try:
129            attr = urwid.AttrSpec(entry, background, colors)
130        except urwid.AttrSpecError:
131            return None
132        return attr, entry
133    return parse_chart(chart, convert_foreground)
134
135def background_chart(chart, foreground, colors):
136    """
137    Create text markup for a background colour chart
138
139    chart -- palette chart as string
140    foreground -- colour to use for foreground of chart
141    colors -- number of colors (88 or 256)
142
143    This will remap 8 <= colour < 16 to high-colour versions
144    in the hopes of greater compatibility
145    """
146    def convert_background(entry):
147        try:
148            attr = urwid.AttrSpec(foreground, entry, colors)
149        except urwid.AttrSpecError:
150            return None
151        # fix 8 <= colour < 16
152        if colors > 16 and attr.background_basic and \
153            attr.background_number >= 8:
154            # use high-colour with same number
155            entry = 'h%d'%attr.background_number
156            attr = urwid.AttrSpec(foreground, entry, colors)
157        return attr, entry
158    return parse_chart(chart, convert_background)
159
160
161def main():
162    palette = [
163        ('header', 'black,underline', 'light gray', 'standout,underline',
164            'black,underline', '#88a'),
165        ('panel', 'light gray', 'dark blue', '',
166            '#ffd', '#00a'),
167        ('focus', 'light gray', 'dark cyan', 'standout',
168            '#ff8', '#806'),
169        ]
170
171    screen = urwid.raw_display.Screen()
172    screen.register_palette(palette)
173
174    lb = urwid.SimpleListWalker([])
175    chart_offset = None  # offset of chart in lb list
176
177    mode_radio_buttons = []
178    chart_radio_buttons = []
179
180    def fcs(widget):
181        # wrap widgets that can take focus
182        return urwid.AttrMap(widget, None, 'focus')
183
184    def set_mode(colors, is_foreground_chart):
185        # set terminal mode and redraw chart
186        screen.set_terminal_properties(colors)
187        screen.reset_default_terminal_palette()
188
189        chart_fn = (background_chart, foreground_chart)[is_foreground_chart]
190        if colors == 1:
191            lb[chart_offset] = urwid.Divider()
192        else:
193            chart = {16: CHART_16, 88: CHART_88, 256: CHART_256}[colors]
194            txt = chart_fn(chart, 'default', colors)
195            lb[chart_offset] = urwid.Text(txt, wrap='clip')
196
197    def on_mode_change(rb, state, colors):
198        # if this radio button is checked
199        if state:
200            is_foreground_chart = chart_radio_buttons[0].state
201            set_mode(colors, is_foreground_chart)
202           
203    def mode_rb(text, colors, state=False):
204        # mode radio buttons
205        rb = urwid.RadioButton(mode_radio_buttons, text, state)
206        urwid.connect_signal(rb, 'change', on_mode_change, colors)
207        return fcs(rb)
208
209    def on_chart_change(rb, state):
210        # handle foreground check box state change
211        set_mode(screen.colors, state)
212       
213    def click_exit(button):
214        raise urwid.ExitMainLoop()
215   
216    lb.extend([
217        urwid.AttrMap(urwid.Text("Urwid Palette Test"), 'header'),
218        urwid.AttrMap(urwid.Columns([
219            urwid.Pile([
220                mode_rb("Monochrome", 1),
221                mode_rb("16-Color", 16, True),
222                mode_rb("88-Color", 88),
223                mode_rb("256-Color", 256),]),
224            urwid.Pile([
225                fcs(urwid.RadioButton(chart_radio_buttons,
226                    "Foreground Colors", True, on_chart_change)),
227                fcs(urwid.RadioButton(chart_radio_buttons,
228                    "Background Colors")),
229                urwid.Divider(),
230                fcs(urwid.Button("Exit", click_exit)),
231                ]),
232            ]),'panel')
233        ])
234
235    chart_offset = len(lb)
236    lb.extend([
237        urwid.Divider() # placeholder for the chart
238        ])
239
240    set_mode(16, True) # displays the chart
241   
242    def unhandled_input(key):
243        if key in ('Q','q','esc'):
244            raise urwid.ExitMainLoop()
245
246    urwid.MainLoop(urwid.ListBox(lb), screen=screen,
247        unhandled_input=unhandled_input).run()
248
249if __name__ == "__main__":
250    main()
251
Note: See TracBrowser for help on using the browser.