grepfruit 1.1.1 → 2.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32c9440099c6773c0462e07588d75db0dbc068417e01f1d9a1449dcdc2ee1031
4
- data.tar.gz: 6ee33ae41606b4ee5d65204e6a9ae0c7d162d0b3fe6a30bac230aec272e91940
3
+ metadata.gz: 8e88618b796ae6c0d9f54ec4bc64033e44ecee9fef5a3a889a0585dff11741e4
4
+ data.tar.gz: 1d6acc4c77b5175b9d13b3c4eb23b8ed069caf6f8e031037a1ec0244d945fa5c
5
5
  SHA512:
6
- metadata.gz: be872e34b8520febbadefc4ab7a747f7bdf0bc4f59fc4a7b09902d6eb3b1caba434820b6745c0086dacde3d82c21c21c0722f3e7b492a014c08311586188b865
7
- data.tar.gz: 10c7be4bc77fa12b3f7da587ac921073424af09df6534d4df4929f8d24402a76daf349fd2ded696be121469dbea1fb1fad7323ba11559809dfa3aa87d5827286
6
+ metadata.gz: 1690b2abec8f59847eace9a70cbaa9d8b08c54d64e35b76ef5d8f2ce6c707478a044e40fad514932f2bbcd9ec2cd289129e05b47497b102ab83fa6ed78dd631b
7
+ data.tar.gz: 322537a62dbb5d81731af9d973f8b5e69dc557e0721cfabbd8add2da69712b88a231371d5842b2e710fa882b7d03c9e7fd3ed9dfc4a3a5422c893ce0b9f21050
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## v2.0.0
2
+
3
+ - Added support for Ruby 3.4
4
+ - Dropped support for Ruby 3.0
5
+
6
+ ## v1.1.2
7
+
8
+ - Refactored code significantly for improved search efficiency and easier maintenance
9
+ - Enhanced search result output for better readability
10
+
1
11
  ## v1.1.1
2
12
 
3
13
  - Added test dataset to make testing and development easier
data/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Grepfruit is a Ruby gem for searching files within a directory for a specified regular expression pattern, with options to exclude certain files or directories from the search and colorized output for better readability.
7
7
 
8
- <img width="416" alt="Screenshot 2024-07-28 at 03 52 37" src="https://github.com/user-attachments/assets/95b26b81-dcc1-430b-ac44-641251cb84b6">
8
+ <img width="440" alt="Screenshot 2024-08-16 at 21 17 25" src="https://github.com/user-attachments/assets/3caaa1f4-5636-4ca1-ae45-6fc56f8945e4">
9
9
 
10
10
  Grepfruit was originally created to be used in CI/CD pipelines to search for `TODO` comments in Ruby on Rails applications and provide more user-friendly output than the standard `grep` command, but it is flexible enough to be used for other similar purposes as well.
11
11
 
@@ -23,14 +23,22 @@ And then execute:
23
23
  bundle install
24
24
  ```
25
25
 
26
+ Or install it yourself as:
27
+
28
+ ```shell
29
+ gem install grepfruit
30
+ ```
31
+
26
32
  ## Usage
27
33
 
28
34
  You can use Grepfruit from the command line to search for a regex pattern within files in a specified directory.
29
35
 
30
36
  ```shell
31
- bundle exec grepfruit [options] PATH
37
+ grepfruit [options] PATH
32
38
  ```
33
39
 
40
+ If no matches are found, Grepfruit returns exit status 0; otherwise, it returns exit status 1.
41
+
34
42
  ### Options
35
43
 
36
44
  - `-r, --regex REGEX`: Regex pattern to search for (required).
@@ -43,31 +51,31 @@ bundle exec grepfruit [options] PATH
43
51
  Search for the pattern `/TODO/` in the current directory, excluding `log`, `tmp`, `vendor`, `node_modules`, and `assets` directories:
44
52
 
45
53
  ```shell
46
- bundle exec grepfruit -r 'TODO' -e 'log,tmp,vendor,node_modules,assets'
54
+ grepfruit -r 'TODO' -e 'log,tmp,vendor,node_modules,assets'
47
55
  ```
48
56
 
49
57
  Search for the pattern `/FIXME|TODO/` in `dev/grepfruit` directory, excluding `bin`, `tmp/log`, and `Gemfile.lock` files and directories:
50
58
 
51
59
  ```shell
52
- bundle exec grepfruit -r 'FIXME|TODO' -e 'bin,tmp/log,Gemfile.lock' dev/grepfruit
60
+ grepfruit -r 'FIXME|TODO' -e 'bin,tmp/log,Gemfile.lock' dev/grepfruit
53
61
  ```
54
62
 
55
63
  Search for the pattern `/FIXME|TODO/` in the current directory, excluding line 18 of `README.md`:
56
64
 
57
65
  ```shell
58
- bundle exec grepfruit -r 'FIXME|TODO' -e 'README.md:18'
66
+ grepfruit -r 'FIXME|TODO' -e 'README.md:18'
59
67
  ```
60
68
 
61
69
  Search for the pattern `/FIXME|TODO/` in the current directory, truncating the output of the search results to 50 characters:
62
70
 
63
71
  ```shell
64
- bundle exec grepfruit -r 'FIXME|TODO' -t 50
72
+ grepfruit -r 'FIXME|TODO' -t 50
65
73
  ```
66
74
 
67
75
  Search for the pattern `/FIXME|TODO/` in the current directory, including hidden files and directories:
68
76
 
69
77
  ```shell
70
- bundle exec grepfruit -r 'FIXME|TODO' --search-hidden
78
+ grepfruit -r 'FIXME|TODO' --search-hidden
71
79
  ```
72
80
 
73
81
  ## Problems?
data/exe/grepfruit CHANGED
@@ -15,22 +15,10 @@ options = {
15
15
 
16
16
  OptionParser.new do |opts|
17
17
  opts.banner = "Usage: grepfruit [options] PATH"
18
-
19
- opts.on("-r", "--regex REGEX", Regexp, "Regex pattern to search for") do |regex|
20
- options[:regex] = regex
21
- end
22
-
23
- opts.on("-e", "--exclude x,y,z", Array, "Comma-separated list of files and directories to exclude") do |exclude|
24
- options[:exclude] = exclude.map { |path| path.split("/") }
25
- end
26
-
27
- opts.on("-t", "--truncate N", Integer, "Truncate output to N characters") do |truncate|
28
- options[:truncate] = truncate
29
- end
30
-
31
- opts.on("--search-hidden", TrueClass, "Search hidden files and directories") do |search_hidden|
32
- options[:search_hidden] = search_hidden
33
- end
18
+ opts.on("-r", "--regex REGEX", Regexp, "Regex pattern to search for") { options[:regex] = _1 }
19
+ opts.on("-e", "--exclude x,y,z", Array, "Comma-separated list of files and directories to exclude") { options[:exclude] = _1 }
20
+ opts.on("-t", "--truncate N", Integer, "Truncate output to N characters") { options[:truncate] = _1 }
21
+ opts.on("--search-hidden", TrueClass, "Search hidden files and directories") { options[:search_hidden] = _1 }
34
22
  end.parse!
35
23
 
36
24
  if options[:regex].nil?
@@ -40,4 +28,4 @@ end
40
28
 
41
29
  options[:dir] = ARGV[0] if ARGV[0]
42
30
 
43
- Grepfruit.run(**options)
31
+ Grepfruit::Search.new(**options).run
data/grepfruit.gemspec CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  spec.metadata["rubygems_mfa_required"] = "true"
12
12
  spec.summary = "A Ruby gem for searching text patterns in files with colorized output"
13
13
  spec.license = "MIT"
14
- spec.required_ruby_version = ">= 3.0", "< 3.4"
14
+ spec.required_ruby_version = ">= 3.1", "< 3.5"
15
15
 
16
16
  spec.files = [
17
17
  "grepfruit.gemspec", "README.md", "CHANGELOG.md", "LICENSE.txt"
@@ -1,3 +1,3 @@
1
1
  module Grepfruit
2
- VERSION = "1.1.1"
2
+ VERSION = "2.0.0"
3
3
  end
data/lib/grepfruit.rb CHANGED
@@ -1,53 +1,6 @@
1
1
  require_relative "grepfruit/version"
2
- require "pathname"
3
- require "find"
2
+ require_relative "search"
4
3
 
5
4
  module Grepfruit
6
- def self.run(dir:, regex:, exclude:, truncate:, search_hidden:)
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,99 @@
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 { _1.split("/") }.partition { _1.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) && !excluded_line?(path, line_num)
39
+ lines << "#{CYAN}#{relative_path_with_line_num(path, line_num)}#{RESET}: #{processed_line(line)}"
40
+ match = true
41
+ end
42
+ end
43
+
44
+ print match ? "#{RED}M#{RESET}" : "#{GREEN}.#{RESET}"
45
+ end
46
+
47
+ puts "\n\n" if files.positive?
48
+
49
+ if lines.empty?
50
+ puts "#{number_of_files(files)} checked, #{GREEN}no matches found#{RESET}"
51
+ exit(0)
52
+ else
53
+ puts "Matches:\n\n"
54
+ puts "#{lines.join("\n")}\n\n"
55
+ puts "#{number_of_files(files)} checked, #{RED}#{number_of_matches(lines.size)} found#{RESET}"
56
+ exit(1)
57
+ end
58
+ end
59
+
60
+ private
61
+
62
+ def excluded_path?(path)
63
+ excluded?(excluded_paths, relative_path(path))
64
+ end
65
+
66
+ def excluded_line?(path, line_num)
67
+ excluded?(excluded_lines, relative_path_with_line_num(path, line_num))
68
+ end
69
+
70
+ def excluded?(list, path)
71
+ list.any? { path.split("/").last(_1.length) == _1 }
72
+ end
73
+
74
+ def relative_path(path)
75
+ Pathname.new(path).relative_path_from(Pathname.new(dir)).to_s
76
+ end
77
+
78
+ def relative_path_with_line_num(path, line_num)
79
+ "#{relative_path(path)}:#{line_num + 1}"
80
+ end
81
+
82
+ def processed_line(line)
83
+ stripped_line = line.strip
84
+ truncate && stripped_line.length > truncate ? "#{stripped_line[0..truncate - 1]}..." : stripped_line
85
+ end
86
+
87
+ def hidden?(path)
88
+ File.basename(path).start_with?(".")
89
+ end
90
+
91
+ def number_of_files(num)
92
+ "#{num} file#{'s' if num > 1}"
93
+ end
94
+
95
+ def number_of_matches(num)
96
+ "#{num} match#{'es' if num > 1}"
97
+ end
98
+ end
99
+ 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.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - enjaku4
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-08-05 00:00:00.000000000 Z
11
+ date: 2024-12-25 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -24,6 +24,7 @@ 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
@@ -40,17 +41,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
40
41
  requirements:
41
42
  - - ">="
42
43
  - !ruby/object:Gem::Version
43
- version: '3.0'
44
+ version: '3.1'
44
45
  - - "<"
45
46
  - !ruby/object:Gem::Version
46
- version: '3.4'
47
+ version: '3.5'
47
48
  required_rubygems_version: !ruby/object:Gem::Requirement
48
49
  requirements:
49
50
  - - ">="
50
51
  - !ruby/object:Gem::Version
51
52
  version: '0'
52
53
  requirements: []
53
- rubygems_version: 3.2.33
54
+ rubygems_version: 3.3.27
54
55
  signing_key:
55
56
  specification_version: 4
56
57
  summary: A Ruby gem for searching text patterns in files with colorized output