lib/findr/cli.rb in findr-0.0.3 vs lib/findr/cli.rb in findr-0.0.4
- old
+ new
@@ -1,59 +1,57 @@
#!/usr/bin/env ruby
require 'pathname'
require 'tempfile'
require 'optparse'
require 'yaml'
+require 'pp'
-# this is deprecated on 1.9, but still works fine
-require 'iconv'
-
require 'findr/version'
+require 'findr/encoder'
-
module Findr
-
+
class CLI
-
+
CONFIGFILE = '.findr-config'
-
+
def colorize(text, color_code)
"\e[#{color_code}m#{text}\e[0m"
end
-
+
def red(text); colorize(text, 31); end
def green(text); colorize(text, 32); end
def yellow(text); colorize(text, 33); end
def blue(text); colorize(text, 34); end
-
+
def banner
red( "FINDR VERSION #{Findr::VERSION}. THIS PROGRAM COMES WITH NO WARRANTY WHATSOEVER. MAKE BACKUPS!") + $/ +
"Usage: #{Pathname($0).basename} [options] <search regex> [<replacement string>]"
end
-
+
def show_usage
puts(@option_parser.help)
exit
end
-
+
def execute(stdout, arguments=[])
# unless arguments[0]
# end
-
+
# default options
options = {}
options[:glob] = '*'
options[:coding] = 'utf-8'
-
+
# options from file, if present
if File.exists?( CONFIGFILE )
file_options = YAML.load_file(CONFIGFILE)
file_options.delete(:save)
options.merge!( file_options )
stdout.puts green "Using #{CONFIGFILE}."
end
-
+
# parse command line
@option_parser = OptionParser.new do |opts|
opts.on('-g', '--glob FILE SEARCH GLOB', 'e.g. "*.{rb,erb}"') do |glob|
options[:glob] = glob
end
@@ -64,23 +62,27 @@
options[:coding] = coding
end
opts.on('-s', '--save', "saves your options to #{CONFIGFILE} for future use") do
options[:save] = true
end
+ opts.on('-C', '--codings-list', "list available encodings") do
+ pp Encoder.list
+ exit
+ end
end
@option_parser.banner = self.banner
@option_parser.parse!( arguments )
-
+
# optionally save the configuration to file
if options[:save]
options.delete(:save)
stdout.puts red "Nothing to save." unless options
File.open( CONFIGFILE, 'w' ) { |file| YAML::dump( options, file ) }
stdout.puts green "Saved options to file #{CONFIGFILE}."
exit
end
-
+
show_usage if arguments.size == 0
arguments.clone.each do |arg|
if !options[:find]
options[:find] = Regexp.compile( arg )
arguments.delete_at(0)
@@ -89,75 +91,74 @@
arguments.delete_at(0)
else
show_usage
end
end
-
+
show_usage if arguments.size != 0
stdout.puts green "File inclusion glob: " + options[:glob]
stdout.puts green "Searching for regex " + options[:find].to_s
-
+
# some statistics
stats = {}
stats[:total_hits] = stats[:local_hits] = stats[:hit_files] = stats[:total_files] = 0
-
+
replacement_done = false
tempfile = nil
-
- coding_to_utf8 = Iconv.new('utf-8', options[:coding])
- utf8_to_coding = Iconv.new(options[:coding], 'utf-8')
-
+
+ coder = Encoder.new( options[:coding] )
+
Pathname.glob("**/#{options[:glob]}").each do |current_file|
next unless current_file.file?
stats[:total_files] += 1
stats[:local_hits] = 0
firstmatch = true
linenumber = 0
tempfile = Tempfile.new( 'current_file.basename' ) if options[:replace] && options[:force]
current_file.each_line do |l|
begin
- l = coding_to_utf8.iconv(l)
- rescue Iconv::IllegalSequence
- stdout.puts "Skipping file #{current_file} because of error on line #{linenumber}: #{$!.class} #{$!.message}"
+ l = coder.decode(l)
+ rescue Encoder::Error
+ stdout.puts "Skipping file #{current_file} because of error on line #{linenumber}: #{$!.original.class} #{$!.original.message}"
tempfile.unlink if tempfile
break
end
linenumber += 1
if l=~ options[:find]
stats[:local_hits] += 1
if firstmatch
- stdout.puts red("#{current_file.cleanpath}:")
+ stdout.puts red("#{current_file.cleanpath}:")
end
stdout.write( yellow( "%6d:" % [linenumber, l] ) )
stdout.puts l
firstmatch = false
if options[:replace]
stdout.write( blue( "%6d:" % [linenumber, l] ) )
l_repl = l.gsub( options[:find], options[:replace] )
- tempfile.puts utf8_to_coding.iconv(l_repl) if tempfile
+ tempfile.puts coder.encode(l_repl) if tempfile
stdout.puts blue l_repl
replacement_done = true
end
elsif tempfile
- tempfile.puts utf8_to_coding.iconv(l)
+ tempfile.puts coder.encode(l)
end
end
if tempfile
tempfile.close
FileUtils.cp( tempfile.path, current_file ) if stats[:local_hits] > 0
tempfile.unlink
end
-
+
if stats[:local_hits] > 0
stats[:total_hits] += stats[:local_hits]
stats[:hit_files] += 1
end
-
+
end
-
+
# some statistics
stdout.puts green( "#{stats[:total_hits]} occurences (lines) in #{stats[:hit_files]} of #{stats[:total_files]} files found." )
end
-
+
end
end