grepfruit 2.0.2 → 2.0.4

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: 9c4d580e130902313d154cc1584dcc1a610252638678dcbb05f6010226987bf9
4
- data.tar.gz: e0814d3764457e9386b3c5850cb82719cfa6dd580016ce213ef4ddb3fd76d310
3
+ metadata.gz: 510715dadc6ac5afba47b5a02b122eb6ae53e46dcb4454a3d83adf7374615b1e
4
+ data.tar.gz: 4797c7612d6f0ab3e0ec3c15a3c48941984f9eba4837a919ba98f10551d3c4fb
5
5
  SHA512:
6
- metadata.gz: b73b3561372a4f7fe6a86d7b38de4b618fd1a5b730883bbe6ad338035a8a44c1c6788fee5d3202cde8d78c9d8ee4bd9d3ec65251f92dfae3fa5d4a06a1634df0
7
- data.tar.gz: 8772fcef03d57c21a9dea7e7135027c878e351f9d58b221d7c831435064035c7ce93cb0bac20be43051a6edcb2d5778dbf4040dc3709f3e1a9b53e3f2b826496
6
+ metadata.gz: a62a669cb08f455f3105ee73b4f70d991216c7b34e68477adf6546d922e43e5994ff9a9cfca38671adf69b90cb89edf1960019b8d5dd2fb3bb8df5602f6ccc2c
7
+ data.tar.gz: b85bd902107f90713cd14be4ce8662250975c76dfd95e7757a12f36da4004261098545e7929abe103c9b8204b7c457c011d129ff5daff5cc5dafa5e4aa163b34
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## v2.0.4
2
+ - Fixed path resolution bug where searching in relative directories such as `.`, `./`, or `..` did not work correctly
3
+
4
+ ## v2.0.3
5
+
6
+ - Updated gemspec metadata to include the correct homepage URL
7
+
1
8
  ## v2.0.2
2
9
 
3
10
  - Replaced `git ls-files` with `Dir.glob` in gemspec for improved portability and compatibility
data/README.md CHANGED
@@ -1,102 +1,156 @@
1
- # Grepfruit
1
+ # Grepfruit: File Pattern Search Tool for Ruby
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/grepfruit.svg)](http://badge.fury.io/rb/grepfruit)
4
- [![Github Actions badge](https://github.com/enjaku4/grepfruit/actions/workflows/main.yml/badge.svg)](https://github.com/enjaku4/grepfruit/actions/workflows/main.yml)
4
+ [![Github Actions badge](https://github.com/brownboxdev/grepfruit/actions/workflows/ci.yml/badge.svg)](https://github.com/brownboxdev/grepfruit/actions/workflows/ci.yml)
5
5
 
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.
6
+ Grepfruit is a Ruby gem for searching files within a directory for specified regular expression patterns, with intelligent exclusion options and colorized output for enhanced readability. Originally designed for CI/CD pipelines to search for `TODO` comments in Ruby on Rails applications, Grepfruit provides more user-friendly output than the standard `grep` command while maintaining the flexibility for diverse search scenarios.
7
7
 
8
- <img width="431" alt="Screenshot 2024-12-26 at 18 01 39" src="https://github.com/user-attachments/assets/e3fdb4f7-c4d9-4c8d-9a5a-228f2be55d52" />
8
+ **Key Features:**
9
9
 
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.
10
+ - Regular expression search within files and directories
11
+ - Intelligent file and directory exclusion capabilities
12
+ - Colorized output for improved readability
13
+ - Hidden file and directory search support
14
+ - Configurable output truncation
15
+ - CI/CD pipeline friendly with meaningful exit codes
16
+ - Line-specific exclusion for precise control
17
+
18
+ ## Table of Contents
19
+
20
+ **Gem Usage:**
21
+ - [Installation](#installation)
22
+ - [Basic Usage](#basic-usage)
23
+ - [Command Line Options](#command-line-options)
24
+ - [Usage Examples](#usage-examples)
25
+ - [Exit Status](#exit-status)
26
+
27
+ **Community Resources:**
28
+ - [Contributing](#contributing)
29
+ - [License](#license)
30
+ - [Code of Conduct](#code-of-conduct)
11
31
 
12
32
  ## Installation
13
33
 
14
- Add this line to your application's Gemfile:
34
+ Add Grepfruit to your Gemfile:
15
35
 
16
- ```ruby
36
+ ```rb
17
37
  gem "grepfruit"
18
38
  ```
19
39
 
20
- And then execute:
40
+ Install the gem:
21
41
 
22
- ```shell
42
+ ```bash
23
43
  bundle install
24
44
  ```
25
45
 
26
- Or install it yourself as:
46
+ Or install it directly:
27
47
 
28
- ```shell
48
+ ```bash
29
49
  gem install grepfruit
30
50
  ```
31
51
 
32
- ## Usage
52
+ ## Basic Usage
33
53
 
34
- You can use Grepfruit from the command line to search for a regex pattern within files in a specified directory.
54
+ Search for regex patterns within files in a specified directory:
35
55
 
36
- ```shell
56
+ ```bash
37
57
  grepfruit [options] PATH
38
58
  ```
39
59
 
40
- If no matches are found, Grepfruit returns exit status 0; otherwise, it returns exit status 1.
60
+ If no PATH is specified, Grepfruit searches the current directory.
61
+
62
+ ## Command Line Options
41
63
 
42
- ### Options
64
+ | Option | Description |
65
+ |--------|-------------|
66
+ | `-r, --regex REGEX` | Regex pattern to search for (required) |
67
+ | `-e, --exclude x,y,z` | Comma-separated list of files, directories, or lines to exclude |
68
+ | `-t, --truncate N` | Truncate search result output to N characters |
69
+ | `--search-hidden` | Include hidden files and directories in search |
43
70
 
44
- - `-r, --regex REGEX`: Regex pattern to search for (required).
45
- - `-e, --exclude x,y,z`: Comma-separated list of files, directories, or lines to exclude from the search.
46
- - `-t, --truncate N`: Truncate the output of the search results to N characters.
47
- - `--search-hidden`: Search hidden files and directories.
71
+ ## Usage Examples
72
+
73
+ ### Basic Pattern Search
74
+
75
+ Search for `TODO` comments in the current directory:
76
+
77
+ ```bash
78
+ grepfruit -r 'TODO'
79
+ ```
48
80
 
49
- ### Examples
81
+ ### Excluding Directories
50
82
 
51
- Search for the pattern `/TODO/` in the current directory, excluding `log`, `tmp`, `vendor`, `node_modules`, and `assets` directories:
83
+ Search for `TODO` patterns while excluding common build and dependency directories:
52
84
 
53
- ```shell
85
+ ```bash
54
86
  grepfruit -r 'TODO' -e 'log,tmp,vendor,node_modules,assets'
55
87
  ```
56
88
 
57
- Search for the pattern `/FIXME|TODO/` in `dev/grepfruit` directory, excluding `bin`, `tmp/log`, and `Gemfile.lock` files and directories:
89
+ ### Multiple Pattern Search Excluding Both Directories and Files
58
90
 
59
- ```shell
91
+ Search for both `FIXME` and `TODO` comments in a specific directory:
92
+
93
+ ```bash
60
94
  grepfruit -r 'FIXME|TODO' -e 'bin,tmp/log,Gemfile.lock' dev/grepfruit
61
95
  ```
62
96
 
63
- Search for the pattern `/FIXME|TODO/` in the current directory, excluding line 18 of `README.md`:
97
+ ### Line-Specific Exclusion
98
+
99
+ Exclude specific lines from search results:
64
100
 
65
- ```shell
101
+ ```bash
66
102
  grepfruit -r 'FIXME|TODO' -e 'README.md:18'
67
103
  ```
68
104
 
69
- Search for the pattern `/FIXME|TODO/` in the current directory, truncating the output of the search results to 50 characters:
105
+ ### Output Truncation
70
106
 
71
- ```shell
107
+ Limit output length for cleaner results:
108
+
109
+ ```bash
72
110
  grepfruit -r 'FIXME|TODO' -t 50
73
111
  ```
74
112
 
75
- Search for the pattern `/FIXME|TODO/` in the current directory, including hidden files and directories:
113
+ ### Including Hidden Files
114
+
115
+ Search hidden files and directories:
76
116
 
77
- ```shell
117
+ ```bash
78
118
  grepfruit -r 'FIXME|TODO' --search-hidden
79
119
  ```
80
120
 
81
- ## Problems?
121
+ ## Exit Status
82
122
 
83
- Facing a problem or want to suggest an enhancement?
123
+ Grepfruit returns meaningful exit codes for CI/CD integration:
84
124
 
85
- - **Open a Discussion**: If you have a question, experience difficulties using the gem, or have a suggestion for improvements, feel free to use the Discussions section.
125
+ - **Exit code 0**: No matches found
126
+ - **Exit code 1**: Pattern matches were found
86
127
 
87
- Encountered a bug?
128
+ ## Contributing
88
129
 
89
- - **Create an Issue**: If you've identified a bug, please create an issue. Be sure to provide detailed information about the problem, including the steps to reproduce it.
90
- - **Contribute a Solution**: Found a fix for the issue? Feel free to create a pull request with your changes.
130
+ ### Getting Help
131
+ Have a question or need assistance? Open a discussion in our [discussions section](https://github.com/brownboxdev/grepfruit/discussions) for:
132
+ - Usage questions
133
+ - Implementation guidance
134
+ - Feature suggestions
91
135
 
92
- ## Contributing
136
+ ### Reporting Issues
137
+ Found a bug? Please [create an issue](https://github.com/brownboxdev/grepfruit/issues) with:
138
+ - A clear description of the problem
139
+ - Steps to reproduce the issue
140
+ - Your environment details (Ruby version, OS, etc.)
141
+
142
+ ### Contributing Code
143
+ Ready to contribute? You can:
144
+ - Fix bugs by submitting pull requests
145
+ - Improve documentation
146
+ - Add new features (please discuss first in our [discussions section](https://github.com/brownboxdev/grepfruit/discussions))
93
147
 
94
- Before creating an issue or a pull request, please read the [contributing guidelines](https://github.com/enjaku4/grepfruit/blob/master/CONTRIBUTING.md).
148
+ Before contributing, please read the [contributing guidelines](https://github.com/brownboxdev/grepfruit/blob/master/CONTRIBUTING.md)
95
149
 
96
150
  ## License
97
151
 
98
- The gem is available as open source under the terms of the [MIT License](https://github.com/enjaku4/grepfruit/blob/master/LICENSE.txt).
152
+ The gem is available as open source under the terms of the [MIT License](https://github.com/brownboxdev/grepfruit/blob/master/LICENSE.txt).
99
153
 
100
154
  ## Code of Conduct
101
155
 
102
- Everyone interacting in the Grepfruit project is expected to follow the [code of conduct](https://github.com/enjaku4/grepfruit/blob/master/CODE_OF_CONDUCT.md).
156
+ Everyone interacting in the Grepfruit project is expected to follow the [code of conduct](https://github.com/brownboxdev/grepfruit/blob/master/CODE_OF_CONDUCT.md).
data/exe/grepfruit CHANGED
@@ -6,7 +6,7 @@ require "optparse"
6
6
  require "grepfruit"
7
7
 
8
8
  options = {
9
- dir: Dir.pwd,
9
+ dir: ".",
10
10
  regex: nil,
11
11
  exclude: [],
12
12
  truncate: nil,
data/grepfruit.gemspec CHANGED
@@ -4,7 +4,7 @@ Gem::Specification.new do |spec|
4
4
  spec.name = "grepfruit"
5
5
  spec.version = Grepfruit::VERSION
6
6
  spec.authors = ["enjaku4"]
7
- spec.homepage = "https://github.com/enjaku4/grepfruit"
7
+ spec.homepage = "https://github.com/brownboxdev/grepfruit"
8
8
  spec.metadata["homepage_uri"] = spec.homepage
9
9
  spec.metadata["source_code_uri"] = spec.homepage
10
10
  spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/master/CHANGELOG.md"
@@ -0,0 +1,58 @@
1
+ module Grepfruit
2
+ module Decorator
3
+ COLORS = { cyan: "\e[36m", red: "\e[31m", green: "\e[32m", reset: "\e[0m" }
4
+ private_constant :COLORS
5
+
6
+ private
7
+
8
+ def green(text)
9
+ "#{COLORS[:green]}#{text}#{COLORS[:reset]}"
10
+ end
11
+
12
+ def red(text)
13
+ "#{COLORS[:red]}#{text}#{COLORS[:reset]}"
14
+ end
15
+
16
+ def cyan(text)
17
+ "#{COLORS[:cyan]}#{text}#{COLORS[:reset]}"
18
+ end
19
+
20
+ def number_of_files(num)
21
+ "#{num} file#{'s' if num > 1}"
22
+ end
23
+
24
+ def number_of_matches(num)
25
+ "#{num} match#{'es' if num > 1}"
26
+ end
27
+
28
+ def relative_path(path)
29
+ Pathname.new(path).relative_path_from(Pathname.new(dir)).to_s
30
+ end
31
+
32
+ def relative_path_with_line_num(path, line_num)
33
+ "#{relative_path(path)}:#{line_num + 1}"
34
+ end
35
+
36
+ def processed_line(line)
37
+ stripped_line = line.strip
38
+ truncate && stripped_line.length > truncate ? "#{stripped_line[0..truncate - 1]}..." : stripped_line
39
+ end
40
+
41
+ def decorated_line(path, line_num, line)
42
+ "#{cyan(relative_path_with_line_num(path, line_num))}: #{processed_line(line)}"
43
+ end
44
+
45
+ def display_results(lines, files, files_with_matches)
46
+ puts "\n\n" if files.positive?
47
+
48
+ if lines.empty?
49
+ puts "#{number_of_files(files)} checked, #{green('no matches found')}"
50
+ exit(0)
51
+ else
52
+ puts "Matches:\n\n#{lines.join("\n")}\n\n"
53
+ puts "#{number_of_files(files)} checked, #{red("#{number_of_matches(lines.size)} found in #{number_of_files(files_with_matches)}")}"
54
+ exit(1)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -1,12 +1,17 @@
1
1
  require "pathname"
2
2
  require "find"
3
+ require "byebug"
4
+
5
+ require_relative "decorator"
3
6
 
4
7
  module Grepfruit
5
8
  class Search
9
+ include Decorator
10
+
6
11
  attr_reader :dir, :regex, :excluded_paths, :excluded_lines, :truncate, :search_hidden
7
12
 
8
13
  def initialize(dir:, regex:, exclude:, truncate:, search_hidden:)
9
- @dir = dir
14
+ @dir = File.expand_path(dir)
10
15
  @regex = regex
11
16
  @excluded_lines, @excluded_paths = exclude.map { _1.split("/") }.partition { _1.last.include?(":") }
12
17
  @truncate = truncate
@@ -28,18 +33,15 @@ module Grepfruit
28
33
 
29
34
  if match
30
35
  files_with_matches += 1
31
- print "#{COLORS[:red]}M#{COLORS[:reset]}"
36
+ print red("M")
32
37
  else
33
- print "#{COLORS[:green]}.#{COLORS[:reset]}"
38
+ print green(".")
34
39
  end
35
40
  end
36
41
 
37
42
  display_results(lines, files, files_with_matches)
38
43
  end
39
44
 
40
- COLORS = { cyan: "\e[36m", red: "\e[31m", green: "\e[32m", reset: "\e[0m" }
41
- private_constant :COLORS
42
-
43
45
  private
44
46
 
45
47
  def not_searchable?(path)
@@ -52,25 +54,12 @@ module Grepfruit
52
54
  File.foreach(path).with_index do |line, line_num|
53
55
  next if !line.valid_encoding? || !line.match?(regex) || excluded_line?(path, line_num)
54
56
 
55
- lines << "#{COLORS[:cyan]}#{relative_path_with_line_num(path, line_num)}#{COLORS[:reset]}: #{processed_line(line)}"
57
+ lines << decorated_line(path, line_num, line)
56
58
  end
57
59
 
58
60
  lines.size > lines_size
59
61
  end
60
62
 
61
- def display_results(lines, files, files_with_matches)
62
- puts "\n\n" if files.positive?
63
-
64
- if lines.empty?
65
- puts "#{number_of_files(files)} checked, #{COLORS[:green]}no matches found#{COLORS[:reset]}"
66
- exit(0)
67
- else
68
- puts "Matches:\n\n#{lines.join("\n")}\n\n"
69
- puts "#{number_of_files(files)} checked, #{COLORS[:red]}#{number_of_matches(lines.size)} found in #{number_of_files(files_with_matches)}#{COLORS[:reset]}"
70
- exit(1)
71
- end
72
- end
73
-
74
63
  def excluded_path?(path)
75
64
  excluded?(excluded_paths, relative_path(path)) || !search_hidden && hidden?(path)
76
65
  end
@@ -83,29 +72,8 @@ module Grepfruit
83
72
  list.any? { path.split("/").last(_1.length) == _1 }
84
73
  end
85
74
 
86
- def relative_path(path)
87
- Pathname.new(path).relative_path_from(Pathname.new(dir)).to_s
88
- end
89
-
90
- def relative_path_with_line_num(path, line_num)
91
- "#{relative_path(path)}:#{line_num + 1}"
92
- end
93
-
94
- def processed_line(line)
95
- stripped_line = line.strip
96
- truncate && stripped_line.length > truncate ? "#{stripped_line[0..truncate - 1]}..." : stripped_line
97
- end
98
-
99
75
  def hidden?(path)
100
76
  File.basename(path).start_with?(".")
101
77
  end
102
-
103
- def number_of_files(num)
104
- "#{num} file#{'s' if num > 1}"
105
- end
106
-
107
- def number_of_matches(num)
108
- "#{num} match#{'es' if num > 1}"
109
- end
110
78
  end
111
79
  end
@@ -1,3 +1,3 @@
1
1
  module Grepfruit
2
- VERSION = "2.0.2"
2
+ VERSION = "2.0.4"
3
3
  end
data/lib/grepfruit.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require_relative "grepfruit/version"
2
- require_relative "search"
2
+ require_relative "grepfruit/search"
3
3
 
4
4
  module Grepfruit
5
5
  class Error < StandardError; end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grepfruit
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - enjaku4
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-02-21 00:00:00.000000000 Z
10
+ date: 2025-05-30 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  executables:
13
13
  - grepfruit
@@ -20,15 +20,16 @@ files:
20
20
  - exe/grepfruit
21
21
  - grepfruit.gemspec
22
22
  - lib/grepfruit.rb
23
+ - lib/grepfruit/decorator.rb
24
+ - lib/grepfruit/search.rb
23
25
  - lib/grepfruit/version.rb
24
- - lib/search.rb
25
- homepage: https://github.com/enjaku4/grepfruit
26
+ homepage: https://github.com/brownboxdev/grepfruit
26
27
  licenses:
27
28
  - MIT
28
29
  metadata:
29
- homepage_uri: https://github.com/enjaku4/grepfruit
30
- source_code_uri: https://github.com/enjaku4/grepfruit
31
- changelog_uri: https://github.com/enjaku4/grepfruit/blob/master/CHANGELOG.md
30
+ homepage_uri: https://github.com/brownboxdev/grepfruit
31
+ source_code_uri: https://github.com/brownboxdev/grepfruit
32
+ changelog_uri: https://github.com/brownboxdev/grepfruit/blob/master/CHANGELOG.md
32
33
  rubygems_mfa_required: 'true'
33
34
  rdoc_options: []
34
35
  require_paths: