##// END OF EJS Templates
color: add support for Windows consoles...
Steve Borho -
r10870:a4944b43 default
parent child Browse files
Show More
@@ -61,6 +61,15 b' Default effects may be overridden from t'
61 resolve.resolved = green bold
61 resolve.resolved = green bold
62
62
63 bookmarks.current = green
63 bookmarks.current = green
64
65 The color extension will try to detect whether to use ANSI codes or
66 Win32 console APIs, unless it is made explicit::
67
68 [color]
69 mode = ansi
70
71 Any value other than 'ansi', 'win32', or 'auto' will disable color.
72
64 '''
73 '''
65
74
66 import os, sys
75 import os, sys
@@ -150,19 +159,43 b' def popbuffer(orig, labeled=False):'
150 return ''.join(style(a, label) for a, label in _buffers.pop())
159 return ''.join(style(a, label) for a, label in _buffers.pop())
151 return ''.join(a for a, label in _buffers.pop())
160 return ''.join(a for a, label in _buffers.pop())
152
161
162 mode = 'ansi'
153 def write(orig, *args, **opts):
163 def write(orig, *args, **opts):
154 label = opts.get('label', '')
164 label = opts.get('label', '')
155 global _buffers
165 global _buffers
156 if _buffers:
166 if _buffers:
157 _buffers[-1].extend([(str(a), label) for a in args])
167 _buffers[-1].extend([(str(a), label) for a in args])
168 elif mode == 'win32':
169 for a in args:
170 win32print(a, orig, **opts)
158 else:
171 else:
159 return orig(*[style(str(a), label) for a in args], **opts)
172 return orig(*[style(str(a), label) for a in args], **opts)
160
173
161 def write_err(orig, *args, **opts):
174 def write_err(orig, *args, **opts):
162 label = opts.get('label', '')
175 label = opts.get('label', '')
163 return orig(*[style(str(a), label) for a in args], **opts)
176 if mode == 'win32':
177 for a in args:
178 win32print(a, orig, **opts)
179 else:
180 return orig(*[style(str(a), label) for a in args], **opts)
164
181
165 def uisetup(ui):
182 def uisetup(ui):
183 global mode
184 mode = ui.config('color', 'mode', 'auto')
185 if mode == 'auto':
186 if os.name == 'nt' and 'TERM' not in os.environ:
187 # looks line a cmd.exe console, use win32 API or nothing
188 mode = w32effects and 'win32' or 'none'
189 else:
190 mode = 'ansi'
191 if mode == 'win32':
192 if w32effects is None:
193 # only warn if color.mode is explicitly set to win32
194 ui.warn(_('win32console not found, please install pywin32\n'))
195 return
196 _effects.update(w32effects)
197 elif mode != 'ansi':
198 return
166 def colorcmd(orig, ui_, opts, cmd, cmdfunc):
199 def colorcmd(orig, ui_, opts, cmd, cmdfunc):
167 if (opts['color'] == 'always' or
200 if (opts['color'] == 'always' or
168 (opts['color'] == 'auto' and (os.environ.get('TERM') != 'dumb'
201 (opts['color'] == 'auto' and (os.environ.get('TERM') != 'dumb'
@@ -180,3 +213,64 b' def uisetup(ui):'
180
213
181 commands.globalopts.append(('', 'color', 'auto',
214 commands.globalopts.append(('', 'color', 'auto',
182 _("when to colorize (always, auto, or never)")))
215 _("when to colorize (always, auto, or never)")))
216
217 try:
218 import re
219 from win32console import *
220
221 # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx
222 w32effects = {
223 'none': 0,
224 'black': 0,
225 'red': FOREGROUND_RED,
226 'green': FOREGROUND_GREEN,
227 'yellow': FOREGROUND_RED | FOREGROUND_GREEN,
228 'blue': FOREGROUND_BLUE,
229 'magenta': FOREGROUND_BLUE | FOREGROUND_RED,
230 'cyan': FOREGROUND_BLUE | FOREGROUND_GREEN,
231 'white': FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
232 'bold': FOREGROUND_INTENSITY,
233 'black_background': 0,
234 'red_background': BACKGROUND_RED,
235 'green_background': BACKGROUND_GREEN,
236 'blue_background': BACKGROUND_BLUE,
237 'cyan_background': BACKGROUND_BLUE | BACKGROUND_GREEN,
238 'bold_background': FOREGROUND_INTENSITY,
239 'underline': COMMON_LVB_UNDERSCORE, # double-byte charsets only
240 'inverse': COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only
241 }
242
243 stdout = GetStdHandle(STD_OUTPUT_HANDLE)
244 origattr = stdout.GetConsoleScreenBufferInfo()['Attributes']
245 ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)', re.MULTILINE | re.DOTALL)
246
247 def win32print(text, orig, **opts):
248 label = opts.get('label', '')
249 attr = 0
250
251 # determine console attributes based on labels
252 for l in label.split():
253 style = _styles.get(l, '')
254 for effect in style.split():
255 attr |= w32effects[effect]
256
257 # hack to ensure regexp finds data
258 if not text.startswith('\033['):
259 text = '\033[m' + text
260
261 # Look for ANSI-like codes embedded in text
262 m = re.match(ansire, text)
263 while m:
264 for sattr in m.group(1).split(';'):
265 if sattr:
266 val = int(sattr)
267 attr = val and attr|val or 0
268 stdout.SetConsoleTextAttribute(attr or origattr)
269 orig(m.group(2), **opts)
270 m = re.match(ansire, m.group(3))
271
272 # Explicity reset original attributes
273 stdout.SetConsoleTextAttribute(origattr)
274
275 except ImportError:
276 w32effects = None
General Comments 0
You need to be logged in to leave comments. Login now