Skip to content

Commit c6b6d23

Browse files
authored
Merge pull request pre-commit#716 from tdeo/multiline_pygrep
Add multiline mode to pygrep
2 parents 5a98765 + 55ef3ce commit c6b6d23

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

pre_commit/languages/pygrep.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,23 @@ def _process_filename_by_line(pattern, filename):
2727
return retv
2828

2929

30+
def _process_filename_at_once(pattern, filename):
31+
retv = 0
32+
with open(filename, 'rb') as f:
33+
contents = f.read()
34+
match = pattern.search(contents)
35+
if match:
36+
retv = 1
37+
line_no = contents[:match.start()].count(b'\n')
38+
output.write('{}:{}:'.format(filename, line_no + 1))
39+
40+
matched_lines = match.group().split(b'\n')
41+
matched_lines[0] = contents.split(b'\n')[line_no]
42+
43+
output.write_line(b'\n'.join(matched_lines))
44+
return retv
45+
46+
3047
def run_hook(prefix, hook, file_args):
3148
exe = (sys.executable, '-m', __name__)
3249
exe += tuple(hook['args']) + (hook['entry'],)
@@ -42,16 +59,23 @@ def main(argv=None):
4259
),
4360
)
4461
parser.add_argument('-i', '--ignore-case', action='store_true')
62+
parser.add_argument('--multiline', action='store_true')
4563
parser.add_argument('pattern', help='python regex pattern.')
4664
parser.add_argument('filenames', nargs='*')
4765
args = parser.parse_args(argv)
4866

4967
flags = re.IGNORECASE if args.ignore_case else 0
68+
if args.multiline:
69+
flags |= re.MULTILINE | re.DOTALL
70+
5071
pattern = re.compile(args.pattern.encode(), flags)
5172

5273
retv = 0
5374
for filename in args.filenames:
54-
retv |= _process_filename_by_line(pattern, filename)
75+
if args.multiline:
76+
retv |= _process_filename_at_once(pattern, filename)
77+
else:
78+
retv |= _process_filename_by_line(pattern, filename)
5579
return retv
5680

5781

tests/languages/pygrep_test.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,31 @@ def test_ignore_case(some_files, cap_out):
3838
out = cap_out.get()
3939
assert ret == 1
4040
assert out == 'f2:1:[INFO] hi\n'
41+
42+
43+
def test_multiline(some_files, cap_out):
44+
ret = pygrep.main(('--multiline', r'foo\nbar', 'f1', 'f2', 'f3'))
45+
out = cap_out.get()
46+
assert ret == 1
47+
assert out == 'f1:1:foo\nbar\n'
48+
49+
50+
def test_multiline_line_number(some_files, cap_out):
51+
ret = pygrep.main(('--multiline', r'ar', 'f1', 'f2', 'f3'))
52+
out = cap_out.get()
53+
assert ret == 1
54+
assert out == 'f1:2:bar\n'
55+
56+
57+
def test_multiline_dotall_flag_is_enabled(some_files, cap_out):
58+
ret = pygrep.main(('--multiline', r'o.*bar', 'f1', 'f2', 'f3'))
59+
out = cap_out.get()
60+
assert ret == 1
61+
assert out == 'f1:1:foo\nbar\n'
62+
63+
64+
def test_multiline_multiline_flag_is_enabled(some_files, cap_out):
65+
ret = pygrep.main(('--multiline', r'foo$.*bar', 'f1', 'f2', 'f3'))
66+
out = cap_out.get()
67+
assert ret == 1
68+
assert out == 'f1:1:foo\nbar\n'

0 commit comments

Comments
 (0)