]> git.cworth.org Git - apitrace/blob - scripts/highlight.py
Handle less not existing.
[apitrace] / scripts / highlight.py
1 ##########################################################################
2 #
3 # Copyright 2011-2012 Jose Fonseca
4 # Copyright 2008-2009 VMware, Inc.
5 # All Rights Reserved.
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to deal
9 # in the Software without restriction, including without limitation the rights
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 # copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
13 #
14 # The above copyright notice and this permission notice shall be included in
15 # all copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 # THE SOFTWARE.
24 #
25 ##########################################################################/
26
27
28 import platform
29 import subprocess
30 import sys
31
32
33 class PlainHighlighter:
34     '''Plain formatter'''
35
36     black = None
37     red = None
38     green = None
39     yellow = None
40     blue = None
41     magenta = None
42     cyan = None
43     white = None
44
45     def __init__(self, stream = sys.stdout):
46         self.stream = stream
47
48     def write(self, text):
49         self.stream.write(text)
50
51     def flush(self):
52         self.stream.flush()
53
54     def normal(self):
55         pass
56
57     def color(self, color):
58         pass
59
60     def bold(self, enable):
61         pass
62
63     def italic(self):
64         pass
65
66
67 class AnsiHighlighter(PlainHighlighter):
68     '''Highlighter for plain-text files which outputs ANSI escape codes. See
69     http://en.wikipedia.org/wiki/ANSI_escape_code for more information
70     concerning ANSI escape codes.
71     '''
72
73     _csi = '\33['
74
75     _normal = '0m'
76     _italic = '3m'
77
78     black = 0
79     red = 1
80     green = 2
81     yellow = 3
82     blue = 4
83     magenta = 5
84     cyan = 6
85     white = 7
86
87     def __init__(self, stream = sys.stdout):
88         PlainHighlighter.__init__(self, stream)
89
90     def _escape(self, code):
91         self.stream.write(self._csi + code)
92
93     def normal(self):
94         self._escape(self._normal)
95
96     def color(self, color):
97         self._escape(str(30 + color) + 'm')
98
99     def bold(self, enable = True):
100         if enable:
101             self._escape('1m')
102         else:
103             self._escape('21m')
104
105     def italic(self):
106         self._escape(self._italic)
107
108
109 class WindowsConsoleHighlighter(PlainHighlighter):
110     '''Highlighter for the Windows Console. See 
111     http://code.activestate.com/recipes/496901/ for more information.
112     '''
113
114     INVALID_HANDLE_VALUE = -1
115     STD_INPUT_HANDLE  = -10
116     STD_OUTPUT_HANDLE = -11
117     STD_ERROR_HANDLE  = -12
118
119     FOREGROUND_BLUE      = 0x01
120     FOREGROUND_GREEN     = 0x02
121     FOREGROUND_RED       = 0x04
122     FOREGROUND_INTENSITY = 0x08
123     BACKGROUND_BLUE      = 0x10
124     BACKGROUND_GREEN     = 0x20
125     BACKGROUND_RED       = 0x40
126     BACKGROUND_INTENSITY = 0x80
127
128     COMMON_LVB_LEADING_BYTE = 0x0100
129     COMMON_LVB_TRAILING_BYTE = 0x0200
130     COMMON_LVB_GRID_HORIZONTAL = 0x0400
131     COMMON_LVB_GRID_LVERTICAL = 0x0800
132     COMMON_LVB_GRID_RVERTICAL = 0x1000
133     COMMON_LVB_REVERSE_VIDEO = 0x4000
134     COMMON_LVB_UNDERSCORE = 0x8000
135
136     _normal = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
137     _italic = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
138
139     black   = 0
140     red     =                                      FOREGROUND_RED
141     green   =                   FOREGROUND_GREEN                 
142     blue    = FOREGROUND_BLUE                                    
143     white   = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
144
145     def __init__(self, stream = sys.stdout):
146         PlainHighlighter.__init__(self, stream)
147
148         if stream is sys.stdin:
149             nStdHandle = self.STD_INPUT_HANDLE
150         elif stream is sys.stdout:
151             nStdHandle = self.STD_OUTPUT_HANDLE
152         elif stream is sys.stderr:
153             nStdHandle = self.STD_ERROR_HANDLE
154         else:
155             nStdHandle = None
156
157         if nStdHandle is not None:
158             import ctypes
159             self._handle = ctypes.windll.kernel32.GetStdHandle(nStdHandle)
160         else:
161             self._handle = self.INVALID_HANDLE_VALUE
162
163         self._attribute = self.white
164
165     def _setAttribute(self, attr):
166         if self._handle != self.INVALID_HANDLE_VALUE:
167             import ctypes
168             ctypes.windll.kernel32.SetConsoleTextAttribute(self._handle, attr)
169         self._attribute = attr
170
171     def normal(self):
172         self._setAttribute(self._normal)
173
174     def color(self, color):
175         intensity = self._attribute & self.FOREGROUND_INTENSITY
176         self._setAttribute(color | intensity)
177
178     def bold(self, enable):
179         if enable:
180             attribute = self._attribute | self.FOREGROUND_INTENSITY
181         else:
182             attribute = self._attribute & ~self.FOREGROUND_INTENSITY
183         self._setAttribute(attribute)
184
185     def italic(self):
186         pass
187
188
189 if platform.system() == 'Windows':
190     ColorHighlighter = WindowsConsoleHighlighter
191 else:
192     ColorHighlighter = AnsiHighlighter
193
194
195 def AutoHighlighter(stream = sys.stdout):
196     if stream.isatty():
197         return ColorHighlighter(stream)
198     else:
199         return PlainHighlighter(stream)
200
201
202 class _LessHighlighter(AnsiHighlighter):
203
204     def __init__(self, less):
205         AnsiHighlighter.__init__(self, less.stdin)
206         self.less = less
207
208     def __del__(self):
209         self.less.stdin.close()
210         self.less.wait()
211
212
213 def LessHighlighter():
214     if sys.stdout.isatty():
215         try:
216             less = subprocess.Popen(
217                 args = ['less', '-FRXn'],
218                 stdin = subprocess.PIPE
219             )
220         except OSError:
221             return ColorHighlighter()
222         else:
223             return _LessHighlighter(less)
224     return PlainHighlighter(sys.stdout)
225