grepfruit 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/exe/grepfruit +2 -2
- data/grepfruit.gemspec +6 -3
- data/lib/grepfruit/version.rb +1 -1
- data/lib/grepfruit.rb +2 -49
- data/lib/search.rb +101 -0
- metadata +9 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d6d72bac5375937fd7214c4d0f13de9f619695de3614202af1d877aaffdaf1f4
|
4
|
+
data.tar.gz: 7d1abd0f67111b48ccf0e988c8bfcab18fd90cf0510d02571292d29f2b4642b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 18e978abd3bd6beeb29e14b88e8847f1410e3adfe8e1ad4b82910075cae099e25e5139c4ca8c4077b3666e7b2ad63911eb9a5cb637c8b3306ac42ad908f3caf1
|
7
|
+
data.tar.gz: 7d48ec2fd3f5f04baa4c69b9187675e0664c46d728907702aaa9a82f62b4689f999fc923bf5cc6035feb298d80350d9cd4f2906e006276b79b6e1a9768a6bc5b
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
## v1.1.2
|
2
|
+
|
3
|
+
- Refactored code significantly for improved search efficiency and easier maintenance
|
4
|
+
- Enhanced search result output for better readability
|
5
|
+
|
6
|
+
## v1.1.1
|
7
|
+
|
8
|
+
- Added test dataset to make testing and development easier
|
9
|
+
- Updated gemspec file to include missing metadata
|
10
|
+
|
1
11
|
## v1.1.0
|
2
12
|
|
3
13
|
- Added `--truncate` option to truncate the output of the search results
|
data/exe/grepfruit
CHANGED
@@ -21,7 +21,7 @@ OptionParser.new do |opts|
|
|
21
21
|
end
|
22
22
|
|
23
23
|
opts.on("-e", "--exclude x,y,z", Array, "Comma-separated list of files and directories to exclude") do |exclude|
|
24
|
-
options[:exclude] = exclude
|
24
|
+
options[:exclude] = exclude
|
25
25
|
end
|
26
26
|
|
27
27
|
opts.on("-t", "--truncate N", Integer, "Truncate output to N characters") do |truncate|
|
@@ -40,4 +40,4 @@ end
|
|
40
40
|
|
41
41
|
options[:dir] = ARGV[0] if ARGV[0]
|
42
42
|
|
43
|
-
Grepfruit.
|
43
|
+
Grepfruit::Search.new(**options).run
|
data/grepfruit.gemspec
CHANGED
@@ -4,11 +4,14 @@ Gem::Specification.new do |spec|
|
|
4
4
|
spec.name = "grepfruit"
|
5
5
|
spec.version = Grepfruit::VERSION
|
6
6
|
spec.authors = ["enjaku4"]
|
7
|
-
spec.metadata["rubygems_mfa_required"] = "true"
|
8
|
-
spec.summary = "A Ruby gem for searching text patterns in files with colorized output."
|
9
7
|
spec.homepage = "https://github.com/enjaku4/grepfruit"
|
8
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
9
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
10
|
+
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md"
|
11
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
12
|
+
spec.summary = "A Ruby gem for searching text patterns in files with colorized output"
|
10
13
|
spec.license = "MIT"
|
11
|
-
spec.required_ruby_version = ">= 3.0
|
14
|
+
spec.required_ruby_version = ">= 3.0", "< 3.4"
|
12
15
|
|
13
16
|
spec.files = [
|
14
17
|
"grepfruit.gemspec", "README.md", "CHANGELOG.md", "LICENSE.txt"
|
data/lib/grepfruit/version.rb
CHANGED
data/lib/grepfruit.rb
CHANGED
@@ -1,53 +1,6 @@
|
|
1
1
|
require_relative "grepfruit/version"
|
2
|
-
|
3
|
-
require "find"
|
2
|
+
require_relative "search"
|
4
3
|
|
5
4
|
module Grepfruit
|
6
|
-
|
7
|
-
lines = []
|
8
|
-
files = 0
|
9
|
-
excluded_lines = exclude.select { |e| e.any? { |s| s.include?(":") } }
|
10
|
-
excluded_paths = exclude - excluded_lines
|
11
|
-
|
12
|
-
puts "Searching for #{regex.inspect} in #{dir.inspect}...\n\n"
|
13
|
-
|
14
|
-
Find.find(dir) do |path|
|
15
|
-
Find.prune if excluded_paths.any? { |e| path.split("/").last(e.length) == e } || !search_hidden && File.basename(path).start_with?(".")
|
16
|
-
|
17
|
-
next if File.directory?(path) || File.symlink?(path)
|
18
|
-
|
19
|
-
files += 1
|
20
|
-
|
21
|
-
match = false
|
22
|
-
|
23
|
-
File.foreach(path).with_index do |line, line_num|
|
24
|
-
next unless line.valid_encoding?
|
25
|
-
|
26
|
-
if line.match?(regex)
|
27
|
-
path_with_line = "#{Pathname.new(path).relative_path_from(Pathname.new(dir))}:#{line_num + 1}"
|
28
|
-
|
29
|
-
next if excluded_lines.any? { |e| path_with_line.split("/").last(e.length) == e }
|
30
|
-
|
31
|
-
processed_line = line.strip
|
32
|
-
processed_line = "#{processed_line[0..truncate - 1]}..." if truncate && processed_line.length > truncate
|
33
|
-
lines << "\e[36m#{path_with_line}\e[0m: #{processed_line}"
|
34
|
-
match = true
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
print match ? "\e[31mF\e[0m" : "\e[32m.\e[0m"
|
39
|
-
end
|
40
|
-
|
41
|
-
puts "\n\n"
|
42
|
-
|
43
|
-
if lines.empty?
|
44
|
-
puts "#{files} file#{'s' if files > 1} checked, \e[32mno matches found\e[0m"
|
45
|
-
exit(0)
|
46
|
-
else
|
47
|
-
puts "Matches:\n\n"
|
48
|
-
puts "#{lines.join("\n")}\n\n"
|
49
|
-
puts "#{files} file#{'s' if files > 1} checked, \e[31m#{lines.size} match#{'es' if lines.size > 1} found\e[0m"
|
50
|
-
exit(1)
|
51
|
-
end
|
52
|
-
end
|
5
|
+
class Error < StandardError; end
|
53
6
|
end
|
data/lib/search.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require "pathname"
|
2
|
+
require "find"
|
3
|
+
|
4
|
+
module Grepfruit
|
5
|
+
class Search
|
6
|
+
CYAN = "\e[36m"
|
7
|
+
RED = "\e[31m"
|
8
|
+
GREEN = "\e[32m"
|
9
|
+
RESET = "\e[0m"
|
10
|
+
|
11
|
+
attr_reader :dir, :regex, :excluded_paths, :excluded_lines, :truncate, :search_hidden
|
12
|
+
|
13
|
+
def initialize(dir:, regex:, exclude:, truncate:, search_hidden:)
|
14
|
+
@dir = dir
|
15
|
+
@regex = regex
|
16
|
+
@excluded_lines, @excluded_paths = exclude.map { |e| e.split("/") }.partition { |e| e.last.include?(":") }
|
17
|
+
@truncate = truncate
|
18
|
+
@search_hidden = search_hidden
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
lines, files = [], 0
|
23
|
+
|
24
|
+
puts "Searching for #{regex.inspect} in #{dir.inspect}...\n\n"
|
25
|
+
|
26
|
+
Find.find(dir) do |path|
|
27
|
+
Find.prune if excluded_path?(path) || !search_hidden && hidden?(path)
|
28
|
+
|
29
|
+
next if File.directory?(path) || File.symlink?(path)
|
30
|
+
|
31
|
+
files += 1
|
32
|
+
|
33
|
+
match = false
|
34
|
+
|
35
|
+
File.foreach(path).with_index do |line, line_num|
|
36
|
+
next unless line.valid_encoding?
|
37
|
+
|
38
|
+
if line.match?(regex)
|
39
|
+
next if excluded_line?(path, line_num)
|
40
|
+
|
41
|
+
lines << "#{CYAN}#{relative_path_with_line_num(path, line_num)}#{RESET}: #{processed_line(line)}"
|
42
|
+
match = true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
print match ? "#{RED}M#{RESET}" : "#{GREEN}.#{RESET}"
|
47
|
+
end
|
48
|
+
|
49
|
+
puts "\n\n" if files.positive?
|
50
|
+
|
51
|
+
if lines.empty?
|
52
|
+
puts "#{number_of_files(files)} checked, #{GREEN}no matches found#{RESET}"
|
53
|
+
exit(0)
|
54
|
+
else
|
55
|
+
puts "Matches:\n\n"
|
56
|
+
puts "#{lines.join("\n")}\n\n"
|
57
|
+
puts "#{number_of_files(files)} checked, #{RED}#{number_of_matches(lines.size)} found#{RESET}"
|
58
|
+
exit(1)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def excluded_path?(path)
|
65
|
+
excluded?(excluded_paths, relative_path(path))
|
66
|
+
end
|
67
|
+
|
68
|
+
def excluded_line?(path, line_num)
|
69
|
+
excluded?(excluded_lines, relative_path_with_line_num(path, line_num))
|
70
|
+
end
|
71
|
+
|
72
|
+
def excluded?(list, path)
|
73
|
+
list.any? { |e| path.split("/").last(e.length) == e }
|
74
|
+
end
|
75
|
+
|
76
|
+
def relative_path(path)
|
77
|
+
Pathname.new(path).relative_path_from(Pathname.new(dir)).to_s
|
78
|
+
end
|
79
|
+
|
80
|
+
def relative_path_with_line_num(path, line_num)
|
81
|
+
"#{relative_path(path)}:#{line_num + 1}"
|
82
|
+
end
|
83
|
+
|
84
|
+
def processed_line(line)
|
85
|
+
stripped_line = line.strip
|
86
|
+
truncate && stripped_line.length > truncate ? "#{stripped_line[0..truncate - 1]}..." : stripped_line
|
87
|
+
end
|
88
|
+
|
89
|
+
def hidden?(path)
|
90
|
+
File.basename(path).start_with?(".")
|
91
|
+
end
|
92
|
+
|
93
|
+
def number_of_files(num)
|
94
|
+
"#{num} file#{'s' if num > 1}"
|
95
|
+
end
|
96
|
+
|
97
|
+
def number_of_matches(num)
|
98
|
+
"#{num} match#{'es' if num > 1}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grepfruit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- enjaku4
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-08-15 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -24,10 +24,14 @@ files:
|
|
24
24
|
- grepfruit.gemspec
|
25
25
|
- lib/grepfruit.rb
|
26
26
|
- lib/grepfruit/version.rb
|
27
|
+
- lib/search.rb
|
27
28
|
homepage: https://github.com/enjaku4/grepfruit
|
28
29
|
licenses:
|
29
30
|
- MIT
|
30
31
|
metadata:
|
32
|
+
homepage_uri: https://github.com/enjaku4/grepfruit
|
33
|
+
source_code_uri: https://github.com/enjaku4/grepfruit
|
34
|
+
changelog_uri: https://github.com/enjaku4/grepfruit/blob/master/CHANGELOG.md
|
31
35
|
rubygems_mfa_required: 'true'
|
32
36
|
post_install_message:
|
33
37
|
rdoc_options: []
|
@@ -37,7 +41,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
37
41
|
requirements:
|
38
42
|
- - ">="
|
39
43
|
- !ruby/object:Gem::Version
|
40
|
-
version: 3.0
|
44
|
+
version: '3.0'
|
41
45
|
- - "<"
|
42
46
|
- !ruby/object:Gem::Version
|
43
47
|
version: '3.4'
|
@@ -47,8 +51,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
47
51
|
- !ruby/object:Gem::Version
|
48
52
|
version: '0'
|
49
53
|
requirements: []
|
50
|
-
rubygems_version: 3.
|
54
|
+
rubygems_version: 3.5.11
|
51
55
|
signing_key:
|
52
56
|
specification_version: 4
|
53
|
-
summary: A Ruby gem for searching text patterns in files with colorized output
|
57
|
+
summary: A Ruby gem for searching text patterns in files with colorized output
|
54
58
|
test_files: []
|