-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcode-count.py
More file actions
137 lines (122 loc) · 4.76 KB
/
code-count.py
File metadata and controls
137 lines (122 loc) · 4.76 KB
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
import sys
import os
import re
import pdb
ONE_LINE_COMMENT_DELIMITER = {'py': '#',
'pde':'//',
'cpp':'//',
'c':'//',
'cu':'//'}
MULTI_LINE_COMMENT_DELIMITER = {'py': ('"""','"""'),
'pde':('/*','*/'),
'cpp':('/*','*/'),
'c':('/*','*/'),
'cu':('/*','*/') }
def get_extension(filename):
ext = re.findall(r'\..+',filename)[0]
return ext[1:]
def count_lines(extension,filepath):
"""
Takes a source code file's extension and absolute file path,
counts and return the number of lines that are:
blank lines (only consists of whitespace)
comment lines (only consists of comments/documentation)
code lines (neither comment nor blank)
"""
fil = open(filepath,'r')
remaining_code = fil.readlines()
blank_lines,remaining_code = count_blank_lines(remaining_code)
commented_lines,remaining_code = count_commented_lines(remaining_code,extension)
in_line_comments = count_inline_comments(remaining_code,extension)
code_lines = len(remaining_code)
return blank_lines, commented_lines, code_lines
def count_inline_comments(code,extension):
"""
Takes code as an array of strings, extension as a string (e.g. 'py' for Python,
'cpp' for C++), returns the count of in-line comments in code
"""
comment_flag = ONE_LINE_COMMENT_DELIMITER[extension]
count = 0
for line in code:
if comment_flag in line:
count += 1
return count
def count_commented_lines(code,extension):
"""
Takes code as an array of strings, extension as a string (e.g. 'py' for Python,
'cpp' for C++), counts the commented lines, removes them,
and returns the number of commented lines and the code that remains
"""
multi_line_flag = MULTI_LINE_COMMENT_DELIMITER[extension]
single_line_flag = ONE_LINE_COMMENT_DELIMITER[extension]
in_comment = False
remaining_code = []
num_lines = 0
for line in code:
stripped_line = line.lstrip()
if stripped_line=="":
continue
is_single_comment = stripped_line[:len(single_line_flag)]==single_line_flag
is_multi_comment = stripped_line[:len(multi_line_flag[0])]==multi_line_flag[0]
if is_single_comment or is_multi_comment or in_comment:
num_lines += 1
else:
remaining_code.append(line)
in_comment = detect_in_comment(stripped_line, multi_line_flag, in_comment)
return num_lines,remaining_code
def count_blank_lines(code):
"""
Takes code as an array of strings, counts the blank lines, removes them,
and returns the number of blank lines and the code that remains
"""
remaining_code = []
blank_lines = 0
for line in code:
stripped_line = line.lstrip().rstrip()
if stripped_line=='':
blank_lines += 1
else:
remaining_code.append(stripped_line + "\n")
return blank_lines,remaining_code
def detect_in_comment(line, mlc, comment_depth):
"""
Given a line, the multi-comment delimiters for this code, and whether or not we're
already in a comment, returns true if the line counts as a comment or not.
"""
comment_depth += line.count(mlc[0]) # python will treat True as 1, and False as 0
comment_depth -= line.count(mlc[1])
return comment_depth > 0
def get_short_filename(filename):
"""
get relative filename out of absolute filename (i.e. take out the path to
current directory)
"""
return filename[len(os.getcwd())+1:]
def get_max_filename_length():
"""
Get the length of the largest filename to determine how wide the "name"
column needs to be in the output
"""
return reduce( max, # feeling fancy
map( lambda x: len(get_short_filename(x)),
source_files),
len('Total'))
def format_output(name,loc,blank,comment):
"""
Prints out the output in neat table format.
"""
x = get_max_filename_length()
print ("%"+str(x)+"s %10s %10s %10s") %(name,loc,blank,comment)
source_files = []
for arg in sys.argv[1:]:
if arg[0]=='.': # get full file path names
source_files.append(os.getcwd() + arg[1:])
tot_code, tot_white, tot_comment = 0,0,0
format_output("Name","LOC","Blank","Comments")
for src_file in source_files:
white_lines,comment_lines,code_lines = count_lines(get_extension(src_file),src_file)
format_output(get_short_filename(src_file), code_lines, white_lines, comment_lines)
tot_code += code_lines
tot_white += white_lines
tot_comment += comment_lines
format_output('Total', tot_code, tot_white, tot_comment)