##// END OF EJS Templates
color: respect HGPLAINEXCEPT=color to allow colors while scripting (issue5749)...
Augie Fackler -
r35176:d4805a5e default
parent child Browse files
Show More
@@ -1,518 +1,518
1 # utility for color output for Mercurial commands
1 # utility for color output for Mercurial commands
2 #
2 #
3 # Copyright (C) 2007 Kevin Christen <kevin.christen@gmail.com> and other
3 # Copyright (C) 2007 Kevin Christen <kevin.christen@gmail.com> and other
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 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import re
10 import re
11
11
12 from .i18n import _
12 from .i18n import _
13
13
14 from . import (
14 from . import (
15 encoding,
15 encoding,
16 pycompat,
16 pycompat,
17 util
17 util
18 )
18 )
19
19
20 try:
20 try:
21 import curses
21 import curses
22 # Mapping from effect name to terminfo attribute name (or raw code) or
22 # Mapping from effect name to terminfo attribute name (or raw code) or
23 # color number. This will also force-load the curses module.
23 # color number. This will also force-load the curses module.
24 _baseterminfoparams = {
24 _baseterminfoparams = {
25 'none': (True, 'sgr0', ''),
25 'none': (True, 'sgr0', ''),
26 'standout': (True, 'smso', ''),
26 'standout': (True, 'smso', ''),
27 'underline': (True, 'smul', ''),
27 'underline': (True, 'smul', ''),
28 'reverse': (True, 'rev', ''),
28 'reverse': (True, 'rev', ''),
29 'inverse': (True, 'rev', ''),
29 'inverse': (True, 'rev', ''),
30 'blink': (True, 'blink', ''),
30 'blink': (True, 'blink', ''),
31 'dim': (True, 'dim', ''),
31 'dim': (True, 'dim', ''),
32 'bold': (True, 'bold', ''),
32 'bold': (True, 'bold', ''),
33 'invisible': (True, 'invis', ''),
33 'invisible': (True, 'invis', ''),
34 'italic': (True, 'sitm', ''),
34 'italic': (True, 'sitm', ''),
35 'black': (False, curses.COLOR_BLACK, ''),
35 'black': (False, curses.COLOR_BLACK, ''),
36 'red': (False, curses.COLOR_RED, ''),
36 'red': (False, curses.COLOR_RED, ''),
37 'green': (False, curses.COLOR_GREEN, ''),
37 'green': (False, curses.COLOR_GREEN, ''),
38 'yellow': (False, curses.COLOR_YELLOW, ''),
38 'yellow': (False, curses.COLOR_YELLOW, ''),
39 'blue': (False, curses.COLOR_BLUE, ''),
39 'blue': (False, curses.COLOR_BLUE, ''),
40 'magenta': (False, curses.COLOR_MAGENTA, ''),
40 'magenta': (False, curses.COLOR_MAGENTA, ''),
41 'cyan': (False, curses.COLOR_CYAN, ''),
41 'cyan': (False, curses.COLOR_CYAN, ''),
42 'white': (False, curses.COLOR_WHITE, ''),
42 'white': (False, curses.COLOR_WHITE, ''),
43 }
43 }
44 except ImportError:
44 except ImportError:
45 curses = None
45 curses = None
46 _baseterminfoparams = {}
46 _baseterminfoparams = {}
47
47
48 # start and stop parameters for effects
48 # start and stop parameters for effects
49 _effects = {
49 _effects = {
50 'none': 0,
50 'none': 0,
51 'black': 30,
51 'black': 30,
52 'red': 31,
52 'red': 31,
53 'green': 32,
53 'green': 32,
54 'yellow': 33,
54 'yellow': 33,
55 'blue': 34,
55 'blue': 34,
56 'magenta': 35,
56 'magenta': 35,
57 'cyan': 36,
57 'cyan': 36,
58 'white': 37,
58 'white': 37,
59 'bold': 1,
59 'bold': 1,
60 'italic': 3,
60 'italic': 3,
61 'underline': 4,
61 'underline': 4,
62 'inverse': 7,
62 'inverse': 7,
63 'dim': 2,
63 'dim': 2,
64 'black_background': 40,
64 'black_background': 40,
65 'red_background': 41,
65 'red_background': 41,
66 'green_background': 42,
66 'green_background': 42,
67 'yellow_background': 43,
67 'yellow_background': 43,
68 'blue_background': 44,
68 'blue_background': 44,
69 'purple_background': 45,
69 'purple_background': 45,
70 'cyan_background': 46,
70 'cyan_background': 46,
71 'white_background': 47,
71 'white_background': 47,
72 }
72 }
73
73
74 _defaultstyles = {
74 _defaultstyles = {
75 'grep.match': 'red bold',
75 'grep.match': 'red bold',
76 'grep.linenumber': 'green',
76 'grep.linenumber': 'green',
77 'grep.rev': 'green',
77 'grep.rev': 'green',
78 'grep.change': 'green',
78 'grep.change': 'green',
79 'grep.sep': 'cyan',
79 'grep.sep': 'cyan',
80 'grep.filename': 'magenta',
80 'grep.filename': 'magenta',
81 'grep.user': 'magenta',
81 'grep.user': 'magenta',
82 'grep.date': 'magenta',
82 'grep.date': 'magenta',
83 'bookmarks.active': 'green',
83 'bookmarks.active': 'green',
84 'branches.active': 'none',
84 'branches.active': 'none',
85 'branches.closed': 'black bold',
85 'branches.closed': 'black bold',
86 'branches.current': 'green',
86 'branches.current': 'green',
87 'branches.inactive': 'none',
87 'branches.inactive': 'none',
88 'diff.changed': 'white',
88 'diff.changed': 'white',
89 'diff.deleted': 'red',
89 'diff.deleted': 'red',
90 'diff.diffline': 'bold',
90 'diff.diffline': 'bold',
91 'diff.extended': 'cyan bold',
91 'diff.extended': 'cyan bold',
92 'diff.file_a': 'red bold',
92 'diff.file_a': 'red bold',
93 'diff.file_b': 'green bold',
93 'diff.file_b': 'green bold',
94 'diff.hunk': 'magenta',
94 'diff.hunk': 'magenta',
95 'diff.inserted': 'green',
95 'diff.inserted': 'green',
96 'diff.tab': '',
96 'diff.tab': '',
97 'diff.trailingwhitespace': 'bold red_background',
97 'diff.trailingwhitespace': 'bold red_background',
98 'changeset.public': '',
98 'changeset.public': '',
99 'changeset.draft': '',
99 'changeset.draft': '',
100 'changeset.secret': '',
100 'changeset.secret': '',
101 'diffstat.deleted': 'red',
101 'diffstat.deleted': 'red',
102 'diffstat.inserted': 'green',
102 'diffstat.inserted': 'green',
103 'histedit.remaining': 'red bold',
103 'histedit.remaining': 'red bold',
104 'ui.prompt': 'yellow',
104 'ui.prompt': 'yellow',
105 'log.changeset': 'yellow',
105 'log.changeset': 'yellow',
106 'patchbomb.finalsummary': '',
106 'patchbomb.finalsummary': '',
107 'patchbomb.from': 'magenta',
107 'patchbomb.from': 'magenta',
108 'patchbomb.to': 'cyan',
108 'patchbomb.to': 'cyan',
109 'patchbomb.subject': 'green',
109 'patchbomb.subject': 'green',
110 'patchbomb.diffstats': '',
110 'patchbomb.diffstats': '',
111 'rebase.rebased': 'blue',
111 'rebase.rebased': 'blue',
112 'rebase.remaining': 'red bold',
112 'rebase.remaining': 'red bold',
113 'resolve.resolved': 'green bold',
113 'resolve.resolved': 'green bold',
114 'resolve.unresolved': 'red bold',
114 'resolve.unresolved': 'red bold',
115 'shelve.age': 'cyan',
115 'shelve.age': 'cyan',
116 'shelve.newest': 'green bold',
116 'shelve.newest': 'green bold',
117 'shelve.name': 'blue bold',
117 'shelve.name': 'blue bold',
118 'status.added': 'green bold',
118 'status.added': 'green bold',
119 'status.clean': 'none',
119 'status.clean': 'none',
120 'status.copied': 'none',
120 'status.copied': 'none',
121 'status.deleted': 'cyan bold underline',
121 'status.deleted': 'cyan bold underline',
122 'status.ignored': 'black bold',
122 'status.ignored': 'black bold',
123 'status.modified': 'blue bold',
123 'status.modified': 'blue bold',
124 'status.removed': 'red bold',
124 'status.removed': 'red bold',
125 'status.unknown': 'magenta bold underline',
125 'status.unknown': 'magenta bold underline',
126 'tags.normal': 'green',
126 'tags.normal': 'green',
127 'tags.local': 'black bold',
127 'tags.local': 'black bold',
128 }
128 }
129
129
130 def loadcolortable(ui, extname, colortable):
130 def loadcolortable(ui, extname, colortable):
131 _defaultstyles.update(colortable)
131 _defaultstyles.update(colortable)
132
132
133 def _terminfosetup(ui, mode, formatted):
133 def _terminfosetup(ui, mode, formatted):
134 '''Initialize terminfo data and the terminal if we're in terminfo mode.'''
134 '''Initialize terminfo data and the terminal if we're in terminfo mode.'''
135
135
136 # If we failed to load curses, we go ahead and return.
136 # If we failed to load curses, we go ahead and return.
137 if curses is None:
137 if curses is None:
138 return
138 return
139 # Otherwise, see what the config file says.
139 # Otherwise, see what the config file says.
140 if mode not in ('auto', 'terminfo'):
140 if mode not in ('auto', 'terminfo'):
141 return
141 return
142 ui._terminfoparams.update(_baseterminfoparams)
142 ui._terminfoparams.update(_baseterminfoparams)
143
143
144 for key, val in ui.configitems('color'):
144 for key, val in ui.configitems('color'):
145 if key.startswith('color.'):
145 if key.startswith('color.'):
146 newval = (False, int(val), '')
146 newval = (False, int(val), '')
147 ui._terminfoparams[key[6:]] = newval
147 ui._terminfoparams[key[6:]] = newval
148 elif key.startswith('terminfo.'):
148 elif key.startswith('terminfo.'):
149 newval = (True, '', val.replace('\\E', '\x1b'))
149 newval = (True, '', val.replace('\\E', '\x1b'))
150 ui._terminfoparams[key[9:]] = newval
150 ui._terminfoparams[key[9:]] = newval
151 try:
151 try:
152 curses.setupterm()
152 curses.setupterm()
153 except curses.error as e:
153 except curses.error as e:
154 ui._terminfoparams.clear()
154 ui._terminfoparams.clear()
155 return
155 return
156
156
157 for key, (b, e, c) in ui._terminfoparams.items():
157 for key, (b, e, c) in ui._terminfoparams.items():
158 if not b:
158 if not b:
159 continue
159 continue
160 if not c and not curses.tigetstr(e):
160 if not c and not curses.tigetstr(e):
161 # Most terminals don't support dim, invis, etc, so don't be
161 # Most terminals don't support dim, invis, etc, so don't be
162 # noisy and use ui.debug().
162 # noisy and use ui.debug().
163 ui.debug("no terminfo entry for %s\n" % e)
163 ui.debug("no terminfo entry for %s\n" % e)
164 del ui._terminfoparams[key]
164 del ui._terminfoparams[key]
165 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'):
165 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'):
166 # Only warn about missing terminfo entries if we explicitly asked for
166 # Only warn about missing terminfo entries if we explicitly asked for
167 # terminfo mode and we're in a formatted terminal.
167 # terminfo mode and we're in a formatted terminal.
168 if mode == "terminfo" and formatted:
168 if mode == "terminfo" and formatted:
169 ui.warn(_("no terminfo entry for setab/setaf: reverting to "
169 ui.warn(_("no terminfo entry for setab/setaf: reverting to "
170 "ECMA-48 color\n"))
170 "ECMA-48 color\n"))
171 ui._terminfoparams.clear()
171 ui._terminfoparams.clear()
172
172
173 def setup(ui):
173 def setup(ui):
174 """configure color on a ui
174 """configure color on a ui
175
175
176 That function both set the colormode for the ui object and read
176 That function both set the colormode for the ui object and read
177 the configuration looking for custom colors and effect definitions."""
177 the configuration looking for custom colors and effect definitions."""
178 mode = _modesetup(ui)
178 mode = _modesetup(ui)
179 ui._colormode = mode
179 ui._colormode = mode
180 if mode and mode != 'debug':
180 if mode and mode != 'debug':
181 configstyles(ui)
181 configstyles(ui)
182
182
183 def _modesetup(ui):
183 def _modesetup(ui):
184 if ui.plain():
184 if ui.plain('color'):
185 return None
185 return None
186 config = ui.config('ui', 'color')
186 config = ui.config('ui', 'color')
187 if config == 'debug':
187 if config == 'debug':
188 return 'debug'
188 return 'debug'
189
189
190 auto = (config == 'auto')
190 auto = (config == 'auto')
191 always = False
191 always = False
192 if not auto and util.parsebool(config):
192 if not auto and util.parsebool(config):
193 # We want the config to behave like a boolean, "on" is actually auto,
193 # We want the config to behave like a boolean, "on" is actually auto,
194 # but "always" value is treated as a special case to reduce confusion.
194 # but "always" value is treated as a special case to reduce confusion.
195 if ui.configsource('ui', 'color') == '--color' or config == 'always':
195 if ui.configsource('ui', 'color') == '--color' or config == 'always':
196 always = True
196 always = True
197 else:
197 else:
198 auto = True
198 auto = True
199
199
200 if not always and not auto:
200 if not always and not auto:
201 return None
201 return None
202
202
203 formatted = (always or (encoding.environ.get('TERM') != 'dumb'
203 formatted = (always or (encoding.environ.get('TERM') != 'dumb'
204 and ui.formatted()))
204 and ui.formatted()))
205
205
206 mode = ui.config('color', 'mode')
206 mode = ui.config('color', 'mode')
207
207
208 # If pager is active, color.pagermode overrides color.mode.
208 # If pager is active, color.pagermode overrides color.mode.
209 if getattr(ui, 'pageractive', False):
209 if getattr(ui, 'pageractive', False):
210 mode = ui.config('color', 'pagermode', mode)
210 mode = ui.config('color', 'pagermode', mode)
211
211
212 realmode = mode
212 realmode = mode
213 if pycompat.iswindows:
213 if pycompat.iswindows:
214 from . import win32
214 from . import win32
215
215
216 term = encoding.environ.get('TERM')
216 term = encoding.environ.get('TERM')
217 # TERM won't be defined in a vanilla cmd.exe environment.
217 # TERM won't be defined in a vanilla cmd.exe environment.
218
218
219 # UNIX-like environments on Windows such as Cygwin and MSYS will
219 # UNIX-like environments on Windows such as Cygwin and MSYS will
220 # set TERM. They appear to make a best effort attempt at setting it
220 # set TERM. They appear to make a best effort attempt at setting it
221 # to something appropriate. However, not all environments with TERM
221 # to something appropriate. However, not all environments with TERM
222 # defined support ANSI.
222 # defined support ANSI.
223 ansienviron = term and 'xterm' in term
223 ansienviron = term and 'xterm' in term
224
224
225 if mode == 'auto':
225 if mode == 'auto':
226 # Since "ansi" could result in terminal gibberish, we error on the
226 # Since "ansi" could result in terminal gibberish, we error on the
227 # side of selecting "win32". However, if w32effects is not defined,
227 # side of selecting "win32". However, if w32effects is not defined,
228 # we almost certainly don't support "win32", so don't even try.
228 # we almost certainly don't support "win32", so don't even try.
229 # w32ffects is not populated when stdout is redirected, so checking
229 # w32ffects is not populated when stdout is redirected, so checking
230 # it first avoids win32 calls in a state known to error out.
230 # it first avoids win32 calls in a state known to error out.
231 if ansienviron or not w32effects or win32.enablevtmode():
231 if ansienviron or not w32effects or win32.enablevtmode():
232 realmode = 'ansi'
232 realmode = 'ansi'
233 else:
233 else:
234 realmode = 'win32'
234 realmode = 'win32'
235 # An empty w32effects is a clue that stdout is redirected, and thus
235 # An empty w32effects is a clue that stdout is redirected, and thus
236 # cannot enable VT mode.
236 # cannot enable VT mode.
237 elif mode == 'ansi' and w32effects and not ansienviron:
237 elif mode == 'ansi' and w32effects and not ansienviron:
238 win32.enablevtmode()
238 win32.enablevtmode()
239 elif mode == 'auto':
239 elif mode == 'auto':
240 realmode = 'ansi'
240 realmode = 'ansi'
241
241
242 def modewarn():
242 def modewarn():
243 # only warn if color.mode was explicitly set and we're in
243 # only warn if color.mode was explicitly set and we're in
244 # a formatted terminal
244 # a formatted terminal
245 if mode == realmode and formatted:
245 if mode == realmode and formatted:
246 ui.warn(_('warning: failed to set color mode to %s\n') % mode)
246 ui.warn(_('warning: failed to set color mode to %s\n') % mode)
247
247
248 if realmode == 'win32':
248 if realmode == 'win32':
249 ui._terminfoparams.clear()
249 ui._terminfoparams.clear()
250 if not w32effects:
250 if not w32effects:
251 modewarn()
251 modewarn()
252 return None
252 return None
253 elif realmode == 'ansi':
253 elif realmode == 'ansi':
254 ui._terminfoparams.clear()
254 ui._terminfoparams.clear()
255 elif realmode == 'terminfo':
255 elif realmode == 'terminfo':
256 _terminfosetup(ui, mode, formatted)
256 _terminfosetup(ui, mode, formatted)
257 if not ui._terminfoparams:
257 if not ui._terminfoparams:
258 ## FIXME Shouldn't we return None in this case too?
258 ## FIXME Shouldn't we return None in this case too?
259 modewarn()
259 modewarn()
260 realmode = 'ansi'
260 realmode = 'ansi'
261 else:
261 else:
262 return None
262 return None
263
263
264 if always or (auto and formatted):
264 if always or (auto and formatted):
265 return realmode
265 return realmode
266 return None
266 return None
267
267
268 def configstyles(ui):
268 def configstyles(ui):
269 ui._styles.update(_defaultstyles)
269 ui._styles.update(_defaultstyles)
270 for status, cfgeffects in ui.configitems('color'):
270 for status, cfgeffects in ui.configitems('color'):
271 if '.' not in status or status.startswith(('color.', 'terminfo.')):
271 if '.' not in status or status.startswith(('color.', 'terminfo.')):
272 continue
272 continue
273 cfgeffects = ui.configlist('color', status)
273 cfgeffects = ui.configlist('color', status)
274 if cfgeffects:
274 if cfgeffects:
275 good = []
275 good = []
276 for e in cfgeffects:
276 for e in cfgeffects:
277 if valideffect(ui, e):
277 if valideffect(ui, e):
278 good.append(e)
278 good.append(e)
279 else:
279 else:
280 ui.warn(_("ignoring unknown color/effect %r "
280 ui.warn(_("ignoring unknown color/effect %r "
281 "(configured in color.%s)\n")
281 "(configured in color.%s)\n")
282 % (e, status))
282 % (e, status))
283 ui._styles[status] = ' '.join(good)
283 ui._styles[status] = ' '.join(good)
284
284
285 def _activeeffects(ui):
285 def _activeeffects(ui):
286 '''Return the effects map for the color mode set on the ui.'''
286 '''Return the effects map for the color mode set on the ui.'''
287 if ui._colormode == 'win32':
287 if ui._colormode == 'win32':
288 return w32effects
288 return w32effects
289 elif ui._colormode is not None:
289 elif ui._colormode is not None:
290 return _effects
290 return _effects
291 return {}
291 return {}
292
292
293 def valideffect(ui, effect):
293 def valideffect(ui, effect):
294 'Determine if the effect is valid or not.'
294 'Determine if the effect is valid or not.'
295 return ((not ui._terminfoparams and effect in _activeeffects(ui))
295 return ((not ui._terminfoparams and effect in _activeeffects(ui))
296 or (effect in ui._terminfoparams
296 or (effect in ui._terminfoparams
297 or effect[:-11] in ui._terminfoparams))
297 or effect[:-11] in ui._terminfoparams))
298
298
299 def _effect_str(ui, effect):
299 def _effect_str(ui, effect):
300 '''Helper function for render_effects().'''
300 '''Helper function for render_effects().'''
301
301
302 bg = False
302 bg = False
303 if effect.endswith('_background'):
303 if effect.endswith('_background'):
304 bg = True
304 bg = True
305 effect = effect[:-11]
305 effect = effect[:-11]
306 try:
306 try:
307 attr, val, termcode = ui._terminfoparams[effect]
307 attr, val, termcode = ui._terminfoparams[effect]
308 except KeyError:
308 except KeyError:
309 return ''
309 return ''
310 if attr:
310 if attr:
311 if termcode:
311 if termcode:
312 return termcode
312 return termcode
313 else:
313 else:
314 return curses.tigetstr(val)
314 return curses.tigetstr(val)
315 elif bg:
315 elif bg:
316 return curses.tparm(curses.tigetstr('setab'), val)
316 return curses.tparm(curses.tigetstr('setab'), val)
317 else:
317 else:
318 return curses.tparm(curses.tigetstr('setaf'), val)
318 return curses.tparm(curses.tigetstr('setaf'), val)
319
319
320 def _mergeeffects(text, start, stop):
320 def _mergeeffects(text, start, stop):
321 """Insert start sequence at every occurrence of stop sequence
321 """Insert start sequence at every occurrence of stop sequence
322
322
323 >>> s = _mergeeffects(b'cyan', b'[C]', b'|')
323 >>> s = _mergeeffects(b'cyan', b'[C]', b'|')
324 >>> s = _mergeeffects(s + b'yellow', b'[Y]', b'|')
324 >>> s = _mergeeffects(s + b'yellow', b'[Y]', b'|')
325 >>> s = _mergeeffects(b'ma' + s + b'genta', b'[M]', b'|')
325 >>> s = _mergeeffects(b'ma' + s + b'genta', b'[M]', b'|')
326 >>> s = _mergeeffects(b'red' + s, b'[R]', b'|')
326 >>> s = _mergeeffects(b'red' + s, b'[R]', b'|')
327 >>> s
327 >>> s
328 '[R]red[M]ma[Y][C]cyan|[R][M][Y]yellow|[R][M]genta|'
328 '[R]red[M]ma[Y][C]cyan|[R][M][Y]yellow|[R][M]genta|'
329 """
329 """
330 parts = []
330 parts = []
331 for t in text.split(stop):
331 for t in text.split(stop):
332 if not t:
332 if not t:
333 continue
333 continue
334 parts.extend([start, t, stop])
334 parts.extend([start, t, stop])
335 return ''.join(parts)
335 return ''.join(parts)
336
336
337 def _render_effects(ui, text, effects):
337 def _render_effects(ui, text, effects):
338 'Wrap text in commands to turn on each effect.'
338 'Wrap text in commands to turn on each effect.'
339 if not text:
339 if not text:
340 return text
340 return text
341 if ui._terminfoparams:
341 if ui._terminfoparams:
342 start = ''.join(_effect_str(ui, effect)
342 start = ''.join(_effect_str(ui, effect)
343 for effect in ['none'] + effects.split())
343 for effect in ['none'] + effects.split())
344 stop = _effect_str(ui, 'none')
344 stop = _effect_str(ui, 'none')
345 else:
345 else:
346 activeeffects = _activeeffects(ui)
346 activeeffects = _activeeffects(ui)
347 start = [pycompat.bytestr(activeeffects[e])
347 start = [pycompat.bytestr(activeeffects[e])
348 for e in ['none'] + effects.split()]
348 for e in ['none'] + effects.split()]
349 start = '\033[' + ';'.join(start) + 'm'
349 start = '\033[' + ';'.join(start) + 'm'
350 stop = '\033[' + pycompat.bytestr(activeeffects['none']) + 'm'
350 stop = '\033[' + pycompat.bytestr(activeeffects['none']) + 'm'
351 return _mergeeffects(text, start, stop)
351 return _mergeeffects(text, start, stop)
352
352
353 _ansieffectre = re.compile(br'\x1b\[[0-9;]*m')
353 _ansieffectre = re.compile(br'\x1b\[[0-9;]*m')
354
354
355 def stripeffects(text):
355 def stripeffects(text):
356 """Strip ANSI control codes which could be inserted by colorlabel()"""
356 """Strip ANSI control codes which could be inserted by colorlabel()"""
357 return _ansieffectre.sub('', text)
357 return _ansieffectre.sub('', text)
358
358
359 def colorlabel(ui, msg, label):
359 def colorlabel(ui, msg, label):
360 """add color control code according to the mode"""
360 """add color control code according to the mode"""
361 if ui._colormode == 'debug':
361 if ui._colormode == 'debug':
362 if label and msg:
362 if label and msg:
363 if msg[-1] == '\n':
363 if msg[-1] == '\n':
364 msg = "[%s|%s]\n" % (label, msg[:-1])
364 msg = "[%s|%s]\n" % (label, msg[:-1])
365 else:
365 else:
366 msg = "[%s|%s]" % (label, msg)
366 msg = "[%s|%s]" % (label, msg)
367 elif ui._colormode is not None:
367 elif ui._colormode is not None:
368 effects = []
368 effects = []
369 for l in label.split():
369 for l in label.split():
370 s = ui._styles.get(l, '')
370 s = ui._styles.get(l, '')
371 if s:
371 if s:
372 effects.append(s)
372 effects.append(s)
373 elif valideffect(ui, l):
373 elif valideffect(ui, l):
374 effects.append(l)
374 effects.append(l)
375 effects = ' '.join(effects)
375 effects = ' '.join(effects)
376 if effects:
376 if effects:
377 msg = '\n'.join([_render_effects(ui, line, effects)
377 msg = '\n'.join([_render_effects(ui, line, effects)
378 for line in msg.split('\n')])
378 for line in msg.split('\n')])
379 return msg
379 return msg
380
380
381 w32effects = None
381 w32effects = None
382 if pycompat.iswindows:
382 if pycompat.iswindows:
383 import ctypes
383 import ctypes
384
384
385 _kernel32 = ctypes.windll.kernel32
385 _kernel32 = ctypes.windll.kernel32
386
386
387 _WORD = ctypes.c_ushort
387 _WORD = ctypes.c_ushort
388
388
389 _INVALID_HANDLE_VALUE = -1
389 _INVALID_HANDLE_VALUE = -1
390
390
391 class _COORD(ctypes.Structure):
391 class _COORD(ctypes.Structure):
392 _fields_ = [('X', ctypes.c_short),
392 _fields_ = [('X', ctypes.c_short),
393 ('Y', ctypes.c_short)]
393 ('Y', ctypes.c_short)]
394
394
395 class _SMALL_RECT(ctypes.Structure):
395 class _SMALL_RECT(ctypes.Structure):
396 _fields_ = [('Left', ctypes.c_short),
396 _fields_ = [('Left', ctypes.c_short),
397 ('Top', ctypes.c_short),
397 ('Top', ctypes.c_short),
398 ('Right', ctypes.c_short),
398 ('Right', ctypes.c_short),
399 ('Bottom', ctypes.c_short)]
399 ('Bottom', ctypes.c_short)]
400
400
401 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
401 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
402 _fields_ = [('dwSize', _COORD),
402 _fields_ = [('dwSize', _COORD),
403 ('dwCursorPosition', _COORD),
403 ('dwCursorPosition', _COORD),
404 ('wAttributes', _WORD),
404 ('wAttributes', _WORD),
405 ('srWindow', _SMALL_RECT),
405 ('srWindow', _SMALL_RECT),
406 ('dwMaximumWindowSize', _COORD)]
406 ('dwMaximumWindowSize', _COORD)]
407
407
408 _STD_OUTPUT_HANDLE = 0xfffffff5 # (DWORD)-11
408 _STD_OUTPUT_HANDLE = 0xfffffff5 # (DWORD)-11
409 _STD_ERROR_HANDLE = 0xfffffff4 # (DWORD)-12
409 _STD_ERROR_HANDLE = 0xfffffff4 # (DWORD)-12
410
410
411 _FOREGROUND_BLUE = 0x0001
411 _FOREGROUND_BLUE = 0x0001
412 _FOREGROUND_GREEN = 0x0002
412 _FOREGROUND_GREEN = 0x0002
413 _FOREGROUND_RED = 0x0004
413 _FOREGROUND_RED = 0x0004
414 _FOREGROUND_INTENSITY = 0x0008
414 _FOREGROUND_INTENSITY = 0x0008
415
415
416 _BACKGROUND_BLUE = 0x0010
416 _BACKGROUND_BLUE = 0x0010
417 _BACKGROUND_GREEN = 0x0020
417 _BACKGROUND_GREEN = 0x0020
418 _BACKGROUND_RED = 0x0040
418 _BACKGROUND_RED = 0x0040
419 _BACKGROUND_INTENSITY = 0x0080
419 _BACKGROUND_INTENSITY = 0x0080
420
420
421 _COMMON_LVB_REVERSE_VIDEO = 0x4000
421 _COMMON_LVB_REVERSE_VIDEO = 0x4000
422 _COMMON_LVB_UNDERSCORE = 0x8000
422 _COMMON_LVB_UNDERSCORE = 0x8000
423
423
424 # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx
424 # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx
425 w32effects = {
425 w32effects = {
426 'none': -1,
426 'none': -1,
427 'black': 0,
427 'black': 0,
428 'red': _FOREGROUND_RED,
428 'red': _FOREGROUND_RED,
429 'green': _FOREGROUND_GREEN,
429 'green': _FOREGROUND_GREEN,
430 'yellow': _FOREGROUND_RED | _FOREGROUND_GREEN,
430 'yellow': _FOREGROUND_RED | _FOREGROUND_GREEN,
431 'blue': _FOREGROUND_BLUE,
431 'blue': _FOREGROUND_BLUE,
432 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED,
432 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED,
433 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN,
433 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN,
434 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE,
434 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE,
435 'bold': _FOREGROUND_INTENSITY,
435 'bold': _FOREGROUND_INTENSITY,
436 'black_background': 0x100, # unused value > 0x0f
436 'black_background': 0x100, # unused value > 0x0f
437 'red_background': _BACKGROUND_RED,
437 'red_background': _BACKGROUND_RED,
438 'green_background': _BACKGROUND_GREEN,
438 'green_background': _BACKGROUND_GREEN,
439 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN,
439 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN,
440 'blue_background': _BACKGROUND_BLUE,
440 'blue_background': _BACKGROUND_BLUE,
441 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED,
441 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED,
442 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN,
442 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN,
443 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN |
443 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN |
444 _BACKGROUND_BLUE),
444 _BACKGROUND_BLUE),
445 'bold_background': _BACKGROUND_INTENSITY,
445 'bold_background': _BACKGROUND_INTENSITY,
446 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only
446 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only
447 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only
447 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only
448 }
448 }
449
449
450 passthrough = {_FOREGROUND_INTENSITY,
450 passthrough = {_FOREGROUND_INTENSITY,
451 _BACKGROUND_INTENSITY,
451 _BACKGROUND_INTENSITY,
452 _COMMON_LVB_UNDERSCORE,
452 _COMMON_LVB_UNDERSCORE,
453 _COMMON_LVB_REVERSE_VIDEO}
453 _COMMON_LVB_REVERSE_VIDEO}
454
454
455 stdout = _kernel32.GetStdHandle(
455 stdout = _kernel32.GetStdHandle(
456 _STD_OUTPUT_HANDLE) # don't close the handle returned
456 _STD_OUTPUT_HANDLE) # don't close the handle returned
457 if stdout is None or stdout == _INVALID_HANDLE_VALUE:
457 if stdout is None or stdout == _INVALID_HANDLE_VALUE:
458 w32effects = None
458 w32effects = None
459 else:
459 else:
460 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
460 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
461 if not _kernel32.GetConsoleScreenBufferInfo(
461 if not _kernel32.GetConsoleScreenBufferInfo(
462 stdout, ctypes.byref(csbi)):
462 stdout, ctypes.byref(csbi)):
463 # stdout may not support GetConsoleScreenBufferInfo()
463 # stdout may not support GetConsoleScreenBufferInfo()
464 # when called from subprocess or redirected
464 # when called from subprocess or redirected
465 w32effects = None
465 w32effects = None
466 else:
466 else:
467 origattr = csbi.wAttributes
467 origattr = csbi.wAttributes
468 ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)',
468 ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)',
469 re.MULTILINE | re.DOTALL)
469 re.MULTILINE | re.DOTALL)
470
470
471 def win32print(ui, writefunc, *msgs, **opts):
471 def win32print(ui, writefunc, *msgs, **opts):
472 for text in msgs:
472 for text in msgs:
473 _win32print(ui, text, writefunc, **opts)
473 _win32print(ui, text, writefunc, **opts)
474
474
475 def _win32print(ui, text, writefunc, **opts):
475 def _win32print(ui, text, writefunc, **opts):
476 label = opts.get('label', '')
476 label = opts.get('label', '')
477 attr = origattr
477 attr = origattr
478
478
479 def mapcolor(val, attr):
479 def mapcolor(val, attr):
480 if val == -1:
480 if val == -1:
481 return origattr
481 return origattr
482 elif val in passthrough:
482 elif val in passthrough:
483 return attr | val
483 return attr | val
484 elif val > 0x0f:
484 elif val > 0x0f:
485 return (val & 0x70) | (attr & 0x8f)
485 return (val & 0x70) | (attr & 0x8f)
486 else:
486 else:
487 return (val & 0x07) | (attr & 0xf8)
487 return (val & 0x07) | (attr & 0xf8)
488
488
489 # determine console attributes based on labels
489 # determine console attributes based on labels
490 for l in label.split():
490 for l in label.split():
491 style = ui._styles.get(l, '')
491 style = ui._styles.get(l, '')
492 for effect in style.split():
492 for effect in style.split():
493 try:
493 try:
494 attr = mapcolor(w32effects[effect], attr)
494 attr = mapcolor(w32effects[effect], attr)
495 except KeyError:
495 except KeyError:
496 # w32effects could not have certain attributes so we skip
496 # w32effects could not have certain attributes so we skip
497 # them if not found
497 # them if not found
498 pass
498 pass
499 # hack to ensure regexp finds data
499 # hack to ensure regexp finds data
500 if not text.startswith('\033['):
500 if not text.startswith('\033['):
501 text = '\033[m' + text
501 text = '\033[m' + text
502
502
503 # Look for ANSI-like codes embedded in text
503 # Look for ANSI-like codes embedded in text
504 m = re.match(ansire, text)
504 m = re.match(ansire, text)
505
505
506 try:
506 try:
507 while m:
507 while m:
508 for sattr in m.group(1).split(';'):
508 for sattr in m.group(1).split(';'):
509 if sattr:
509 if sattr:
510 attr = mapcolor(int(sattr), attr)
510 attr = mapcolor(int(sattr), attr)
511 ui.flush()
511 ui.flush()
512 _kernel32.SetConsoleTextAttribute(stdout, attr)
512 _kernel32.SetConsoleTextAttribute(stdout, attr)
513 writefunc(m.group(2), **opts)
513 writefunc(m.group(2), **opts)
514 m = re.match(ansire, m.group(3))
514 m = re.match(ansire, m.group(3))
515 finally:
515 finally:
516 # Explicitly reset original attributes
516 # Explicitly reset original attributes
517 ui.flush()
517 ui.flush()
518 _kernel32.SetConsoleTextAttribute(stdout, origattr)
518 _kernel32.SetConsoleTextAttribute(stdout, origattr)
@@ -1,111 +1,113
1 HG
1 HG
2 Path to the 'hg' executable, automatically passed when running
2 Path to the 'hg' executable, automatically passed when running
3 hooks, extensions or external tools. If unset or empty, this is
3 hooks, extensions or external tools. If unset or empty, this is
4 the hg executable's name if it's frozen, or an executable named
4 the hg executable's name if it's frozen, or an executable named
5 'hg' (with %PATHEXT% [defaulting to COM/EXE/BAT/CMD] extensions on
5 'hg' (with %PATHEXT% [defaulting to COM/EXE/BAT/CMD] extensions on
6 Windows) is searched.
6 Windows) is searched.
7
7
8 HGEDITOR
8 HGEDITOR
9 This is the name of the editor to run when committing. See EDITOR.
9 This is the name of the editor to run when committing. See EDITOR.
10
10
11 (deprecated, see :hg:`help config.ui.editor`)
11 (deprecated, see :hg:`help config.ui.editor`)
12
12
13 HGENCODING
13 HGENCODING
14 This overrides the default locale setting detected by Mercurial.
14 This overrides the default locale setting detected by Mercurial.
15 This setting is used to convert data including usernames,
15 This setting is used to convert data including usernames,
16 changeset descriptions, tag names, and branches. This setting can
16 changeset descriptions, tag names, and branches. This setting can
17 be overridden with the --encoding command-line option.
17 be overridden with the --encoding command-line option.
18
18
19 HGENCODINGMODE
19 HGENCODINGMODE
20 This sets Mercurial's behavior for handling unknown characters
20 This sets Mercurial's behavior for handling unknown characters
21 while transcoding user input. The default is "strict", which
21 while transcoding user input. The default is "strict", which
22 causes Mercurial to abort if it can't map a character. Other
22 causes Mercurial to abort if it can't map a character. Other
23 settings include "replace", which replaces unknown characters, and
23 settings include "replace", which replaces unknown characters, and
24 "ignore", which drops them. This setting can be overridden with
24 "ignore", which drops them. This setting can be overridden with
25 the --encodingmode command-line option.
25 the --encodingmode command-line option.
26
26
27 HGENCODINGAMBIGUOUS
27 HGENCODINGAMBIGUOUS
28 This sets Mercurial's behavior for handling characters with
28 This sets Mercurial's behavior for handling characters with
29 "ambiguous" widths like accented Latin characters with East Asian
29 "ambiguous" widths like accented Latin characters with East Asian
30 fonts. By default, Mercurial assumes ambiguous characters are
30 fonts. By default, Mercurial assumes ambiguous characters are
31 narrow, set this variable to "wide" if such characters cause
31 narrow, set this variable to "wide" if such characters cause
32 formatting problems.
32 formatting problems.
33
33
34 HGMERGE
34 HGMERGE
35 An executable to use for resolving merge conflicts. The program
35 An executable to use for resolving merge conflicts. The program
36 will be executed with three arguments: local file, remote file,
36 will be executed with three arguments: local file, remote file,
37 ancestor file.
37 ancestor file.
38
38
39 (deprecated, see :hg:`help config.ui.merge`)
39 (deprecated, see :hg:`help config.ui.merge`)
40
40
41 HGRCPATH
41 HGRCPATH
42 A list of files or directories to search for configuration
42 A list of files or directories to search for configuration
43 files. Item separator is ":" on Unix, ";" on Windows. If HGRCPATH
43 files. Item separator is ":" on Unix, ";" on Windows. If HGRCPATH
44 is not set, platform default search path is used. If empty, only
44 is not set, platform default search path is used. If empty, only
45 the .hg/hgrc from the current repository is read.
45 the .hg/hgrc from the current repository is read.
46
46
47 For each element in HGRCPATH:
47 For each element in HGRCPATH:
48
48
49 - if it's a directory, all files ending with .rc are added
49 - if it's a directory, all files ending with .rc are added
50 - otherwise, the file itself will be added
50 - otherwise, the file itself will be added
51
51
52 HGPLAIN
52 HGPLAIN
53 When set, this disables any configuration settings that might
53 When set, this disables any configuration settings that might
54 change Mercurial's default output. This includes encoding,
54 change Mercurial's default output. This includes encoding,
55 defaults, verbose mode, debug mode, quiet mode, tracebacks, and
55 defaults, verbose mode, debug mode, quiet mode, tracebacks, and
56 localization. This can be useful when scripting against Mercurial
56 localization. This can be useful when scripting against Mercurial
57 in the face of existing user configuration.
57 in the face of existing user configuration.
58
58
59 Equivalent options set via command line flags or environment
59 Equivalent options set via command line flags or environment
60 variables are not overridden.
60 variables are not overridden.
61
61
62 HGPLAINEXCEPT
62 HGPLAINEXCEPT
63 This is a comma-separated list of features to preserve when
63 This is a comma-separated list of features to preserve when
64 HGPLAIN is enabled. Currently the following values are supported:
64 HGPLAIN is enabled. Currently the following values are supported:
65
65
66 ``alias``
66 ``alias``
67 Don't remove aliases.
67 Don't remove aliases.
68 ``color``
69 Don't disable colored output.
68 ``i18n``
70 ``i18n``
69 Preserve internationalization.
71 Preserve internationalization.
70 ``revsetalias``
72 ``revsetalias``
71 Don't remove revset aliases.
73 Don't remove revset aliases.
72 ``templatealias``
74 ``templatealias``
73 Don't remove template aliases.
75 Don't remove template aliases.
74 ``progress``
76 ``progress``
75 Don't hide progress output.
77 Don't hide progress output.
76
78
77 Setting HGPLAINEXCEPT to anything (even an empty string) will
79 Setting HGPLAINEXCEPT to anything (even an empty string) will
78 enable plain mode.
80 enable plain mode.
79
81
80 HGUSER
82 HGUSER
81 This is the string used as the author of a commit. If not set,
83 This is the string used as the author of a commit. If not set,
82 available values will be considered in this order:
84 available values will be considered in this order:
83
85
84 - HGUSER (deprecated)
86 - HGUSER (deprecated)
85 - configuration files from the HGRCPATH
87 - configuration files from the HGRCPATH
86 - EMAIL
88 - EMAIL
87 - interactive prompt
89 - interactive prompt
88 - LOGNAME (with ``@hostname`` appended)
90 - LOGNAME (with ``@hostname`` appended)
89
91
90 (deprecated, see :hg:`help config.ui.username`)
92 (deprecated, see :hg:`help config.ui.username`)
91
93
92 EMAIL
94 EMAIL
93 May be used as the author of a commit; see HGUSER.
95 May be used as the author of a commit; see HGUSER.
94
96
95 LOGNAME
97 LOGNAME
96 May be used as the author of a commit; see HGUSER.
98 May be used as the author of a commit; see HGUSER.
97
99
98 VISUAL
100 VISUAL
99 This is the name of the editor to use when committing. See EDITOR.
101 This is the name of the editor to use when committing. See EDITOR.
100
102
101 EDITOR
103 EDITOR
102 Sometimes Mercurial needs to open a text file in an editor for a
104 Sometimes Mercurial needs to open a text file in an editor for a
103 user to modify, for example when writing commit messages. The
105 user to modify, for example when writing commit messages. The
104 editor it uses is determined by looking at the environment
106 editor it uses is determined by looking at the environment
105 variables HGEDITOR, VISUAL and EDITOR, in that order. The first
107 variables HGEDITOR, VISUAL and EDITOR, in that order. The first
106 non-empty one is chosen. If all of them are empty, the editor
108 non-empty one is chosen. If all of them are empty, the editor
107 defaults to 'vi'.
109 defaults to 'vi'.
108
110
109 PYTHONPATH
111 PYTHONPATH
110 This is used by Python to find imported modules and may need to be
112 This is used by Python to find imported modules and may need to be
111 set appropriately if this Mercurial is not installed system-wide.
113 set appropriately if this Mercurial is not installed system-wide.
@@ -1,389 +1,405
1 $ cat <<EOF >> $HGRCPATH
1 $ cat <<EOF >> $HGRCPATH
2 > [ui]
2 > [ui]
3 > color = always
3 > color = always
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
17 $ hg status
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 HGPLAIN disables color
33 $ HGPLAIN=1 hg status --color=debug
34 ? a/1/in_a_1
35 ? a/in_a
36 ? b/1/in_b_1
37 ? b/2/in_b_2
38 ? b/in_b
39 ? in_root
40 HGPLAINEXCEPT=color does not disable color
41 $ HGPLAINEXCEPT=color hg status --color=debug
42 [status.unknown|? ][status.unknown|a/1/in_a_1]
43 [status.unknown|? ][status.unknown|a/in_a]
44 [status.unknown|? ][status.unknown|b/1/in_b_1]
45 [status.unknown|? ][status.unknown|b/2/in_b_2]
46 [status.unknown|? ][status.unknown|b/in_b]
47 [status.unknown|? ][status.unknown|in_root]
32
48
33 hg status with template
49 hg status with template
34 $ hg status -T "{label('red', path)}\n" --color=debug
50 $ hg status -T "{label('red', path)}\n" --color=debug
35 [red|a/1/in_a_1]
51 [red|a/1/in_a_1]
36 [red|a/in_a]
52 [red|a/in_a]
37 [red|b/1/in_b_1]
53 [red|b/1/in_b_1]
38 [red|b/2/in_b_2]
54 [red|b/2/in_b_2]
39 [red|b/in_b]
55 [red|b/in_b]
40 [red|in_root]
56 [red|in_root]
41
57
42 hg status . in repo root:
58 hg status . in repo root:
43
59
44 $ hg status .
60 $ hg status .
45 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
61 \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)
62 \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)
63 \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)
64 \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)
65 \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)
66 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
51
67
52 $ hg status --cwd a
68 $ hg status --cwd a
53 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
69 \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)
70 \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)
71 \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)
72 \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)
73 \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)
74 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
59 $ hg status --cwd a .
75 $ hg status --cwd a .
60 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m1/in_a_1\x1b[0m (esc)
76 \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)
77 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a\x1b[0m (esc)
62 $ hg status --cwd a ..
78 $ hg status --cwd a ..
63 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m1/in_a_1\x1b[0m (esc)
79 \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)
80 \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)
81 \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)
82 \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)
83 \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)
84 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_root\x1b[0m (esc)
69
85
70 $ hg status --cwd b
86 $ hg status --cwd b
71 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
87 \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)
88 \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)
89 \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)
90 \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)
91 \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)
92 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
77 $ hg status --cwd b .
93 $ hg status --cwd b .
78 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m1/in_b_1\x1b[0m (esc)
94 \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)
95 \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)
96 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b\x1b[0m (esc)
81 $ hg status --cwd b ..
97 $ hg status --cwd b ..
82 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../a/1/in_a_1\x1b[0m (esc)
98 \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)
99 \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)
100 \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)
101 \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)
102 \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)
103 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_root\x1b[0m (esc)
88
104
89 $ hg status --cwd a/1
105 $ hg status --cwd a/1
90 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
106 \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)
107 \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)
108 \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)
109 \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)
110 \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)
111 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
96 $ hg status --cwd a/1 .
112 $ hg status --cwd a/1 .
97 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a_1\x1b[0m (esc)
113 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a_1\x1b[0m (esc)
98 $ hg status --cwd a/1 ..
114 $ hg status --cwd a/1 ..
99 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_a_1\x1b[0m (esc)
115 \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)
116 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_a\x1b[0m (esc)
101
117
102 $ hg status --cwd b/1
118 $ hg status --cwd b/1
103 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
119 \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)
120 \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)
121 \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)
122 \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)
123 \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)
124 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
109 $ hg status --cwd b/1 .
125 $ hg status --cwd b/1 .
110 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_1\x1b[0m (esc)
126 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_1\x1b[0m (esc)
111 $ hg status --cwd b/1 ..
127 $ hg status --cwd b/1 ..
112 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_1\x1b[0m (esc)
128 \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)
129 \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)
130 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_b\x1b[0m (esc)
115
131
116 $ hg status --cwd b/2
132 $ hg status --cwd b/2
117 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4ma/1/in_a_1\x1b[0m (esc)
133 \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)
134 \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)
135 \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)
136 \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)
137 \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)
138 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_root\x1b[0m (esc)
123 $ hg status --cwd b/2 .
139 $ hg status --cwd b/2 .
124 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_2\x1b[0m (esc)
140 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4min_b_2\x1b[0m (esc)
125 $ hg status --cwd b/2 ..
141 $ hg status --cwd b/2 ..
126 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../1/in_b_1\x1b[0m (esc)
142 \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)
143 \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)
144 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4m../in_b\x1b[0m (esc)
129
145
130 Make sure --color=never works
146 Make sure --color=never works
131 $ hg status --color=never
147 $ hg status --color=never
132 ? a/1/in_a_1
148 ? a/1/in_a_1
133 ? a/in_a
149 ? a/in_a
134 ? b/1/in_b_1
150 ? b/1/in_b_1
135 ? b/2/in_b_2
151 ? b/2/in_b_2
136 ? b/in_b
152 ? b/in_b
137 ? in_root
153 ? in_root
138
154
139 Make sure ui.formatted=False works
155 Make sure ui.formatted=False works
140 $ hg status --color=auto --config ui.formatted=False
156 $ hg status --color=auto --config ui.formatted=False
141 ? a/1/in_a_1
157 ? a/1/in_a_1
142 ? a/in_a
158 ? a/in_a
143 ? b/1/in_b_1
159 ? b/1/in_b_1
144 ? b/2/in_b_2
160 ? b/2/in_b_2
145 ? b/in_b
161 ? b/in_b
146 ? in_root
162 ? in_root
147
163
148 $ cd ..
164 $ cd ..
149
165
150 $ hg init repo2
166 $ hg init repo2
151 $ cd repo2
167 $ cd repo2
152 $ touch modified removed deleted ignored
168 $ touch modified removed deleted ignored
153 $ echo "^ignored$" > .hgignore
169 $ echo "^ignored$" > .hgignore
154 $ hg ci -A -m 'initial checkin'
170 $ hg ci -A -m 'initial checkin'
155 adding .hgignore
171 adding .hgignore
156 adding deleted
172 adding deleted
157 adding modified
173 adding modified
158 adding removed
174 adding removed
159 $ hg log --color=debug
175 $ hg log --color=debug
160 [log.changeset changeset.draft|changeset: 0:389aef86a55e]
176 [log.changeset changeset.draft|changeset: 0:389aef86a55e]
161 [log.tag|tag: tip]
177 [log.tag|tag: tip]
162 [log.user|user: test]
178 [log.user|user: test]
163 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
179 [log.date|date: Thu Jan 01 00:00:00 1970 +0000]
164 [log.summary|summary: initial checkin]
180 [log.summary|summary: initial checkin]
165
181
166 $ hg log -Tcompact --color=debug
182 $ 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]
183 [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]
184 [ui.note log.description|initial checkin]
169
185
170 Labels on empty strings should not be displayed, labels on custom
186 Labels on empty strings should not be displayed, labels on custom
171 templates should be.
187 templates should be.
172
188
173 $ hg log --color=debug -T '{label("my.label",author)}\n{label("skipped.label","")}'
189 $ hg log --color=debug -T '{label("my.label",author)}\n{label("skipped.label","")}'
174 [my.label|test]
190 [my.label|test]
175 $ touch modified added unknown ignored
191 $ touch modified added unknown ignored
176 $ hg add added
192 $ hg add added
177 $ hg remove removed
193 $ hg remove removed
178 $ rm deleted
194 $ rm deleted
179
195
180 hg status:
196 hg status:
181
197
182 $ hg status
198 $ hg status
183 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
199 \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)
200 \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)
201 \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)
202 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
187
203
188 hg status modified added removed deleted unknown never-existed ignored:
204 hg status modified added removed deleted unknown never-existed ignored:
189
205
190 $ hg status modified added removed deleted unknown never-existed ignored
206 $ hg status modified added removed deleted unknown never-existed ignored
191 never-existed: * (glob)
207 never-existed: * (glob)
192 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
208 \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)
209 \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)
210 \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)
211 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
196
212
197 $ hg copy modified copied
213 $ hg copy modified copied
198
214
199 hg status -C:
215 hg status -C:
200
216
201 $ hg status -C
217 $ hg status -C
202 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
218 \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)
219 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mcopied\x1b[0m (esc)
204 \x1b[0;0m modified\x1b[0m (esc)
220 \x1b[0;0m modified\x1b[0m (esc)
205 \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
221 \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)
222 \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)
223 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
208
224
209 hg status -A:
225 hg status -A:
210
226
211 $ hg status -A
227 $ hg status -A
212 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
228 \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)
229 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mcopied\x1b[0m (esc)
214 \x1b[0;0m modified\x1b[0m (esc)
230 \x1b[0;0m modified\x1b[0m (esc)
215 \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
231 \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)
232 \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)
233 \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)
234 \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)
235 \x1b[0;0mC \x1b[0m\x1b[0;0m.hgignore\x1b[0m (esc)
220 \x1b[0;0mC \x1b[0m\x1b[0;0mmodified\x1b[0m (esc)
236 \x1b[0;0mC \x1b[0m\x1b[0;0mmodified\x1b[0m (esc)
221
237
222
238
223 hg status -A (with terminfo color):
239 hg status -A (with terminfo color):
224
240
225 #if tic
241 #if tic
226
242
227 $ mkdir "$TESTTMP/terminfo"
243 $ mkdir "$TESTTMP/terminfo"
228 $ TERMINFO="$TESTTMP/terminfo" tic "$TESTDIR/hgterm.ti"
244 $ TERMINFO="$TESTTMP/terminfo" tic "$TESTDIR/hgterm.ti"
229 $ TERM=hgterm TERMINFO="$TESTTMP/terminfo" hg status --config color.mode=terminfo -A
245 $ TERM=hgterm TERMINFO="$TESTTMP/terminfo" hg status --config color.mode=terminfo -A
230 \x1b[30m\x1b[32m\x1b[1mA \x1b[30m\x1b[30m\x1b[32m\x1b[1madded\x1b[30m (esc)
246 \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)
247 \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)
248 \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)
249 \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)
250 \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)
251 \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)
252 \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)
253 \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)
254 \x1b[30m\x1b[30mC \x1b[30m\x1b[30m\x1b[30mmodified\x1b[30m (esc)
239
255
240 The user can define effects with raw terminfo codes:
256 The user can define effects with raw terminfo codes:
241
257
242 $ cat <<EOF >> $HGRCPATH
258 $ cat <<EOF >> $HGRCPATH
243 > # Completely bogus code for dim
259 > # Completely bogus code for dim
244 > terminfo.dim = \E[88m
260 > terminfo.dim = \E[88m
245 > # We can override what's in the terminfo database, too
261 > # We can override what's in the terminfo database, too
246 > terminfo.bold = \E[2m
262 > terminfo.bold = \E[2m
247 > EOF
263 > EOF
248 $ TERM=hgterm TERMINFO="$TESTTMP/terminfo" hg status --config color.mode=terminfo --config color.status.clean=dim -A
264 $ TERM=hgterm TERMINFO="$TESTTMP/terminfo" hg status --config color.mode=terminfo --config color.status.clean=dim -A
249 \x1b[30m\x1b[32m\x1b[2mA \x1b[30m\x1b[30m\x1b[32m\x1b[2madded\x1b[30m (esc)
265 \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)
266 \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)
267 \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)
268 \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)
269 \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)
270 \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)
271 \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)
272 \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)
273 \x1b[30m\x1b[88mC \x1b[30m\x1b[30m\x1b[88mmodified\x1b[30m (esc)
258
274
259 #endif
275 #endif
260
276
261
277
262 $ echo "^ignoreddir$" > .hgignore
278 $ echo "^ignoreddir$" > .hgignore
263 $ mkdir ignoreddir
279 $ mkdir ignoreddir
264 $ touch ignoreddir/file
280 $ touch ignoreddir/file
265
281
266 hg status ignoreddir/file:
282 hg status ignoreddir/file:
267
283
268 $ hg status ignoreddir/file
284 $ hg status ignoreddir/file
269
285
270 hg status -i ignoreddir/file:
286 hg status -i ignoreddir/file:
271
287
272 $ hg status -i ignoreddir/file
288 $ hg status -i ignoreddir/file
273 \x1b[0;30;1mI \x1b[0m\x1b[0;30;1mignoreddir/file\x1b[0m (esc)
289 \x1b[0;30;1mI \x1b[0m\x1b[0;30;1mignoreddir/file\x1b[0m (esc)
274 $ cd ..
290 $ cd ..
275
291
276 check 'status -q' and some combinations
292 check 'status -q' and some combinations
277
293
278 $ hg init repo3
294 $ hg init repo3
279 $ cd repo3
295 $ cd repo3
280 $ touch modified removed deleted ignored
296 $ touch modified removed deleted ignored
281 $ echo "^ignored$" > .hgignore
297 $ echo "^ignored$" > .hgignore
282 $ hg commit -A -m 'initial checkin'
298 $ hg commit -A -m 'initial checkin'
283 adding .hgignore
299 adding .hgignore
284 adding deleted
300 adding deleted
285 adding modified
301 adding modified
286 adding removed
302 adding removed
287 $ touch added unknown ignored
303 $ touch added unknown ignored
288 $ hg add added
304 $ hg add added
289 $ echo "test" >> modified
305 $ echo "test" >> modified
290 $ hg remove removed
306 $ hg remove removed
291 $ rm deleted
307 $ rm deleted
292 $ hg copy modified copied
308 $ hg copy modified copied
293
309
294 test unknown color
310 test unknown color
295
311
296 $ hg --config color.status.modified=periwinkle status
312 $ hg --config color.status.modified=periwinkle status
297 ignoring unknown color/effect 'periwinkle' (configured in color.status.modified)
313 ignoring unknown color/effect 'periwinkle' (configured in color.status.modified)
298 ignoring unknown color/effect 'periwinkle' (configured in color.status.modified)
314 ignoring unknown color/effect 'periwinkle' (configured in color.status.modified)
299 ignoring unknown color/effect 'periwinkle' (configured in color.status.modified)
315 ignoring unknown color/effect 'periwinkle' (configured in color.status.modified)
300 M modified
316 M modified
301 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
317 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1madded\x1b[0m (esc)
302 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mcopied\x1b[0m (esc)
318 \x1b[0;32;1mA \x1b[0m\x1b[0;32;1mcopied\x1b[0m (esc)
303 \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
319 \x1b[0;31;1mR \x1b[0m\x1b[0;31;1mremoved\x1b[0m (esc)
304 \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
320 \x1b[0;36;1;4m! \x1b[0m\x1b[0;36;1;4mdeleted\x1b[0m (esc)
305 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
321 \x1b[0;35;1;4m? \x1b[0m\x1b[0;35;1;4munknown\x1b[0m (esc)
306
322
307 Run status with 2 different flags.
323 Run status with 2 different flags.
308 Check if result is the same or different.
324 Check if result is the same or different.
309 If result is not as expected, raise error
325 If result is not as expected, raise error
310
326
311 $ assert() {
327 $ assert() {
312 > hg status $1 > ../a
328 > hg status $1 > ../a
313 > hg status $2 > ../b
329 > hg status $2 > ../b
314 > if diff ../a ../b > /dev/null; then
330 > if diff ../a ../b > /dev/null; then
315 > out=0
331 > out=0
316 > else
332 > else
317 > out=1
333 > out=1
318 > fi
334 > fi
319 > if [ $3 -eq 0 ]; then
335 > if [ $3 -eq 0 ]; then
320 > df="same"
336 > df="same"
321 > else
337 > else
322 > df="different"
338 > df="different"
323 > fi
339 > fi
324 > if [ $out -ne $3 ]; then
340 > if [ $out -ne $3 ]; then
325 > echo "Error on $1 and $2, should be $df."
341 > echo "Error on $1 and $2, should be $df."
326 > fi
342 > fi
327 > }
343 > }
328
344
329 assert flag1 flag2 [0-same | 1-different]
345 assert flag1 flag2 [0-same | 1-different]
330
346
331 $ assert "-q" "-mard" 0
347 $ assert "-q" "-mard" 0
332 $ assert "-A" "-marduicC" 0
348 $ assert "-A" "-marduicC" 0
333 $ assert "-qA" "-mardcC" 0
349 $ assert "-qA" "-mardcC" 0
334 $ assert "-qAui" "-A" 0
350 $ assert "-qAui" "-A" 0
335 $ assert "-qAu" "-marducC" 0
351 $ assert "-qAu" "-marducC" 0
336 $ assert "-qAi" "-mardicC" 0
352 $ assert "-qAi" "-mardicC" 0
337 $ assert "-qu" "-u" 0
353 $ assert "-qu" "-u" 0
338 $ assert "-q" "-u" 1
354 $ assert "-q" "-u" 1
339 $ assert "-m" "-a" 1
355 $ assert "-m" "-a" 1
340 $ assert "-r" "-d" 1
356 $ assert "-r" "-d" 1
341 $ cd ..
357 $ cd ..
342
358
343 test 'resolve -l'
359 test 'resolve -l'
344
360
345 $ hg init repo4
361 $ hg init repo4
346 $ cd repo4
362 $ cd repo4
347 $ echo "file a" > a
363 $ echo "file a" > a
348 $ echo "file b" > b
364 $ echo "file b" > b
349 $ hg add a b
365 $ hg add a b
350 $ hg commit -m "initial"
366 $ hg commit -m "initial"
351 $ echo "file a change 1" > a
367 $ echo "file a change 1" > a
352 $ echo "file b change 1" > b
368 $ echo "file b change 1" > b
353 $ hg commit -m "head 1"
369 $ hg commit -m "head 1"
354 $ hg update 0
370 $ hg update 0
355 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
371 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
356 $ echo "file a change 2" > a
372 $ echo "file a change 2" > a
357 $ echo "file b change 2" > b
373 $ echo "file b change 2" > b
358 $ hg commit -m "head 2"
374 $ hg commit -m "head 2"
359 created new head
375 created new head
360 $ hg merge
376 $ hg merge
361 merging a
377 merging a
362 merging b
378 merging b
363 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
379 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
364 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
380 warning: conflicts while merging b! (edit, then use 'hg resolve --mark')
365 0 files updated, 0 files merged, 0 files removed, 2 files unresolved
381 0 files updated, 0 files merged, 0 files removed, 2 files unresolved
366 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
382 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
367 [1]
383 [1]
368 $ hg resolve -m b
384 $ hg resolve -m b
369
385
370 hg resolve with one unresolved, one resolved:
386 hg resolve with one unresolved, one resolved:
371
387
372 $ hg resolve -l
388 $ hg resolve -l
373 \x1b[0;31;1mU \x1b[0m\x1b[0;31;1ma\x1b[0m (esc)
389 \x1b[0;31;1mU \x1b[0m\x1b[0;31;1ma\x1b[0m (esc)
374 \x1b[0;32;1mR \x1b[0m\x1b[0;32;1mb\x1b[0m (esc)
390 \x1b[0;32;1mR \x1b[0m\x1b[0;32;1mb\x1b[0m (esc)
375
391
376 color coding of error message with current availability of curses
392 color coding of error message with current availability of curses
377
393
378 $ hg unknowncommand > /dev/null
394 $ hg unknowncommand > /dev/null
379 hg: unknown command 'unknowncommand'
395 hg: unknown command 'unknowncommand'
380 [255]
396 [255]
381
397
382 color coding of error message without curses
398 color coding of error message without curses
383
399
384 $ echo 'raise ImportError' > curses.py
400 $ echo 'raise ImportError' > curses.py
385 $ PYTHONPATH=`pwd`:$PYTHONPATH hg unknowncommand > /dev/null
401 $ PYTHONPATH=`pwd`:$PYTHONPATH hg unknowncommand > /dev/null
386 hg: unknown command 'unknowncommand'
402 hg: unknown command 'unknowncommand'
387 [255]
403 [255]
388
404
389 $ cd ..
405 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now