##// END OF EJS Templates
grep: add formatter support...
Yuya Nishihara -
r29858:33461139 default
parent child Browse files
Show More
@@ -4283,7 +4283,7 b' def _dograft(ui, repo, *revs, **opts):'
4283 _('only search files changed within revision range'), _('REV')),
4283 _('only search files changed within revision range'), _('REV')),
4284 ('u', 'user', None, _('list the author (long with -v)')),
4284 ('u', 'user', None, _('list the author (long with -v)')),
4285 ('d', 'date', None, _('list the date (short with -q)')),
4285 ('d', 'date', None, _('list the date (short with -q)')),
4286 ] + walkopts,
4286 ] + formatteropts + walkopts,
4287 _('[OPTION]... PATTERN [FILE]...'),
4287 _('[OPTION]... PATTERN [FILE]...'),
4288 inferrepo=True)
4288 inferrepo=True)
4289 def grep(ui, repo, pattern, *pats, **opts):
4289 def grep(ui, repo, pattern, *pats, **opts):
@@ -4380,59 +4380,75 b' def grep(ui, repo, pattern, *pats, **opt'
4380 for i in xrange(blo, bhi):
4380 for i in xrange(blo, bhi):
4381 yield ('+', b[i])
4381 yield ('+', b[i])
4382
4382
4383 def display(fn, ctx, pstates, states):
4383 def display(fm, fn, ctx, pstates, states):
4384 rev = ctx.rev()
4384 rev = ctx.rev()
4385 if fm:
4386 formatuser = str
4387 else:
4388 formatuser = ui.shortuser
4385 if ui.quiet:
4389 if ui.quiet:
4386 datefunc = util.shortdate
4390 datefmt = '%Y-%m-%d'
4387 else:
4391 else:
4388 datefunc = util.datestr
4392 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
4389 found = False
4393 found = False
4390 @util.cachefunc
4394 @util.cachefunc
4391 def binary():
4395 def binary():
4392 flog = getfile(fn)
4396 flog = getfile(fn)
4393 return util.binary(flog.read(ctx.filenode(fn)))
4397 return util.binary(flog.read(ctx.filenode(fn)))
4394
4398
4399 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
4395 if opts.get('all'):
4400 if opts.get('all'):
4396 iter = difflinestates(pstates, states)
4401 iter = difflinestates(pstates, states)
4397 else:
4402 else:
4398 iter = [('', l) for l in states]
4403 iter = [('', l) for l in states]
4399 for change, l in iter:
4404 for change, l in iter:
4405 fm.startitem()
4406 fm.data(node=fm.hexfunc(ctx.node()))
4400 cols = [
4407 cols = [
4401 ('filename', fn, True),
4408 ('filename', fn, True),
4402 ('rev', str(rev), True),
4409 ('rev', rev, True),
4403 ('linenumber', str(l.linenum), opts.get('line_number')),
4410 ('linenumber', l.linenum, opts.get('line_number')),
4404 ]
4411 ]
4405 if opts.get('all'):
4412 if opts.get('all'):
4406 cols.append(('change', change, True))
4413 cols.append(('change', change, True))
4407 cols.extend([
4414 cols.extend([
4408 ('user', ui.shortuser(ctx.user()), opts.get('user')),
4415 ('user', formatuser(ctx.user()), opts.get('user')),
4409 ('date', datefunc(ctx.date()), opts.get('date')),
4416 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
4410 ])
4417 ])
4411 lastcol = next(name for name, data, cond in reversed(cols) if cond)
4418 lastcol = next(name for name, data, cond in reversed(cols) if cond)
4412 for name, data, cond in cols:
4419 for name, data, cond in cols:
4413 if cond:
4420 field = fieldnamemap.get(name, name)
4414 ui.write(data, label='grep.%s' % name)
4421 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
4415 if cond and name != lastcol:
4422 if cond and name != lastcol:
4416 ui.write(sep, label='grep.sep')
4423 fm.plain(sep, label='grep.sep')
4417 if not opts.get('files_with_matches'):
4424 if not opts.get('files_with_matches'):
4418 ui.write(sep, label='grep.sep')
4425 fm.plain(sep, label='grep.sep')
4419 if not opts.get('text') and binary():
4426 if not opts.get('text') and binary():
4420 ui.write(_(" Binary file matches"))
4427 fm.plain(_(" Binary file matches"))
4421 else:
4428 else:
4422 displaymatches(l)
4429 displaymatches(fm.nested('texts'), l)
4423 ui.write(eol)
4430 fm.plain(eol)
4424 found = True
4431 found = True
4425 if opts.get('files_with_matches'):
4432 if opts.get('files_with_matches'):
4426 break
4433 break
4427 return found
4434 return found
4428
4435
4429 def displaymatches(l):
4436 def displaymatches(fm, l):
4430 p = 0
4437 p = 0
4431 for s, e in l.findpos():
4438 for s, e in l.findpos():
4432 ui.write(l.line[p:s])
4439 if p < s:
4433 ui.write(l.line[s:e], label='grep.match')
4440 fm.startitem()
4441 fm.write('text', '%s', l.line[p:s])
4442 fm.data(matched=False)
4443 fm.startitem()
4444 fm.write('text', '%s', l.line[s:e], label='grep.match')
4445 fm.data(matched=True)
4434 p = e
4446 p = e
4435 ui.write(l.line[p:])
4447 if p < len(l.line):
4448 fm.startitem()
4449 fm.write('text', '%s', l.line[p:])
4450 fm.data(matched=False)
4451 fm.end()
4436
4452
4437 skip = {}
4453 skip = {}
4438 revfiles = {}
4454 revfiles = {}
@@ -4475,6 +4491,7 b' def grep(ui, repo, pattern, *pats, **opt'
4475 except error.LookupError:
4491 except error.LookupError:
4476 pass
4492 pass
4477
4493
4494 fm = ui.formatter('grep', opts)
4478 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4495 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4479 rev = ctx.rev()
4496 rev = ctx.rev()
4480 parent = ctx.p1().rev()
4497 parent = ctx.p1().rev()
@@ -4487,7 +4504,7 b' def grep(ui, repo, pattern, *pats, **opt'
4487 continue
4504 continue
4488 pstates = matches.get(parent, {}).get(copy or fn, [])
4505 pstates = matches.get(parent, {}).get(copy or fn, [])
4489 if pstates or states:
4506 if pstates or states:
4490 r = display(fn, ctx, pstates, states)
4507 r = display(fm, fn, ctx, pstates, states)
4491 found = found or r
4508 found = found or r
4492 if r and not opts.get('all'):
4509 if r and not opts.get('all'):
4493 skip[fn] = True
4510 skip[fn] = True
@@ -4495,6 +4512,7 b' def grep(ui, repo, pattern, *pats, **opt'
4495 skip[copy] = True
4512 skip[copy] = True
4496 del matches[rev]
4513 del matches[rev]
4497 del revfiles[rev]
4514 del revfiles[rev]
4515 fm.end()
4498
4516
4499 return not found
4517 return not found
4500
4518
@@ -278,7 +278,7 b' Show all commands + options'
278 debugwireargs: three, four, five, ssh, remotecmd, insecure
278 debugwireargs: three, four, five, ssh, remotecmd, insecure
279 files: rev, print0, include, exclude, template, subrepos
279 files: rev, print0, include, exclude, template, subrepos
280 graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
280 graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
281 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
281 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, template, include, exclude
282 heads: rev, topo, active, closed, style, template
282 heads: rev, topo, active, closed, style, template
283 help: extension, command, keyword, system
283 help: extension, command, keyword, system
284 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
284 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
@@ -40,6 +40,61 b' simple with color'
40 \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)
40 \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)
41 \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)
41 \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)
42
42
43 simple templated
44
45 $ hg grep port \
46 > -T '{file}:{rev}:{node|short}:{texts % "{if(matched, text|upper, text)}"}\n'
47 port:4:914fa752cdea:exPORT
48 port:4:914fa752cdea:vaPORTight
49 port:4:914fa752cdea:imPORT/exPORT
50
51 simple JSON (no "change" field)
52
53 $ hg grep -Tjson port
54 [
55 {
56 "date": [4.0, 0],
57 "file": "port",
58 "line_number": 1,
59 "node": "914fa752cdea87777ac1a8d5c858b0c736218f6c",
60 "rev": 4,
61 "texts": [{"matched": false, "text": "ex"}, {"matched": true, "text": "port"}],
62 "user": "spam"
63 },
64 {
65 "date": [4.0, 0],
66 "file": "port",
67 "line_number": 2,
68 "node": "914fa752cdea87777ac1a8d5c858b0c736218f6c",
69 "rev": 4,
70 "texts": [{"matched": false, "text": "va"}, {"matched": true, "text": "port"}, {"matched": false, "text": "ight"}],
71 "user": "spam"
72 },
73 {
74 "date": [4.0, 0],
75 "file": "port",
76 "line_number": 3,
77 "node": "914fa752cdea87777ac1a8d5c858b0c736218f6c",
78 "rev": 4,
79 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}, {"matched": false, "text": "/ex"}, {"matched": true, "text": "port"}],
80 "user": "spam"
81 }
82 ]
83
84 simple JSON without matching lines
85
86 $ hg grep -Tjson -l port
87 [
88 {
89 "date": [4.0, 0],
90 "file": "port",
91 "line_number": 1,
92 "node": "914fa752cdea87777ac1a8d5c858b0c736218f6c",
93 "rev": 4,
94 "user": "spam"
95 }
96 ]
97
43 all
98 all
44
99
45 $ hg grep --traceback --all -nu port port
100 $ hg grep --traceback --all -nu port port
@@ -53,6 +108,102 b' all'
53 port:1:2:+:eggs:export
108 port:1:2:+:eggs:export
54 port:0:1:+:spam:import
109 port:0:1:+:spam:import
55
110
111 all JSON
112
113 $ hg grep --all -Tjson port port
114 [
115 {
116 "change": "-",
117 "date": [4.0, 0],
118 "file": "port",
119 "line_number": 4,
120 "node": "914fa752cdea87777ac1a8d5c858b0c736218f6c",
121 "rev": 4,
122 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}, {"matched": false, "text": "/ex"}, {"matched": true, "text": "port"}],
123 "user": "spam"
124 },
125 {
126 "change": "+",
127 "date": [3.0, 0],
128 "file": "port",
129 "line_number": 4,
130 "node": "95040cfd017d658c536071c6290230a613c4c2a6",
131 "rev": 3,
132 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}, {"matched": false, "text": "/ex"}, {"matched": true, "text": "port"}],
133 "user": "eggs"
134 },
135 {
136 "change": "-",
137 "date": [2.0, 0],
138 "file": "port",
139 "line_number": 1,
140 "node": "3b325e3481a1f07435d81dfdbfa434d9a0245b47",
141 "rev": 2,
142 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}],
143 "user": "spam"
144 },
145 {
146 "change": "-",
147 "date": [2.0, 0],
148 "file": "port",
149 "line_number": 2,
150 "node": "3b325e3481a1f07435d81dfdbfa434d9a0245b47",
151 "rev": 2,
152 "texts": [{"matched": false, "text": "ex"}, {"matched": true, "text": "port"}],
153 "user": "spam"
154 },
155 {
156 "change": "+",
157 "date": [2.0, 0],
158 "file": "port",
159 "line_number": 1,
160 "node": "3b325e3481a1f07435d81dfdbfa434d9a0245b47",
161 "rev": 2,
162 "texts": [{"matched": false, "text": "ex"}, {"matched": true, "text": "port"}],
163 "user": "spam"
164 },
165 {
166 "change": "+",
167 "date": [2.0, 0],
168 "file": "port",
169 "line_number": 2,
170 "node": "3b325e3481a1f07435d81dfdbfa434d9a0245b47",
171 "rev": 2,
172 "texts": [{"matched": false, "text": "va"}, {"matched": true, "text": "port"}, {"matched": false, "text": "ight"}],
173 "user": "spam"
174 },
175 {
176 "change": "+",
177 "date": [2.0, 0],
178 "file": "port",
179 "line_number": 3,
180 "node": "3b325e3481a1f07435d81dfdbfa434d9a0245b47",
181 "rev": 2,
182 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}, {"matched": false, "text": "/ex"}, {"matched": true, "text": "port"}],
183 "user": "spam"
184 },
185 {
186 "change": "+",
187 "date": [1.0, 0],
188 "file": "port",
189 "line_number": 2,
190 "node": "8b20f75c158513ff5ac80bd0e5219bfb6f0eb587",
191 "rev": 1,
192 "texts": [{"matched": false, "text": "ex"}, {"matched": true, "text": "port"}],
193 "user": "eggs"
194 },
195 {
196 "change": "+",
197 "date": [0.0, 0],
198 "file": "port",
199 "line_number": 1,
200 "node": "f31323c9217050ba245ee8b537c713ec2e8ab226",
201 "rev": 0,
202 "texts": [{"matched": false, "text": "im"}, {"matched": true, "text": "port"}],
203 "user": "spam"
204 }
205 ]
206
56 other
207 other
57
208
58 $ hg grep -l port port
209 $ hg grep -l port port
General Comments 0
You need to be logged in to leave comments. Login now