visionmedia-san 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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