##// END OF EJS Templates
color: minor simplification of some terminfo setup code...
Pierre-Yves David -
r31069:cf2bc379 default
parent child Browse files
Show More
@@ -1,434 +1,435
1 # color.py color output for Mercurial commands
1 # color.py color output for Mercurial commands
2 #
2 #
3 # Copyright (C) 2007 Kevin Christen <kevin.christen@gmail.com>
3 # Copyright (C) 2007 Kevin Christen <kevin.christen@gmail.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 '''colorize output from some commands
8 '''colorize output from some commands
9
9
10 The color extension colorizes output from several Mercurial commands.
10 The color extension colorizes output from several Mercurial commands.
11 For example, the diff command shows additions in green and deletions
11 For example, the diff command shows additions in green and deletions
12 in red, while the status command shows modified files in magenta. Many
12 in red, while the status command shows modified files in magenta. Many
13 other commands have analogous colors. It is possible to customize
13 other commands have analogous colors. It is possible to customize
14 these colors.
14 these colors.
15
15
16 Effects
16 Effects
17 -------
17 -------
18
18
19 Other effects in addition to color, like bold and underlined text, are
19 Other effects in addition to color, like bold and underlined text, are
20 also available. By default, the terminfo database is used to find the
20 also available. By default, the terminfo database is used to find the
21 terminal codes used to change color and effect. If terminfo is not
21 terminal codes used to change color and effect. If terminfo is not
22 available, then effects are rendered with the ECMA-48 SGR control
22 available, then effects are rendered with the ECMA-48 SGR control
23 function (aka ANSI escape codes).
23 function (aka ANSI escape codes).
24
24
25 The available effects in terminfo mode are 'blink', 'bold', 'dim',
25 The available effects in terminfo mode are 'blink', 'bold', 'dim',
26 'inverse', 'invisible', 'italic', 'standout', and 'underline'; in
26 'inverse', 'invisible', 'italic', 'standout', and 'underline'; in
27 ECMA-48 mode, the options are 'bold', 'inverse', 'italic', and
27 ECMA-48 mode, the options are 'bold', 'inverse', 'italic', and
28 'underline'. How each is rendered depends on the terminal emulator.
28 'underline'. How each is rendered depends on the terminal emulator.
29 Some may not be available for a given terminal type, and will be
29 Some may not be available for a given terminal type, and will be
30 silently ignored.
30 silently ignored.
31
31
32 If the terminfo entry for your terminal is missing codes for an effect
32 If the terminfo entry for your terminal is missing codes for an effect
33 or has the wrong codes, you can add or override those codes in your
33 or has the wrong codes, you can add or override those codes in your
34 configuration::
34 configuration::
35
35
36 [color]
36 [color]
37 terminfo.dim = \E[2m
37 terminfo.dim = \E[2m
38
38
39 where '\E' is substituted with an escape character.
39 where '\E' is substituted with an escape character.
40
40
41 Labels
41 Labels
42 ------
42 ------
43
43
44 Text receives color effects depending on the labels that it has. Many
44 Text receives color effects depending on the labels that it has. Many
45 default Mercurial commands emit labelled text. You can also define
45 default Mercurial commands emit labelled text. You can also define
46 your own labels in templates using the label function, see :hg:`help
46 your own labels in templates using the label function, see :hg:`help
47 templates`. A single portion of text may have more than one label. In
47 templates`. A single portion of text may have more than one label. In
48 that case, effects given to the last label will override any other
48 that case, effects given to the last label will override any other
49 effects. This includes the special "none" effect, which nullifies
49 effects. This includes the special "none" effect, which nullifies
50 other effects.
50 other effects.
51
51
52 Labels are normally invisible. In order to see these labels and their
52 Labels are normally invisible. In order to see these labels and their
53 position in the text, use the global --color=debug option. The same
53 position in the text, use the global --color=debug option. The same
54 anchor text may be associated to multiple labels, e.g.
54 anchor text may be associated to multiple labels, e.g.
55
55
56 [log.changeset changeset.secret|changeset: 22611:6f0a53c8f587]
56 [log.changeset changeset.secret|changeset: 22611:6f0a53c8f587]
57
57
58 The following are the default effects for some default labels. Default
58 The following are the default effects for some default labels. Default
59 effects may be overridden from your configuration file::
59 effects may be overridden from your configuration file::
60
60
61 [color]
61 [color]
62 status.modified = blue bold underline red_background
62 status.modified = blue bold underline red_background
63 status.added = green bold
63 status.added = green bold
64 status.removed = red bold blue_background
64 status.removed = red bold blue_background
65 status.deleted = cyan bold underline
65 status.deleted = cyan bold underline
66 status.unknown = magenta bold underline
66 status.unknown = magenta bold underline
67 status.ignored = black bold
67 status.ignored = black bold
68
68
69 # 'none' turns off all effects
69 # 'none' turns off all effects
70 status.clean = none
70 status.clean = none
71 status.copied = none
71 status.copied = none
72
72
73 qseries.applied = blue bold underline
73 qseries.applied = blue bold underline
74 qseries.unapplied = black bold
74 qseries.unapplied = black bold
75 qseries.missing = red bold
75 qseries.missing = red bold
76
76
77 diff.diffline = bold
77 diff.diffline = bold
78 diff.extended = cyan bold
78 diff.extended = cyan bold
79 diff.file_a = red bold
79 diff.file_a = red bold
80 diff.file_b = green bold
80 diff.file_b = green bold
81 diff.hunk = magenta
81 diff.hunk = magenta
82 diff.deleted = red
82 diff.deleted = red
83 diff.inserted = green
83 diff.inserted = green
84 diff.changed = white
84 diff.changed = white
85 diff.tab =
85 diff.tab =
86 diff.trailingwhitespace = bold red_background
86 diff.trailingwhitespace = bold red_background
87
87
88 # Blank so it inherits the style of the surrounding label
88 # Blank so it inherits the style of the surrounding label
89 changeset.public =
89 changeset.public =
90 changeset.draft =
90 changeset.draft =
91 changeset.secret =
91 changeset.secret =
92
92
93 resolve.unresolved = red bold
93 resolve.unresolved = red bold
94 resolve.resolved = green bold
94 resolve.resolved = green bold
95
95
96 bookmarks.active = green
96 bookmarks.active = green
97
97
98 branches.active = none
98 branches.active = none
99 branches.closed = black bold
99 branches.closed = black bold
100 branches.current = green
100 branches.current = green
101 branches.inactive = none
101 branches.inactive = none
102
102
103 tags.normal = green
103 tags.normal = green
104 tags.local = black bold
104 tags.local = black bold
105
105
106 rebase.rebased = blue
106 rebase.rebased = blue
107 rebase.remaining = red bold
107 rebase.remaining = red bold
108
108
109 shelve.age = cyan
109 shelve.age = cyan
110 shelve.newest = green bold
110 shelve.newest = green bold
111 shelve.name = blue bold
111 shelve.name = blue bold
112
112
113 histedit.remaining = red bold
113 histedit.remaining = red bold
114
114
115 Custom colors
115 Custom colors
116 -------------
116 -------------
117
117
118 Because there are only eight standard colors, this module allows you
118 Because there are only eight standard colors, this module allows you
119 to define color names for other color slots which might be available
119 to define color names for other color slots which might be available
120 for your terminal type, assuming terminfo mode. For instance::
120 for your terminal type, assuming terminfo mode. For instance::
121
121
122 color.brightblue = 12
122 color.brightblue = 12
123 color.pink = 207
123 color.pink = 207
124 color.orange = 202
124 color.orange = 202
125
125
126 to set 'brightblue' to color slot 12 (useful for 16 color terminals
126 to set 'brightblue' to color slot 12 (useful for 16 color terminals
127 that have brighter colors defined in the upper eight) and, 'pink' and
127 that have brighter colors defined in the upper eight) and, 'pink' and
128 'orange' to colors in 256-color xterm's default color cube. These
128 'orange' to colors in 256-color xterm's default color cube. These
129 defined colors may then be used as any of the pre-defined eight,
129 defined colors may then be used as any of the pre-defined eight,
130 including appending '_background' to set the background to that color.
130 including appending '_background' to set the background to that color.
131
131
132 Modes
132 Modes
133 -----
133 -----
134
134
135 By default, the color extension will use ANSI mode (or win32 mode on
135 By default, the color extension will use ANSI mode (or win32 mode on
136 Windows) if it detects a terminal. To override auto mode (to enable
136 Windows) if it detects a terminal. To override auto mode (to enable
137 terminfo mode, for example), set the following configuration option::
137 terminfo mode, for example), set the following configuration option::
138
138
139 [color]
139 [color]
140 mode = terminfo
140 mode = terminfo
141
141
142 Any value other than 'ansi', 'win32', 'terminfo', or 'auto' will
142 Any value other than 'ansi', 'win32', 'terminfo', or 'auto' will
143 disable color.
143 disable color.
144
144
145 Note that on some systems, terminfo mode may cause problems when using
145 Note that on some systems, terminfo mode may cause problems when using
146 color with the pager extension and less -R. less with the -R option
146 color with the pager extension and less -R. less with the -R option
147 will only display ECMA-48 color codes, and terminfo mode may sometimes
147 will only display ECMA-48 color codes, and terminfo mode may sometimes
148 emit codes that less doesn't understand. You can work around this by
148 emit codes that less doesn't understand. You can work around this by
149 either using ansi mode (or auto mode), or by using less -r (which will
149 either using ansi mode (or auto mode), or by using less -r (which will
150 pass through all terminal control codes, not just color control
150 pass through all terminal control codes, not just color control
151 codes).
151 codes).
152
152
153 On some systems (such as MSYS in Windows), the terminal may support
153 On some systems (such as MSYS in Windows), the terminal may support
154 a different color mode than the pager (activated via the "pager"
154 a different color mode than the pager (activated via the "pager"
155 extension). It is possible to define separate modes depending on whether
155 extension). It is possible to define separate modes depending on whether
156 the pager is active::
156 the pager is active::
157
157
158 [color]
158 [color]
159 mode = auto
159 mode = auto
160 pagermode = ansi
160 pagermode = ansi
161
161
162 If ``pagermode`` is not defined, the ``mode`` will be used.
162 If ``pagermode`` is not defined, the ``mode`` will be used.
163 '''
163 '''
164
164
165 from __future__ import absolute_import
165 from __future__ import absolute_import
166
166
167 try:
167 try:
168 import curses
168 import curses
169 curses.COLOR_BLACK # force import
169 curses.COLOR_BLACK # force import
170 except ImportError:
170 except ImportError:
171 curses = None
171 curses = None
172
172
173 from mercurial.i18n import _
173 from mercurial.i18n import _
174 from mercurial import (
174 from mercurial import (
175 cmdutil,
175 cmdutil,
176 color,
176 color,
177 commands,
177 commands,
178 dispatch,
178 dispatch,
179 encoding,
179 encoding,
180 extensions,
180 extensions,
181 pycompat,
181 pycompat,
182 subrepo,
182 subrepo,
183 ui as uimod,
183 ui as uimod,
184 util,
184 util,
185 )
185 )
186
186
187 cmdtable = {}
187 cmdtable = {}
188 command = cmdutil.command(cmdtable)
188 command = cmdutil.command(cmdtable)
189 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
189 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
190 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
190 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
191 # be specifying the version(s) of Mercurial they are tested with, or
191 # be specifying the version(s) of Mercurial they are tested with, or
192 # leave the attribute unspecified.
192 # leave the attribute unspecified.
193 testedwith = 'ships-with-hg-core'
193 testedwith = 'ships-with-hg-core'
194
194
195 def _terminfosetup(ui, mode):
195 def _terminfosetup(ui, mode):
196 '''Initialize terminfo data and the terminal if we're in terminfo mode.'''
196 '''Initialize terminfo data and the terminal if we're in terminfo mode.'''
197
197
198 # If we failed to load curses, we go ahead and return.
198 # If we failed to load curses, we go ahead and return.
199 if curses is None:
199 if curses is None:
200 return
200 return
201 # Otherwise, see what the config file says.
201 # Otherwise, see what the config file says.
202 if mode not in ('auto', 'terminfo'):
202 if mode not in ('auto', 'terminfo'):
203 return
203 return
204
204
205 color._terminfo_params.update((key[6:], (False, int(val), ''))
205 for key, val in ui.configitems('color'):
206 for key, val in ui.configitems('color')
206 if key.startswith('color.'):
207 if key.startswith('color.'))
207 newval = (False, int(val), '')
208 color._terminfo_params.update((key[9:],
208 color._terminfo_params[key[6:]] = newval
209 (True, '', val.replace('\\E', '\x1b')))
210 for key, val in ui.configitems('color')
211 if key.startswith('terminfo.'))
212
209
210 for key, val in ui.configitems('color'):
211 if key.startswith('terminfo.'):
212 newval = (True, '', val.replace('\\E', '\x1b'))
213 color._terminfo_params[key[9:]] = newval
213 try:
214 try:
214 curses.setupterm()
215 curses.setupterm()
215 except curses.error as e:
216 except curses.error as e:
216 color._terminfo_params.clear()
217 color._terminfo_params.clear()
217 return
218 return
218
219
219 for key, (b, e, c) in color._terminfo_params.items():
220 for key, (b, e, c) in color._terminfo_params.items():
220 if not b:
221 if not b:
221 continue
222 continue
222 if not c and not curses.tigetstr(e):
223 if not c and not curses.tigetstr(e):
223 # Most terminals don't support dim, invis, etc, so don't be
224 # Most terminals don't support dim, invis, etc, so don't be
224 # noisy and use ui.debug().
225 # noisy and use ui.debug().
225 ui.debug("no terminfo entry for %s\n" % e)
226 ui.debug("no terminfo entry for %s\n" % e)
226 del color._terminfo_params[key]
227 del color._terminfo_params[key]
227 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'):
228 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'):
228 # Only warn about missing terminfo entries if we explicitly asked for
229 # Only warn about missing terminfo entries if we explicitly asked for
229 # terminfo mode.
230 # terminfo mode.
230 if mode == "terminfo":
231 if mode == "terminfo":
231 ui.warn(_("no terminfo entry for setab/setaf: reverting to "
232 ui.warn(_("no terminfo entry for setab/setaf: reverting to "
232 "ECMA-48 color\n"))
233 "ECMA-48 color\n"))
233 color._terminfo_params.clear()
234 color._terminfo_params.clear()
234
235
235 def _modesetup(ui, coloropt):
236 def _modesetup(ui, coloropt):
236 if coloropt == 'debug':
237 if coloropt == 'debug':
237 return 'debug'
238 return 'debug'
238
239
239 auto = (coloropt == 'auto')
240 auto = (coloropt == 'auto')
240 always = not auto and util.parsebool(coloropt)
241 always = not auto and util.parsebool(coloropt)
241 if not always and not auto:
242 if not always and not auto:
242 return None
243 return None
243
244
244 formatted = (always or (encoding.environ.get('TERM') != 'dumb'
245 formatted = (always or (encoding.environ.get('TERM') != 'dumb'
245 and ui.formatted()))
246 and ui.formatted()))
246
247
247 mode = ui.config('color', 'mode', 'auto')
248 mode = ui.config('color', 'mode', 'auto')
248
249
249 # If pager is active, color.pagermode overrides color.mode.
250 # If pager is active, color.pagermode overrides color.mode.
250 if getattr(ui, 'pageractive', False):
251 if getattr(ui, 'pageractive', False):
251 mode = ui.config('color', 'pagermode', mode)
252 mode = ui.config('color', 'pagermode', mode)
252
253
253 realmode = mode
254 realmode = mode
254 if mode == 'auto':
255 if mode == 'auto':
255 if pycompat.osname == 'nt':
256 if pycompat.osname == 'nt':
256 term = encoding.environ.get('TERM')
257 term = encoding.environ.get('TERM')
257 # TERM won't be defined in a vanilla cmd.exe environment.
258 # TERM won't be defined in a vanilla cmd.exe environment.
258
259
259 # UNIX-like environments on Windows such as Cygwin and MSYS will
260 # UNIX-like environments on Windows such as Cygwin and MSYS will
260 # set TERM. They appear to make a best effort attempt at setting it
261 # set TERM. They appear to make a best effort attempt at setting it
261 # to something appropriate. However, not all environments with TERM
262 # to something appropriate. However, not all environments with TERM
262 # defined support ANSI. Since "ansi" could result in terminal
263 # defined support ANSI. Since "ansi" could result in terminal
263 # gibberish, we error on the side of selecting "win32". However, if
264 # gibberish, we error on the side of selecting "win32". However, if
264 # w32effects is not defined, we almost certainly don't support
265 # w32effects is not defined, we almost certainly don't support
265 # "win32", so don't even try.
266 # "win32", so don't even try.
266 if (term and 'xterm' in term) or not color.w32effects:
267 if (term and 'xterm' in term) or not color.w32effects:
267 realmode = 'ansi'
268 realmode = 'ansi'
268 else:
269 else:
269 realmode = 'win32'
270 realmode = 'win32'
270 else:
271 else:
271 realmode = 'ansi'
272 realmode = 'ansi'
272
273
273 def modewarn():
274 def modewarn():
274 # only warn if color.mode was explicitly set and we're in
275 # only warn if color.mode was explicitly set and we're in
275 # a formatted terminal
276 # a formatted terminal
276 if mode == realmode and ui.formatted():
277 if mode == realmode and ui.formatted():
277 ui.warn(_('warning: failed to set color mode to %s\n') % mode)
278 ui.warn(_('warning: failed to set color mode to %s\n') % mode)
278
279
279 if realmode == 'win32':
280 if realmode == 'win32':
280 color._terminfo_params.clear()
281 color._terminfo_params.clear()
281 if not color.w32effects:
282 if not color.w32effects:
282 modewarn()
283 modewarn()
283 return None
284 return None
284 color._effects.update(color.w32effects)
285 color._effects.update(color.w32effects)
285 elif realmode == 'ansi':
286 elif realmode == 'ansi':
286 color._terminfo_params.clear()
287 color._terminfo_params.clear()
287 elif realmode == 'terminfo':
288 elif realmode == 'terminfo':
288 _terminfosetup(ui, mode)
289 _terminfosetup(ui, mode)
289 if not color._terminfo_params:
290 if not color._terminfo_params:
290 ## FIXME Shouldn't we return None in this case too?
291 ## FIXME Shouldn't we return None in this case too?
291 modewarn()
292 modewarn()
292 realmode = 'ansi'
293 realmode = 'ansi'
293 else:
294 else:
294 return None
295 return None
295
296
296 if always or (auto and formatted):
297 if always or (auto and formatted):
297 return realmode
298 return realmode
298 return None
299 return None
299
300
300 class colorui(uimod.ui):
301 class colorui(uimod.ui):
301 _colormode = 'ansi'
302 _colormode = 'ansi'
302 def write(self, *args, **opts):
303 def write(self, *args, **opts):
303 if self._colormode is None:
304 if self._colormode is None:
304 return super(colorui, self).write(*args, **opts)
305 return super(colorui, self).write(*args, **opts)
305
306
306 label = opts.get('label', '')
307 label = opts.get('label', '')
307 if self._buffers and not opts.get('prompt', False):
308 if self._buffers and not opts.get('prompt', False):
308 if self._bufferapplylabels:
309 if self._bufferapplylabels:
309 self._buffers[-1].extend(self.label(a, label) for a in args)
310 self._buffers[-1].extend(self.label(a, label) for a in args)
310 else:
311 else:
311 self._buffers[-1].extend(args)
312 self._buffers[-1].extend(args)
312 elif self._colormode == 'win32':
313 elif self._colormode == 'win32':
313 for a in args:
314 for a in args:
314 color.win32print(a, super(colorui, self).write, **opts)
315 color.win32print(a, super(colorui, self).write, **opts)
315 else:
316 else:
316 return super(colorui, self).write(
317 return super(colorui, self).write(
317 *[self.label(a, label) for a in args], **opts)
318 *[self.label(a, label) for a in args], **opts)
318
319
319 def write_err(self, *args, **opts):
320 def write_err(self, *args, **opts):
320 if self._colormode is None:
321 if self._colormode is None:
321 return super(colorui, self).write_err(*args, **opts)
322 return super(colorui, self).write_err(*args, **opts)
322
323
323 label = opts.get('label', '')
324 label = opts.get('label', '')
324 if self._bufferstates and self._bufferstates[-1][0]:
325 if self._bufferstates and self._bufferstates[-1][0]:
325 return self.write(*args, **opts)
326 return self.write(*args, **opts)
326 if self._colormode == 'win32':
327 if self._colormode == 'win32':
327 for a in args:
328 for a in args:
328 color.win32print(a, super(colorui, self).write_err, **opts)
329 color.win32print(a, super(colorui, self).write_err, **opts)
329 else:
330 else:
330 return super(colorui, self).write_err(
331 return super(colorui, self).write_err(
331 *[self.label(a, label) for a in args], **opts)
332 *[self.label(a, label) for a in args], **opts)
332
333
333 def showlabel(self, msg, label):
334 def showlabel(self, msg, label):
334 if label and msg:
335 if label and msg:
335 if msg[-1] == '\n':
336 if msg[-1] == '\n':
336 return "[%s|%s]\n" % (label, msg[:-1])
337 return "[%s|%s]\n" % (label, msg[:-1])
337 else:
338 else:
338 return "[%s|%s]" % (label, msg)
339 return "[%s|%s]" % (label, msg)
339 else:
340 else:
340 return msg
341 return msg
341
342
342 def label(self, msg, label):
343 def label(self, msg, label):
343 if self._colormode is None:
344 if self._colormode is None:
344 return super(colorui, self).label(msg, label)
345 return super(colorui, self).label(msg, label)
345
346
346 if self._colormode == 'debug':
347 if self._colormode == 'debug':
347 return self.showlabel(msg, label)
348 return self.showlabel(msg, label)
348
349
349 effects = []
350 effects = []
350 for l in label.split():
351 for l in label.split():
351 s = color._styles.get(l, '')
352 s = color._styles.get(l, '')
352 if s:
353 if s:
353 effects.append(s)
354 effects.append(s)
354 elif color.valideffect(l):
355 elif color.valideffect(l):
355 effects.append(l)
356 effects.append(l)
356 effects = ' '.join(effects)
357 effects = ' '.join(effects)
357 if effects:
358 if effects:
358 return '\n'.join([color._render_effects(line, effects)
359 return '\n'.join([color._render_effects(line, effects)
359 for line in msg.split('\n')])
360 for line in msg.split('\n')])
360 return msg
361 return msg
361
362
362 def uisetup(ui):
363 def uisetup(ui):
363 if ui.plain():
364 if ui.plain():
364 return
365 return
365 if not isinstance(ui, colorui):
366 if not isinstance(ui, colorui):
366 colorui.__bases__ = (ui.__class__,)
367 colorui.__bases__ = (ui.__class__,)
367 ui.__class__ = colorui
368 ui.__class__ = colorui
368 def colorcmd(orig, ui_, opts, cmd, cmdfunc):
369 def colorcmd(orig, ui_, opts, cmd, cmdfunc):
369 mode = _modesetup(ui_, opts['color'])
370 mode = _modesetup(ui_, opts['color'])
370 colorui._colormode = mode
371 colorui._colormode = mode
371 if mode and mode != 'debug':
372 if mode and mode != 'debug':
372 color.configstyles(ui_)
373 color.configstyles(ui_)
373 return orig(ui_, opts, cmd, cmdfunc)
374 return orig(ui_, opts, cmd, cmdfunc)
374 def colorgit(orig, gitsub, commands, env=None, stream=False, cwd=None):
375 def colorgit(orig, gitsub, commands, env=None, stream=False, cwd=None):
375 if gitsub.ui._colormode and len(commands) and commands[0] == "diff":
376 if gitsub.ui._colormode and len(commands) and commands[0] == "diff":
376 # insert the argument in the front,
377 # insert the argument in the front,
377 # the end of git diff arguments is used for paths
378 # the end of git diff arguments is used for paths
378 commands.insert(1, '--color')
379 commands.insert(1, '--color')
379 return orig(gitsub, commands, env, stream, cwd)
380 return orig(gitsub, commands, env, stream, cwd)
380 extensions.wrapfunction(dispatch, '_runcommand', colorcmd)
381 extensions.wrapfunction(dispatch, '_runcommand', colorcmd)
381 extensions.wrapfunction(subrepo.gitsubrepo, '_gitnodir', colorgit)
382 extensions.wrapfunction(subrepo.gitsubrepo, '_gitnodir', colorgit)
382
383
383 def extsetup(ui):
384 def extsetup(ui):
384 commands.globalopts.append(
385 commands.globalopts.append(
385 ('', 'color', 'auto',
386 ('', 'color', 'auto',
386 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
387 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
387 # and should not be translated
388 # and should not be translated
388 _("when to colorize (boolean, always, auto, never, or debug)"),
389 _("when to colorize (boolean, always, auto, never, or debug)"),
389 _('TYPE')))
390 _('TYPE')))
390
391
391 @command('debugcolor',
392 @command('debugcolor',
392 [('', 'style', None, _('show all configured styles'))],
393 [('', 'style', None, _('show all configured styles'))],
393 'hg debugcolor')
394 'hg debugcolor')
394 def debugcolor(ui, repo, **opts):
395 def debugcolor(ui, repo, **opts):
395 """show available color, effects or style"""
396 """show available color, effects or style"""
396 ui.write(('color mode: %s\n') % ui._colormode)
397 ui.write(('color mode: %s\n') % ui._colormode)
397 if opts.get('style'):
398 if opts.get('style'):
398 return _debugdisplaystyle(ui)
399 return _debugdisplaystyle(ui)
399 else:
400 else:
400 return _debugdisplaycolor(ui)
401 return _debugdisplaycolor(ui)
401
402
402 def _debugdisplaycolor(ui):
403 def _debugdisplaycolor(ui):
403 oldstyle = color._styles.copy()
404 oldstyle = color._styles.copy()
404 try:
405 try:
405 color._styles.clear()
406 color._styles.clear()
406 for effect in color._effects.keys():
407 for effect in color._effects.keys():
407 color._styles[effect] = effect
408 color._styles[effect] = effect
408 if color._terminfo_params:
409 if color._terminfo_params:
409 for k, v in ui.configitems('color'):
410 for k, v in ui.configitems('color'):
410 if k.startswith('color.'):
411 if k.startswith('color.'):
411 color._styles[k] = k[6:]
412 color._styles[k] = k[6:]
412 elif k.startswith('terminfo.'):
413 elif k.startswith('terminfo.'):
413 color._styles[k] = k[9:]
414 color._styles[k] = k[9:]
414 ui.write(_('available colors:\n'))
415 ui.write(_('available colors:\n'))
415 # sort label with a '_' after the other to group '_background' entry.
416 # sort label with a '_' after the other to group '_background' entry.
416 items = sorted(color._styles.items(),
417 items = sorted(color._styles.items(),
417 key=lambda i: ('_' in i[0], i[0], i[1]))
418 key=lambda i: ('_' in i[0], i[0], i[1]))
418 for colorname, label in items:
419 for colorname, label in items:
419 ui.write(('%s\n') % colorname, label=label)
420 ui.write(('%s\n') % colorname, label=label)
420 finally:
421 finally:
421 color._styles.clear()
422 color._styles.clear()
422 color._styles.update(oldstyle)
423 color._styles.update(oldstyle)
423
424
424 def _debugdisplaystyle(ui):
425 def _debugdisplaystyle(ui):
425 ui.write(_('available style:\n'))
426 ui.write(_('available style:\n'))
426 width = max(len(s) for s in color._styles)
427 width = max(len(s) for s in color._styles)
427 for label, effects in sorted(color._styles.items()):
428 for label, effects in sorted(color._styles.items()):
428 ui.write('%s' % label, label=label)
429 ui.write('%s' % label, label=label)
429 if effects:
430 if effects:
430 # 50
431 # 50
431 ui.write(': ')
432 ui.write(': ')
432 ui.write(' ' * (max(0, width - len(label))))
433 ui.write(' ' * (max(0, width - len(label))))
433 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
434 ui.write(', '.join(ui.label(e, e) for e in effects.split()))
434 ui.write('\n')
435 ui.write('\n')
General Comments 0
You need to be logged in to leave comments. Login now