patternrubyMinor
Search utility that searches through source code files
Viewed 0 times
searchsourceutilityfilesthatthroughcodesearches
Problem
I'm working on a search utility that searches through source files. It's only the beginning of the project. It lacks a lot of features, but a backbone of the project works and it would be great if you can take a look at it.
```
path, keyword = ARGV if ARGV.length == 2
if ARGV.length != 2
puts "Not enough argumetns. Type 'finder --help' for help"
abort if ARGV.length != 2
end
IGNORED_DIRS = ['..', '.', '.git', 'blib', '_build', '.bzr', '.cdv', 'cover_db',
'__pycache', 'CVS', '_darcs', '~.dep', '~.dot', '.hg', '~.nib', '.pc', '~.plst', 'RCS', 'SCCS',
'_sgbak', '.svn', '.tox','.metadata', '.cover']
# colorize output
class String
def black; "\033[30m#{self}\033[0m" end
def red; "\033[31m#{self}\033[0m" end
def green; "\033[32m#{self}\033[0m" end
def brown; "\033[33m#{self}\033[0m" end
def blue; "\033[34m#{self}\033[0m" end
def magenta; "\033[35m#{self}\033[0m" end
def cyan; "\033[36m#{self}\033[0m" end
def gray; "\033[37m#{self}\033[0m" end
def bg_black; "\033[40m#{self}\033[0m" end
def bg_red; "\033[41m#{self}\033[0m" end
def bg_green; "\033[42m#{self}\033[0m" end
def bg_brown; "\033[43m#{self}\033[0m" end
def bg_blue; "\033[44m#{self}\033[0m" end
def bg_magenta; "\033[45m#{self}\033[0m" end
def bg_cyan; "\033[46m#{self}\033[0m" end
def bg_gray; "\033[47m#{self}\033[0m" end
def bold; "\033[1m#{self}\033[22m" end
def reverse_color; "\033[7m#{self}\033[27m" end
end
# convert given path to full path
# which can be used in 'Dir.chdir()'
def expand_path(path)
case path
when '.'
Dir.pwd
when /~(\/[a-zA-Z\w]*)+/
File.expand_path(path, __FILE__)
when /\.\/[a-z]*/
Dir.pwd + path[1..-1]
when /\/[a-z]*/
Dir.pwd + path
else
puts "Wrong path name"
end
end
def search_in_file(path_to_file, keyword)
f = open(path_to_file)
flag = tr
```
path, keyword = ARGV if ARGV.length == 2
if ARGV.length != 2
puts "Not enough argumetns. Type 'finder --help' for help"
abort if ARGV.length != 2
end
IGNORED_DIRS = ['..', '.', '.git', 'blib', '_build', '.bzr', '.cdv', 'cover_db',
'__pycache', 'CVS', '_darcs', '~.dep', '~.dot', '.hg', '~.nib', '.pc', '~.plst', 'RCS', 'SCCS',
'_sgbak', '.svn', '.tox','.metadata', '.cover']
# colorize output
class String
def black; "\033[30m#{self}\033[0m" end
def red; "\033[31m#{self}\033[0m" end
def green; "\033[32m#{self}\033[0m" end
def brown; "\033[33m#{self}\033[0m" end
def blue; "\033[34m#{self}\033[0m" end
def magenta; "\033[35m#{self}\033[0m" end
def cyan; "\033[36m#{self}\033[0m" end
def gray; "\033[37m#{self}\033[0m" end
def bg_black; "\033[40m#{self}\033[0m" end
def bg_red; "\033[41m#{self}\033[0m" end
def bg_green; "\033[42m#{self}\033[0m" end
def bg_brown; "\033[43m#{self}\033[0m" end
def bg_blue; "\033[44m#{self}\033[0m" end
def bg_magenta; "\033[45m#{self}\033[0m" end
def bg_cyan; "\033[46m#{self}\033[0m" end
def bg_gray; "\033[47m#{self}\033[0m" end
def bold; "\033[1m#{self}\033[22m" end
def reverse_color; "\033[7m#{self}\033[27m" end
end
# convert given path to full path
# which can be used in 'Dir.chdir()'
def expand_path(path)
case path
when '.'
Dir.pwd
when /~(\/[a-zA-Z\w]*)+/
File.expand_path(path, __FILE__)
when /\.\/[a-z]*/
Dir.pwd + path[1..-1]
when /\/[a-z]*/
Dir.pwd + path
else
puts "Wrong path name"
end
end
def search_in_file(path_to_file, keyword)
f = open(path_to_file)
flag = tr
Solution
The POSIX
You misspelled "argumetns". Also, I recommend writing
It is customary to put all of the class / method definitions first, then all of the "main" code at the end. You've put the argument-handling code at the top, and the
Avoid using
For efficiency,
Your
When expanding a path starting with
In case of an error, you should raise an exception instead of printing a message here. However, I don't see any reason why there should be an error in the first place.
If you avoid changing directories altogether, then you wouldn't need to generate absolute paths at all. Then you could just eliminate this function and call
Opening a file without closing it causes a file descriptor leak.
I'm not a fan of augmenting the
grep command accepts the keyword as the first parameter, then the paths to search as subsequent parameters. That has the advantage of letting the user specify any number of paths to search.You misspelled "argumetns". Also, I recommend writing
"#{File::basename($0)}" rather than hardcoding "finder" as the program name.It is customary to put all of the class / method definitions first, then all of the "main" code at the end. You've put the argument-handling code at the top, and the
file_finder(expand_path(path), keyword) call at the bottom. Curiously, you test ARGV.length in three places — is it really that important?file_finderAvoid using
Dir#chdir, as changing the current directory alters the global state of the process. One consequence of Dir#chdir is that you need to use absolute paths. For portability, use File::join(path, item) instead of path + "/" + item.For efficiency,
IGNORED_DIRS should be a Set.def file_finder(path, keyword)
Dir.foreach(path) do |item|
next if IGNORED_DIRS.include?(item)
item_path = File::join(path, item)
if File.file?(item_path)
search_in_file(item_path, keyword)
else
file_finder(item_path, keyword)
end
end
endexpand_pathYour
expand_path incorrectly treats an absolute path as a relative path.When expanding a path starting with
~, I don't see any reason to provide __FILE__ as the second argument to File.expand_path.In case of an error, you should raise an exception instead of printing a message here. However, I don't see any reason why there should be an error in the first place.
If you avoid changing directories altogether, then you wouldn't need to generate absolute paths at all. Then you could just eliminate this function and call
File::expand_path instead.search_in_fileOpening a file without closing it causes a file descriptor leak.
flag is a poor variable name.I'm not a fan of augmenting the
String class, especially for code that is, strictly speaking, related more to terminal control than strings.def search_in_file(path_to_file, keyword)
seen = false
File::open(path_to_file) do |f|
f.each_with_index do |line, i|
if line.include?(keyword)
if not seen
puts path_to_file.bold.blue
seen = true
end
puts "#{i+1}:".bold.gray + " #{line}".sub(keyword, keyword.bg_red)
end
end
end
puts "" if seen
endCode Snippets
def file_finder(path, keyword)
Dir.foreach(path) do |item|
next if IGNORED_DIRS.include?(item)
item_path = File::join(path, item)
if File.file?(item_path)
search_in_file(item_path, keyword)
else
file_finder(item_path, keyword)
end
end
enddef search_in_file(path_to_file, keyword)
seen = false
File::open(path_to_file) do |f|
f.each_with_index do |line, i|
if line.include?(keyword)
if not seen
puts path_to_file.bold.blue
seen = true
end
puts "#{i+1}:".bold.gray + " #{line}".sub(keyword, keyword.bg_red)
end
end
end
puts "" if seen
endContext
StackExchange Code Review Q#88103, answer score: 3
Revisions (0)
No revisions yet.