-
Notifications
You must be signed in to change notification settings - Fork 0
/
cr.rb
executable file
·123 lines (104 loc) · 3.35 KB
/
cr.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env ruby
require 'optparse'
require 'async'
options = {
# the following at the default options value
:recursive => false,
:method => 'ractor'
}
search_method_options = {
'serial' => 'serial',
'fiber' => 'fiber',
'ractor' => 'ractor'
}
option_parser = OptionParser.new do |opts|
opts.banner = "Usage: cr.rb [options] search_term search_directory_path"
opts.on('-r', '--recursive', 'Recursively search files in sub-directories') do
options[:recursive] = true
end
opts.on('--method METHOD', search_method_options, 'Method to search by: serial (one file at a time), fiber (multiple files at the same time), or ractor (multiple files at the same time)') do |method|
options[:method] = method
end
opts.on('-h', '--help', "Prints this help") do
puts opts
exit
end
end
option_parser.parse!
arguments = {}
arguments[:search_term] = ARGV.shift
if arguments[:search_term].nil? or arguments[:search_term].empty?
puts "missing argument: NO search term provided"
exit
end
arguments[:search_directory_path] = ARGV.shift
if arguments[:search_directory_path].nil? or arguments[:search_directory_path].empty?
puts "missing argument: NO search directory path provided"
exit
end
if Dir.exists? arguments[:search_directory_path]
if options[:recursive]
files_to_search_in = Dir.glob("#{arguments[:search_directory_path]}/**/*")
else
files_to_search_in = Dir.glob("#{arguments[:search_directory_path]}/*")
end
else
files_to_search_in = [arguments[:search_directory_path]]
end
def ignore_file?(file)
skip_locations = ["bin/", "tmp/", "_site/", "log/", "node_modules/", ".git/"]
skip_locations.each do |skip_location|
if File.directory? file
return true
elsif file.include? skip_location
return true
end
end
return false
end
files_to_search_in.reject! { |file| ignore_file? file }
def search_in_file(search_term, file)
File.readlines(file).each do |line|
if line.include? search_term
puts "#{file}: #{line}"
end
end
end
def serial_search(search_term, files)
files.each do |file|
search_in_file search_term, file
end
end
def fiber_search(search_term, file)
Async do |task|
search_in_file search_term, file
end
end
def ractor_search(search_term, files)
files.each do |file|
Ractor.new(file, search_term) do |file_in_ractor, search_term_in_ractor|
# we don't re-use the mehod search_in_file here
# because since every Ractor instance is in it's own thread
# we cannot access data outside of said thread (like the other thread where main is in)
File.readlines(file_in_ractor).each do |line|
if line.include? search_term_in_ractor
puts "#{file_in_ractor}: #{line}"
end
end
end
# notice, not using the Ractor take command here
# as we are not depending on the Ractor object/thread to return any value for us to use here
end
end
case options[:method]
when 'serial'
serial_search arguments[:search_term], files_to_search_in
when 'fiber'
Async do
files_to_search_in.each do |file|
fiber_search arguments[:search_term], file
end
end
when 'ractor'
ractor_search arguments[:search_term], files_to_search_in
end