#!/usr/bin/env ruby
#
# Run like this:
#
#       ./find_long_lines.rb [DIR]
#
###############################################################
# Idea from the command line:                                 #
#                                                             #
# > cd wherever-you-want                                      #
# > files=$(find . -iname "*.f90")                            #
# > ruby -ne 'puts $<.filename, $_ if $_.length > 132' $files #
###############################################################

# -- where to look. Default to '~/TM5'.

if ARGV.size==1
  root=ARGV[0]
else
  root=File.join(ENV['HOME'],'TM5')
end

if not File.directory?(root)
  puts "Dir #{root} does not exist! Returning..."
  exit
end


# -- get list of files

f90=Dir["#{root}/**/*.[fF]90"]


# -- build list of culprit

flist_with_longlines=[]

f90.each do |fname|
  lines=File.open(fname).each_with_index.select {|li,ind| li.length>132} 
  if lines.any? 
    fobj=Hash.new()
    fobj['name']=fname
    fobj['ind']=lines.map(&:last).map{|v| v+1}
    fobj['longuest']=lines.map{|p| p[0].length}.max

    begin
      fobj['isComment']=lines.select{|l,i| l=~/^\s*!/}.map(&:last).map{|v| v+1}
      fobj['isOMP']=lines.select{|l,i| l=~/^\s*!\$OMP/i}.map(&:last).map{|v| v+1}
    rescue Exception
      STDERR.puts "Problem with file: #{fname} (bad encoding?)"
      STDERR.puts "All lon lines considered as code."
      fobj['isComment']=[]
      fobj['isOMP']=[]
    end

    fobj['isComment']-=fobj['isOMP']
    fobj['isCode']=fobj['ind']-fobj['isComment']-fobj['isOMP']

    flist_with_longlines << fobj
  end
end


# -- Verbose

total=flist_with_longlines.map {|f| f['ind'].length}.inject(:+)
totalf=flist_with_longlines.map {|f| f['isCode'].length}.inject(:+)
totalc=flist_with_longlines.map {|f| f['isComment'].length}.inject(:+)
totalo=flist_with_longlines.map {|f| f['isOMP'].length}.inject(:+)
longuest=flist_with_longlines.map {|f| f['longuest']}.max

puts "There are #{flist_with_longlines.length} files out of #{f90.length} with too long lines,"
puts "for a total of #{total} too long lines (Code: #{totalf}; Comment: #{totalc}; OpenMP: #{totalo})."
puts "The longest line is #{longuest} characters long."
print "Do you want the list of files AND all lines numbers [Y/n]? "
res=$stdin.gets.chomp

if res=='' or res.upcase=='Y'
  flist_with_longlines.each do |f|
    puts
    puts f['name'].sub(root,'.') +':',"--long code--",f['isCode'],"--long comment--",f['isComment']
    puts "--long OpenMP--",f['isOMP']
  end
else
  print "Do you want the ONLY the list of files (no lines numbers) [Y/n]? "
  res2=$stdin.gets.chomp
  if res2=='' or res2.upcase=='Y'
    flist_with_longlines.each do |f|
      nlc=f['isCode'].length
      if nlc>0
        puts f['name'].sub(root,'.') +" (#{nlc})"
      end
    end
  end
end
