##// END OF EJS Templates
color: change color of grep.rev label (BC)...
Jordi Gutiérrez Hermoso -
r41889:a91615b7 default
parent child Browse files
Show More
@@ -1,534 +1,534
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 )
17 )
18
18
19 from .utils import (
19 from .utils import (
20 stringutil,
20 stringutil,
21 )
21 )
22
22
23 try:
23 try:
24 import curses
24 import curses
25 # Mapping from effect name to terminfo attribute name (or raw code) or
25 # Mapping from effect name to terminfo attribute name (or raw code) or
26 # color number. This will also force-load the curses module.
26 # color number. This will also force-load the curses module.
27 _baseterminfoparams = {
27 _baseterminfoparams = {
28 'none': (True, 'sgr0', ''),
28 'none': (True, 'sgr0', ''),
29 'standout': (True, 'smso', ''),
29 'standout': (True, 'smso', ''),
30 'underline': (True, 'smul', ''),
30 'underline': (True, 'smul', ''),
31 'reverse': (True, 'rev', ''),
31 'reverse': (True, 'rev', ''),
32 'inverse': (True, 'rev', ''),
32 'inverse': (True, 'rev', ''),
33 'blink': (True, 'blink', ''),
33 'blink': (True, 'blink', ''),
34 'dim': (True, 'dim', ''),
34 'dim': (True, 'dim', ''),
35 'bold': (True, 'bold', ''),
35 'bold': (True, 'bold', ''),
36 'invisible': (True, 'invis', ''),
36 'invisible': (True, 'invis', ''),
37 'italic': (True, 'sitm', ''),
37 'italic': (True, 'sitm', ''),
38 'black': (False, curses.COLOR_BLACK, ''),
38 'black': (False, curses.COLOR_BLACK, ''),
39 'red': (False, curses.COLOR_RED, ''),
39 'red': (False, curses.COLOR_RED, ''),
40 'green': (False, curses.COLOR_GREEN, ''),
40 'green': (False, curses.COLOR_GREEN, ''),
41 'yellow': (False, curses.COLOR_YELLOW, ''),
41 'yellow': (False, curses.COLOR_YELLOW, ''),
42 'blue': (False, curses.COLOR_BLUE, ''),
42 'blue': (False, curses.COLOR_BLUE, ''),
43 'magenta': (False, curses.COLOR_MAGENTA, ''),
43 'magenta': (False, curses.COLOR_MAGENTA, ''),
44 'cyan': (False, curses.COLOR_CYAN, ''),
44 'cyan': (False, curses.COLOR_CYAN, ''),
45 'white': (False, curses.COLOR_WHITE, ''),
45 'white': (False, curses.COLOR_WHITE, ''),
46 }
46 }
47 except ImportError:
47 except ImportError:
48 curses = None
48 curses = None
49 _baseterminfoparams = {}
49 _baseterminfoparams = {}
50
50
51 # start and stop parameters for effects
51 # start and stop parameters for effects
52 _effects = {
52 _effects = {
53 'none': 0,
53 'none': 0,
54 'black': 30,
54 'black': 30,
55 'red': 31,
55 'red': 31,
56 'green': 32,
56 'green': 32,
57 'yellow': 33,
57 'yellow': 33,
58 'blue': 34,
58 'blue': 34,
59 'magenta': 35,
59 'magenta': 35,
60 'cyan': 36,
60 'cyan': 36,
61 'white': 37,
61 'white': 37,
62 'bold': 1,
62 'bold': 1,
63 'italic': 3,
63 'italic': 3,
64 'underline': 4,
64 'underline': 4,
65 'inverse': 7,
65 'inverse': 7,
66 'dim': 2,
66 'dim': 2,
67 'black_background': 40,
67 'black_background': 40,
68 'red_background': 41,
68 'red_background': 41,
69 'green_background': 42,
69 'green_background': 42,
70 'yellow_background': 43,
70 'yellow_background': 43,
71 'blue_background': 44,
71 'blue_background': 44,
72 'purple_background': 45,
72 'purple_background': 45,
73 'cyan_background': 46,
73 'cyan_background': 46,
74 'white_background': 47,
74 'white_background': 47,
75 }
75 }
76
76
77 _defaultstyles = {
77 _defaultstyles = {
78 'grep.match': 'red bold',
78 'grep.match': 'red bold',
79 'grep.linenumber': 'green',
79 'grep.linenumber': 'green',
80 'grep.rev': 'green',
80 'grep.rev': 'blue',
81 'grep.sep': 'cyan',
81 'grep.sep': 'cyan',
82 'grep.filename': 'magenta',
82 'grep.filename': 'magenta',
83 'grep.user': 'magenta',
83 'grep.user': 'magenta',
84 'grep.date': 'magenta',
84 'grep.date': 'magenta',
85 'grep.inserted': 'green bold',
85 'grep.inserted': 'green bold',
86 'grep.deleted': 'red bold',
86 'grep.deleted': 'red bold',
87 'bookmarks.active': 'green',
87 'bookmarks.active': 'green',
88 'branches.active': 'none',
88 'branches.active': 'none',
89 'branches.closed': 'black bold',
89 'branches.closed': 'black bold',
90 'branches.current': 'green',
90 'branches.current': 'green',
91 'branches.inactive': 'none',
91 'branches.inactive': 'none',
92 'diff.changed': 'white',
92 'diff.changed': 'white',
93 'diff.deleted': 'red',
93 'diff.deleted': 'red',
94 'diff.deleted.changed': 'red bold underline',
94 'diff.deleted.changed': 'red bold underline',
95 'diff.deleted.unchanged': 'red',
95 'diff.deleted.unchanged': 'red',
96 'diff.diffline': 'bold',
96 'diff.diffline': 'bold',
97 'diff.extended': 'cyan bold',
97 'diff.extended': 'cyan bold',
98 'diff.file_a': 'red bold',
98 'diff.file_a': 'red bold',
99 'diff.file_b': 'green bold',
99 'diff.file_b': 'green bold',
100 'diff.hunk': 'magenta',
100 'diff.hunk': 'magenta',
101 'diff.inserted': 'green',
101 'diff.inserted': 'green',
102 'diff.inserted.changed': 'green bold underline',
102 'diff.inserted.changed': 'green bold underline',
103 'diff.inserted.unchanged': 'green',
103 'diff.inserted.unchanged': 'green',
104 'diff.tab': '',
104 'diff.tab': '',
105 'diff.trailingwhitespace': 'bold red_background',
105 'diff.trailingwhitespace': 'bold red_background',
106 'changeset.public': '',
106 'changeset.public': '',
107 'changeset.draft': '',
107 'changeset.draft': '',
108 'changeset.secret': '',
108 'changeset.secret': '',
109 'diffstat.deleted': 'red',
109 'diffstat.deleted': 'red',
110 'diffstat.inserted': 'green',
110 'diffstat.inserted': 'green',
111 'formatvariant.name.mismatchconfig': 'red',
111 'formatvariant.name.mismatchconfig': 'red',
112 'formatvariant.name.mismatchdefault': 'yellow',
112 'formatvariant.name.mismatchdefault': 'yellow',
113 'formatvariant.name.uptodate': 'green',
113 'formatvariant.name.uptodate': 'green',
114 'formatvariant.repo.mismatchconfig': 'red',
114 'formatvariant.repo.mismatchconfig': 'red',
115 'formatvariant.repo.mismatchdefault': 'yellow',
115 'formatvariant.repo.mismatchdefault': 'yellow',
116 'formatvariant.repo.uptodate': 'green',
116 'formatvariant.repo.uptodate': 'green',
117 'formatvariant.config.special': 'yellow',
117 'formatvariant.config.special': 'yellow',
118 'formatvariant.config.default': 'green',
118 'formatvariant.config.default': 'green',
119 'formatvariant.default': '',
119 'formatvariant.default': '',
120 'histedit.remaining': 'red bold',
120 'histedit.remaining': 'red bold',
121 'ui.addremove.added': 'green',
121 'ui.addremove.added': 'green',
122 'ui.addremove.removed': 'red',
122 'ui.addremove.removed': 'red',
123 'ui.error': 'red',
123 'ui.error': 'red',
124 'ui.prompt': 'yellow',
124 'ui.prompt': 'yellow',
125 'log.changeset': 'yellow',
125 'log.changeset': 'yellow',
126 'patchbomb.finalsummary': '',
126 'patchbomb.finalsummary': '',
127 'patchbomb.from': 'magenta',
127 'patchbomb.from': 'magenta',
128 'patchbomb.to': 'cyan',
128 'patchbomb.to': 'cyan',
129 'patchbomb.subject': 'green',
129 'patchbomb.subject': 'green',
130 'patchbomb.diffstats': '',
130 'patchbomb.diffstats': '',
131 'rebase.rebased': 'blue',
131 'rebase.rebased': 'blue',
132 'rebase.remaining': 'red bold',
132 'rebase.remaining': 'red bold',
133 'resolve.resolved': 'green bold',
133 'resolve.resolved': 'green bold',
134 'resolve.unresolved': 'red bold',
134 'resolve.unresolved': 'red bold',
135 'shelve.age': 'cyan',
135 'shelve.age': 'cyan',
136 'shelve.newest': 'green bold',
136 'shelve.newest': 'green bold',
137 'shelve.name': 'blue bold',
137 'shelve.name': 'blue bold',
138 'status.added': 'green bold',
138 'status.added': 'green bold',
139 'status.clean': 'none',
139 'status.clean': 'none',
140 'status.copied': 'none',
140 'status.copied': 'none',
141 'status.deleted': 'cyan bold underline',
141 'status.deleted': 'cyan bold underline',
142 'status.ignored': 'black bold',
142 'status.ignored': 'black bold',
143 'status.modified': 'blue bold',
143 'status.modified': 'blue bold',
144 'status.removed': 'red bold',
144 'status.removed': 'red bold',
145 'status.unknown': 'magenta bold underline',
145 'status.unknown': 'magenta bold underline',
146 'tags.normal': 'green',
146 'tags.normal': 'green',
147 'tags.local': 'black bold',
147 'tags.local': 'black bold',
148 }
148 }
149
149
150 def loadcolortable(ui, extname, colortable):
150 def loadcolortable(ui, extname, colortable):
151 _defaultstyles.update(colortable)
151 _defaultstyles.update(colortable)
152
152
153 def _terminfosetup(ui, mode, formatted):
153 def _terminfosetup(ui, mode, formatted):
154 '''Initialize terminfo data and the terminal if we're in terminfo mode.'''
154 '''Initialize terminfo data and the terminal if we're in terminfo mode.'''
155
155
156 # If we failed to load curses, we go ahead and return.
156 # If we failed to load curses, we go ahead and return.
157 if curses is None:
157 if curses is None:
158 return
158 return
159 # Otherwise, see what the config file says.
159 # Otherwise, see what the config file says.
160 if mode not in ('auto', 'terminfo'):
160 if mode not in ('auto', 'terminfo'):
161 return
161 return
162 ui._terminfoparams.update(_baseterminfoparams)
162 ui._terminfoparams.update(_baseterminfoparams)
163
163
164 for key, val in ui.configitems('color'):
164 for key, val in ui.configitems('color'):
165 if key.startswith('color.'):
165 if key.startswith('color.'):
166 newval = (False, int(val), '')
166 newval = (False, int(val), '')
167 ui._terminfoparams[key[6:]] = newval
167 ui._terminfoparams[key[6:]] = newval
168 elif key.startswith('terminfo.'):
168 elif key.startswith('terminfo.'):
169 newval = (True, '', val.replace('\\E', '\x1b'))
169 newval = (True, '', val.replace('\\E', '\x1b'))
170 ui._terminfoparams[key[9:]] = newval
170 ui._terminfoparams[key[9:]] = newval
171 try:
171 try:
172 curses.setupterm()
172 curses.setupterm()
173 except curses.error:
173 except curses.error:
174 ui._terminfoparams.clear()
174 ui._terminfoparams.clear()
175 return
175 return
176
176
177 for key, (b, e, c) in ui._terminfoparams.copy().items():
177 for key, (b, e, c) in ui._terminfoparams.copy().items():
178 if not b:
178 if not b:
179 continue
179 continue
180 if not c and not curses.tigetstr(pycompat.sysstr(e)):
180 if not c and not curses.tigetstr(pycompat.sysstr(e)):
181 # Most terminals don't support dim, invis, etc, so don't be
181 # Most terminals don't support dim, invis, etc, so don't be
182 # noisy and use ui.debug().
182 # noisy and use ui.debug().
183 ui.debug("no terminfo entry for %s\n" % e)
183 ui.debug("no terminfo entry for %s\n" % e)
184 del ui._terminfoparams[key]
184 del ui._terminfoparams[key]
185 if not curses.tigetstr(r'setaf') or not curses.tigetstr(r'setab'):
185 if not curses.tigetstr(r'setaf') or not curses.tigetstr(r'setab'):
186 # Only warn about missing terminfo entries if we explicitly asked for
186 # Only warn about missing terminfo entries if we explicitly asked for
187 # terminfo mode and we're in a formatted terminal.
187 # terminfo mode and we're in a formatted terminal.
188 if mode == "terminfo" and formatted:
188 if mode == "terminfo" and formatted:
189 ui.warn(_("no terminfo entry for setab/setaf: reverting to "
189 ui.warn(_("no terminfo entry for setab/setaf: reverting to "
190 "ECMA-48 color\n"))
190 "ECMA-48 color\n"))
191 ui._terminfoparams.clear()
191 ui._terminfoparams.clear()
192
192
193 def setup(ui):
193 def setup(ui):
194 """configure color on a ui
194 """configure color on a ui
195
195
196 That function both set the colormode for the ui object and read
196 That function both set the colormode for the ui object and read
197 the configuration looking for custom colors and effect definitions."""
197 the configuration looking for custom colors and effect definitions."""
198 mode = _modesetup(ui)
198 mode = _modesetup(ui)
199 ui._colormode = mode
199 ui._colormode = mode
200 if mode and mode != 'debug':
200 if mode and mode != 'debug':
201 configstyles(ui)
201 configstyles(ui)
202
202
203 def _modesetup(ui):
203 def _modesetup(ui):
204 if ui.plain('color'):
204 if ui.plain('color'):
205 return None
205 return None
206 config = ui.config('ui', 'color')
206 config = ui.config('ui', 'color')
207 if config == 'debug':
207 if config == 'debug':
208 return 'debug'
208 return 'debug'
209
209
210 auto = (config == 'auto')
210 auto = (config == 'auto')
211 always = False
211 always = False
212 if not auto and stringutil.parsebool(config):
212 if not auto and stringutil.parsebool(config):
213 # We want the config to behave like a boolean, "on" is actually auto,
213 # We want the config to behave like a boolean, "on" is actually auto,
214 # but "always" value is treated as a special case to reduce confusion.
214 # but "always" value is treated as a special case to reduce confusion.
215 if ui.configsource('ui', 'color') == '--color' or config == 'always':
215 if ui.configsource('ui', 'color') == '--color' or config == 'always':
216 always = True
216 always = True
217 else:
217 else:
218 auto = True
218 auto = True
219
219
220 if not always and not auto:
220 if not always and not auto:
221 return None
221 return None
222
222
223 formatted = (always or (encoding.environ.get('TERM') != 'dumb'
223 formatted = (always or (encoding.environ.get('TERM') != 'dumb'
224 and ui.formatted()))
224 and ui.formatted()))
225
225
226 mode = ui.config('color', 'mode')
226 mode = ui.config('color', 'mode')
227
227
228 # If pager is active, color.pagermode overrides color.mode.
228 # If pager is active, color.pagermode overrides color.mode.
229 if getattr(ui, 'pageractive', False):
229 if getattr(ui, 'pageractive', False):
230 mode = ui.config('color', 'pagermode', mode)
230 mode = ui.config('color', 'pagermode', mode)
231
231
232 realmode = mode
232 realmode = mode
233 if pycompat.iswindows:
233 if pycompat.iswindows:
234 from . import win32
234 from . import win32
235
235
236 term = encoding.environ.get('TERM')
236 term = encoding.environ.get('TERM')
237 # TERM won't be defined in a vanilla cmd.exe environment.
237 # TERM won't be defined in a vanilla cmd.exe environment.
238
238
239 # UNIX-like environments on Windows such as Cygwin and MSYS will
239 # UNIX-like environments on Windows such as Cygwin and MSYS will
240 # set TERM. They appear to make a best effort attempt at setting it
240 # set TERM. They appear to make a best effort attempt at setting it
241 # to something appropriate. However, not all environments with TERM
241 # to something appropriate. However, not all environments with TERM
242 # defined support ANSI.
242 # defined support ANSI.
243 ansienviron = term and 'xterm' in term
243 ansienviron = term and 'xterm' in term
244
244
245 if mode == 'auto':
245 if mode == 'auto':
246 # Since "ansi" could result in terminal gibberish, we error on the
246 # Since "ansi" could result in terminal gibberish, we error on the
247 # side of selecting "win32". However, if w32effects is not defined,
247 # side of selecting "win32". However, if w32effects is not defined,
248 # we almost certainly don't support "win32", so don't even try.
248 # we almost certainly don't support "win32", so don't even try.
249 # w32effects is not populated when stdout is redirected, so checking
249 # w32effects is not populated when stdout is redirected, so checking
250 # it first avoids win32 calls in a state known to error out.
250 # it first avoids win32 calls in a state known to error out.
251 if ansienviron or not w32effects or win32.enablevtmode():
251 if ansienviron or not w32effects or win32.enablevtmode():
252 realmode = 'ansi'
252 realmode = 'ansi'
253 else:
253 else:
254 realmode = 'win32'
254 realmode = 'win32'
255 # An empty w32effects is a clue that stdout is redirected, and thus
255 # An empty w32effects is a clue that stdout is redirected, and thus
256 # cannot enable VT mode.
256 # cannot enable VT mode.
257 elif mode == 'ansi' and w32effects and not ansienviron:
257 elif mode == 'ansi' and w32effects and not ansienviron:
258 win32.enablevtmode()
258 win32.enablevtmode()
259 elif mode == 'auto':
259 elif mode == 'auto':
260 realmode = 'ansi'
260 realmode = 'ansi'
261
261
262 def modewarn():
262 def modewarn():
263 # only warn if color.mode was explicitly set and we're in
263 # only warn if color.mode was explicitly set and we're in
264 # a formatted terminal
264 # a formatted terminal
265 if mode == realmode and formatted:
265 if mode == realmode and formatted:
266 ui.warn(_('warning: failed to set color mode to %s\n') % mode)
266 ui.warn(_('warning: failed to set color mode to %s\n') % mode)
267
267
268 if realmode == 'win32':
268 if realmode == 'win32':
269 ui._terminfoparams.clear()
269 ui._terminfoparams.clear()
270 if not w32effects:
270 if not w32effects:
271 modewarn()
271 modewarn()
272 return None
272 return None
273 elif realmode == 'ansi':
273 elif realmode == 'ansi':
274 ui._terminfoparams.clear()
274 ui._terminfoparams.clear()
275 elif realmode == 'terminfo':
275 elif realmode == 'terminfo':
276 _terminfosetup(ui, mode, formatted)
276 _terminfosetup(ui, mode, formatted)
277 if not ui._terminfoparams:
277 if not ui._terminfoparams:
278 ## FIXME Shouldn't we return None in this case too?
278 ## FIXME Shouldn't we return None in this case too?
279 modewarn()
279 modewarn()
280 realmode = 'ansi'
280 realmode = 'ansi'
281 else:
281 else:
282 return None
282 return None
283
283
284 if always or (auto and formatted):
284 if always or (auto and formatted):
285 return realmode
285 return realmode
286 return None
286 return None
287
287
288 def configstyles(ui):
288 def configstyles(ui):
289 ui._styles.update(_defaultstyles)
289 ui._styles.update(_defaultstyles)
290 for status, cfgeffects in ui.configitems('color'):
290 for status, cfgeffects in ui.configitems('color'):
291 if '.' not in status or status.startswith(('color.', 'terminfo.')):
291 if '.' not in status or status.startswith(('color.', 'terminfo.')):
292 continue
292 continue
293 cfgeffects = ui.configlist('color', status)
293 cfgeffects = ui.configlist('color', status)
294 if cfgeffects:
294 if cfgeffects:
295 good = []
295 good = []
296 for e in cfgeffects:
296 for e in cfgeffects:
297 if valideffect(ui, e):
297 if valideffect(ui, e):
298 good.append(e)
298 good.append(e)
299 else:
299 else:
300 ui.warn(_("ignoring unknown color/effect %s "
300 ui.warn(_("ignoring unknown color/effect %s "
301 "(configured in color.%s)\n")
301 "(configured in color.%s)\n")
302 % (stringutil.pprint(e), status))
302 % (stringutil.pprint(e), status))
303 ui._styles[status] = ' '.join(good)
303 ui._styles[status] = ' '.join(good)
304
304
305 def _activeeffects(ui):
305 def _activeeffects(ui):
306 '''Return the effects map for the color mode set on the ui.'''
306 '''Return the effects map for the color mode set on the ui.'''
307 if ui._colormode == 'win32':
307 if ui._colormode == 'win32':
308 return w32effects
308 return w32effects
309 elif ui._colormode is not None:
309 elif ui._colormode is not None:
310 return _effects
310 return _effects
311 return {}
311 return {}
312
312
313 def valideffect(ui, effect):
313 def valideffect(ui, effect):
314 'Determine if the effect is valid or not.'
314 'Determine if the effect is valid or not.'
315 return ((not ui._terminfoparams and effect in _activeeffects(ui))
315 return ((not ui._terminfoparams and effect in _activeeffects(ui))
316 or (effect in ui._terminfoparams
316 or (effect in ui._terminfoparams
317 or effect[:-11] in ui._terminfoparams))
317 or effect[:-11] in ui._terminfoparams))
318
318
319 def _effect_str(ui, effect):
319 def _effect_str(ui, effect):
320 '''Helper function for render_effects().'''
320 '''Helper function for render_effects().'''
321
321
322 bg = False
322 bg = False
323 if effect.endswith('_background'):
323 if effect.endswith('_background'):
324 bg = True
324 bg = True
325 effect = effect[:-11]
325 effect = effect[:-11]
326 try:
326 try:
327 attr, val, termcode = ui._terminfoparams[effect]
327 attr, val, termcode = ui._terminfoparams[effect]
328 except KeyError:
328 except KeyError:
329 return ''
329 return ''
330 if attr:
330 if attr:
331 if termcode:
331 if termcode:
332 return termcode
332 return termcode
333 else:
333 else:
334 return curses.tigetstr(pycompat.sysstr(val))
334 return curses.tigetstr(pycompat.sysstr(val))
335 elif bg:
335 elif bg:
336 return curses.tparm(curses.tigetstr(r'setab'), val)
336 return curses.tparm(curses.tigetstr(r'setab'), val)
337 else:
337 else:
338 return curses.tparm(curses.tigetstr(r'setaf'), val)
338 return curses.tparm(curses.tigetstr(r'setaf'), val)
339
339
340 def _mergeeffects(text, start, stop):
340 def _mergeeffects(text, start, stop):
341 """Insert start sequence at every occurrence of stop sequence
341 """Insert start sequence at every occurrence of stop sequence
342
342
343 >>> s = _mergeeffects(b'cyan', b'[C]', b'|')
343 >>> s = _mergeeffects(b'cyan', b'[C]', b'|')
344 >>> s = _mergeeffects(s + b'yellow', b'[Y]', b'|')
344 >>> s = _mergeeffects(s + b'yellow', b'[Y]', b'|')
345 >>> s = _mergeeffects(b'ma' + s + b'genta', b'[M]', b'|')
345 >>> s = _mergeeffects(b'ma' + s + b'genta', b'[M]', b'|')
346 >>> s = _mergeeffects(b'red' + s, b'[R]', b'|')
346 >>> s = _mergeeffects(b'red' + s, b'[R]', b'|')
347 >>> s
347 >>> s
348 '[R]red[M]ma[Y][C]cyan|[R][M][Y]yellow|[R][M]genta|'
348 '[R]red[M]ma[Y][C]cyan|[R][M][Y]yellow|[R][M]genta|'
349 """
349 """
350 parts = []
350 parts = []
351 for t in text.split(stop):
351 for t in text.split(stop):
352 if not t:
352 if not t:
353 continue
353 continue
354 parts.extend([start, t, stop])
354 parts.extend([start, t, stop])
355 return ''.join(parts)
355 return ''.join(parts)
356
356
357 def _render_effects(ui, text, effects):
357 def _render_effects(ui, text, effects):
358 'Wrap text in commands to turn on each effect.'
358 'Wrap text in commands to turn on each effect.'
359 if not text:
359 if not text:
360 return text
360 return text
361 if ui._terminfoparams:
361 if ui._terminfoparams:
362 start = ''.join(_effect_str(ui, effect)
362 start = ''.join(_effect_str(ui, effect)
363 for effect in ['none'] + effects.split())
363 for effect in ['none'] + effects.split())
364 stop = _effect_str(ui, 'none')
364 stop = _effect_str(ui, 'none')
365 else:
365 else:
366 activeeffects = _activeeffects(ui)
366 activeeffects = _activeeffects(ui)
367 start = [pycompat.bytestr(activeeffects[e])
367 start = [pycompat.bytestr(activeeffects[e])
368 for e in ['none'] + effects.split()]
368 for e in ['none'] + effects.split()]
369 start = '\033[' + ';'.join(start) + 'm'
369 start = '\033[' + ';'.join(start) + 'm'
370 stop = '\033[' + pycompat.bytestr(activeeffects['none']) + 'm'
370 stop = '\033[' + pycompat.bytestr(activeeffects['none']) + 'm'
371 return _mergeeffects(text, start, stop)
371 return _mergeeffects(text, start, stop)
372
372
373 _ansieffectre = re.compile(br'\x1b\[[0-9;]*m')
373 _ansieffectre = re.compile(br'\x1b\[[0-9;]*m')
374
374
375 def stripeffects(text):
375 def stripeffects(text):
376 """Strip ANSI control codes which could be inserted by colorlabel()"""
376 """Strip ANSI control codes which could be inserted by colorlabel()"""
377 return _ansieffectre.sub('', text)
377 return _ansieffectre.sub('', text)
378
378
379 def colorlabel(ui, msg, label):
379 def colorlabel(ui, msg, label):
380 """add color control code according to the mode"""
380 """add color control code according to the mode"""
381 if ui._colormode == 'debug':
381 if ui._colormode == 'debug':
382 if label and msg:
382 if label and msg:
383 if msg.endswith('\n'):
383 if msg.endswith('\n'):
384 msg = "[%s|%s]\n" % (label, msg[:-1])
384 msg = "[%s|%s]\n" % (label, msg[:-1])
385 else:
385 else:
386 msg = "[%s|%s]" % (label, msg)
386 msg = "[%s|%s]" % (label, msg)
387 elif ui._colormode is not None:
387 elif ui._colormode is not None:
388 effects = []
388 effects = []
389 for l in label.split():
389 for l in label.split():
390 s = ui._styles.get(l, '')
390 s = ui._styles.get(l, '')
391 if s:
391 if s:
392 effects.append(s)
392 effects.append(s)
393 elif valideffect(ui, l):
393 elif valideffect(ui, l):
394 effects.append(l)
394 effects.append(l)
395 effects = ' '.join(effects)
395 effects = ' '.join(effects)
396 if effects:
396 if effects:
397 msg = '\n'.join([_render_effects(ui, line, effects)
397 msg = '\n'.join([_render_effects(ui, line, effects)
398 for line in msg.split('\n')])
398 for line in msg.split('\n')])
399 return msg
399 return msg
400
400
401 w32effects = None
401 w32effects = None
402 if pycompat.iswindows:
402 if pycompat.iswindows:
403 import ctypes
403 import ctypes
404
404
405 _kernel32 = ctypes.windll.kernel32
405 _kernel32 = ctypes.windll.kernel32
406
406
407 _WORD = ctypes.c_ushort
407 _WORD = ctypes.c_ushort
408
408
409 _INVALID_HANDLE_VALUE = -1
409 _INVALID_HANDLE_VALUE = -1
410
410
411 class _COORD(ctypes.Structure):
411 class _COORD(ctypes.Structure):
412 _fields_ = [(r'X', ctypes.c_short),
412 _fields_ = [(r'X', ctypes.c_short),
413 (r'Y', ctypes.c_short)]
413 (r'Y', ctypes.c_short)]
414
414
415 class _SMALL_RECT(ctypes.Structure):
415 class _SMALL_RECT(ctypes.Structure):
416 _fields_ = [(r'Left', ctypes.c_short),
416 _fields_ = [(r'Left', ctypes.c_short),
417 (r'Top', ctypes.c_short),
417 (r'Top', ctypes.c_short),
418 (r'Right', ctypes.c_short),
418 (r'Right', ctypes.c_short),
419 (r'Bottom', ctypes.c_short)]
419 (r'Bottom', ctypes.c_short)]
420
420
421 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
421 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
422 _fields_ = [(r'dwSize', _COORD),
422 _fields_ = [(r'dwSize', _COORD),
423 (r'dwCursorPosition', _COORD),
423 (r'dwCursorPosition', _COORD),
424 (r'wAttributes', _WORD),
424 (r'wAttributes', _WORD),
425 (r'srWindow', _SMALL_RECT),
425 (r'srWindow', _SMALL_RECT),
426 (r'dwMaximumWindowSize', _COORD)]
426 (r'dwMaximumWindowSize', _COORD)]
427
427
428 _STD_OUTPUT_HANDLE = 0xfffffff5 # (DWORD)-11
428 _STD_OUTPUT_HANDLE = 0xfffffff5 # (DWORD)-11
429 _STD_ERROR_HANDLE = 0xfffffff4 # (DWORD)-12
429 _STD_ERROR_HANDLE = 0xfffffff4 # (DWORD)-12
430
430
431 _FOREGROUND_BLUE = 0x0001
431 _FOREGROUND_BLUE = 0x0001
432 _FOREGROUND_GREEN = 0x0002
432 _FOREGROUND_GREEN = 0x0002
433 _FOREGROUND_RED = 0x0004
433 _FOREGROUND_RED = 0x0004
434 _FOREGROUND_INTENSITY = 0x0008
434 _FOREGROUND_INTENSITY = 0x0008
435
435
436 _BACKGROUND_BLUE = 0x0010
436 _BACKGROUND_BLUE = 0x0010
437 _BACKGROUND_GREEN = 0x0020
437 _BACKGROUND_GREEN = 0x0020
438 _BACKGROUND_RED = 0x0040
438 _BACKGROUND_RED = 0x0040
439 _BACKGROUND_INTENSITY = 0x0080
439 _BACKGROUND_INTENSITY = 0x0080
440
440
441 _COMMON_LVB_REVERSE_VIDEO = 0x4000
441 _COMMON_LVB_REVERSE_VIDEO = 0x4000
442 _COMMON_LVB_UNDERSCORE = 0x8000
442 _COMMON_LVB_UNDERSCORE = 0x8000
443
443
444 # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx
444 # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx
445 w32effects = {
445 w32effects = {
446 'none': -1,
446 'none': -1,
447 'black': 0,
447 'black': 0,
448 'red': _FOREGROUND_RED,
448 'red': _FOREGROUND_RED,
449 'green': _FOREGROUND_GREEN,
449 'green': _FOREGROUND_GREEN,
450 'yellow': _FOREGROUND_RED | _FOREGROUND_GREEN,
450 'yellow': _FOREGROUND_RED | _FOREGROUND_GREEN,
451 'blue': _FOREGROUND_BLUE,
451 'blue': _FOREGROUND_BLUE,
452 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED,
452 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED,
453 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN,
453 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN,
454 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE,
454 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE,
455 'bold': _FOREGROUND_INTENSITY,
455 'bold': _FOREGROUND_INTENSITY,
456 'black_background': 0x100, # unused value > 0x0f
456 'black_background': 0x100, # unused value > 0x0f
457 'red_background': _BACKGROUND_RED,
457 'red_background': _BACKGROUND_RED,
458 'green_background': _BACKGROUND_GREEN,
458 'green_background': _BACKGROUND_GREEN,
459 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN,
459 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN,
460 'blue_background': _BACKGROUND_BLUE,
460 'blue_background': _BACKGROUND_BLUE,
461 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED,
461 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED,
462 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN,
462 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN,
463 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN |
463 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN |
464 _BACKGROUND_BLUE),
464 _BACKGROUND_BLUE),
465 'bold_background': _BACKGROUND_INTENSITY,
465 'bold_background': _BACKGROUND_INTENSITY,
466 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only
466 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only
467 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only
467 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only
468 }
468 }
469
469
470 passthrough = {_FOREGROUND_INTENSITY,
470 passthrough = {_FOREGROUND_INTENSITY,
471 _BACKGROUND_INTENSITY,
471 _BACKGROUND_INTENSITY,
472 _COMMON_LVB_UNDERSCORE,
472 _COMMON_LVB_UNDERSCORE,
473 _COMMON_LVB_REVERSE_VIDEO}
473 _COMMON_LVB_REVERSE_VIDEO}
474
474
475 stdout = _kernel32.GetStdHandle(
475 stdout = _kernel32.GetStdHandle(
476 _STD_OUTPUT_HANDLE) # don't close the handle returned
476 _STD_OUTPUT_HANDLE) # don't close the handle returned
477 if stdout is None or stdout == _INVALID_HANDLE_VALUE:
477 if stdout is None or stdout == _INVALID_HANDLE_VALUE:
478 w32effects = None
478 w32effects = None
479 else:
479 else:
480 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
480 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
481 if not _kernel32.GetConsoleScreenBufferInfo(
481 if not _kernel32.GetConsoleScreenBufferInfo(
482 stdout, ctypes.byref(csbi)):
482 stdout, ctypes.byref(csbi)):
483 # stdout may not support GetConsoleScreenBufferInfo()
483 # stdout may not support GetConsoleScreenBufferInfo()
484 # when called from subprocess or redirected
484 # when called from subprocess or redirected
485 w32effects = None
485 w32effects = None
486 else:
486 else:
487 origattr = csbi.wAttributes
487 origattr = csbi.wAttributes
488 ansire = re.compile(br'\033\[([^m]*)m([^\033]*)(.*)',
488 ansire = re.compile(br'\033\[([^m]*)m([^\033]*)(.*)',
489 re.MULTILINE | re.DOTALL)
489 re.MULTILINE | re.DOTALL)
490
490
491 def win32print(ui, writefunc, text, **opts):
491 def win32print(ui, writefunc, text, **opts):
492 label = opts.get(r'label', '')
492 label = opts.get(r'label', '')
493 attr = origattr
493 attr = origattr
494
494
495 def mapcolor(val, attr):
495 def mapcolor(val, attr):
496 if val == -1:
496 if val == -1:
497 return origattr
497 return origattr
498 elif val in passthrough:
498 elif val in passthrough:
499 return attr | val
499 return attr | val
500 elif val > 0x0f:
500 elif val > 0x0f:
501 return (val & 0x70) | (attr & 0x8f)
501 return (val & 0x70) | (attr & 0x8f)
502 else:
502 else:
503 return (val & 0x07) | (attr & 0xf8)
503 return (val & 0x07) | (attr & 0xf8)
504
504
505 # determine console attributes based on labels
505 # determine console attributes based on labels
506 for l in label.split():
506 for l in label.split():
507 style = ui._styles.get(l, '')
507 style = ui._styles.get(l, '')
508 for effect in style.split():
508 for effect in style.split():
509 try:
509 try:
510 attr = mapcolor(w32effects[effect], attr)
510 attr = mapcolor(w32effects[effect], attr)
511 except KeyError:
511 except KeyError:
512 # w32effects could not have certain attributes so we skip
512 # w32effects could not have certain attributes so we skip
513 # them if not found
513 # them if not found
514 pass
514 pass
515 # hack to ensure regexp finds data
515 # hack to ensure regexp finds data
516 if not text.startswith(b'\033['):
516 if not text.startswith(b'\033['):
517 text = b'\033[m' + text
517 text = b'\033[m' + text
518
518
519 # Look for ANSI-like codes embedded in text
519 # Look for ANSI-like codes embedded in text
520 m = re.match(ansire, text)
520 m = re.match(ansire, text)
521
521
522 try:
522 try:
523 while m:
523 while m:
524 for sattr in m.group(1).split(b';'):
524 for sattr in m.group(1).split(b';'):
525 if sattr:
525 if sattr:
526 attr = mapcolor(int(sattr), attr)
526 attr = mapcolor(int(sattr), attr)
527 ui.flush()
527 ui.flush()
528 _kernel32.SetConsoleTextAttribute(stdout, attr)
528 _kernel32.SetConsoleTextAttribute(stdout, attr)
529 writefunc(m.group(2))
529 writefunc(m.group(2))
530 m = re.match(ansire, m.group(3))
530 m = re.match(ansire, m.group(3))
531 finally:
531 finally:
532 # Explicitly reset original attributes
532 # Explicitly reset original attributes
533 ui.flush()
533 ui.flush()
534 _kernel32.SetConsoleTextAttribute(stdout, origattr)
534 _kernel32.SetConsoleTextAttribute(stdout, origattr)
@@ -1,533 +1,533
1 $ hg init t
1 $ hg init t
2 $ cd t
2 $ cd t
3 $ echo import > port
3 $ echo import > port
4 $ hg add port
4 $ hg add port
5 $ hg commit -m 0 -u spam -d '0 0'
5 $ hg commit -m 0 -u spam -d '0 0'
6 $ echo export >> port
6 $ echo export >> port
7 $ hg commit -m 1 -u eggs -d '1 0'
7 $ hg commit -m 1 -u eggs -d '1 0'
8 $ echo export > port
8 $ echo export > port
9 $ echo vaportight >> port
9 $ echo vaportight >> port
10 $ echo 'import/export' >> port
10 $ echo 'import/export' >> port
11 $ hg commit -m 2 -u spam -d '2 0'
11 $ hg commit -m 2 -u spam -d '2 0'
12 $ echo 'import/export' >> port
12 $ echo 'import/export' >> port
13 $ hg commit -m 3 -u eggs -d '3 0'
13 $ hg commit -m 3 -u eggs -d '3 0'
14 $ head -n 3 port > port1
14 $ head -n 3 port > port1
15 $ mv port1 port
15 $ mv port1 port
16 $ hg commit -m 4 -u spam -d '4 0'
16 $ hg commit -m 4 -u spam -d '4 0'
17
17
18 pattern error
18 pattern error
19
19
20 $ hg grep '**test**'
20 $ hg grep '**test**'
21 grep: invalid match pattern: nothing to repeat* (glob)
21 grep: invalid match pattern: nothing to repeat* (glob)
22 [1]
22 [1]
23
23
24 simple
24 simple
25
25
26 $ hg grep -r tip:0 '.*'
26 $ hg grep -r tip:0 '.*'
27 port:4:export
27 port:4:export
28 port:4:vaportight
28 port:4:vaportight
29 port:4:import/export
29 port:4:import/export
30 $ hg grep -r tip:0 port port
30 $ hg grep -r tip:0 port port
31 port:4:export
31 port:4:export
32 port:4:vaportight
32 port:4:vaportight
33 port:4:import/export
33 port:4:import/export
34
34
35 simple from subdirectory
35 simple from subdirectory
36
36
37 $ mkdir dir
37 $ mkdir dir
38 $ cd dir
38 $ cd dir
39 $ hg grep -r tip:0 port
39 $ hg grep -r tip:0 port
40 port:4:export
40 port:4:export
41 port:4:vaportight
41 port:4:vaportight
42 port:4:import/export
42 port:4:import/export
43 $ hg grep -r tip:0 port --config ui.relative-paths=yes
43 $ hg grep -r tip:0 port --config ui.relative-paths=yes
44 ../port:4:export
44 ../port:4:export
45 ../port:4:vaportight
45 ../port:4:vaportight
46 ../port:4:import/export
46 ../port:4:import/export
47 $ cd ..
47 $ cd ..
48
48
49 simple with color
49 simple with color
50
50
51 $ hg --config extensions.color= grep --config color.mode=ansi \
51 $ hg --config extensions.color= grep --config color.mode=ansi \
52 > --color=always port port -r tip:0
52 > --color=always port port -r tip:0
53 \x1b[0;35mport\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32m4\x1b[0m\x1b[0;36m:\x1b[0mex\x1b[0;31;1mport\x1b[0m (esc)
53 \x1b[0;35mport\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;34m4\x1b[0m\x1b[0;36m:\x1b[0mex\x1b[0;31;1mport\x1b[0m (esc)
54 \x1b[0;35mport\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32m4\x1b[0m\x1b[0;36m:\x1b[0mva\x1b[0;31;1mport\x1b[0might (esc)
54 \x1b[0;35mport\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;34m4\x1b[0m\x1b[0;36m:\x1b[0mva\x1b[0;31;1mport\x1b[0might (esc)
55 \x1b[0;35mport\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32m4\x1b[0m\x1b[0;36m:\x1b[0mim\x1b[0;31;1mport\x1b[0m/ex\x1b[0;31;1mport\x1b[0m (esc)
55 \x1b[0;35mport\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;34m4\x1b[0m\x1b[0;36m:\x1b[0mim\x1b[0;31;1mport\x1b[0m/ex\x1b[0;31;1mport\x1b[0m (esc)
56
56
57 simple templated
57 simple templated
58
58
59 $ hg grep port -r tip:0 \
59 $ hg grep port -r tip:0 \
60 > -T '{path}:{rev}:{node|short}:{texts % "{if(matched, text|upper, text)}"}\n'
60 > -T '{path}:{rev}:{node|short}:{texts % "{if(matched, text|upper, text)}"}\n'
61 port:4:914fa752cdea:exPORT
61 port:4:914fa752cdea:exPORT
62 port:4:914fa752cdea:vaPORTight
62 port:4:914fa752cdea:vaPORTight
63 port:4:914fa752cdea:imPORT/exPORT
63 port:4:914fa752cdea:imPORT/exPORT
64
64
65 $ hg grep port -r tip:0 -T '{path}:{rev}:{texts}\n'
65 $ hg grep port -r tip:0 -T '{path}:{rev}:{texts}\n'
66 port:4:export
66 port:4:export
67 port:4:vaportight
67 port:4:vaportight
68 port:4:import/export
68 port:4:import/export
69
69
70 $ hg grep port -r tip:0 -T '{path}:{tags}:{texts}\n'
70 $ hg grep port -r tip:0 -T '{path}:{tags}:{texts}\n'
71 port:tip:export
71 port:tip:export
72 port:tip:vaportight
72 port:tip:vaportight
73 port:tip:import/export
73 port:tip:import/export
74
74
75 simple JSON (no "change" field)
75 simple JSON (no "change" field)
76
76
77 $ hg grep -r tip:0 -Tjson port
77 $ hg grep -r tip:0 -Tjson port
78 [
78 [
79 {
79 {
80 "date": [4, 0],
80 "date": [4, 0],
81 "lineno": 1,
81 "lineno": 1,
82 "node": "914fa752cdea87777ac1a8d5c858b0c736218f6c",
82 "node": "914fa752cdea87777ac1a8d5c858b0c736218f6c",
83 "path": "port",
83 "path": "port",
84 "rev": 4,
84 "rev": 4,
85 "texts": [{"matched": false, "text": "ex"}, {"matched": true, "text": "port"}],
85 "texts": [{"matched": false, "text": "ex"}, {"matched": true, "text": "port"}],
86 "user": "spam"
86 "user": "spam"
87 },
87 },
88 {
88 {
89 "date": [4, 0],
89 "date": [4, 0],
90 "lineno": 2,
90 "lineno": 2,
91 "node": "914fa752cdea87777ac1a8d5c858b0c736218f6c",
91 "node": "914fa752cdea87777ac1a8d5c858b0c736218f6c",
92 "path": "port",
92 "path": "port",
93 "rev": 4,
93 "rev": 4,
94 "texts": [{"matched": false, "text": "va"}, {"matched": true, "text": "port"}, {"matched": false, "text": "ight"}],
94 "texts": [{"matched": false, "text": "va"}, {"matched": true, "text": "port"}, {"matched": false, "text": "ight"}],
95 "user": "spam"
95 "user": "spam"
96 },
96 },
97 {
97 {
98 "date": [4, 0],
98 "date": [4, 0],
99 "lineno": 3,
99 "lineno": 3,
100 "node": "914fa752cdea87777ac1a8d5c858b0c736218f6c",
100 "node": "914fa752cdea87777ac1a8d5c858b0c736218f6c",
101 "path": "port",
101 "path": "port",
102 "rev": 4,
102 "rev": 4,
103 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}, {"matched": false, "text": "/ex"}, {"matched": true, "text": "port"}],
103 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}, {"matched": false, "text": "/ex"}, {"matched": true, "text": "port"}],
104 "user": "spam"
104 "user": "spam"
105 }
105 }
106 ]
106 ]
107
107
108 simple JSON without matching lines
108 simple JSON without matching lines
109
109
110 $ hg grep -r tip:0 -Tjson -l port
110 $ hg grep -r tip:0 -Tjson -l port
111 [
111 [
112 {
112 {
113 "date": [4, 0],
113 "date": [4, 0],
114 "lineno": 1,
114 "lineno": 1,
115 "node": "914fa752cdea87777ac1a8d5c858b0c736218f6c",
115 "node": "914fa752cdea87777ac1a8d5c858b0c736218f6c",
116 "path": "port",
116 "path": "port",
117 "rev": 4,
117 "rev": 4,
118 "user": "spam"
118 "user": "spam"
119 }
119 }
120 ]
120 ]
121
121
122 all
122 all
123
123
124 $ hg grep --traceback --all -nu port port
124 $ hg grep --traceback --all -nu port port
125 port:4:4:-:spam:import/export
125 port:4:4:-:spam:import/export
126 port:3:4:+:eggs:import/export
126 port:3:4:+:eggs:import/export
127 port:2:1:-:spam:import
127 port:2:1:-:spam:import
128 port:2:2:-:spam:export
128 port:2:2:-:spam:export
129 port:2:1:+:spam:export
129 port:2:1:+:spam:export
130 port:2:2:+:spam:vaportight
130 port:2:2:+:spam:vaportight
131 port:2:3:+:spam:import/export
131 port:2:3:+:spam:import/export
132 port:1:2:+:eggs:export
132 port:1:2:+:eggs:export
133 port:0:1:+:spam:import
133 port:0:1:+:spam:import
134
134
135 all JSON
135 all JSON
136
136
137 $ hg grep --all -Tjson port port
137 $ hg grep --all -Tjson port port
138 [
138 [
139 {
139 {
140 "change": "-",
140 "change": "-",
141 "date": [4, 0],
141 "date": [4, 0],
142 "lineno": 4,
142 "lineno": 4,
143 "node": "914fa752cdea87777ac1a8d5c858b0c736218f6c",
143 "node": "914fa752cdea87777ac1a8d5c858b0c736218f6c",
144 "path": "port",
144 "path": "port",
145 "rev": 4,
145 "rev": 4,
146 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}, {"matched": false, "text": "/ex"}, {"matched": true, "text": "port"}],
146 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}, {"matched": false, "text": "/ex"}, {"matched": true, "text": "port"}],
147 "user": "spam"
147 "user": "spam"
148 },
148 },
149 {
149 {
150 "change": "+",
150 "change": "+",
151 "date": [3, 0],
151 "date": [3, 0],
152 "lineno": 4,
152 "lineno": 4,
153 "node": "95040cfd017d658c536071c6290230a613c4c2a6",
153 "node": "95040cfd017d658c536071c6290230a613c4c2a6",
154 "path": "port",
154 "path": "port",
155 "rev": 3,
155 "rev": 3,
156 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}, {"matched": false, "text": "/ex"}, {"matched": true, "text": "port"}],
156 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}, {"matched": false, "text": "/ex"}, {"matched": true, "text": "port"}],
157 "user": "eggs"
157 "user": "eggs"
158 },
158 },
159 {
159 {
160 "change": "-",
160 "change": "-",
161 "date": [2, 0],
161 "date": [2, 0],
162 "lineno": 1,
162 "lineno": 1,
163 "node": "3b325e3481a1f07435d81dfdbfa434d9a0245b47",
163 "node": "3b325e3481a1f07435d81dfdbfa434d9a0245b47",
164 "path": "port",
164 "path": "port",
165 "rev": 2,
165 "rev": 2,
166 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}],
166 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}],
167 "user": "spam"
167 "user": "spam"
168 },
168 },
169 {
169 {
170 "change": "-",
170 "change": "-",
171 "date": [2, 0],
171 "date": [2, 0],
172 "lineno": 2,
172 "lineno": 2,
173 "node": "3b325e3481a1f07435d81dfdbfa434d9a0245b47",
173 "node": "3b325e3481a1f07435d81dfdbfa434d9a0245b47",
174 "path": "port",
174 "path": "port",
175 "rev": 2,
175 "rev": 2,
176 "texts": [{"matched": false, "text": "ex"}, {"matched": true, "text": "port"}],
176 "texts": [{"matched": false, "text": "ex"}, {"matched": true, "text": "port"}],
177 "user": "spam"
177 "user": "spam"
178 },
178 },
179 {
179 {
180 "change": "+",
180 "change": "+",
181 "date": [2, 0],
181 "date": [2, 0],
182 "lineno": 1,
182 "lineno": 1,
183 "node": "3b325e3481a1f07435d81dfdbfa434d9a0245b47",
183 "node": "3b325e3481a1f07435d81dfdbfa434d9a0245b47",
184 "path": "port",
184 "path": "port",
185 "rev": 2,
185 "rev": 2,
186 "texts": [{"matched": false, "text": "ex"}, {"matched": true, "text": "port"}],
186 "texts": [{"matched": false, "text": "ex"}, {"matched": true, "text": "port"}],
187 "user": "spam"
187 "user": "spam"
188 },
188 },
189 {
189 {
190 "change": "+",
190 "change": "+",
191 "date": [2, 0],
191 "date": [2, 0],
192 "lineno": 2,
192 "lineno": 2,
193 "node": "3b325e3481a1f07435d81dfdbfa434d9a0245b47",
193 "node": "3b325e3481a1f07435d81dfdbfa434d9a0245b47",
194 "path": "port",
194 "path": "port",
195 "rev": 2,
195 "rev": 2,
196 "texts": [{"matched": false, "text": "va"}, {"matched": true, "text": "port"}, {"matched": false, "text": "ight"}],
196 "texts": [{"matched": false, "text": "va"}, {"matched": true, "text": "port"}, {"matched": false, "text": "ight"}],
197 "user": "spam"
197 "user": "spam"
198 },
198 },
199 {
199 {
200 "change": "+",
200 "change": "+",
201 "date": [2, 0],
201 "date": [2, 0],
202 "lineno": 3,
202 "lineno": 3,
203 "node": "3b325e3481a1f07435d81dfdbfa434d9a0245b47",
203 "node": "3b325e3481a1f07435d81dfdbfa434d9a0245b47",
204 "path": "port",
204 "path": "port",
205 "rev": 2,
205 "rev": 2,
206 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}, {"matched": false, "text": "/ex"}, {"matched": true, "text": "port"}],
206 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}, {"matched": false, "text": "/ex"}, {"matched": true, "text": "port"}],
207 "user": "spam"
207 "user": "spam"
208 },
208 },
209 {
209 {
210 "change": "+",
210 "change": "+",
211 "date": [1, 0],
211 "date": [1, 0],
212 "lineno": 2,
212 "lineno": 2,
213 "node": "8b20f75c158513ff5ac80bd0e5219bfb6f0eb587",
213 "node": "8b20f75c158513ff5ac80bd0e5219bfb6f0eb587",
214 "path": "port",
214 "path": "port",
215 "rev": 1,
215 "rev": 1,
216 "texts": [{"matched": false, "text": "ex"}, {"matched": true, "text": "port"}],
216 "texts": [{"matched": false, "text": "ex"}, {"matched": true, "text": "port"}],
217 "user": "eggs"
217 "user": "eggs"
218 },
218 },
219 {
219 {
220 "change": "+",
220 "change": "+",
221 "date": [0, 0],
221 "date": [0, 0],
222 "lineno": 1,
222 "lineno": 1,
223 "node": "f31323c9217050ba245ee8b537c713ec2e8ab226",
223 "node": "f31323c9217050ba245ee8b537c713ec2e8ab226",
224 "path": "port",
224 "path": "port",
225 "rev": 0,
225 "rev": 0,
226 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}],
226 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}],
227 "user": "spam"
227 "user": "spam"
228 }
228 }
229 ]
229 ]
230
230
231 other
231 other
232
232
233 $ hg grep -r tip:0 -l port port
233 $ hg grep -r tip:0 -l port port
234 port:4
234 port:4
235 $ hg grep -r tip:0 import port
235 $ hg grep -r tip:0 import port
236 port:4:import/export
236 port:4:import/export
237
237
238 $ hg cp port port2
238 $ hg cp port port2
239 $ hg commit -m 4 -u spam -d '5 0'
239 $ hg commit -m 4 -u spam -d '5 0'
240
240
241 follow
241 follow
242
242
243 $ hg grep -r tip:0 --traceback -f 'import\n\Z' port2
243 $ hg grep -r tip:0 --traceback -f 'import\n\Z' port2
244 port:0:import
244 port:0:import
245
245
246 $ echo deport >> port2
246 $ echo deport >> port2
247 $ hg commit -m 5 -u eggs -d '6 0'
247 $ hg commit -m 5 -u eggs -d '6 0'
248 $ hg grep -f --all -nu port port2
248 $ hg grep -f --all -nu port port2
249 port2:6:4:+:eggs:deport
249 port2:6:4:+:eggs:deport
250 port:4:4:-:spam:import/export
250 port:4:4:-:spam:import/export
251 port:3:4:+:eggs:import/export
251 port:3:4:+:eggs:import/export
252 port:2:1:-:spam:import
252 port:2:1:-:spam:import
253 port:2:2:-:spam:export
253 port:2:2:-:spam:export
254 port:2:1:+:spam:export
254 port:2:1:+:spam:export
255 port:2:2:+:spam:vaportight
255 port:2:2:+:spam:vaportight
256 port:2:3:+:spam:import/export
256 port:2:3:+:spam:import/export
257 port:1:2:+:eggs:export
257 port:1:2:+:eggs:export
258 port:0:1:+:spam:import
258 port:0:1:+:spam:import
259
259
260 $ hg up -q null
260 $ hg up -q null
261 $ hg grep -r 'reverse(:.)' -f port
261 $ hg grep -r 'reverse(:.)' -f port
262 port:0:import
262 port:0:import
263
263
264 Test wdir
264 Test wdir
265 (at least, this shouldn't crash)
265 (at least, this shouldn't crash)
266
266
267 $ hg up -q
267 $ hg up -q
268 $ echo wport >> port2
268 $ echo wport >> port2
269 $ hg stat
269 $ hg stat
270 M port2
270 M port2
271 $ hg grep -r 'wdir()' port
271 $ hg grep -r 'wdir()' port
272 port2:2147483647:export
272 port2:2147483647:export
273 port2:2147483647:vaportight
273 port2:2147483647:vaportight
274 port2:2147483647:import/export
274 port2:2147483647:import/export
275 port2:2147483647:deport
275 port2:2147483647:deport
276 port2:2147483647:wport
276 port2:2147483647:wport
277
277
278 $ cd ..
278 $ cd ..
279 $ hg init t2
279 $ hg init t2
280 $ cd t2
280 $ cd t2
281 $ hg grep -r tip:0 foobar foo
281 $ hg grep -r tip:0 foobar foo
282 [1]
282 [1]
283 $ hg grep -r tip:0 foobar
283 $ hg grep -r tip:0 foobar
284 [1]
284 [1]
285 $ echo blue >> color
285 $ echo blue >> color
286 $ echo black >> color
286 $ echo black >> color
287 $ hg add color
287 $ hg add color
288 $ hg ci -m 0
288 $ hg ci -m 0
289 $ echo orange >> color
289 $ echo orange >> color
290 $ hg ci -m 1
290 $ hg ci -m 1
291 $ echo black > color
291 $ echo black > color
292 $ hg ci -m 2
292 $ hg ci -m 2
293 $ echo orange >> color
293 $ echo orange >> color
294 $ echo blue >> color
294 $ echo blue >> color
295 $ hg ci -m 3
295 $ hg ci -m 3
296 $ hg grep -r tip:0 orange
296 $ hg grep -r tip:0 orange
297 color:3:orange
297 color:3:orange
298 $ hg grep --all orange
298 $ hg grep --all orange
299 color:3:+:orange
299 color:3:+:orange
300 color:2:-:orange
300 color:2:-:orange
301 color:1:+:orange
301 color:1:+:orange
302 $ hg grep --diff orange --color=debug
302 $ hg grep --diff orange --color=debug
303 [grep.filename|color][grep.sep|:][grep.rev|3][grep.sep|:][grep.inserted grep.change|+][grep.sep|:][grep.match|orange]
303 [grep.filename|color][grep.sep|:][grep.rev|3][grep.sep|:][grep.inserted grep.change|+][grep.sep|:][grep.match|orange]
304 [grep.filename|color][grep.sep|:][grep.rev|2][grep.sep|:][grep.deleted grep.change|-][grep.sep|:][grep.match|orange]
304 [grep.filename|color][grep.sep|:][grep.rev|2][grep.sep|:][grep.deleted grep.change|-][grep.sep|:][grep.match|orange]
305 [grep.filename|color][grep.sep|:][grep.rev|1][grep.sep|:][grep.inserted grep.change|+][grep.sep|:][grep.match|orange]
305 [grep.filename|color][grep.sep|:][grep.rev|1][grep.sep|:][grep.inserted grep.change|+][grep.sep|:][grep.match|orange]
306
306
307 $ hg grep --diff orange --color=yes
307 $ hg grep --diff orange --color=yes
308 \x1b[0;35mcolor\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32m3\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32;1m+\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;31;1morange\x1b[0m (esc)
308 \x1b[0;35mcolor\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;34m3\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32;1m+\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;31;1morange\x1b[0m (esc)
309 \x1b[0;35mcolor\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32m2\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;31;1m-\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;31;1morange\x1b[0m (esc)
309 \x1b[0;35mcolor\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;34m2\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;31;1m-\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;31;1morange\x1b[0m (esc)
310 \x1b[0;35mcolor\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32m1\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32;1m+\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;31;1morange\x1b[0m (esc)
310 \x1b[0;35mcolor\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;34m1\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;32;1m+\x1b[0m\x1b[0;36m:\x1b[0m\x1b[0;31;1morange\x1b[0m (esc)
311
311
312 $ hg grep --diff orange
312 $ hg grep --diff orange
313 color:3:+:orange
313 color:3:+:orange
314 color:2:-:orange
314 color:2:-:orange
315 color:1:+:orange
315 color:1:+:orange
316
316
317 test substring match: '^' should only match at the beginning
317 test substring match: '^' should only match at the beginning
318
318
319 $ hg grep -r tip:0 '^.' --config extensions.color= --color debug
319 $ hg grep -r tip:0 '^.' --config extensions.color= --color debug
320 [grep.filename|color][grep.sep|:][grep.rev|3][grep.sep|:][grep.match|b]lack
320 [grep.filename|color][grep.sep|:][grep.rev|3][grep.sep|:][grep.match|b]lack
321 [grep.filename|color][grep.sep|:][grep.rev|3][grep.sep|:][grep.match|o]range
321 [grep.filename|color][grep.sep|:][grep.rev|3][grep.sep|:][grep.match|o]range
322 [grep.filename|color][grep.sep|:][grep.rev|3][grep.sep|:][grep.match|b]lue
322 [grep.filename|color][grep.sep|:][grep.rev|3][grep.sep|:][grep.match|b]lue
323
323
324 match in last "line" without newline
324 match in last "line" without newline
325
325
326 $ "$PYTHON" -c 'fp = open("noeol", "wb"); fp.write(b"no infinite loop"); fp.close();'
326 $ "$PYTHON" -c 'fp = open("noeol", "wb"); fp.write(b"no infinite loop"); fp.close();'
327 $ hg ci -Amnoeol
327 $ hg ci -Amnoeol
328 adding noeol
328 adding noeol
329 $ hg grep -r tip:0 loop
329 $ hg grep -r tip:0 loop
330 noeol:4:no infinite loop
330 noeol:4:no infinite loop
331
331
332 $ cd ..
332 $ cd ..
333
333
334 Issue685: traceback in grep -r after rename
334 Issue685: traceback in grep -r after rename
335
335
336 Got a traceback when using grep on a single
336 Got a traceback when using grep on a single
337 revision with renamed files.
337 revision with renamed files.
338
338
339 $ hg init issue685
339 $ hg init issue685
340 $ cd issue685
340 $ cd issue685
341 $ echo octarine > color
341 $ echo octarine > color
342 $ hg ci -Amcolor
342 $ hg ci -Amcolor
343 adding color
343 adding color
344 $ hg rename color colour
344 $ hg rename color colour
345 $ hg ci -Am rename
345 $ hg ci -Am rename
346 $ hg grep -r tip:0 octarine
346 $ hg grep -r tip:0 octarine
347 colour:1:octarine
347 colour:1:octarine
348 color:0:octarine
348 color:0:octarine
349
349
350 Used to crash here
350 Used to crash here
351
351
352 $ hg grep -r 1 octarine
352 $ hg grep -r 1 octarine
353 colour:1:octarine
353 colour:1:octarine
354 $ cd ..
354 $ cd ..
355
355
356
356
357 Issue337: test that grep follows parent-child relationships instead
357 Issue337: test that grep follows parent-child relationships instead
358 of just using revision numbers.
358 of just using revision numbers.
359
359
360 $ hg init issue337
360 $ hg init issue337
361 $ cd issue337
361 $ cd issue337
362
362
363 $ echo white > color
363 $ echo white > color
364 $ hg commit -A -m "0 white"
364 $ hg commit -A -m "0 white"
365 adding color
365 adding color
366
366
367 $ echo red > color
367 $ echo red > color
368 $ hg commit -A -m "1 red"
368 $ hg commit -A -m "1 red"
369
369
370 $ hg update 0
370 $ hg update 0
371 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
371 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
372 $ echo black > color
372 $ echo black > color
373 $ hg commit -A -m "2 black"
373 $ hg commit -A -m "2 black"
374 created new head
374 created new head
375
375
376 $ hg update --clean 1
376 $ hg update --clean 1
377 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
377 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
378 $ echo blue > color
378 $ echo blue > color
379 $ hg commit -A -m "3 blue"
379 $ hg commit -A -m "3 blue"
380
380
381 $ hg grep --all red
381 $ hg grep --all red
382 color:3:-:red
382 color:3:-:red
383 color:1:+:red
383 color:1:+:red
384
384
385 $ hg grep --diff red
385 $ hg grep --diff red
386 color:3:-:red
386 color:3:-:red
387 color:1:+:red
387 color:1:+:red
388
388
389 Issue3885: test that changing revision order does not alter the
389 Issue3885: test that changing revision order does not alter the
390 revisions printed, just their order.
390 revisions printed, just their order.
391
391
392 $ hg grep --all red -r "all()"
392 $ hg grep --all red -r "all()"
393 color:1:+:red
393 color:1:+:red
394 color:3:-:red
394 color:3:-:red
395
395
396 $ hg grep --all red -r "reverse(all())"
396 $ hg grep --all red -r "reverse(all())"
397 color:3:-:red
397 color:3:-:red
398 color:1:+:red
398 color:1:+:red
399
399
400 $ hg grep --diff red -r "all()"
400 $ hg grep --diff red -r "all()"
401 color:1:+:red
401 color:1:+:red
402 color:3:-:red
402 color:3:-:red
403
403
404 $ hg grep --diff red -r "reverse(all())"
404 $ hg grep --diff red -r "reverse(all())"
405 color:3:-:red
405 color:3:-:red
406 color:1:+:red
406 color:1:+:red
407
407
408 $ cd ..
408 $ cd ..
409
409
410 $ hg init a
410 $ hg init a
411 $ cd a
411 $ cd a
412 $ cp "$TESTDIR/binfile.bin" .
412 $ cp "$TESTDIR/binfile.bin" .
413 $ hg add binfile.bin
413 $ hg add binfile.bin
414 $ hg ci -m 'add binfile.bin'
414 $ hg ci -m 'add binfile.bin'
415 $ hg grep "MaCam" --all
415 $ hg grep "MaCam" --all
416 binfile.bin:0:+: Binary file matches
416 binfile.bin:0:+: Binary file matches
417
417
418 $ hg grep "MaCam" --diff
418 $ hg grep "MaCam" --diff
419 binfile.bin:0:+: Binary file matches
419 binfile.bin:0:+: Binary file matches
420
420
421 $ cd ..
421 $ cd ..
422
422
423 Test for showing working of allfiles flag
423 Test for showing working of allfiles flag
424
424
425 $ hg init sng
425 $ hg init sng
426 $ cd sng
426 $ cd sng
427 $ echo "unmod" >> um
427 $ echo "unmod" >> um
428 $ hg ci -A -m "adds unmod to um"
428 $ hg ci -A -m "adds unmod to um"
429 adding um
429 adding um
430 $ echo "something else" >> new
430 $ echo "something else" >> new
431 $ hg ci -A -m "second commit"
431 $ hg ci -A -m "second commit"
432 adding new
432 adding new
433 $ hg grep -r "." "unmod"
433 $ hg grep -r "." "unmod"
434 [1]
434 [1]
435 $ hg grep -r "." "unmod" --all-files
435 $ hg grep -r "." "unmod" --all-files
436 um:1:unmod
436 um:1:unmod
437
437
438 With --all-files, the working directory is searched by default
438 With --all-files, the working directory is searched by default
439
439
440 $ echo modified >> new
440 $ echo modified >> new
441 $ hg grep --all-files mod
441 $ hg grep --all-files mod
442 new:modified
442 new:modified
443 um:unmod
443 um:unmod
444
444
445 which can be overridden by -rREV
445 which can be overridden by -rREV
446
446
447 $ hg grep --all-files -r. mod
447 $ hg grep --all-files -r. mod
448 um:1:unmod
448 um:1:unmod
449
449
450 commands.all-files can be negated by --no-all-files
450 commands.all-files can be negated by --no-all-files
451
451
452 $ hg grep --config commands.grep.all-files=True mod
452 $ hg grep --config commands.grep.all-files=True mod
453 new:modified
453 new:modified
454 um:unmod
454 um:unmod
455 $ hg grep --config commands.grep.all-files=True --no-all-files mod
455 $ hg grep --config commands.grep.all-files=True --no-all-files mod
456 um:0:unmod
456 um:0:unmod
457
457
458 --diff --all-files makes no sense since --diff is the option to grep history
458 --diff --all-files makes no sense since --diff is the option to grep history
459
459
460 $ hg grep --diff --all-files um
460 $ hg grep --diff --all-files um
461 abort: --diff and --all-files are mutually exclusive
461 abort: --diff and --all-files are mutually exclusive
462 [255]
462 [255]
463
463
464 but --diff should precede the commands.grep.all-files option
464 but --diff should precede the commands.grep.all-files option
465
465
466 $ hg grep --config commands.grep.all-files=True --diff mod
466 $ hg grep --config commands.grep.all-files=True --diff mod
467 um:0:+:unmod
467 um:0:+:unmod
468
468
469 $ cd ..
469 $ cd ..
470
470
471 Fix_Wdir(): test that passing wdir() t -r flag does greps on the
471 Fix_Wdir(): test that passing wdir() t -r flag does greps on the
472 files modified in the working directory
472 files modified in the working directory
473
473
474 $ cd a
474 $ cd a
475 $ echo "abracadara" >> a
475 $ echo "abracadara" >> a
476 $ hg add a
476 $ hg add a
477 $ hg grep -r "wdir()" "abra"
477 $ hg grep -r "wdir()" "abra"
478 a:2147483647:abracadara
478 a:2147483647:abracadara
479
479
480 $ cd ..
480 $ cd ..
481
481
482 Change Default of grep by ui.tweakdefaults, that is, the files not in current
482 Change Default of grep by ui.tweakdefaults, that is, the files not in current
483 working directory should not be grepp-ed on
483 working directory should not be grepp-ed on
484
484
485 $ hg init ab
485 $ hg init ab
486 $ cd ab
486 $ cd ab
487 $ cat <<'EOF' >> .hg/hgrc
487 $ cat <<'EOF' >> .hg/hgrc
488 > [ui]
488 > [ui]
489 > tweakdefaults = True
489 > tweakdefaults = True
490 > EOF
490 > EOF
491 $ echo "some text">>file1
491 $ echo "some text">>file1
492 $ hg add file1
492 $ hg add file1
493 $ hg commit -m "adds file1"
493 $ hg commit -m "adds file1"
494 $ hg mv file1 file2
494 $ hg mv file1 file2
495
495
496 wdir revision is hidden by default:
496 wdir revision is hidden by default:
497
497
498 $ hg grep "some"
498 $ hg grep "some"
499 file2:some text
499 file2:some text
500
500
501 but it should be available in template dict:
501 but it should be available in template dict:
502
502
503 $ hg grep "some" -Tjson
503 $ hg grep "some" -Tjson
504 [
504 [
505 {
505 {
506 "date": [0, 0],
506 "date": [0, 0],
507 "lineno": 1,
507 "lineno": 1,
508 "node": "ffffffffffffffffffffffffffffffffffffffff",
508 "node": "ffffffffffffffffffffffffffffffffffffffff",
509 "path": "file2",
509 "path": "file2",
510 "rev": 2147483647,
510 "rev": 2147483647,
511 "texts": [{"matched": true, "text": "some"}, {"matched": false, "text": " text"}],
511 "texts": [{"matched": true, "text": "some"}, {"matched": false, "text": " text"}],
512 "user": "test"
512 "user": "test"
513 }
513 }
514 ]
514 ]
515
515
516 $ cd ..
516 $ cd ..
517
517
518 test -rMULTIREV with --all-files
518 test -rMULTIREV with --all-files
519
519
520 $ cd sng
520 $ cd sng
521 $ hg rm um
521 $ hg rm um
522 $ hg commit -m "deletes um"
522 $ hg commit -m "deletes um"
523 $ hg grep -r "0:2" "unmod" --all-files
523 $ hg grep -r "0:2" "unmod" --all-files
524 um:0:unmod
524 um:0:unmod
525 um:1:unmod
525 um:1:unmod
526 $ hg grep -r "0:2" "unmod" --all-files um
526 $ hg grep -r "0:2" "unmod" --all-files um
527 um:0:unmod
527 um:0:unmod
528 um:1:unmod
528 um:1:unmod
529 $ hg grep -r "0:2" "unmod" --all-files "glob:**/um" # Check that patterns also work
529 $ hg grep -r "0:2" "unmod" --all-files "glob:**/um" # Check that patterns also work
530 um:0:unmod
530 um:0:unmod
531 um:1:unmod
531 um:1:unmod
532 $ cd ..
532 $ cd ..
533
533
General Comments 0
You need to be logged in to leave comments. Login now