exe/gloc in gloc-0.3.1 vs exe/gloc in gloc-0.4.0
- old
+ new
@@ -1,12 +1,24 @@
#!/usr/bin/env ruby -s
+#
+# rubocop:disable Layout/AlignHash
+# rubocop:disable Layout/ElseAlignment
+# rubocop:disable Layout/EndAlignment
+# rubocop:disable Layout/IndentationWidth
+#
+# rubocop:disable Style/EmptyCaseCondition
+# rubocop:disable Style/GlobalVars
+# rubocop:disable Style/RegexpLiteral
+#
+
+require 'English'
require 'ostruct'
source_files = if STDIN.tty? || $tty
`git rev-parse --show-toplevel &> /dev/null`
- if $?.success?
+ if $CHILD_STATUS.success?
# we're inside a git repo so
# get list of files from git
`git ls-files -z #{ARGV.join(' ')}`.split("\0")
else
# we are not inside a git repo:
@@ -14,11 +26,11 @@
`find #{ARGV.empty? ? Dir.pwd : ARGV.join(' ')} -print0`.split("\0")
end
else
# assume we're running it in a pipeline
# and read list of filenames from STDIN
- STDIN.read.split($/).map(&:chomp)
+ STDIN.read.split($RS).map(&:chomp)
end
# exclude binary files from stats
# (files with NUL in file header)
#
@@ -38,88 +50,102 @@
File.basename(file) =~ /\A\..*\z/ || # skip hidden ".*" files
!File.exist?(file) || # skip non-existent paths
!File.file?(file) || # skip directories
!File.size?(file) || # skip empty files
!File.read(file, 16)["\0"].nil? # skip binary files
- ) && ( $verbose && warn("SKIPPING #{file}...") ; true )
+ ) && ($verbose && warn("SKIPPING #{file}..."); true)
}
-BLANKS = %r{\A\s*\Z}.freeze
+BLANKS = Hash.new(%r{\A\s*\Z}.freeze) # TODO: ext-specific regex for blanks?
COMMENTS = {
- # FIXME does not work for multi-line comments
- # (for the languages that support them)
+ # FIXME: does not work for multi-line comments
+ # (for the languages that support them)
'*.rb' => %r{\A\s*(#.*)\s*\Z},
'*.sh' => %r{\A\s*(#.*)\s*\Z},
'*.xml' => %r{\A\s*(<!--.*-->)\s*\Z},
'*.html' => %r{\A\s*(<!--.*-->)\s*\Z},
'*.css' => %r{\A\s*(/\*.*\*/)\s*\Z},
'*.js' => %r{\A\s*(//.*|/\*.*\*/)\s*\Z},
}.freeze
-source_stats = source_files.each_with_object({}) { |file, stats|
- file_ext = '*' + File.extname(file) # e.g. '*.rb' or '*' if no ext!
- stats_for_ext = begin
- stats[file_ext] ||= OpenStruct.new({
- file_count: 0,
- line_count: 0,
- blank_count: 0,
- comment_count: 0,
- })
- end
- file_content = File.read(file, :encoding => 'UTF-8')
+STATS_FOR_FILE = Hash.new do |stats_for_file, (file, blank_re, comment_re)|
+ file_content = File.read(file, encoding: 'UTF-8')
unless file_content.valid_encoding?
- file_content = File.read(file, :encoding => 'ISO-8859-1')
- # FIXME what about file encodings other than these two???
+ file_content = File.read(file, encoding: 'ISO-8859-1')
+ # FIXME: what about file encodings other than these two???
end
- source_lines = file_content.each_line
- stats_for_ext.file_count += 1
- stats_for_ext.line_count += source_lines.count
- stats_for_ext.blank_count += source_lines.grep(BLANKS).count
- next unless COMMENTS[file_ext] # only scan for comments if a regex exists!
- stats_for_ext.comment_count += source_lines.grep(COMMENTS[file_ext]).count
-}
-source_stats.values.each do |stats_for_ext|
- stats_for_ext.code_count = stats_for_ext.line_count - (
- stats_for_ext.blank_count + stats_for_ext.comment_count
+ lines = file_content.each_line
+
+ stats_for_file[[file, blank_re, comment_re]] = OpenStruct.new(
+ line_count: line_count = lines.count,
+ blank_count: blank_count = lines.grep(blank_re).count,
+ comment_count: comment_count = lines.grep(comment_re).count,
+ code_count: (line_count - blank_count - comment_count),
)
end
-sort_metric = case
- when $files then :file_count
- when $lines then :line_count
- when $blank then :blank_count
- when $comment then :comment_count
- when $code then :code_count
- else :code_count
+STATS_FOR = Hash.new do |stats_for_ext, ext|
+ stats_for_ext[ext] = OpenStruct.new(
+ file_count: 0,
+ line_count: 0,
+ blank_count: 0,
+ comment_count: 0,
+ code_count: 0,
+ )
end
+source_files.each do |file|
+ ext = '*' + File.extname(file) # e.g. '*.rb' or '*' if no ext!
+
+ blank_regex = BLANKS[ext]
+ comment_regex = COMMENTS[ext]
+
+ stats_for_file = STATS_FOR_FILE[[file, blank_regex, comment_regex]]
+ stats_for_ext = STATS_FOR[ext]
+
+ stats_for_ext.file_count += 1
+ stats_for_ext.line_count += stats_for_file.line_count
+ stats_for_ext.blank_count += stats_for_file.blank_count
+ stats_for_ext.comment_count += stats_for_file.comment_count
+ stats_for_ext.code_count += stats_for_file.code_count
+end
+
+sort_metric = case
+ when $files then :file_count
+ when $lines then :line_count
+ when $blank then :blank_count
+ when $comment then :comment_count
+ when $code then :code_count
+ else :code_count
+ end
+
source_stats = Hash[
- source_stats.sort_by { |_, stats|
+ STATS_FOR.sort_by { |_, stats|
stats.send(sort_metric)
}.reverse
]
-source_stats["TOTAL"] = OpenStruct.new({
+source_stats['TOTAL'] = OpenStruct.new(
file_count: source_stats.values.map(&:file_count).reduce(:+) || 0,
line_count: source_stats.values.map(&:line_count).reduce(:+) || 0,
blank_count: source_stats.values.map(&:blank_count).reduce(:+) || 0,
comment_count: source_stats.values.map(&:comment_count).reduce(:+) || 0,
code_count: source_stats.values.map(&:code_count).reduce(:+) || 0,
-})
+)
#
# JSON formatting for non-TTY output
#
unless STDOUT.tty? || $tty
require 'json'
class OpenStruct
def to_json(*args)
- self.to_h.to_json(args)
+ to_h.to_json(args)
end
end
puts source_stats.to_json
@@ -130,11 +156,11 @@
# fancy formatting for TTY output
#
class String
def commify
- gsub(/(\d)(?=(\d{3})+(\..*)?$)/,'\1,')
+ gsub(/(\d)(?=(\d{3})+(\..*)?$)/, '\1,')
end
end
class Numeric
def commify
@@ -155,34 +181,42 @@
# widest_line_count = source_stats.values.map(&:line_count).map(&:length).max
# widest_blank_count = source_stats.values.map(&:blank_count).map(&:length).max
# widest_comment_count = source_stats.values.map(&:comment_count).map(&:length).max
# widest_code_count = source_stats.values.map(&:code_count).map(&:length).max
-totals = source_stats.delete("TOTAL").to_h.values
+DIVIDER = ('-' * 80) # because loc uses 80 columns
+TEMPLATE = ' %-13s %12s %12s %12s %12s %12s'.freeze
-TEMPLATE = " %-13s %12s %12s %12s %12s %12s".freeze
-DIVIDER = ('-' * 80).freeze # `loc` uses 80 columns
-
-puts format("%s\n#{TEMPLATE}\n%s",
- DIVIDER,
- *%w(Language Files Lines Blank Comment Code),
- DIVIDER,
+puts format(
+ "#{DIVIDER}\n#{TEMPLATE}\n#{DIVIDER}",
+ 'Language', 'Files', 'Lines', 'Blank', 'Comment', 'Code'
)
source_stats.each do |file_ext, stats|
- puts format(TEMPLATE,
+ puts format(
+ TEMPLATE,
file_ext,
stats.file_count,
stats.line_count,
stats.blank_count,
stats.comment_count,
stats.code_count,
)
end
-puts format("%s\n#{TEMPLATE}\n%s",
- DIVIDER,
- "Total", *totals,
- DIVIDER,
+puts format(
+ "#{DIVIDER}\n#{TEMPLATE}\n#{DIVIDER}",
+ 'Total', *source_stats.delete('TOTAL').to_h.values
)
+
+#
+# rubocop:enable Style/RegexpLiteral
+# rubocop:enable Style/GlobalVars
+# rubocop:enable Style/EmptyCaseCondition
+#
+# rubocop:enable Layout/IndentationWidth
+# rubocop:enable Layout/EndAlignment
+# rubocop:enable Layout/ElseAlignment
+# rubocop:enable Layout/AlignHash
+#
# That's all Folks!