~ntt-pf-lab/nova/monkey_patch_notification

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/twisted/conch/insults/text.py

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- test-case-name: twisted.conch.test.test_text -*-
 
2
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
 
3
# See LICENSE for details.
 
4
 
 
5
"""
 
6
Character attribute manipulation API
 
7
 
 
8
This module provides a domain-specific language (using Python syntax)
 
9
for the creation of text with additional display attributes associated
 
10
with it.  It is intended as an alternative to manually building up
 
11
strings containing ECMA 48 character attribute control codes.  It
 
12
currently supports foreground and background colors (black, red,
 
13
green, yellow, blue, magenta, cyan, and white), intensity selection,
 
14
underlining, blinking and reverse video.  Character set selection
 
15
support is planned.
 
16
 
 
17
Character attributes are specified by using two Python operations:
 
18
attribute lookup and indexing.  For example, the string \"Hello
 
19
world\" with red foreground and all other attributes set to their
 
20
defaults, assuming the name twisted.conch.insults.text.attributes has
 
21
been imported and bound to the name \"A\" (with the statement C{from
 
22
twisted.conch.insults.text import attributes as A}, for example) one
 
23
uses this expression::
 
24
 
 
25
 | A.fg.red[\"Hello world\"]
 
26
 
 
27
Other foreground colors are set by substituting their name for
 
28
\"red\".  To set both a foreground and a background color, this
 
29
expression is used::
 
30
 
 
31
 | A.fg.red[A.bg.green[\"Hello world\"]]
 
32
 
 
33
Note that either A.bg.green can be nested within A.fg.red or vice
 
34
versa.  Also note that multiple items can be nested within a single
 
35
index operation by separating them with commas::
 
36
 
 
37
 | A.bg.green[A.fg.red[\"Hello\"], " ", A.fg.blue[\"world\"]]
 
38
 
 
39
Other character attributes are set in a similar fashion.  To specify a
 
40
blinking version of the previous expression::
 
41
 
 
42
 | A.blink[A.bg.green[A.fg.red[\"Hello\"], " ", A.fg.blue[\"world\"]]]
 
43
 
 
44
C{A.reverseVideo}, C{A.underline}, and C{A.bold} are also valid.
 
45
 
 
46
A third operation is actually supported: unary negation.  This turns
 
47
off an attribute when an enclosing expression would otherwise have
 
48
caused it to be on.  For example::
 
49
 
 
50
 | A.underline[A.fg.red[\"Hello\", -A.underline[\" world\"]]]
 
51
 
 
52
@author: Jp Calderone
 
53
"""
 
54
 
 
55
from twisted.conch.insults import helper, insults
 
56
 
 
57
class _Attribute(object):
 
58
    def __init__(self):
 
59
        self.children = []
 
60
 
 
61
    def __getitem__(self, item):
 
62
        assert isinstance(item, (list, tuple, _Attribute, str))
 
63
        if isinstance(item, (list, tuple)):
 
64
            self.children.extend(item)
 
65
        else:
 
66
            self.children.append(item)
 
67
        return self
 
68
 
 
69
    def serialize(self, write, attrs=None):
 
70
        if attrs is None:
 
71
            attrs = helper.CharacterAttribute()
 
72
        for ch in self.children:
 
73
            if isinstance(ch, _Attribute):
 
74
                ch.serialize(write, attrs.copy())
 
75
            else:
 
76
                write(attrs.toVT102())
 
77
                write(ch)
 
78
 
 
79
class _NormalAttr(_Attribute):
 
80
    def serialize(self, write, attrs):
 
81
        attrs.__init__()
 
82
        super(_NormalAttr, self).serialize(write, attrs)
 
83
 
 
84
class _OtherAttr(_Attribute):
 
85
    def __init__(self, attrname, attrvalue):
 
86
        self.attrname = attrname
 
87
        self.attrvalue = attrvalue
 
88
        self.children = []
 
89
 
 
90
    def __neg__(self):
 
91
        result = _OtherAttr(self.attrname, not self.attrvalue)
 
92
        result.children.extend(self.children)
 
93
        return result
 
94
 
 
95
    def serialize(self, write, attrs):
 
96
        attrs = attrs.wantOne(**{self.attrname: self.attrvalue})
 
97
        super(_OtherAttr, self).serialize(write, attrs)
 
98
 
 
99
class _ColorAttr(_Attribute):
 
100
    def __init__(self, color, ground):
 
101
        self.color = color
 
102
        self.ground = ground
 
103
        self.children = []
 
104
 
 
105
    def serialize(self, write, attrs):
 
106
        attrs = attrs.wantOne(**{self.ground: self.color})
 
107
        super(_ColorAttr, self).serialize(write, attrs)
 
108
 
 
109
class _ForegroundColorAttr(_ColorAttr):
 
110
    def __init__(self, color):
 
111
        super(_ForegroundColorAttr, self).__init__(color, 'foreground')
 
112
 
 
113
class _BackgroundColorAttr(_ColorAttr):
 
114
    def __init__(self, color):
 
115
        super(_BackgroundColorAttr, self).__init__(color, 'background')
 
116
 
 
117
class CharacterAttributes(object):
 
118
    class _ColorAttribute(object):
 
119
        def __init__(self, ground):
 
120
            self.ground = ground
 
121
 
 
122
        attrs = {
 
123
            'black': helper.BLACK,
 
124
            'red': helper.RED,
 
125
            'green': helper.GREEN,
 
126
            'yellow': helper.YELLOW,
 
127
            'blue': helper.BLUE,
 
128
            'magenta': helper.MAGENTA,
 
129
            'cyan': helper.CYAN,
 
130
            'white': helper.WHITE}
 
131
 
 
132
        def __getattr__(self, name):
 
133
            try:
 
134
                return self.ground(self.attrs[name])
 
135
            except KeyError:
 
136
                raise AttributeError(name)
 
137
 
 
138
    fg = _ColorAttribute(_ForegroundColorAttr)
 
139
    bg = _ColorAttribute(_BackgroundColorAttr)
 
140
 
 
141
    attrs = {
 
142
        'bold': insults.BOLD,
 
143
        'blink': insults.BLINK,
 
144
        'underline': insults.UNDERLINE,
 
145
        'reverseVideo': insults.REVERSE_VIDEO}
 
146
 
 
147
    def __getattr__(self, name):
 
148
        if name == 'normal':
 
149
            return _NormalAttr()
 
150
        if name in self.attrs:
 
151
            return _OtherAttr(name, True)
 
152
        raise AttributeError(name)
 
153
 
 
154
def flatten(output, attrs):
 
155
    """Serialize a sequence of characters with attribute information
 
156
 
 
157
    The resulting string can be interpreted by VT102-compatible
 
158
    terminals so that the contained characters are displayed and, for
 
159
    those attributes which the terminal supports, have the attributes
 
160
    specified in the input.
 
161
 
 
162
    For example, if your terminal is VT102 compatible, you might run
 
163
    this for a colorful variation on the \"hello world\" theme::
 
164
 
 
165
     | from twisted.conch.insults.text import flatten, attributes as A
 
166
     | from twisted.conch.insults.helper import CharacterAttribute
 
167
     | print flatten(
 
168
     |     A.normal[A.bold[A.fg.red['He'], A.fg.green['ll'], A.fg.magenta['o'], ' ',
 
169
     |                     A.fg.yellow['Wo'], A.fg.blue['rl'], A.fg.cyan['d!']]],
 
170
     |     CharacterAttribute())
 
171
 
 
172
    @param output: Object returned by accessing attributes of the
 
173
    module-level attributes object.
 
174
 
 
175
    @param attrs: A L{twisted.conch.insults.helper.CharacterAttribute}
 
176
    instance
 
177
 
 
178
    @return: A VT102-friendly string
 
179
    """
 
180
    L = []
 
181
    output.serialize(L.append, attrs)
 
182
    return ''.join(L)
 
183
 
 
184
attributes = CharacterAttributes()
 
185
 
 
186
__all__ = ['attributes', 'flatten']