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