##// END OF EJS Templates
color: allow for user-configurable terminfo codes for effects...
Danek Duvall -
r30173:f34a8cff default
parent child Browse files
Show More
@@ -1,665 +1,671 b''
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 Labels
32 Labels
33 ------
33 ------
34
34
35 Text receives color effects depending on the labels that it has. Many
35 Text receives color effects depending on the labels that it has. Many
36 default Mercurial commands emit labelled text. You can also define
36 default Mercurial commands emit labelled text. You can also define
37 your own labels in templates using the label function, see :hg:`help
37 your own labels in templates using the label function, see :hg:`help
38 templates`. A single portion of text may have more than one label. In
38 templates`. A single portion of text may have more than one label. In
39 that case, effects given to the last label will override any other
39 that case, effects given to the last label will override any other
40 effects. This includes the special "none" effect, which nullifies
40 effects. This includes the special "none" effect, which nullifies
41 other effects.
41 other effects.
42
42
43 Labels are normally invisible. In order to see these labels and their
43 Labels are normally invisible. In order to see these labels and their
44 position in the text, use the global --color=debug option. The same
44 position in the text, use the global --color=debug option. The same
45 anchor text may be associated to multiple labels, e.g.
45 anchor text may be associated to multiple labels, e.g.
46
46
47 [log.changeset changeset.secret|changeset: 22611:6f0a53c8f587]
47 [log.changeset changeset.secret|changeset: 22611:6f0a53c8f587]
48
48
49 The following are the default effects for some default labels. Default
49 The following are the default effects for some default labels. Default
50 effects may be overridden from your configuration file::
50 effects may be overridden from your configuration file::
51
51
52 [color]
52 [color]
53 status.modified = blue bold underline red_background
53 status.modified = blue bold underline red_background
54 status.added = green bold
54 status.added = green bold
55 status.removed = red bold blue_background
55 status.removed = red bold blue_background
56 status.deleted = cyan bold underline
56 status.deleted = cyan bold underline
57 status.unknown = magenta bold underline
57 status.unknown = magenta bold underline
58 status.ignored = black bold
58 status.ignored = black bold
59
59
60 # 'none' turns off all effects
60 # 'none' turns off all effects
61 status.clean = none
61 status.clean = none
62 status.copied = none
62 status.copied = none
63
63
64 qseries.applied = blue bold underline
64 qseries.applied = blue bold underline
65 qseries.unapplied = black bold
65 qseries.unapplied = black bold
66 qseries.missing = red bold
66 qseries.missing = red bold
67
67
68 diff.diffline = bold
68 diff.diffline = bold
69 diff.extended = cyan bold
69 diff.extended = cyan bold
70 diff.file_a = red bold
70 diff.file_a = red bold
71 diff.file_b = green bold
71 diff.file_b = green bold
72 diff.hunk = magenta
72 diff.hunk = magenta
73 diff.deleted = red
73 diff.deleted = red
74 diff.inserted = green
74 diff.inserted = green
75 diff.changed = white
75 diff.changed = white
76 diff.tab =
76 diff.tab =
77 diff.trailingwhitespace = bold red_background
77 diff.trailingwhitespace = bold red_background
78
78
79 # Blank so it inherits the style of the surrounding label
79 # Blank so it inherits the style of the surrounding label
80 changeset.public =
80 changeset.public =
81 changeset.draft =
81 changeset.draft =
82 changeset.secret =
82 changeset.secret =
83
83
84 resolve.unresolved = red bold
84 resolve.unresolved = red bold
85 resolve.resolved = green bold
85 resolve.resolved = green bold
86
86
87 bookmarks.active = green
87 bookmarks.active = green
88
88
89 branches.active = none
89 branches.active = none
90 branches.closed = black bold
90 branches.closed = black bold
91 branches.current = green
91 branches.current = green
92 branches.inactive = none
92 branches.inactive = none
93
93
94 tags.normal = green
94 tags.normal = green
95 tags.local = black bold
95 tags.local = black bold
96
96
97 rebase.rebased = blue
97 rebase.rebased = blue
98 rebase.remaining = red bold
98 rebase.remaining = red bold
99
99
100 shelve.age = cyan
100 shelve.age = cyan
101 shelve.newest = green bold
101 shelve.newest = green bold
102 shelve.name = blue bold
102 shelve.name = blue bold
103
103
104 histedit.remaining = red bold
104 histedit.remaining = red bold
105
105
106 Custom colors
106 Custom colors
107 -------------
107 -------------
108
108
109 Because there are only eight standard colors, this module allows you
109 Because there are only eight standard colors, this module allows you
110 to define color names for other color slots which might be available
110 to define color names for other color slots which might be available
111 for your terminal type, assuming terminfo mode. For instance::
111 for your terminal type, assuming terminfo mode. For instance::
112
112
113 color.brightblue = 12
113 color.brightblue = 12
114 color.pink = 207
114 color.pink = 207
115 color.orange = 202
115 color.orange = 202
116
116
117 to set 'brightblue' to color slot 12 (useful for 16 color terminals
117 to set 'brightblue' to color slot 12 (useful for 16 color terminals
118 that have brighter colors defined in the upper eight) and, 'pink' and
118 that have brighter colors defined in the upper eight) and, 'pink' and
119 'orange' to colors in 256-color xterm's default color cube. These
119 'orange' to colors in 256-color xterm's default color cube. These
120 defined colors may then be used as any of the pre-defined eight,
120 defined colors may then be used as any of the pre-defined eight,
121 including appending '_background' to set the background to that color.
121 including appending '_background' to set the background to that color.
122
122
123 Modes
123 Modes
124 -----
124 -----
125
125
126 By default, the color extension will use ANSI mode (or win32 mode on
126 By default, the color extension will use ANSI mode (or win32 mode on
127 Windows) if it detects a terminal. To override auto mode (to enable
127 Windows) if it detects a terminal. To override auto mode (to enable
128 terminfo mode, for example), set the following configuration option::
128 terminfo mode, for example), set the following configuration option::
129
129
130 [color]
130 [color]
131 mode = terminfo
131 mode = terminfo
132
132
133 Any value other than 'ansi', 'win32', 'terminfo', or 'auto' will
133 Any value other than 'ansi', 'win32', 'terminfo', or 'auto' will
134 disable color.
134 disable color.
135
135
136 Note that on some systems, terminfo mode may cause problems when using
136 Note that on some systems, terminfo mode may cause problems when using
137 color with the pager extension and less -R. less with the -R option
137 color with the pager extension and less -R. less with the -R option
138 will only display ECMA-48 color codes, and terminfo mode may sometimes
138 will only display ECMA-48 color codes, and terminfo mode may sometimes
139 emit codes that less doesn't understand. You can work around this by
139 emit codes that less doesn't understand. You can work around this by
140 either using ansi mode (or auto mode), or by using less -r (which will
140 either using ansi mode (or auto mode), or by using less -r (which will
141 pass through all terminal control codes, not just color control
141 pass through all terminal control codes, not just color control
142 codes).
142 codes).
143
143
144 On some systems (such as MSYS in Windows), the terminal may support
144 On some systems (such as MSYS in Windows), the terminal may support
145 a different color mode than the pager (activated via the "pager"
145 a different color mode than the pager (activated via the "pager"
146 extension). It is possible to define separate modes depending on whether
146 extension). It is possible to define separate modes depending on whether
147 the pager is active::
147 the pager is active::
148
148
149 [color]
149 [color]
150 mode = auto
150 mode = auto
151 pagermode = ansi
151 pagermode = ansi
152
152
153 If ``pagermode`` is not defined, the ``mode`` will be used.
153 If ``pagermode`` is not defined, the ``mode`` will be used.
154 '''
154 '''
155
155
156 from __future__ import absolute_import
156 from __future__ import absolute_import
157
157
158 import os
158 import os
159
159
160 from mercurial.i18n import _
160 from mercurial.i18n import _
161 from mercurial import (
161 from mercurial import (
162 cmdutil,
162 cmdutil,
163 commands,
163 commands,
164 dispatch,
164 dispatch,
165 extensions,
165 extensions,
166 subrepo,
166 subrepo,
167 ui as uimod,
167 ui as uimod,
168 util,
168 util,
169 )
169 )
170
170
171 cmdtable = {}
171 cmdtable = {}
172 command = cmdutil.command(cmdtable)
172 command = cmdutil.command(cmdtable)
173 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
173 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
174 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
174 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
175 # be specifying the version(s) of Mercurial they are tested with, or
175 # be specifying the version(s) of Mercurial they are tested with, or
176 # leave the attribute unspecified.
176 # leave the attribute unspecified.
177 testedwith = 'ships-with-hg-core'
177 testedwith = 'ships-with-hg-core'
178
178
179 # start and stop parameters for effects
179 # start and stop parameters for effects
180 _effects = {'none': 0, 'black': 30, 'red': 31, 'green': 32, 'yellow': 33,
180 _effects = {'none': 0, 'black': 30, 'red': 31, 'green': 32, 'yellow': 33,
181 'blue': 34, 'magenta': 35, 'cyan': 36, 'white': 37, 'bold': 1,
181 'blue': 34, 'magenta': 35, 'cyan': 36, 'white': 37, 'bold': 1,
182 'italic': 3, 'underline': 4, 'inverse': 7, 'dim': 2,
182 'italic': 3, 'underline': 4, 'inverse': 7, 'dim': 2,
183 'black_background': 40, 'red_background': 41,
183 'black_background': 40, 'red_background': 41,
184 'green_background': 42, 'yellow_background': 43,
184 'green_background': 42, 'yellow_background': 43,
185 'blue_background': 44, 'purple_background': 45,
185 'blue_background': 44, 'purple_background': 45,
186 'cyan_background': 46, 'white_background': 47}
186 'cyan_background': 46, 'white_background': 47}
187
187
188 def _terminfosetup(ui, mode):
188 def _terminfosetup(ui, mode):
189 '''Initialize terminfo data and the terminal if we're in terminfo mode.'''
189 '''Initialize terminfo data and the terminal if we're in terminfo mode.'''
190
190
191 global _terminfo_params
191 global _terminfo_params
192 # If we failed to load curses, we go ahead and return.
192 # If we failed to load curses, we go ahead and return.
193 if not _terminfo_params:
193 if not _terminfo_params:
194 return
194 return
195 # Otherwise, see what the config file says.
195 # Otherwise, see what the config file says.
196 if mode not in ('auto', 'terminfo'):
196 if mode not in ('auto', 'terminfo'):
197 return
197 return
198
198
199 _terminfo_params.update((key[6:], (False, int(val)))
199 _terminfo_params.update((key[6:], (False, int(val), ''))
200 for key, val in ui.configitems('color')
200 for key, val in ui.configitems('color')
201 if key.startswith('color.'))
201 if key.startswith('color.'))
202 _terminfo_params.update((key[9:], (True, '', val.replace('\\E', '\x1b')))
203 for key, val in ui.configitems('color')
204 if key.startswith('terminfo.'))
202
205
203 try:
206 try:
204 curses.setupterm()
207 curses.setupterm()
205 except curses.error as e:
208 except curses.error as e:
206 _terminfo_params = {}
209 _terminfo_params = {}
207 return
210 return
208
211
209 for key, (b, e) in _terminfo_params.items():
212 for key, (b, e, c) in _terminfo_params.items():
210 if not b:
213 if not b:
211 continue
214 continue
212 if not curses.tigetstr(e):
215 if not c and not curses.tigetstr(e):
213 # Most terminals don't support dim, invis, etc, so don't be
216 # Most terminals don't support dim, invis, etc, so don't be
214 # noisy and use ui.debug().
217 # noisy and use ui.debug().
215 ui.debug("no terminfo entry for %s\n" % e)
218 ui.debug("no terminfo entry for %s\n" % e)
216 del _terminfo_params[key]
219 del _terminfo_params[key]
217 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'):
220 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'):
218 # Only warn about missing terminfo entries if we explicitly asked for
221 # Only warn about missing terminfo entries if we explicitly asked for
219 # terminfo mode.
222 # terminfo mode.
220 if mode == "terminfo":
223 if mode == "terminfo":
221 ui.warn(_("no terminfo entry for setab/setaf: reverting to "
224 ui.warn(_("no terminfo entry for setab/setaf: reverting to "
222 "ECMA-48 color\n"))
225 "ECMA-48 color\n"))
223 _terminfo_params = {}
226 _terminfo_params = {}
224
227
225 def _modesetup(ui, coloropt):
228 def _modesetup(ui, coloropt):
226 global _terminfo_params
229 global _terminfo_params
227
230
228 if coloropt == 'debug':
231 if coloropt == 'debug':
229 return 'debug'
232 return 'debug'
230
233
231 auto = (coloropt == 'auto')
234 auto = (coloropt == 'auto')
232 always = not auto and util.parsebool(coloropt)
235 always = not auto and util.parsebool(coloropt)
233 if not always and not auto:
236 if not always and not auto:
234 return None
237 return None
235
238
236 formatted = always or (os.environ.get('TERM') != 'dumb' and ui.formatted())
239 formatted = always or (os.environ.get('TERM') != 'dumb' and ui.formatted())
237
240
238 mode = ui.config('color', 'mode', 'auto')
241 mode = ui.config('color', 'mode', 'auto')
239
242
240 # If pager is active, color.pagermode overrides color.mode.
243 # If pager is active, color.pagermode overrides color.mode.
241 if getattr(ui, 'pageractive', False):
244 if getattr(ui, 'pageractive', False):
242 mode = ui.config('color', 'pagermode', mode)
245 mode = ui.config('color', 'pagermode', mode)
243
246
244 realmode = mode
247 realmode = mode
245 if mode == 'auto':
248 if mode == 'auto':
246 if os.name == 'nt':
249 if os.name == 'nt':
247 term = os.environ.get('TERM')
250 term = os.environ.get('TERM')
248 # TERM won't be defined in a vanilla cmd.exe environment.
251 # TERM won't be defined in a vanilla cmd.exe environment.
249
252
250 # UNIX-like environments on Windows such as Cygwin and MSYS will
253 # UNIX-like environments on Windows such as Cygwin and MSYS will
251 # set TERM. They appear to make a best effort attempt at setting it
254 # set TERM. They appear to make a best effort attempt at setting it
252 # to something appropriate. However, not all environments with TERM
255 # to something appropriate. However, not all environments with TERM
253 # defined support ANSI. Since "ansi" could result in terminal
256 # defined support ANSI. Since "ansi" could result in terminal
254 # gibberish, we error on the side of selecting "win32". However, if
257 # gibberish, we error on the side of selecting "win32". However, if
255 # w32effects is not defined, we almost certainly don't support
258 # w32effects is not defined, we almost certainly don't support
256 # "win32", so don't even try.
259 # "win32", so don't even try.
257 if (term and 'xterm' in term) or not w32effects:
260 if (term and 'xterm' in term) or not w32effects:
258 realmode = 'ansi'
261 realmode = 'ansi'
259 else:
262 else:
260 realmode = 'win32'
263 realmode = 'win32'
261 else:
264 else:
262 realmode = 'ansi'
265 realmode = 'ansi'
263
266
264 def modewarn():
267 def modewarn():
265 # only warn if color.mode was explicitly set and we're in
268 # only warn if color.mode was explicitly set and we're in
266 # an interactive terminal
269 # an interactive terminal
267 if mode == realmode and ui.interactive():
270 if mode == realmode and ui.interactive():
268 ui.warn(_('warning: failed to set color mode to %s\n') % mode)
271 ui.warn(_('warning: failed to set color mode to %s\n') % mode)
269
272
270 if realmode == 'win32':
273 if realmode == 'win32':
271 _terminfo_params = {}
274 _terminfo_params = {}
272 if not w32effects:
275 if not w32effects:
273 modewarn()
276 modewarn()
274 return None
277 return None
275 _effects.update(w32effects)
278 _effects.update(w32effects)
276 elif realmode == 'ansi':
279 elif realmode == 'ansi':
277 _terminfo_params = {}
280 _terminfo_params = {}
278 elif realmode == 'terminfo':
281 elif realmode == 'terminfo':
279 _terminfosetup(ui, mode)
282 _terminfosetup(ui, mode)
280 if not _terminfo_params:
283 if not _terminfo_params:
281 ## FIXME Shouldn't we return None in this case too?
284 ## FIXME Shouldn't we return None in this case too?
282 modewarn()
285 modewarn()
283 realmode = 'ansi'
286 realmode = 'ansi'
284 else:
287 else:
285 return None
288 return None
286
289
287 if always or (auto and formatted):
290 if always or (auto and formatted):
288 return realmode
291 return realmode
289 return None
292 return None
290
293
291 try:
294 try:
292 import curses
295 import curses
293 # Mapping from effect name to terminfo attribute name or color number.
296 # Mapping from effect name to terminfo attribute name (or raw code) or
294 # This will also force-load the curses module.
297 # color number. This will also force-load the curses module.
295 _terminfo_params = {'none': (True, 'sgr0'),
298 _terminfo_params = {'none': (True, 'sgr0', ''),
296 'standout': (True, 'smso'),
299 'standout': (True, 'smso', ''),
297 'underline': (True, 'smul'),
300 'underline': (True, 'smul', ''),
298 'reverse': (True, 'rev'),
301 'reverse': (True, 'rev', ''),
299 'inverse': (True, 'rev'),
302 'inverse': (True, 'rev', ''),
300 'blink': (True, 'blink'),
303 'blink': (True, 'blink', ''),
301 'dim': (True, 'dim'),
304 'dim': (True, 'dim', ''),
302 'bold': (True, 'bold'),
305 'bold': (True, 'bold', ''),
303 'invisible': (True, 'invis'),
306 'invisible': (True, 'invis', ''),
304 'italic': (True, 'sitm'),
307 'italic': (True, 'sitm', ''),
305 'black': (False, curses.COLOR_BLACK),
308 'black': (False, curses.COLOR_BLACK, ''),
306 'red': (False, curses.COLOR_RED),
309 'red': (False, curses.COLOR_RED, ''),
307 'green': (False, curses.COLOR_GREEN),
310 'green': (False, curses.COLOR_GREEN, ''),
308 'yellow': (False, curses.COLOR_YELLOW),
311 'yellow': (False, curses.COLOR_YELLOW, ''),
309 'blue': (False, curses.COLOR_BLUE),
312 'blue': (False, curses.COLOR_BLUE, ''),
310 'magenta': (False, curses.COLOR_MAGENTA),
313 'magenta': (False, curses.COLOR_MAGENTA, ''),
311 'cyan': (False, curses.COLOR_CYAN),
314 'cyan': (False, curses.COLOR_CYAN, ''),
312 'white': (False, curses.COLOR_WHITE)}
315 'white': (False, curses.COLOR_WHITE, '')}
313 except ImportError:
316 except ImportError:
314 _terminfo_params = {}
317 _terminfo_params = {}
315
318
316 _styles = {'grep.match': 'red bold',
319 _styles = {'grep.match': 'red bold',
317 'grep.linenumber': 'green',
320 'grep.linenumber': 'green',
318 'grep.rev': 'green',
321 'grep.rev': 'green',
319 'grep.change': 'green',
322 'grep.change': 'green',
320 'grep.sep': 'cyan',
323 'grep.sep': 'cyan',
321 'grep.filename': 'magenta',
324 'grep.filename': 'magenta',
322 'grep.user': 'magenta',
325 'grep.user': 'magenta',
323 'grep.date': 'magenta',
326 'grep.date': 'magenta',
324 'bookmarks.active': 'green',
327 'bookmarks.active': 'green',
325 'branches.active': 'none',
328 'branches.active': 'none',
326 'branches.closed': 'black bold',
329 'branches.closed': 'black bold',
327 'branches.current': 'green',
330 'branches.current': 'green',
328 'branches.inactive': 'none',
331 'branches.inactive': 'none',
329 'diff.changed': 'white',
332 'diff.changed': 'white',
330 'diff.deleted': 'red',
333 'diff.deleted': 'red',
331 'diff.diffline': 'bold',
334 'diff.diffline': 'bold',
332 'diff.extended': 'cyan bold',
335 'diff.extended': 'cyan bold',
333 'diff.file_a': 'red bold',
336 'diff.file_a': 'red bold',
334 'diff.file_b': 'green bold',
337 'diff.file_b': 'green bold',
335 'diff.hunk': 'magenta',
338 'diff.hunk': 'magenta',
336 'diff.inserted': 'green',
339 'diff.inserted': 'green',
337 'diff.tab': '',
340 'diff.tab': '',
338 'diff.trailingwhitespace': 'bold red_background',
341 'diff.trailingwhitespace': 'bold red_background',
339 'changeset.public' : '',
342 'changeset.public' : '',
340 'changeset.draft' : '',
343 'changeset.draft' : '',
341 'changeset.secret' : '',
344 'changeset.secret' : '',
342 'diffstat.deleted': 'red',
345 'diffstat.deleted': 'red',
343 'diffstat.inserted': 'green',
346 'diffstat.inserted': 'green',
344 'histedit.remaining': 'red bold',
347 'histedit.remaining': 'red bold',
345 'ui.prompt': 'yellow',
348 'ui.prompt': 'yellow',
346 'log.changeset': 'yellow',
349 'log.changeset': 'yellow',
347 'patchbomb.finalsummary': '',
350 'patchbomb.finalsummary': '',
348 'patchbomb.from': 'magenta',
351 'patchbomb.from': 'magenta',
349 'patchbomb.to': 'cyan',
352 'patchbomb.to': 'cyan',
350 'patchbomb.subject': 'green',
353 'patchbomb.subject': 'green',
351 'patchbomb.diffstats': '',
354 'patchbomb.diffstats': '',
352 'rebase.rebased': 'blue',
355 'rebase.rebased': 'blue',
353 'rebase.remaining': 'red bold',
356 'rebase.remaining': 'red bold',
354 'resolve.resolved': 'green bold',
357 'resolve.resolved': 'green bold',
355 'resolve.unresolved': 'red bold',
358 'resolve.unresolved': 'red bold',
356 'shelve.age': 'cyan',
359 'shelve.age': 'cyan',
357 'shelve.newest': 'green bold',
360 'shelve.newest': 'green bold',
358 'shelve.name': 'blue bold',
361 'shelve.name': 'blue bold',
359 'status.added': 'green bold',
362 'status.added': 'green bold',
360 'status.clean': 'none',
363 'status.clean': 'none',
361 'status.copied': 'none',
364 'status.copied': 'none',
362 'status.deleted': 'cyan bold underline',
365 'status.deleted': 'cyan bold underline',
363 'status.ignored': 'black bold',
366 'status.ignored': 'black bold',
364 'status.modified': 'blue bold',
367 'status.modified': 'blue bold',
365 'status.removed': 'red bold',
368 'status.removed': 'red bold',
366 'status.unknown': 'magenta bold underline',
369 'status.unknown': 'magenta bold underline',
367 'tags.normal': 'green',
370 'tags.normal': 'green',
368 'tags.local': 'black bold'}
371 'tags.local': 'black bold'}
369
372
370
373
371 def _effect_str(effect):
374 def _effect_str(effect):
372 '''Helper function for render_effects().'''
375 '''Helper function for render_effects().'''
373
376
374 bg = False
377 bg = False
375 if effect.endswith('_background'):
378 if effect.endswith('_background'):
376 bg = True
379 bg = True
377 effect = effect[:-11]
380 effect = effect[:-11]
378 attr, val = _terminfo_params[effect]
381 attr, val, termcode = _terminfo_params[effect]
379 if attr:
382 if attr:
380 return curses.tigetstr(val)
383 if termcode:
384 return termcode
385 else:
386 return curses.tigetstr(val)
381 elif bg:
387 elif bg:
382 return curses.tparm(curses.tigetstr('setab'), val)
388 return curses.tparm(curses.tigetstr('setab'), val)
383 else:
389 else:
384 return curses.tparm(curses.tigetstr('setaf'), val)
390 return curses.tparm(curses.tigetstr('setaf'), val)
385
391
386 def render_effects(text, effects):
392 def render_effects(text, effects):
387 'Wrap text in commands to turn on each effect.'
393 'Wrap text in commands to turn on each effect.'
388 if not text:
394 if not text:
389 return text
395 return text
390 if not _terminfo_params:
396 if not _terminfo_params:
391 start = [str(_effects[e]) for e in ['none'] + effects.split()]
397 start = [str(_effects[e]) for e in ['none'] + effects.split()]
392 start = '\033[' + ';'.join(start) + 'm'
398 start = '\033[' + ';'.join(start) + 'm'
393 stop = '\033[' + str(_effects['none']) + 'm'
399 stop = '\033[' + str(_effects['none']) + 'm'
394 else:
400 else:
395 start = ''.join(_effect_str(effect)
401 start = ''.join(_effect_str(effect)
396 for effect in ['none'] + effects.split())
402 for effect in ['none'] + effects.split())
397 stop = _effect_str('none')
403 stop = _effect_str('none')
398 return ''.join([start, text, stop])
404 return ''.join([start, text, stop])
399
405
400 def extstyles():
406 def extstyles():
401 for name, ext in extensions.extensions():
407 for name, ext in extensions.extensions():
402 _styles.update(getattr(ext, 'colortable', {}))
408 _styles.update(getattr(ext, 'colortable', {}))
403
409
404 def valideffect(effect):
410 def valideffect(effect):
405 'Determine if the effect is valid or not.'
411 'Determine if the effect is valid or not.'
406 good = False
412 good = False
407 if not _terminfo_params and effect in _effects:
413 if not _terminfo_params and effect in _effects:
408 good = True
414 good = True
409 elif effect in _terminfo_params or effect[:-11] in _terminfo_params:
415 elif effect in _terminfo_params or effect[:-11] in _terminfo_params:
410 good = True
416 good = True
411 return good
417 return good
412
418
413 def configstyles(ui):
419 def configstyles(ui):
414 for status, cfgeffects in ui.configitems('color'):
420 for status, cfgeffects in ui.configitems('color'):
415 if '.' not in status or status.startswith('color.'):
421 if '.' not in status or status.startswith(('color.', 'terminfo.')):
416 continue
422 continue
417 cfgeffects = ui.configlist('color', status)
423 cfgeffects = ui.configlist('color', status)
418 if cfgeffects:
424 if cfgeffects:
419 good = []
425 good = []
420 for e in cfgeffects:
426 for e in cfgeffects:
421 if valideffect(e):
427 if valideffect(e):
422 good.append(e)
428 good.append(e)
423 else:
429 else:
424 ui.warn(_("ignoring unknown color/effect %r "
430 ui.warn(_("ignoring unknown color/effect %r "
425 "(configured in color.%s)\n")
431 "(configured in color.%s)\n")
426 % (e, status))
432 % (e, status))
427 _styles[status] = ' '.join(good)
433 _styles[status] = ' '.join(good)
428
434
429 class colorui(uimod.ui):
435 class colorui(uimod.ui):
430 _colormode = 'ansi'
436 _colormode = 'ansi'
431 def write(self, *args, **opts):
437 def write(self, *args, **opts):
432 if self._colormode is None:
438 if self._colormode is None:
433 return super(colorui, self).write(*args, **opts)
439 return super(colorui, self).write(*args, **opts)
434
440
435 label = opts.get('label', '')
441 label = opts.get('label', '')
436 if self._buffers and not opts.get('prompt', False):
442 if self._buffers and not opts.get('prompt', False):
437 if self._bufferapplylabels:
443 if self._bufferapplylabels:
438 self._buffers[-1].extend(self.label(a, label) for a in args)
444 self._buffers[-1].extend(self.label(a, label) for a in args)
439 else:
445 else:
440 self._buffers[-1].extend(args)
446 self._buffers[-1].extend(args)
441 elif self._colormode == 'win32':
447 elif self._colormode == 'win32':
442 for a in args:
448 for a in args:
443 win32print(a, super(colorui, self).write, **opts)
449 win32print(a, super(colorui, self).write, **opts)
444 else:
450 else:
445 return super(colorui, self).write(
451 return super(colorui, self).write(
446 *[self.label(a, label) for a in args], **opts)
452 *[self.label(a, label) for a in args], **opts)
447
453
448 def write_err(self, *args, **opts):
454 def write_err(self, *args, **opts):
449 if self._colormode is None:
455 if self._colormode is None:
450 return super(colorui, self).write_err(*args, **opts)
456 return super(colorui, self).write_err(*args, **opts)
451
457
452 label = opts.get('label', '')
458 label = opts.get('label', '')
453 if self._bufferstates and self._bufferstates[-1][0]:
459 if self._bufferstates and self._bufferstates[-1][0]:
454 return self.write(*args, **opts)
460 return self.write(*args, **opts)
455 if self._colormode == 'win32':
461 if self._colormode == 'win32':
456 for a in args:
462 for a in args:
457 win32print(a, super(colorui, self).write_err, **opts)
463 win32print(a, super(colorui, self).write_err, **opts)
458 else:
464 else:
459 return super(colorui, self).write_err(
465 return super(colorui, self).write_err(
460 *[self.label(a, label) for a in args], **opts)
466 *[self.label(a, label) for a in args], **opts)
461
467
462 def showlabel(self, msg, label):
468 def showlabel(self, msg, label):
463 if label and msg:
469 if label and msg:
464 if msg[-1] == '\n':
470 if msg[-1] == '\n':
465 return "[%s|%s]\n" % (label, msg[:-1])
471 return "[%s|%s]\n" % (label, msg[:-1])
466 else:
472 else:
467 return "[%s|%s]" % (label, msg)
473 return "[%s|%s]" % (label, msg)
468 else:
474 else:
469 return msg
475 return msg
470
476
471 def label(self, msg, label):
477 def label(self, msg, label):
472 if self._colormode is None:
478 if self._colormode is None:
473 return super(colorui, self).label(msg, label)
479 return super(colorui, self).label(msg, label)
474
480
475 if self._colormode == 'debug':
481 if self._colormode == 'debug':
476 return self.showlabel(msg, label)
482 return self.showlabel(msg, label)
477
483
478 effects = []
484 effects = []
479 for l in label.split():
485 for l in label.split():
480 s = _styles.get(l, '')
486 s = _styles.get(l, '')
481 if s:
487 if s:
482 effects.append(s)
488 effects.append(s)
483 elif valideffect(l):
489 elif valideffect(l):
484 effects.append(l)
490 effects.append(l)
485 effects = ' '.join(effects)
491 effects = ' '.join(effects)
486 if effects:
492 if effects:
487 return '\n'.join([render_effects(s, effects)
493 return '\n'.join([render_effects(s, effects)
488 for s in msg.split('\n')])
494 for s in msg.split('\n')])
489 return msg
495 return msg
490
496
491 def uisetup(ui):
497 def uisetup(ui):
492 if ui.plain():
498 if ui.plain():
493 return
499 return
494 if not isinstance(ui, colorui):
500 if not isinstance(ui, colorui):
495 colorui.__bases__ = (ui.__class__,)
501 colorui.__bases__ = (ui.__class__,)
496 ui.__class__ = colorui
502 ui.__class__ = colorui
497 def colorcmd(orig, ui_, opts, cmd, cmdfunc):
503 def colorcmd(orig, ui_, opts, cmd, cmdfunc):
498 mode = _modesetup(ui_, opts['color'])
504 mode = _modesetup(ui_, opts['color'])
499 colorui._colormode = mode
505 colorui._colormode = mode
500 if mode and mode != 'debug':
506 if mode and mode != 'debug':
501 extstyles()
507 extstyles()
502 configstyles(ui_)
508 configstyles(ui_)
503 return orig(ui_, opts, cmd, cmdfunc)
509 return orig(ui_, opts, cmd, cmdfunc)
504 def colorgit(orig, gitsub, commands, env=None, stream=False, cwd=None):
510 def colorgit(orig, gitsub, commands, env=None, stream=False, cwd=None):
505 if gitsub.ui._colormode and len(commands) and commands[0] == "diff":
511 if gitsub.ui._colormode and len(commands) and commands[0] == "diff":
506 # insert the argument in the front,
512 # insert the argument in the front,
507 # the end of git diff arguments is used for paths
513 # the end of git diff arguments is used for paths
508 commands.insert(1, '--color')
514 commands.insert(1, '--color')
509 return orig(gitsub, commands, env, stream, cwd)
515 return orig(gitsub, commands, env, stream, cwd)
510 extensions.wrapfunction(dispatch, '_runcommand', colorcmd)
516 extensions.wrapfunction(dispatch, '_runcommand', colorcmd)
511 extensions.wrapfunction(subrepo.gitsubrepo, '_gitnodir', colorgit)
517 extensions.wrapfunction(subrepo.gitsubrepo, '_gitnodir', colorgit)
512
518
513 def extsetup(ui):
519 def extsetup(ui):
514 commands.globalopts.append(
520 commands.globalopts.append(
515 ('', 'color', 'auto',
521 ('', 'color', 'auto',
516 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
522 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
517 # and should not be translated
523 # and should not be translated
518 _("when to colorize (boolean, always, auto, never, or debug)"),
524 _("when to colorize (boolean, always, auto, never, or debug)"),
519 _('TYPE')))
525 _('TYPE')))
520
526
521 @command('debugcolor', [], 'hg debugcolor')
527 @command('debugcolor', [], 'hg debugcolor')
522 def debugcolor(ui, repo, **opts):
528 def debugcolor(ui, repo, **opts):
523 global _styles
529 global _styles
524 _styles = {}
530 _styles = {}
525 for effect in _effects.keys():
531 for effect in _effects.keys():
526 _styles[effect] = effect
532 _styles[effect] = effect
527 ui.write(('color mode: %s\n') % ui._colormode)
533 ui.write(('color mode: %s\n') % ui._colormode)
528 ui.write(_('available colors:\n'))
534 ui.write(_('available colors:\n'))
529 for label, colors in _styles.items():
535 for label, colors in _styles.items():
530 ui.write(('%s\n') % colors, label=label)
536 ui.write(('%s\n') % colors, label=label)
531
537
532 if os.name != 'nt':
538 if os.name != 'nt':
533 w32effects = None
539 w32effects = None
534 else:
540 else:
535 import ctypes
541 import ctypes
536 import re
542 import re
537
543
538 _kernel32 = ctypes.windll.kernel32
544 _kernel32 = ctypes.windll.kernel32
539
545
540 _WORD = ctypes.c_ushort
546 _WORD = ctypes.c_ushort
541
547
542 _INVALID_HANDLE_VALUE = -1
548 _INVALID_HANDLE_VALUE = -1
543
549
544 class _COORD(ctypes.Structure):
550 class _COORD(ctypes.Structure):
545 _fields_ = [('X', ctypes.c_short),
551 _fields_ = [('X', ctypes.c_short),
546 ('Y', ctypes.c_short)]
552 ('Y', ctypes.c_short)]
547
553
548 class _SMALL_RECT(ctypes.Structure):
554 class _SMALL_RECT(ctypes.Structure):
549 _fields_ = [('Left', ctypes.c_short),
555 _fields_ = [('Left', ctypes.c_short),
550 ('Top', ctypes.c_short),
556 ('Top', ctypes.c_short),
551 ('Right', ctypes.c_short),
557 ('Right', ctypes.c_short),
552 ('Bottom', ctypes.c_short)]
558 ('Bottom', ctypes.c_short)]
553
559
554 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
560 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
555 _fields_ = [('dwSize', _COORD),
561 _fields_ = [('dwSize', _COORD),
556 ('dwCursorPosition', _COORD),
562 ('dwCursorPosition', _COORD),
557 ('wAttributes', _WORD),
563 ('wAttributes', _WORD),
558 ('srWindow', _SMALL_RECT),
564 ('srWindow', _SMALL_RECT),
559 ('dwMaximumWindowSize', _COORD)]
565 ('dwMaximumWindowSize', _COORD)]
560
566
561 _STD_OUTPUT_HANDLE = 0xfffffff5 # (DWORD)-11
567 _STD_OUTPUT_HANDLE = 0xfffffff5 # (DWORD)-11
562 _STD_ERROR_HANDLE = 0xfffffff4 # (DWORD)-12
568 _STD_ERROR_HANDLE = 0xfffffff4 # (DWORD)-12
563
569
564 _FOREGROUND_BLUE = 0x0001
570 _FOREGROUND_BLUE = 0x0001
565 _FOREGROUND_GREEN = 0x0002
571 _FOREGROUND_GREEN = 0x0002
566 _FOREGROUND_RED = 0x0004
572 _FOREGROUND_RED = 0x0004
567 _FOREGROUND_INTENSITY = 0x0008
573 _FOREGROUND_INTENSITY = 0x0008
568
574
569 _BACKGROUND_BLUE = 0x0010
575 _BACKGROUND_BLUE = 0x0010
570 _BACKGROUND_GREEN = 0x0020
576 _BACKGROUND_GREEN = 0x0020
571 _BACKGROUND_RED = 0x0040
577 _BACKGROUND_RED = 0x0040
572 _BACKGROUND_INTENSITY = 0x0080
578 _BACKGROUND_INTENSITY = 0x0080
573
579
574 _COMMON_LVB_REVERSE_VIDEO = 0x4000
580 _COMMON_LVB_REVERSE_VIDEO = 0x4000
575 _COMMON_LVB_UNDERSCORE = 0x8000
581 _COMMON_LVB_UNDERSCORE = 0x8000
576
582
577 # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx
583 # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx
578 w32effects = {
584 w32effects = {
579 'none': -1,
585 'none': -1,
580 'black': 0,
586 'black': 0,
581 'red': _FOREGROUND_RED,
587 'red': _FOREGROUND_RED,
582 'green': _FOREGROUND_GREEN,
588 'green': _FOREGROUND_GREEN,
583 'yellow': _FOREGROUND_RED | _FOREGROUND_GREEN,
589 'yellow': _FOREGROUND_RED | _FOREGROUND_GREEN,
584 'blue': _FOREGROUND_BLUE,
590 'blue': _FOREGROUND_BLUE,
585 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED,
591 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED,
586 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN,
592 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN,
587 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE,
593 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE,
588 'bold': _FOREGROUND_INTENSITY,
594 'bold': _FOREGROUND_INTENSITY,
589 'black_background': 0x100, # unused value > 0x0f
595 'black_background': 0x100, # unused value > 0x0f
590 'red_background': _BACKGROUND_RED,
596 'red_background': _BACKGROUND_RED,
591 'green_background': _BACKGROUND_GREEN,
597 'green_background': _BACKGROUND_GREEN,
592 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN,
598 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN,
593 'blue_background': _BACKGROUND_BLUE,
599 'blue_background': _BACKGROUND_BLUE,
594 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED,
600 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED,
595 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN,
601 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN,
596 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN |
602 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN |
597 _BACKGROUND_BLUE),
603 _BACKGROUND_BLUE),
598 'bold_background': _BACKGROUND_INTENSITY,
604 'bold_background': _BACKGROUND_INTENSITY,
599 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only
605 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only
600 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only
606 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only
601 }
607 }
602
608
603 passthrough = set([_FOREGROUND_INTENSITY,
609 passthrough = set([_FOREGROUND_INTENSITY,
604 _BACKGROUND_INTENSITY,
610 _BACKGROUND_INTENSITY,
605 _COMMON_LVB_UNDERSCORE,
611 _COMMON_LVB_UNDERSCORE,
606 _COMMON_LVB_REVERSE_VIDEO])
612 _COMMON_LVB_REVERSE_VIDEO])
607
613
608 stdout = _kernel32.GetStdHandle(
614 stdout = _kernel32.GetStdHandle(
609 _STD_OUTPUT_HANDLE) # don't close the handle returned
615 _STD_OUTPUT_HANDLE) # don't close the handle returned
610 if stdout is None or stdout == _INVALID_HANDLE_VALUE:
616 if stdout is None or stdout == _INVALID_HANDLE_VALUE:
611 w32effects = None
617 w32effects = None
612 else:
618 else:
613 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
619 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
614 if not _kernel32.GetConsoleScreenBufferInfo(
620 if not _kernel32.GetConsoleScreenBufferInfo(
615 stdout, ctypes.byref(csbi)):
621 stdout, ctypes.byref(csbi)):
616 # stdout may not support GetConsoleScreenBufferInfo()
622 # stdout may not support GetConsoleScreenBufferInfo()
617 # when called from subprocess or redirected
623 # when called from subprocess or redirected
618 w32effects = None
624 w32effects = None
619 else:
625 else:
620 origattr = csbi.wAttributes
626 origattr = csbi.wAttributes
621 ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)',
627 ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)',
622 re.MULTILINE | re.DOTALL)
628 re.MULTILINE | re.DOTALL)
623
629
624 def win32print(text, orig, **opts):
630 def win32print(text, orig, **opts):
625 label = opts.get('label', '')
631 label = opts.get('label', '')
626 attr = origattr
632 attr = origattr
627
633
628 def mapcolor(val, attr):
634 def mapcolor(val, attr):
629 if val == -1:
635 if val == -1:
630 return origattr
636 return origattr
631 elif val in passthrough:
637 elif val in passthrough:
632 return attr | val
638 return attr | val
633 elif val > 0x0f:
639 elif val > 0x0f:
634 return (val & 0x70) | (attr & 0x8f)
640 return (val & 0x70) | (attr & 0x8f)
635 else:
641 else:
636 return (val & 0x07) | (attr & 0xf8)
642 return (val & 0x07) | (attr & 0xf8)
637
643
638 # determine console attributes based on labels
644 # determine console attributes based on labels
639 for l in label.split():
645 for l in label.split():
640 style = _styles.get(l, '')
646 style = _styles.get(l, '')
641 for effect in style.split():
647 for effect in style.split():
642 try:
648 try:
643 attr = mapcolor(w32effects[effect], attr)
649 attr = mapcolor(w32effects[effect], attr)
644 except KeyError:
650 except KeyError:
645 # w32effects could not have certain attributes so we skip
651 # w32effects could not have certain attributes so we skip
646 # them if not found
652 # them if not found
647 pass
653 pass
648 # hack to ensure regexp finds data
654 # hack to ensure regexp finds data
649 if not text.startswith('\033['):
655 if not text.startswith('\033['):
650 text = '\033[m' + text
656 text = '\033[m' + text
651
657
652 # Look for ANSI-like codes embedded in text
658 # Look for ANSI-like codes embedded in text
653 m = re.match(ansire, text)
659 m = re.match(ansire, text)
654
660
655 try:
661 try:
656 while m:
662 while m:
657 for sattr in m.group(1).split(';'):
663 for sattr in m.group(1).split(';'):
658 if sattr:
664 if sattr:
659 attr = mapcolor(int(sattr), attr)
665 attr = mapcolor(int(sattr), attr)
660 _kernel32.SetConsoleTextAttribute(stdout, attr)
666 _kernel32.SetConsoleTextAttribute(stdout, attr)
661 orig(m.group(2), **opts)
667 orig(m.group(2), **opts)
662 m = re.match(ansire, m.group(3))
668 m = re.match(ansire, m.group(3))
663 finally:
669 finally:
664 # Explicitly reset original attributes
670 # Explicitly reset original attributes
665 _kernel32.SetConsoleTextAttribute(stdout, origattr)
671 _kernel32.SetConsoleTextAttribute(stdout, origattr)
@@ -1,368 +1,387 b''
1 $ cat <<EOF >> $HGRCPATH
1 $ cat <<EOF >> $HGRCPATH
2 > [extensions]
2 > [extensions]
3 > color =
3 > color =
4 > [color]
4 > [color]
5 > mode = ansi
5 > mode = ansi
6 > EOF
6 > EOF
7 Terminfo codes compatibility fix
7 Terminfo codes compatibility fix
8 $ echo "color.none=0" >> $HGRCPATH
8 $ echo "color.none=0" >> $HGRCPATH
9
9
10 $ hg init repo1
10 $ hg init repo1
11 $ cd repo1
11 $ cd repo1
12 $ mkdir a b a/1 b/1 b/2
12 $ mkdir a b a/1 b/1 b/2
13 $ touch in_root a/in_a b/in_b a/1/in_a_1 b/1/in_b_1 b/2/in_b_2
13 $ touch in_root a/in_a b/in_b a/1/in_a_1 b/1/in_b_1 b/2/in_b_2
14
14
15 hg status in repo root:
15 hg status in repo root:
16
16
17 $ hg status --color=always
17 $ hg status --color=always
18 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
18 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
19 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
19 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
20 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
20 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
21 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
21 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
22 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
22 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
23 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
23 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
24
24
25 $ hg status --color=debug
25 $ hg status --color=debug
26 [status.unknown|? ][status.unknown|a/1/in_a_1]
26 [status.unknown|? ][status.unknown|a/1/in_a_1]
27 [status.unknown|? ][status.unknown|a/in_a]
27 [status.unknown|? ][status.unknown|a/in_a]
28 [status.unknown|? ][status.unknown|b/1/in_b_1]
28 [status.unknown|? ][status.unknown|b/1/in_b_1]
29 [status.unknown|? ][status.unknown|b/2/in_b_2]
29 [status.unknown|? ][status.unknown|b/2/in_b_2]
30 [status.unknown|? ][status.unknown|b/in_b]
30 [status.unknown|? ][status.unknown|b/in_b]
31 [status.unknown|? ][status.unknown|in_root]
31 [status.unknown|? ][status.unknown|in_root]
32
32
33 hg status with template
33 hg status with template
34 $ hg status -T "{label('red', path)}\n" --color=debug
34 $ hg status -T "{label('red', path)}\n" --color=debug
35 [red|a/1/in_a_1]
35 [red|a/1/in_a_1]
36 [red|a/in_a]
36 [red|a/in_a]
37 [red|b/1/in_b_1]
37 [red|b/1/in_b_1]
38 [red|b/2/in_b_2]
38 [red|b/2/in_b_2]
39 [red|b/in_b]
39 [red|b/in_b]
40 [red|in_root]
40 [red|in_root]
41
41
42 hg status . in repo root:
42 hg status . in repo root:
43
43
44 $ hg status --color=always .
44 $ hg status --color=always .
45 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
45 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
46 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
46 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
47 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
47 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
48 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
48 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
49 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
49 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
50 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
50 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
51
51
52 $ hg status --color=always --cwd a
52 $ hg status --color=always --cwd a
53 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
53 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
54 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
54 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
55 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
55 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
56 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
56 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
57 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
57 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
58 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
58 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
59 $ hg status --color=always --cwd a .
59 $ hg status --color=always --cwd a .
60 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m1/in_a_1\x1b[0m (esc)
60 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m1/in_a_1\x1b[0m (esc)
61 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a\x1b[0m (esc)
61 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a\x1b[0m (esc)
62 $ hg status --color=always --cwd a ..
62 $ hg status --color=always --cwd a ..
63 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m1/in_a_1\x1b[0m (esc)
63 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m1/in_a_1\x1b[0m (esc)
64 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a\x1b[0m (esc)
64 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a\x1b[0m (esc)
65 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../b/1/in_b_1\x1b[0m (esc)
65 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../b/1/in_b_1\x1b[0m (esc)
66 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../b/2/in_b_2\x1b[0m (esc)
66 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../b/2/in_b_2\x1b[0m (esc)
67 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../b/in_b\x1b[0m (esc)
67 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../b/in_b\x1b[0m (esc)
68 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_root\x1b[0m (esc)
68 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_root\x1b[0m (esc)
69
69
70 $ hg status --color=always --cwd b
70 $ hg status --color=always --cwd b
71 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
71 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
72 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
72 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
73 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
73 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
74 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
74 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
75 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
75 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
76 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
76 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
77 $ hg status --color=always --cwd b .
77 $ hg status --color=always --cwd b .
78 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m1/in_b_1\x1b[0m (esc)
78 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m1/in_b_1\x1b[0m (esc)
79 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m2/in_b_2\x1b[0m (esc)
79 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m2/in_b_2\x1b[0m (esc)
80 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b\x1b[0m (esc)
80 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b\x1b[0m (esc)
81 $ hg status --color=always --cwd b ..
81 $ hg status --color=always --cwd b ..
82 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../a/1/in_a_1\x1b[0m (esc)
82 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../a/1/in_a_1\x1b[0m (esc)
83 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../a/in_a\x1b[0m (esc)
83 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../a/in_a\x1b[0m (esc)
84 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m1/in_b_1\x1b[0m (esc)
84 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m1/in_b_1\x1b[0m (esc)
85 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m2/in_b_2\x1b[0m (esc)
85 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m2/in_b_2\x1b[0m (esc)
86 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b\x1b[0m (esc)
86 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b\x1b[0m (esc)
87 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_root\x1b[0m (esc)
87 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_root\x1b[0m (esc)
88
88
89 $ hg status --color=always --cwd a/1
89 $ hg status --color=always --cwd a/1
90 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
90 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
91 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
91 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
92 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
92 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
93 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
93 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
94 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
94 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
95 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
95 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
96 $ hg status --color=always --cwd a/1 .
96 $ hg status --color=always --cwd a/1 .
97 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a_1\x1b[0m (esc)
97 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a_1\x1b[0m (esc)
98 $ hg status --color=always --cwd a/1 ..
98 $ hg status --color=always --cwd a/1 ..
99 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a_1\x1b[0m (esc)
99 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a_1\x1b[0m (esc)
100 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_a\x1b[0m (esc)
100 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_a\x1b[0m (esc)
101
101
102 $ hg status --color=always --cwd b/1
102 $ hg status --color=always --cwd b/1
103 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
103 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
104 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
104 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
105 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
105 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
106 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
106 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
107 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
107 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
108 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
108 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
109 $ hg status --color=always --cwd b/1 .
109 $ hg status --color=always --cwd b/1 .
110 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_1\x1b[0m (esc)
110 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_1\x1b[0m (esc)
111 $ hg status --color=always --cwd b/1 ..
111 $ hg status --color=always --cwd b/1 ..
112 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_1\x1b[0m (esc)
112 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_1\x1b[0m (esc)
113 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../2/in_b_2\x1b[0m (esc)
113 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../2/in_b_2\x1b[0m (esc)
114 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_b\x1b[0m (esc)
114 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_b\x1b[0m (esc)
115
115
116 $ hg status --color=always --cwd b/2
116 $ hg status --color=always --cwd b/2
117 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
117 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
118 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
118 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/in_a\x1b[0m (esc)
119 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
119 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/1/in_b_1\x1b[0m (esc)
120 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
120 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/2/in_b_2\x1b[0m (esc)
121 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
121 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4mb/in_b\x1b[0m (esc)
122 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
122 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
123 $ hg status --color=always --cwd b/2 .
123 $ hg status --color=always --cwd b/2 .
124 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_2\x1b[0m (esc)
124 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_2\x1b[0m (esc)
125 $ hg status --color=always --cwd b/2 ..
125 $ hg status --color=always --cwd b/2 ..
126 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../1/in_b_1\x1b[0m (esc)
126 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../1/in_b_1\x1b[0m (esc)
127 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_2\x1b[0m (esc)
127 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_2\x1b[0m (esc)
128 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_b\x1b[0m (esc)
128 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_b\x1b[0m (esc)
129
129
130 Make sure --color=never works
130 Make sure --color=never works
131 $ hg status --color=never
131 $ hg status --color=never
132 ? a/1/in_a_1
132 ? a/1/in_a_1
133 ? a/in_a
133 ? a/in_a
134 ? b/1/in_b_1
134 ? b/1/in_b_1
135 ? b/2/in_b_2
135 ? b/2/in_b_2
136 ? b/in_b
136 ? b/in_b
137 ? in_root
137 ? in_root
138
138
139 Make sure ui.formatted=False works
139 Make sure ui.formatted=False works
140 $ hg status --config ui.formatted=False
140 $ hg status --config ui.formatted=False
141 ? a/1/in_a_1
141 ? a/1/in_a_1
142 ? a/in_a
142 ? a/in_a
143 ? b/1/in_b_1
143 ? b/1/in_b_1
144 ? b/2/in_b_2
144 ? b/2/in_b_2
145 ? b/in_b
145 ? b/in_b
146 ? in_root
146 ? in_root
147
147
148 $ cd ..
148 $ cd ..
149
149
150 $ hg init repo2
150 $ hg init repo2
151 $ cd repo2
151 $ cd repo2
152 $ touch modified removed deleted ignored
152 $ touch modified removed deleted ignored
153 $ echo "^ignored$" > .hgignore
153 $ echo "^ignored$" > .hgignore
154 $ hg ci -A -m 'initial checkin'
154 $ hg ci -A -m 'initial checkin'
155 adding .hgignore
155 adding .hgignore
156 adding deleted
156 adding deleted
157 adding modified
157 adding modified
158 adding removed
158 adding removed
159 $ hg log --color=debug
159 $ hg log --color=debug
160 [log.changeset changeset.draft|changeset: 0:389aef86a55e]
160 [log.changeset changeset.draft|changeset: 0:389aef86a55e]
161 [log.tag|tag: tip]
161 [log.tag|tag: tip]
162 [log.user|user: test]
162 [log.user|user: test]
163 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
163 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
164 [log.summary|summary: initial checkin]
164 [log.summary|summary: initial checkin]
165
165
166 $ hg log -Tcompact --color=debug
166 $ hg log -Tcompact --color=debug
167 [log.changeset changeset.draft|0][tip] [log.node|389aef86a55e] [log.date|1970-01-01 00:00 +0000] [log.user|test]
167 [log.changeset changeset.draft|0][tip] [log.node|389aef86a55e] [log.date|1970-01-01 00:00 +0000] [log.user|test]
168 [ui.note log.description|initial checkin]
168 [ui.note log.description|initial checkin]
169
169
170 Labels on empty strings should not be displayed, labels on custom
170 Labels on empty strings should not be displayed, labels on custom
171 templates should be.
171 templates should be.
172
172
173 $ hg log --color=debug -T '{label("my.label",author)}\n{label("skipped.label","")}'
173 $ hg log --color=debug -T '{label("my.label",author)}\n{label("skipped.label","")}'
174 [my.label|test]
174 [my.label|test]
175 $ touch modified added unknown ignored
175 $ touch modified added unknown ignored
176 $ hg add added
176 $ hg add added
177 $ hg remove removed
177 $ hg remove removed
178 $ rm deleted
178 $ rm deleted
179
179
180 hg status:
180 hg status:
181
181
182 $ hg status --color=always
182 $ hg status --color=always
183 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
183 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
184 \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
184 \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
185 \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
185 \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
186 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
186 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
187
187
188 hg status modified added removed deleted unknown never-existed ignored:
188 hg status modified added removed deleted unknown never-existed ignored:
189
189
190 $ hg status --color=always modified added removed deleted unknown never-existed ignored
190 $ hg status --color=always modified added removed deleted unknown never-existed ignored
191 never-existed: * (glob)
191 never-existed: * (glob)
192 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
192 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
193 \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
193 \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
194 \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
194 \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
195 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
195 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
196
196
197 $ hg copy modified copied
197 $ hg copy modified copied
198
198
199 hg status -C:
199 hg status -C:
200
200
201 $ hg status --color=always -C
201 $ hg status --color=always -C
202 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
202 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
203 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mcopied\x1b[0m (esc)
203 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mcopied\x1b[0m (esc)
204 \x1b[0;0m modified\x1b[0m (esc)
204 \x1b[0;0m modified\x1b[0m (esc)
205 \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
205 \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
206 \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
206 \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
207 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
207 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
208
208
209 hg status -A:
209 hg status -A:
210
210
211 $ hg status --color=always -A
211 $ hg status --color=always -A
212 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
212 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
213 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mcopied\x1b[0m (esc)
213 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mcopied\x1b[0m (esc)
214 \x1b[0;0m modified\x1b[0m (esc)
214 \x1b[0;0m modified\x1b[0m (esc)
215 \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
215 \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
216 \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
216 \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
217 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
217 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
218 \x1b[0;30;1mI \x1b[0m\x1b[0;30;1mignored\x1b[0m (esc)
218 \x1b[0;30;1mI \x1b[0m\x1b[0;30;1mignored\x1b[0m (esc)
219 \x1b[0;0mC \x1b[0m\x1b[0;0m.hgignore\x1b[0m (esc)
219 \x1b[0;0mC \x1b[0m\x1b[0;0m.hgignore\x1b[0m (esc)
220 \x1b[0;0mC \x1b[0m\x1b[0;0mmodified\x1b[0m (esc)
220 \x1b[0;0mC \x1b[0m\x1b[0;0mmodified\x1b[0m (esc)
221
221
222
222
223 hg status -A (with terminfo color):
223 hg status -A (with terminfo color):
224
224
225 #if tic
225 #if tic
226
226
227 $ mkdir "$TESTTMP/terminfo"
227 $ mkdir "$TESTTMP/terminfo"
228 $ TERMINFO="$TESTTMP/terminfo" tic "$TESTDIR/hgterm.ti"
228 $ TERMINFO="$TESTTMP/terminfo" tic "$TESTDIR/hgterm.ti"
229 $ TERM=hgterm TERMINFO="$TESTTMP/terminfo" hg status --config color.mode=terminfo --color=always -A
229 $ TERM=hgterm TERMINFO="$TESTTMP/terminfo" hg status --config color.mode=terminfo --color=always -A
230 \x1b[30m\x1b[32m\x1b[1mA \x1b[30m\x1b[30m\x1b[32m\x1b[1madded\x1b[30m (esc)
230 \x1b[30m\x1b[32m\x1b[1mA \x1b[30m\x1b[30m\x1b[32m\x1b[1madded\x1b[30m (esc)
231 \x1b[30m\x1b[32m\x1b[1mA \x1b[30m\x1b[30m\x1b[32m\x1b[1mcopied\x1b[30m (esc)
231 \x1b[30m\x1b[32m\x1b[1mA \x1b[30m\x1b[30m\x1b[32m\x1b[1mcopied\x1b[30m (esc)
232 \x1b[30m\x1b[30m modified\x1b[30m (esc)
232 \x1b[30m\x1b[30m modified\x1b[30m (esc)
233 \x1b[30m\x1b[31m\x1b[1mR \x1b[30m\x1b[30m\x1b[31m\x1b[1mremoved\x1b[30m (esc)
233 \x1b[30m\x1b[31m\x1b[1mR \x1b[30m\x1b[30m\x1b[31m\x1b[1mremoved\x1b[30m (esc)
234 \x1b[30m\x1b[36m\x1b[1m\x1b[4m! \x1b[30m\x1b[30m\x1b[36m\x1b[1m\x1b[4mdeleted\x1b[30m (esc)
234 \x1b[30m\x1b[36m\x1b[1m\x1b[4m! \x1b[30m\x1b[30m\x1b[36m\x1b[1m\x1b[4mdeleted\x1b[30m (esc)
235 \x1b[30m\x1b[35m\x1b[1m\x1b[4m? \x1b[30m\x1b[30m\x1b[35m\x1b[1m\x1b[4munknown\x1b[30m (esc)
235 \x1b[30m\x1b[35m\x1b[1m\x1b[4m? \x1b[30m\x1b[30m\x1b[35m\x1b[1m\x1b[4munknown\x1b[30m (esc)
236 \x1b[30m\x1b[30m\x1b[1mI \x1b[30m\x1b[30m\x1b[30m\x1b[1mignored\x1b[30m (esc)
236 \x1b[30m\x1b[30m\x1b[1mI \x1b[30m\x1b[30m\x1b[30m\x1b[1mignored\x1b[30m (esc)
237 \x1b[30m\x1b[30mC \x1b[30m\x1b[30m\x1b[30m.hgignore\x1b[30m (esc)
237 \x1b[30m\x1b[30mC \x1b[30m\x1b[30m\x1b[30m.hgignore\x1b[30m (esc)
238 \x1b[30m\x1b[30mC \x1b[30m\x1b[30m\x1b[30mmodified\x1b[30m (esc)
238 \x1b[30m\x1b[30mC \x1b[30m\x1b[30m\x1b[30mmodified\x1b[30m (esc)
239
239
240 The user can define effects with raw terminfo codes:
241
242 $ cat <<EOF >> $HGRCPATH
243 > # Completely bogus code for dim
244 > terminfo.dim = \E[88m
245 > # We can override what's in the terminfo database, too
246 > terminfo.bold = \E[2m
247 > EOF
248 $ TERM=hgterm TERMINFO="$TESTTMP/terminfo" hg status --config color.mode=terminfo --config color.status.clean=dim --color=always -A
249 \x1b[30m\x1b[32m\x1b[2mA \x1b[30m\x1b[30m\x1b[32m\x1b[2madded\x1b[30m (esc)
250 \x1b[30m\x1b[32m\x1b[2mA \x1b[30m\x1b[30m\x1b[32m\x1b[2mcopied\x1b[30m (esc)
251 \x1b[30m\x1b[30m modified\x1b[30m (esc)
252 \x1b[30m\x1b[31m\x1b[2mR \x1b[30m\x1b[30m\x1b[31m\x1b[2mremoved\x1b[30m (esc)
253 \x1b[30m\x1b[36m\x1b[2m\x1b[4m! \x1b[30m\x1b[30m\x1b[36m\x1b[2m\x1b[4mdeleted\x1b[30m (esc)
254 \x1b[30m\x1b[35m\x1b[2m\x1b[4m? \x1b[30m\x1b[30m\x1b[35m\x1b[2m\x1b[4munknown\x1b[30m (esc)
255 \x1b[30m\x1b[30m\x1b[2mI \x1b[30m\x1b[30m\x1b[30m\x1b[2mignored\x1b[30m (esc)
256 \x1b[30m\x1b[88mC \x1b[30m\x1b[30m\x1b[88m.hgignore\x1b[30m (esc)
257 \x1b[30m\x1b[88mC \x1b[30m\x1b[30m\x1b[88mmodified\x1b[30m (esc)
258
240 #endif
259 #endif
241
260
242
261
243 $ echo "^ignoreddir$" > .hgignore
262 $ echo "^ignoreddir$" > .hgignore
244 $ mkdir ignoreddir
263 $ mkdir ignoreddir
245 $ touch ignoreddir/file
264 $ touch ignoreddir/file
246
265
247 hg status ignoreddir/file:
266 hg status ignoreddir/file:
248
267
249 $ hg status --color=always ignoreddir/file
268 $ hg status --color=always ignoreddir/file
250
269
251 hg status -i ignoreddir/file:
270 hg status -i ignoreddir/file:
252
271
253 $ hg status --color=always -i ignoreddir/file
272 $ hg status --color=always -i ignoreddir/file
254 \x1b[0;30;1mI \x1b[0m\x1b[0;30;1mignoreddir/file\x1b[0m (esc)
273 \x1b[0;30;1mI \x1b[0m\x1b[0;30;1mignoreddir/file\x1b[0m (esc)
255 $ cd ..
274 $ cd ..
256
275
257 check 'status -q' and some combinations
276 check 'status -q' and some combinations
258
277
259 $ hg init repo3
278 $ hg init repo3
260 $ cd repo3
279 $ cd repo3
261 $ touch modified removed deleted ignored
280 $ touch modified removed deleted ignored
262 $ echo "^ignored$" > .hgignore
281 $ echo "^ignored$" > .hgignore
263 $ hg commit -A -m 'initial checkin'
282 $ hg commit -A -m 'initial checkin'
264 adding .hgignore
283 adding .hgignore
265 adding deleted
284 adding deleted
266 adding modified
285 adding modified
267 adding removed
286 adding removed
268 $ touch added unknown ignored
287 $ touch added unknown ignored
269 $ hg add added
288 $ hg add added
270 $ echo "test" >> modified
289 $ echo "test" >> modified
271 $ hg remove removed
290 $ hg remove removed
272 $ rm deleted
291 $ rm deleted
273 $ hg copy modified copied
292 $ hg copy modified copied
274
293
275 test unknown color
294 test unknown color
276
295
277 $ hg --config color.status.modified=periwinkle status --color=always
296 $ hg --config color.status.modified=periwinkle status --color=always
278 ignoring unknown color/effect 'periwinkle' (configured in color.status.modified)
297 ignoring unknown color/effect 'periwinkle' (configured in color.status.modified)
279 M modified
298 M modified
280 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
299 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
281 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mcopied\x1b[0m (esc)
300 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mcopied\x1b[0m (esc)
282 \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
301 \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
283 \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
302 \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
284 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
303 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
285
304
286 Run status with 2 different flags.
305 Run status with 2 different flags.
287 Check if result is the same or different.
306 Check if result is the same or different.
288 If result is not as expected, raise error
307 If result is not as expected, raise error
289
308
290 $ assert() {
309 $ assert() {
291 > hg status --color=always $1 > ../a
310 > hg status --color=always $1 > ../a
292 > hg status --color=always $2 > ../b
311 > hg status --color=always $2 > ../b
293 > if diff ../a ../b > /dev/null; then
312 > if diff ../a ../b > /dev/null; then
294 > out=0
313 > out=0
295 > else
314 > else
296 > out=1
315 > out=1
297 > fi
316 > fi
298 > if [ $3 -eq 0 ]; then
317 > if [ $3 -eq 0 ]; then
299 > df="same"
318 > df="same"
300 > else
319 > else
301 > df="different"
320 > df="different"
302 > fi
321 > fi
303 > if [ $out -ne $3 ]; then
322 > if [ $out -ne $3 ]; then
304 > echo "Error on $1 and $2, should be $df."
323 > echo "Error on $1 and $2, should be $df."
305 > fi
324 > fi
306 > }
325 > }
307
326
308 assert flag1 flag2 [0-same | 1-different]
327 assert flag1 flag2 [0-same | 1-different]
309
328
310 $ assert "-q" "-mard" 0
329 $ assert "-q" "-mard" 0
311 $ assert "-A" "-marduicC" 0
330 $ assert "-A" "-marduicC" 0
312 $ assert "-qA" "-mardcC" 0
331 $ assert "-qA" "-mardcC" 0
313 $ assert "-qAui" "-A" 0
332 $ assert "-qAui" "-A" 0
314 $ assert "-qAu" "-marducC" 0
333 $ assert "-qAu" "-marducC" 0
315 $ assert "-qAi" "-mardicC" 0
334 $ assert "-qAi" "-mardicC" 0
316 $ assert "-qu" "-u" 0
335 $ assert "-qu" "-u" 0
317 $ assert "-q" "-u" 1
336 $ assert "-q" "-u" 1
318 $ assert "-m" "-a" 1
337 $ assert "-m" "-a" 1
319 $ assert "-r" "-d" 1
338 $ assert "-r" "-d" 1
320 $ cd ..
339 $ cd ..
321
340
322 test 'resolve -l'
341 test 'resolve -l'
323
342
324 $ hg init repo4
343 $ hg init repo4
325 $ cd repo4
344 $ cd repo4
326 $ echo "file a" > a
345 $ echo "file a" > a
327 $ echo "file b" > b
346 $ echo "file b" > b
328 $ hg add a b
347 $ hg add a b
329 $ hg commit -m "initial"
348 $ hg commit -m "initial"
330 $ echo "file a change 1" > a
349 $ echo "file a change 1" > a
331 $ echo "file b change 1" > b
350 $ echo "file b change 1" > b
332 $ hg commit -m "head 1"
351 $ hg commit -m "head 1"
333 $ hg update 0
352 $ hg update 0
334 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
353 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
335 $ echo "file a change 2" > a
354 $ echo "file a change 2" > a
336 $ echo "file b change 2" > b
355 $ echo "file b change 2" > b
337 $ hg commit -m "head 2"
356 $ hg commit -m "head 2"
338 created new head
357 created new head
339 $ hg merge
358 $ hg merge
340 merging a
359 merging a
341 merging b
360 merging b
342 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
361 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
343 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
362 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
344 0 files updated, 0 files merged, 0 files removed, 2 files unresolved
363 0 files updated, 0 files merged, 0 files removed, 2 files unresolved
345 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
364 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
346 [1]
365 [1]
347 $ hg resolve -m b
366 $ hg resolve -m b
348
367
349 hg resolve with one unresolved, one resolved:
368 hg resolve with one unresolved, one resolved:
350
369
351 $ hg resolve --color=always -l
370 $ hg resolve --color=always -l
352 \x1b[0;31;1mU \x1b[0m\x1b[0;31;1ma\x1b[0m (esc)
371 \x1b[0;31;1mU \x1b[0m\x1b[0;31;1ma\x1b[0m (esc)
353 \x1b[0;32;1mR \x1b[0m\x1b[0;32;1mb\x1b[0m (esc)
372 \x1b[0;32;1mR \x1b[0m\x1b[0;32;1mb\x1b[0m (esc)
354
373
355 color coding of error message with current availability of curses
374 color coding of error message with current availability of curses
356
375
357 $ hg unknowncommand > /dev/null
376 $ hg unknowncommand > /dev/null
358 hg: unknown command 'unknowncommand'
377 hg: unknown command 'unknowncommand'
359 [255]
378 [255]
360
379
361 color coding of error message without curses
380 color coding of error message without curses
362
381
363 $ echo 'raise ImportError' > curses.py
382 $ echo 'raise ImportError' > curses.py
364 $ PYTHONPATH=`pwd`:$PYTHONPATH hg unknowncommand > /dev/null
383 $ PYTHONPATH=`pwd`:$PYTHONPATH hg unknowncommand > /dev/null
365 hg: unknown command 'unknowncommand'
384 hg: unknown command 'unknowncommand'
366 [255]
385 [255]
367
386
368 $ cd ..
387 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now