1#!/usr/bin/env python
2##########################################################################
3#
4# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
5# All Rights Reserved.
6#
7# Permission is hereby granted, free of charge, to any person obtaining a
8# copy of this software and associated documentation files (the
9# "Software"), to deal in the Software without restriction, including
10# without limitation the rights to use, copy, modify, merge, publish,
11# distribute, sub license, and/or sell copies of the Software, and to
12# permit persons to whom the Software is furnished to do so, subject to
13# the following conditions:
14#
15# The above copyright notice and this permission notice (including the
16# next paragraph) shall be included in all copies or substantial portions
17# of the Software.
18#
19# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26#
27##########################################################################
28
29
30import sys
31
32
33class Formatter:
34    '''Plain formatter'''
35
36    def __init__(self, stream):
37        self.stream = stream
38
39    def text(self, text):
40        self.stream.write(text)
41
42    def newline(self):
43        self.text('\n')
44
45    def function(self, name):
46        self.text(name)
47
48    def variable(self, name):
49        self.text(name)
50
51    def literal(self, value):
52        self.text(str(value))
53
54    def address(self, addr):
55        self.text(str(addr))
56
57
58class AnsiFormatter(Formatter):
59    '''Formatter for plain-text files which outputs ANSI escape codes. See
60    http://en.wikipedia.org/wiki/ANSI_escape_code for more information
61    concerning ANSI escape codes.
62    '''
63
64    _csi = '\33['
65
66    _normal = '0m'
67    _bold = '1m'
68    _italic = '3m'
69    _red = '31m'
70    _green = '32m'
71    _blue = '34m'
72
73    def _escape(self, code):
74        self.text(self._csi + code)
75
76    def function(self, name):
77        self._escape(self._bold)
78        Formatter.function(self, name)
79        self._escape(self._normal)
80
81    def variable(self, name):
82        self._escape(self._italic)
83        Formatter.variable(self, name)
84        self._escape(self._normal)
85
86    def literal(self, value):
87        self._escape(self._blue)
88        Formatter.literal(self, value)
89        self._escape(self._normal)
90
91    def address(self, value):
92        self._escape(self._green)
93        Formatter.address(self, value)
94        self._escape(self._normal)
95
96
97class WindowsConsoleFormatter(Formatter):
98    '''Formatter for the Windows Console. See
99    http://code.activestate.com/recipes/496901/ for more information.
100    '''
101
102    STD_INPUT_HANDLE  = -10
103    STD_OUTPUT_HANDLE = -11
104    STD_ERROR_HANDLE  = -12
105
106    FOREGROUND_BLUE      = 0x01
107    FOREGROUND_GREEN     = 0x02
108    FOREGROUND_RED       = 0x04
109    FOREGROUND_INTENSITY = 0x08
110    BACKGROUND_BLUE      = 0x10
111    BACKGROUND_GREEN     = 0x20
112    BACKGROUND_RED       = 0x40
113    BACKGROUND_INTENSITY = 0x80
114
115    _normal = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
116    _bold = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY
117    _italic = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
118    _red = FOREGROUND_RED | FOREGROUND_INTENSITY
119    _green = FOREGROUND_GREEN | FOREGROUND_INTENSITY
120    _blue = FOREGROUND_BLUE | FOREGROUND_INTENSITY
121
122    def __init__(self, stream):
123        Formatter.__init__(self, stream)
124
125        if stream is sys.stdin:
126            nStdHandle = self.STD_INPUT_HANDLE
127        elif stream is sys.stdout:
128            nStdHandle = self.STD_OUTPUT_HANDLE
129        elif stream is sys.stderr:
130            nStdHandle = self.STD_ERROR_HANDLE
131        else:
132            nStdHandle = None
133
134        if nStdHandle:
135            import ctypes
136            self.handle = ctypes.windll.kernel32.GetStdHandle(nStdHandle)
137        else:
138            self.handle = None
139
140    def _attribute(self, attr):
141        if self.handle:
142            import ctypes
143            ctypes.windll.kernel32.SetConsoleTextAttribute(self.handle, attr)
144
145    def function(self, name):
146        self._attribute(self._bold)
147        Formatter.function(self, name)
148        self._attribute(self._normal)
149
150    def variable(self, name):
151        self._attribute(self._italic)
152        Formatter.variable(self, name)
153        self._attribute(self._normal)
154
155    def literal(self, value):
156        self._attribute(self._blue)
157        Formatter.literal(self, value)
158        self._attribute(self._normal)
159
160    def address(self, value):
161        self._attribute(self._green)
162        Formatter.address(self, value)
163        self._attribute(self._normal)
164
165
166def DefaultFormatter(stream):
167    if sys.platform in ('linux2', 'cygwin'):
168        return AnsiFormatter(stream)
169    elif sys.platform in ('win32',):
170        return WindowsConsoleFormatter(stream)
171    else:
172        return Formatter(stream)
173
174