Credit: Stefan Lang
You want to gather statistics about your Ruby project, like the total number of lines of code.
Heres a class that parses Ruby source files and gathers statistics. Put this in scriptlines.rb in your projects top-level directory.
# scriptlines.rb
# A ScriptLines instance analyses a Ruby script and maintains
# counters for the total number of lines, lines of
code, etc.
class ScriptLines
attr_reader :name
attr_accessor :bytes, :lines, :lines_of_code, :comment_lines
LINE_FORMAT = \%8s %8s %8s %8s %s
def self.headline
sprintf LINE_FORMAT, "BYTES", "LINES", "LOC", "COMMENT", "FILE"
end
# The
ame argument is usually a filename
def initialize(name)
@name = name
@bytes = 0
@lines = 0 # total number of lines
@lines_of_code = 0
@comment_lines = 0
end
# Iterates over all the lines in io (io might be a file or a
# string), analyses them and appropriately increases the counter
# attributes.
def read(io)
in_multiline_comment = false
io.each { |line|
@lines += 1
@bytes += line.size
case line
when /^=begin(s|$)/
in_multiline_comment = true
@comment_lines += 1
when /^=end(s|$)/:
@comment_lines += 1
in_multiline_comment = false
when /^s*#/
@comment_lines += 1
when /^s*$/
# empty/whitespace only line
else
if in_multiline_comment
@comment_lines += 1
else
@lines_of_code += 1
end
end
}
end
# Get a new ScriptLines instance whose counters hold the
# sum of self and other.
def +(other)
sum = self.dup
sum.bytes += other.bytes
sum.lines += other.lines
sum.lines_of_
code += other.lines_of_code
sum.comment_lines += other.comment_lines
sum
end
# Get a formatted string containing all counter numbers and the
# name of this instance.
def to_s
sprintf LINE_FORMAT,
@bytes, @lines, @lines_of_code, @comment_lines, @name
end
end
To tie the class into your build system, give your Rakefile a stats task like the following. This task assumes that the Rakefile and scriptlines.rb are in the same directory:
task stats do
require scriptlines
files = FileList[lib/**/*.rb]
puts ScriptLines.headline
sum = ScriptLines.new("TOTAL (#{files.size} file(s))")
# Print stats for each file.
files.each do |fn|
File.open(fn) do |file|
script_lines = ScriptLines.new(fn)
script_lines.read(file)
sum += script_lines
puts script_lines
end
end
# Print total stats.
puts sum
end
ScriptLines performs a very basic parsing of Ruby code: it divides a source file into blank lines, comment lines, and lines containing Ruby code. If you want more detailed information, you can include each file and get more information about the defined classes and methods with reflection or an extension like Parse Tree.
Invoke the stats task to run all the Ruby scripts beneath your lib/ directory through ScriptLines. The following example output is for the highline library:
$ rake stats (in /usr/local/lib/ruby/gems/1.8/gems/highline-1.0.1) BYTES LINES LOC COMMENT FILE 18626 617 360 196 lib/highline.rb 12745 375 168 181 lib/highline/menu.rb 15760 430 181 227 lib/highline/question.rb 801 25 7 14 lib/highline/import.rb 47932 1447 716 618 TOTAL (4 scripts)
BYTES is the file size in bytes, LINES the number of total lines in each file, LOC stands for "Lines Of Code," and COMMENT is the number of comment-only lines.
These simple metrics are good for gauging the complexity of a project, but don use them as a measure of day-to-day progress. Complexity is not the same as progress, and a good days work might consist of replacing a hundred lines of code with ten.
Strings
Numbers
Date and Time
Arrays
Hashes
Files and Directories
Code Blocks and Iteration
Objects and Classes8
Modules and Namespaces
Reflection and Metaprogramming
XML and HTML
Graphics and Other File Formats
Databases and Persistence
Internet Services
Web Development Ruby on Rails
Web Services and Distributed Programming
Testing, Debugging, Optimizing, and Documenting
Packaging and Distributing Software
Automating Tasks with Rake
Multitasking and Multithreading
User Interface
Extending Ruby with Other Languages
System Administration