-
Notifications
You must be signed in to change notification settings - Fork 0
/
bn_grep.py
executable file
·135 lines (119 loc) · 4.45 KB
/
bn_grep.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/env python
import os
import re
import argparse
from blessings import Terminal
from colorama import init
init()
def pretty_print(content):
print " |---"
for line in content.split('\n'):
print ' | ' + line
print " |"
def colorize(line_nos, line_no, snippet, m_obj, term):
txt = []
for no, code in zip(line_nos, snippet):
line = str(no)
if no == line_no:
line = term.green(str(no)) + ' '
m_start = m_obj.start()
m_end = m_obj.end()
line += code[:m_start]
line += term.bold_green(code[m_start:m_end])
line += code[m_end:]
else:
line += ' ' + code
txt.append(line)
return txt
def get_args():
parser = argparse.ArgumentParser()
parser.add_argument('-p', '--path', help='The path to search.')
parser.add_argument('-f', '--file-name-pattern',
help="A regular expression to filter the filenames to be scanned.")
# parser.add_argument('-nB', '--n-before',
# help='Number of characters before the ocurrence of pattern.',
# type=int)
# parser.add_argument('-nA', '--n-after',
# help='Number of characters after the ocurrence of pattern.',
# type=int)
parser.add_argument('-lB', '--l-before',
help='Number of lines before the ocurrence of pattern.',
type=int)
parser.add_argument('-lA', '--l-after',
help='Number of lines after the ocurrence of pattern.',
type=int)
parser.add_argument('-x', '--exclude-paths', help='Comma separated list of paths to exclude from the search.')
parser.add_argument('regex', help='The expression to find.')
return parser.parse_args()
def main():
term = Terminal()
args = get_args()
dir = '.'
if args.path:
dir = args.path
print dir
pattern = re.compile(args.regex)
fname_pattern = re.compile(r".+")
if args.file_name_pattern:
fname_pattern = re.compile(args.file_name_pattern)
lA, lB = 0, 0
if args.l_before:
lB = args.l_before
if args.l_after:
lA = args.l_after
blacklist = []
if args.exclude_paths:
blacklist = args.exclude_paths.split(',')
for root, dirs, files in os.walk(dir):
if root in blacklist:
continue
for fname in files:
if fname_pattern.match(fname):
try:
file_path = os.path.join(root, fname)
with open(file_path, 'r') as source_file:
contents = source_file.read()
if pattern.search(contents):
print term.bold("\n--- " + file_path + ':')
content_lines = contents.split('\n')
for line_no in range(len(content_lines)):
m_obj = pattern.search(
content_lines[line_no] + '\n')
if m_obj:
start = max(line_no - lB, 0)
end = min(line_no + lA + 1, len(content_lines) - 1)
line_nos = range(start, end)
snippet = content_lines[start:end]
# snippet_with_line_nos = [str(x[0]) + ' ' + x[1] for x in zip(line_nos, snippet)]
csnippet = colorize(
line_nos,
line_no,
snippet,
m_obj,
term
)
pretty_print('\n'.join(csnippet))
except IOError as e:
print e
def print_exit_msg():
term = Terminal()
print "\n\nEnd of Line.\n\n"
print (
" " +
term.bold(term.green("<")) +
"bn" +
term.bold(term.green("/>"))
)
print " Benito-Nemitz Inc."
def interruptable_program(func_name, interrupt_handler=None, exit_handler=None):
try:
func_name()
if exit_handler:
exit_handler()
except KeyboardInterrupt as e:
if interrupt_handler:
interrupt_handler()
else:
print e
if __name__=='__main__':
interruptable_program(main, print_exit_msg, print_exit_msg)