visionmedia-san 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,3 @@
1
+ === 1.0.0 / 2008-09-28
2
+
3
+ * Initial release
data/Manifest.txt ADDED
@@ -0,0 +1,6 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/san
6
+ lib/san.rb
data/README.txt ADDED
@@ -0,0 +1,51 @@
1
+ = san
2
+
3
+ http://vision-media.ca/resources/ruby/source-code-analysis-gem
4
+
5
+ == DESCRIPTION:
6
+
7
+ SAN or Source ANalyzer is an open source Ruby program for analyzing the contents
8
+ of source code, such as line counts and comment ratios.
9
+
10
+ == SYNOPSIS:
11
+
12
+ lc [-hVr] [ dir | file ... ]
13
+
14
+ == REQUIREMENTS:
15
+
16
+ none
17
+
18
+ == INSTALL:
19
+
20
+ sudo gem install san
21
+
22
+ == AUTHOR:
23
+
24
+ TJ Holowaychuk
25
+ tj@vision-media.ca
26
+ http://vision-media.ca
27
+
28
+ == LICENSE:
29
+
30
+ (The MIT License)
31
+
32
+ Copyright (c) 2008 FIX
33
+
34
+ Permission is hereby granted, free of charge, to any person obtaining
35
+ a copy of this software and associated documentation files (the
36
+ 'Software'), to deal in the Software without restriction, including
37
+ without limitation the rights to use, copy, modify, merge, publish,
38
+ distribute, sublicense, and/or sell copies of the Software, and to
39
+ permit persons to whom the Software is furnished to do so, subject to
40
+ the following conditions:
41
+
42
+ The above copyright notice and this permission notice shall be
43
+ included in all copies or substantial portions of the Software.
44
+
45
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
46
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
47
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
48
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
49
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
50
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
51
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require File.dirname(__FILE__) + '/lib/san'
5
+
6
+ desc 'Build and install ruby gem.'
7
+ task :build do
8
+ sh "gem build ./san.gemspec"
9
+ sh "gem install san-#{San::VERSION}.gem"
10
+ end
11
+
12
+ desc 'Remove ruby gem build data.'
13
+ task :remove_build do
14
+ sh "gem uninstall san"
15
+ sh "rm san-#{San::VERSION}.gem"
16
+ end
17
+
18
+ # vim: syntax=Ruby
data/bin/san ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'san'
4
+ counter = San.new
5
+ counter.arguments = ARGV
6
+ counter.run
7
+
data/lib/san.rb ADDED
@@ -0,0 +1,238 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # == Synopsis
4
+ # SAN is an open source Ruby program for analysing the contents
5
+ # of source code, such as line counts and comment ratios.
6
+ #
7
+ # == Usage
8
+ # san [-hVr] [ dir | file ... ]
9
+ #
10
+ # == Examples
11
+ # Analyse current directory
12
+ # san
13
+ #
14
+ # Analyse current directory recursively
15
+ # san --recursive
16
+ #
17
+ # Analyse specific files and a directory recursively
18
+ # san -r ./index.php ./cron.php ./sites/all/modules/gui
19
+ #
20
+ # == Options
21
+ # -h, --help Display this help information.
22
+ # -V, --version Display version of lc.
23
+ # -r, --recurse Scan directories recursively.
24
+ #
25
+ # == Author
26
+ # TJ Holowaychuk
27
+ #
28
+ # == Copyright
29
+ # Copyright (c) 2008 TJ Holowaychuk. Licensed under the MIT License:
30
+ # http://www.opensource.org/licenses/mit-license.php
31
+
32
+ require 'optparse'
33
+ require 'rdoc/usage'
34
+
35
+ # TODO use seperators from /Library/Ruby/Gems/1.8/gems/rails-2.1.1/lib/ with optional --raw-output
36
+ # TODO remove 'and' from Shard
37
+ # TODO pick proper license, and use this RDoc as default for Shard
38
+ # TODO submit on resources.. gem?
39
+ # TODO list todo's line.match??? matches?
40
+ # TODO get gem help working...
41
+
42
+ $syntax = {
43
+ 'rb' => {
44
+ :name => 'Ruby',
45
+ :blank => /^\s*$/,
46
+ :comment => /^[\s]*#/,
47
+ :comment_open => /[\s]*=begin/,
48
+ :comment_close => /[\s]*=end/,
49
+ :function => /def[\s]+[\w]+/,
50
+ :class => /(class|module)[\s]+[\w]+/,
51
+ :todo => /@?todo/,
52
+ :associations => ['rb', 'erb']
53
+ },
54
+ 'php' => {
55
+ :name => 'PHP',
56
+ :blank => /^\s*$/,
57
+ :comment => /^[\s]*\/\//,
58
+ :comment_open => /^[\s]*\/\*/,
59
+ :comment_close => /[\s]*\*\//,
60
+ :function => /^[\s]*function[\s]+[\w]+[\s]*\(/,
61
+ :class => /class[\s]+[\w]+/,
62
+ :todo => /@?todo/,
63
+ :associations => ['php', 'inc', 'module', 'install']
64
+ },
65
+ 'js' => {
66
+ :name => 'JavaScript',
67
+ :blank => /^\s*$/,
68
+ :comment => /^[\s]*\/\//,
69
+ :comment_open => /^[\s]*\/\*/,
70
+ :comment_close => /[\s]*\*\//,
71
+ :function => /^[\s]*(?:function[\s][\w]+|(var)?[\s]*[\w\.]+[\s]+=[\s]+function)[\s]*\(/,
72
+ :todo => /@?todo/,
73
+ :associations => ['js']
74
+ },
75
+ 'css' => {
76
+ :name => 'CSS',
77
+ :blank => /^\s*$/,
78
+ :comment => /^[\s]*\/\//,
79
+ :comment_open => /^[\s]*\/\*/,
80
+ :comment_close => /[\s]*\*\//,
81
+ :todo => /@?todo/,
82
+ :associations => ['css']
83
+ }
84
+ }
85
+
86
+ class San
87
+
88
+ VERSION = '1.0.0'
89
+
90
+ attr_reader :files, :reports
91
+ attr_accessor :options, :arguments
92
+
93
+ # Initialize
94
+ def initialize()
95
+ self.initialize_options
96
+ self.initialize_reports
97
+ end
98
+
99
+ # Initialize option defaults
100
+ def initialize_options
101
+ @options = {}
102
+ @options[:recursive] = false
103
+ end
104
+
105
+ # Initialize reports, create defaults
106
+ def initialize_reports
107
+ @reports = {}
108
+ @reports[:comment_ratio] = 0
109
+ @reports[:totals] = {
110
+ 'files' => 0,
111
+ 'lines' => 0,
112
+ 'lines blank' => 0,
113
+ 'lines comments' => 0,
114
+ 'lines todo' => 0,
115
+ 'declared functions' => 0,
116
+ 'declared classes' => 0,
117
+ }
118
+ $syntax.each do |lang|
119
+ lang[1][:associations].each do |association|
120
+ @reports[:totals]['files ' << association] = 0
121
+ end
122
+ end
123
+ end
124
+
125
+ # Start analysis.
126
+ def run
127
+ # Parse options
128
+ self.parse_options
129
+
130
+ # Default files to cwd
131
+ @files = @arguments.empty? ? ['.'] : @arguments
132
+
133
+ # Parse files and directories
134
+ file_pattern = $syntax.collect{|lang| lang[1][:associations].join(',')}.join(',')
135
+ @files.each do |file|
136
+ if File.directory?(file)
137
+ files = Dir[(@options[:recursive] ? '**/' : '') << file << '/*.{' + file_pattern + '}']
138
+ files.each do |file|
139
+ self.parse_script(file)
140
+ end
141
+ elsif File.file?(file)
142
+ self.parse_script(file)
143
+ end
144
+ end
145
+
146
+ # Report
147
+ self.prep_report
148
+ self.output_report
149
+ exit
150
+ end
151
+
152
+ # Parse options
153
+ def parse_options
154
+ opts = OptionParser.new
155
+ opts.on('-h', '--help') { RDoc.usage(0) }
156
+ opts.on('-V', '--version') { self.output_version; exit 0 }
157
+ opts.on('-r', '--recursive') { @options[:recursive] = true }
158
+ begin
159
+ opts.parse!(@arguments)
160
+ rescue => e
161
+ puts e
162
+ exit 1
163
+ end
164
+ end
165
+
166
+ # Get extension of filepath.
167
+ def get_extension(filepath)
168
+ File.extname(filepath).reverse.chop.reverse
169
+ end
170
+
171
+ # Get syntax based on a filenames extension.
172
+ def get_syntax(filepath)
173
+ extension = get_extension(filepath)
174
+ $syntax.each_pair do |lang, info|
175
+ return $syntax[lang] if info[:associations].include?(extension)
176
+ end
177
+ end
178
+
179
+ # Parse a script and report on findings.
180
+ def parse_script(filepath)
181
+ lang = get_syntax(filepath)
182
+ comment_open = false
183
+ extension = get_extension(filepath)
184
+
185
+ # Ensure syntax was found
186
+ if lang.kind_of? NilClass
187
+ return
188
+ end
189
+
190
+ File.open(filepath) do |file|
191
+ @reports[:totals]['files'] += 1
192
+ @reports[:totals]['files ' << extension] += 1
193
+ file.each_line do |line|
194
+ @reports[:totals]['lines'] += 1
195
+ @reports[:totals]['lines blank'] += 1 if line.match(lang[:blank])
196
+ if !line.match(lang[:blank])
197
+ @reports[:totals]['lines todo'] += 1 if line.match(lang[:todo])
198
+ case
199
+ when line.match(lang[:comment]); @reports[:totals]['lines comments'] += 1
200
+ when line.match(lang[:comment_open]); @reports[:totals]['lines comments'] += 1; comment_open = true
201
+ when line.match(lang[:comment_close]); @reports[:totals]['lines comments'] += 1; comment_open = false
202
+ else
203
+ if comment_open
204
+ @reports[:totals]['lines comments'] += 1
205
+ else
206
+ case
207
+ when lang[:function] && line.match(lang[:function]); @reports[:totals]['declared functions'] += 1
208
+ when lang[:class] && line.match(lang[:class]); @reports[:totals]['declared classes'] += 1
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end
216
+
217
+ # Prepare output of report.
218
+ def prep_report
219
+ if @reports[:totals]['lines comments'] > 0 and @reports[:totals]['lines'] > 0
220
+ @reports[:comment_ratio] = @reports[:totals]['lines comments'].to_f / @reports[:totals]['lines'].to_f
221
+ end
222
+ end
223
+
224
+ # Output report.
225
+ def output_report
226
+ for k in @reports[:totals].keys.sort
227
+ puts k + ' ' + @reports[:totals][k].to_s unless @reports[:totals][k] == 0
228
+ end
229
+ puts 'comment ratio ' << '%.2f' % @reports[:comment_ratio] unless @reports[:comment_ratio] == 0
230
+ end
231
+
232
+ # Output version information.
233
+ def output_version
234
+ puts "Version #{VERSION}"
235
+ end
236
+ end
237
+
238
+
data/san.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "san"
3
+ s.version = "1.0.0"
4
+ s.date = "2008-09-29"
5
+ s.summary = "Source code analysis script"
6
+ s.email = "tj@vision-media.ca"
7
+ s.homepage = "http://vision-media.ca/resources/ruby/source-code-analysis-gem"
8
+ s.description = "Small ruby gem used to analyze the source code of projects or single scripts."
9
+ s.require_path = "lib"
10
+ s.has_rdoc = true
11
+ s.authors = ["tj@vision-media.ca"]
12
+ s.files = ["History.txt",
13
+ "Manifest.txt",
14
+ "README.txt",
15
+ "Rakefile",
16
+ "san.gemspec",
17
+ "lib/san.rb",
18
+ "bin/san"]
19
+ s.executables = ["san"]
20
+ s.test_files = ["test/test_san.rb"]
21
+ s.rdoc_options = ["--main", "README.txt"]
22
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
23
+ end
data/test/test_san.rb ADDED
@@ -0,0 +1 @@
1
+
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: visionmedia-san
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - tj@vision-media.ca
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-09-29 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Small ruby gem used to analyze the source code of projects or single scripts.
17
+ email: tj@vision-media.ca
18
+ executables:
19
+ - san
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - History.txt
24
+ - Manifest.txt
25
+ - README.txt
26
+ files:
27
+ - History.txt
28
+ - Manifest.txt
29
+ - README.txt
30
+ - Rakefile
31
+ - san.gemspec
32
+ - lib/san.rb
33
+ - bin/san
34
+ has_rdoc: true
35
+ homepage: http://vision-media.ca/resources/ruby/source-code-analysis-gem
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --main
39
+ - README.txt
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ requirements: []
55
+
56
+ rubyforge_project:
57
+ rubygems_version: 1.2.0
58
+ signing_key:
59
+ specification_version: 2
60
+ summary: Source code analysis script
61
+ test_files:
62
+ - test/test_san.rb