-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtofi.py
executable file
·225 lines (177 loc) · 5.99 KB
/
tofi.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#!/bin/python
# -*- coding: utf-8 -*
import argparse
from os import walk
from os.path import isdir, isfile
import subprocess
class color:
BLUE = '\033[94m'
GREEN = '\033[92m'
GREY = '\033[38;5;244m'
RED = '\033[91m'
VIOLET = '\033[95m'
YELLOW = '\033[93m'
END = '\033[0m'
BOLD = '\033[1m'
class Setting:
def __init__(self, keyword, symbol, color):
self.color = color
self.keyword = keyword
self.symbol = symbol
MARKS = [
Setting('BUG', '☢', color.RED),
Setting('FIXME', '☠', color.RED),
Setting('HACK', '✄', color.YELLOW),
Setting('NOTE', '✐', color.YELLOW),
Setting('OPTIMIZE', '↻', color.YELLOW),
Setting('TODO', '✓', color.BLUE),
Setting('XXX', '✗', color.VIOLET),
]
COMMENTS = ['/**', '/*', '//', '#', '\'\'', '""', ';', '%', '--']
COMMENTS_MID = ['*']
COMMENTS_END = {
'/**': ['**/', '*/'],
'/*': ['*/']
}
class FileDir(argparse.Action):
def __call__(self, parser, args, dest, option_string=None):
files = []
for entry in dest:
if isfile(entry):
files.append(entry)
elif isdir(entry):
for (dirpath, dirnames, filenames) in walk(entry):
for filename in filenames:
path = "{}/{}".format(dirpath, filename)
files.append(path)
files.sort()
setattr(args, self.dest, files)
def type(dest):
if not isdir(dest) and not isfile(dest):
msg = "{} is neither file nor directory".format(dest)
raise argparse.ArgumentTypeError(msg)
return dest
class Tofi():
_filenames = True
_keywords = True
_numbers = True
_symbols = True
def __init__(self,
numbers=True,
symbols=True,
keywords=True,
filenames=True):
self._filenames = filenames
self._keywords = keywords
self._numbers = numbers
self._symbols = symbols
def _build(self, mark, line, num, indent):
prefix = ''
if self._numbers:
prefix = '{}{:>{}} '.format(color.GREY, num, indent)
if self._symbols:
prefix = prefix + color.BOLD + mark.color + mark.symbol + ' ' + color.END
if self._keywords:
prefix = prefix + color.BOLD + mark.color + mark.keyword + color.END
line = line.split('\n')[0]
text = line.split(mark.keyword)
output = prefix + mark.keyword.join(text[1:])
# Get comment symbols
text = text[0].split()
if text:
text = text[-1][-3:]
for comment in COMMENTS:
if comment in text:
return (output, comment)
return (None, None)
def _build_follower(self, line, prefix):
found = True
line = line.split('\n')[0]
text = line.split(prefix)
if len(text) < 2:
found = False
tmp = line.split()
if len(tmp) > 0 and tmp[0] in COMMENTS_MID:
text = tmp[1:]
found = True
if prefix in COMMENTS_END:
found = True
if not found:
return None
line = ' '.join(text)
line = ' ' + ' '.join(line.split())
return line
def _print(self, output, prefix):
if output:
if prefix in COMMENTS_END:
for symbol in COMMENTS_END[prefix]:
output = output.split(symbol)[0]
print(output)
def parse(self, path, print_filename):
num = 0
output = None
symbol = None
prefix = None
found = False
f = open(path, 'r')
try:
text = f.readlines()
except UnicodeDecodeError:
return False
indent = sum(1 for line in text)
indent = len(str(indent))
for line in text:
num += 1
prefix = None
for mark in MARKS:
if mark.keyword in line:
(suffix, prefix) = self._build(mark, line, num, indent)
if suffix:
if not found and print_filename:
found = True
print('{}:'.format(path))
self._print(output, symbol)
output = suffix
symbol = prefix
if not prefix and symbol:
append = self._build_follower(line, symbol)
if append:
output += append
else:
symbol = None
self._print(output, symbol)
f.close()
return found
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Print TODOs, FIXMEs & Co.')
parser.add_argument('-f', '--hide-filenames', action='store_true',
help='hide filenames')
parser.add_argument('-k', '--hide-keywords', action='store_true',
help='hide keywords')
parser.add_argument('-n', '--hide-numbers', action='store_true',
help='hide number of line')
parser.add_argument('-s', '--hide-symbols', action='store_true',
help='hide symbols')
parser.add_argument('file', nargs='*', type=FileDir.type, action=FileDir,
help='source files', default='.')
args = parser.parse_args()
if args.file == []:
parser.print_usage()
print('tofi.py: error: the following arguments are required: file')
exit(2)
try:
tofi = Tofi(not args.hide_numbers,
not args.hide_symbols,
not args.hide_keywords,
not args.hide_filenames)
except ValueError:
exit(1)
num = len(args.file)
if num == 1 or not tofi._filenames:
num = 0
for file in args.file:
found = tofi.parse(file, num > 0)
num -= 1
if found and num > 0:
print('')
exit(0)