gubed 0.1.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 +7 -0
 - data/CHANGELOG.md +5 -0
 - data/LICENSE +21 -0
 - data/LICENSE.txt +21 -0
 - data/README.md +72 -0
 - data/Rakefile +10 -0
 - data/examples/calculator.rb +22 -0
 - data/examples/sample_app.rb +28 -0
 - data/exe/gubed +69 -0
 - data/lib/gubed/breakpoint_manager.rb +196 -0
 - data/lib/gubed/breakpoint_scanner.rb +93 -0
 - data/lib/gubed/version.rb +5 -0
 - data/lib/gubed.rb +9 -0
 - metadata +59 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 208a0c9f02fb1d518500ba12917be9aa63454f8a1f270a25385b22479a70f29f
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 501f3302b575817e1273decf824d6a640974ddbe43a5471256595f5f27138fd5
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 1ec8528a5c4795934aff69083d308eb8e906b9d69009250e26f96c3892092043d4ff5dbee1231040c0085e542b0eca2f2f678bdae8e9ee9e407ce949c239953b
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: fbe63215e825481e7471a26353034991a4ca9c78a8b8a83f187dfd1bc479505522124fb50eff71839b0f44b258893afee7480c85d75c7d0297738d80d87f451b
         
     | 
    
        data/CHANGELOG.md
    ADDED
    
    
    
        data/LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            MIT License
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Copyright (c) 2025 Thomas Countz
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy
         
     | 
| 
      
 6 
     | 
    
         
            +
            of this software and associated documentation files (the "Software"), to deal
         
     | 
| 
      
 7 
     | 
    
         
            +
            in the Software without restriction, including without limitation the rights
         
     | 
| 
      
 8 
     | 
    
         
            +
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         
     | 
| 
      
 9 
     | 
    
         
            +
            copies of the Software, and to permit persons to whom the Software is
         
     | 
| 
      
 10 
     | 
    
         
            +
            furnished to do so, subject to the following conditions:
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in all
         
     | 
| 
      
 13 
     | 
    
         
            +
            copies or substantial portions of the Software.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 16 
     | 
    
         
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         
     | 
| 
      
 17 
     | 
    
         
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         
     | 
| 
      
 18 
     | 
    
         
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         
     | 
| 
      
 19 
     | 
    
         
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         
     | 
| 
      
 20 
     | 
    
         
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         
     | 
| 
      
 21 
     | 
    
         
            +
            SOFTWARE.
         
     | 
    
        data/LICENSE.txt
    ADDED
    
    | 
         @@ -0,0 +1,21 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            The MIT License (MIT)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Copyright (c) 2025 Thomas Countz
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy
         
     | 
| 
      
 6 
     | 
    
         
            +
            of this software and associated documentation files (the "Software"), to deal
         
     | 
| 
      
 7 
     | 
    
         
            +
            in the Software without restriction, including without limitation the rights
         
     | 
| 
      
 8 
     | 
    
         
            +
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         
     | 
| 
      
 9 
     | 
    
         
            +
            copies of the Software, and to permit persons to whom the Software is
         
     | 
| 
      
 10 
     | 
    
         
            +
            furnished to do so, subject to the following conditions:
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in
         
     | 
| 
      
 13 
     | 
    
         
            +
            all copies or substantial portions of the Software.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         
     | 
| 
      
 16 
     | 
    
         
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         
     | 
| 
      
 17 
     | 
    
         
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         
     | 
| 
      
 18 
     | 
    
         
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         
     | 
| 
      
 19 
     | 
    
         
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         
     | 
| 
      
 20 
     | 
    
         
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
         
     | 
| 
      
 21 
     | 
    
         
            +
            THE SOFTWARE.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,72 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Gubed
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            A command-line tool for managing debugger breakpoints in Ruby projects. Find, comment, uncomment, and delete debugging statements like `binding.pry`, `debugger`, `binding.irb`, and more.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            ## Installation
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            ```bash
         
     | 
| 
      
 8 
     | 
    
         
            +
            gem install gubed
         
     | 
| 
      
 9 
     | 
    
         
            +
            ```
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            ## Usage
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            Run `gubed` in any Ruby project directory to scan for debugging breakpoints:
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            ```bash
         
     | 
| 
      
 16 
     | 
    
         
            +
            $ gubed --help
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            gubed                    # Scan current directory
         
     | 
| 
      
 19 
     | 
    
         
            +
            gubed /path/to/project   # Scan specific directory
         
     | 
| 
      
 20 
     | 
    
         
            +
            ```
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            ### Interactive Mode
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            Once Gubed finds breakpoints, you can:
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            - Navigate with `j` (down) and `k` (up)
         
     | 
| 
      
 27 
     | 
    
         
            +
            - Press `c` to comment/uncomment breakpoints
         
     | 
| 
      
 28 
     | 
    
         
            +
            - Press `d` to delete breakpoints
         
     | 
| 
      
 29 
     | 
    
         
            +
            - Press `v` to view surrounding code context
         
     | 
| 
      
 30 
     | 
    
         
            +
            - Press `q` to quit
         
     | 
| 
      
 31 
     | 
    
         
            +
            - Press `h` for help
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            ### Supported Breakpoint Types
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            These are found based on regex.
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            - `binding.pry`
         
     | 
| 
      
 38 
     | 
    
         
            +
            - `binding.irb`
         
     | 
| 
      
 39 
     | 
    
         
            +
            - `binding.break`
         
     | 
| 
      
 40 
     | 
    
         
            +
            - `debugger`
         
     | 
| 
      
 41 
     | 
    
         
            +
            - `byebug`
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            ## Example
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
            ```bash
         
     | 
| 
      
 46 
     | 
    
         
            +
            $ gubed
         
     | 
| 
      
 47 
     | 
    
         
            +
            Gubed - Ruby Breakpoint Manager
         
     | 
| 
      
 48 
     | 
    
         
            +
            ========================================
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            >  1. [#] binding.irb /Users/thomas.countz/Code/experiments/gubed/examples/calculator.rb:14
         
     | 
| 
      
 51 
     | 
    
         
            +
               2. [ ] binding.break /Users/thomas.countz/Code/experiments/gubed/examples/calculator.rb:19
         
     | 
| 
      
 52 
     | 
    
         
            +
               3. [ ] binding.pry /Users/thomas.countz/Code/experiments/gubed/examples/calculator.rb:3
         
     | 
| 
      
 53 
     | 
    
         
            +
               4. [#] debugger /Users/thomas.countz/Code/experiments/gubed/examples/calculator.rb:8
         
     | 
| 
      
 54 
     | 
    
         
            +
               5. [#] debugger /Users/thomas.countz/Code/experiments/gubed/examples/sample_app.rb:11
         
     | 
| 
      
 55 
     | 
    
         
            +
               6. [ ] debugger /Users/thomas.countz/Code/experiments/gubed/examples/sample_app.rb:15
         
     | 
| 
      
 56 
     | 
    
         
            +
               7. [#] binding.break /Users/thomas.countz/Code/experiments/gubed/examples/sample_app.rb:17
         
     | 
| 
      
 57 
     | 
    
         
            +
               8. [ ] binding.break /Users/thomas.countz/Code/experiments/gubed/examples/sample_app.rb:22
         
     | 
| 
      
 58 
     | 
    
         
            +
               9. [ ] byebug /Users/thomas.countz/Code/experiments/gubed/examples/sample_app.rb:25
         
     | 
| 
      
 59 
     | 
    
         
            +
              10. [ ] binding.pry /Users/thomas.countz/Code/experiments/gubed/examples/sample_app.rb:4
         
     | 
| 
      
 60 
     | 
    
         
            +
              11. [#] binding.irb /Users/thomas.countz/Code/experiments/gubed/examples/sample_app.rb:9
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
            Commands: [j]down [k]up [g]oto [v]iew [t]oggle [d]elete [r]efresh [q]uit [h]elp
         
     | 
| 
      
 63 
     | 
    
         
            +
            Selected: 1 of 11
         
     | 
| 
      
 64 
     | 
    
         
            +
            ```
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
            ## Development
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            After checking out the repo, run `bin/setup` to install dependencies. Run `rake test` to run the tests.
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
            ## License
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
            MIT License Copyright (c) 2025 Thomas Countz
         
     | 
    
        data/Rakefile
    ADDED
    
    
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Calculator
         
     | 
| 
      
 2 
     | 
    
         
            +
              def add(a, b)
         
     | 
| 
      
 3 
     | 
    
         
            +
                binding.pry
         
     | 
| 
      
 4 
     | 
    
         
            +
                a + b
         
     | 
| 
      
 5 
     | 
    
         
            +
              end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              def subtract(a, b)
         
     | 
| 
      
 8 
     | 
    
         
            +
                # debugger
         
     | 
| 
      
 9 
     | 
    
         
            +
                a - b
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              def multiply(a, b)
         
     | 
| 
      
 13 
     | 
    
         
            +
                a * b
         
     | 
| 
      
 14 
     | 
    
         
            +
                # binding.irb
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              def divide(a, b)
         
     | 
| 
      
 18 
     | 
    
         
            +
                return 0 if b == 0
         
     | 
| 
      
 19 
     | 
    
         
            +
                binding.break
         
     | 
| 
      
 20 
     | 
    
         
            +
                a / b
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,28 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class SampleApp
         
     | 
| 
      
 2 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 3 
     | 
    
         
            +
                @users = []
         
     | 
| 
      
 4 
     | 
    
         
            +
                binding.pry # Debug initialization
         
     | 
| 
      
 5 
     | 
    
         
            +
              end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              def add_user(name, email)
         
     | 
| 
      
 8 
     | 
    
         
            +
                user = {name: name, email: email}
         
     | 
| 
      
 9 
     | 
    
         
            +
                # binding.irb # Commented out debug point
         
     | 
| 
      
 10 
     | 
    
         
            +
                @users << user
         
     | 
| 
      
 11 
     | 
    
         
            +
                # debugger # Check user addition
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              def find_user(email)
         
     | 
| 
      
 15 
     | 
    
         
            +
                debugger
         
     | 
| 
      
 16 
     | 
    
         
            +
                @users.find { |user| user[:email] == email }
         
     | 
| 
      
 17 
     | 
    
         
            +
                # binding.break if result.nil?
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              def process_users
         
     | 
| 
      
 21 
     | 
    
         
            +
                require "debug"
         
     | 
| 
      
 22 
     | 
    
         
            +
                binding.break
         
     | 
| 
      
 23 
     | 
    
         
            +
                @users.each do |user|
         
     | 
| 
      
 24 
     | 
    
         
            +
                  puts "Processing #{user[:name]}"
         
     | 
| 
      
 25 
     | 
    
         
            +
                  byebug # Debug each user processing
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
    
        data/exe/gubed
    ADDED
    
    | 
         @@ -0,0 +1,69 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require "optparse"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "gubed"
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            class GubedCLI
         
     | 
| 
      
 8 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 9 
     | 
    
         
            +
                @options = {}
         
     | 
| 
      
 10 
     | 
    
         
            +
                @parser = create_option_parser
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              def run(args = ARGV)
         
     | 
| 
      
 14 
     | 
    
         
            +
                @parser.parse!(args)
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                root_path = args.first || "."
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                unless File.directory?(root_path)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  puts "Error: '#{root_path}' is not a valid directory"
         
     | 
| 
      
 20 
     | 
    
         
            +
                  exit 1
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                manager = Gubed::BreakpointManager.new(root_path)
         
     | 
| 
      
 24 
     | 
    
         
            +
                manager.run
         
     | 
| 
      
 25 
     | 
    
         
            +
              rescue Interrupt
         
     | 
| 
      
 26 
     | 
    
         
            +
                puts "\n\nExiting..."
         
     | 
| 
      
 27 
     | 
    
         
            +
                exit 0
         
     | 
| 
      
 28 
     | 
    
         
            +
              rescue => e
         
     | 
| 
      
 29 
     | 
    
         
            +
                puts "Error: #{e.message}"
         
     | 
| 
      
 30 
     | 
    
         
            +
                exit 1
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
              private
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              def create_option_parser
         
     | 
| 
      
 36 
     | 
    
         
            +
                OptionParser.new do |opts|
         
     | 
| 
      
 37 
     | 
    
         
            +
                  opts.banner = "Usage: gubed [options] [directory]"
         
     | 
| 
      
 38 
     | 
    
         
            +
                  opts.separator ""
         
     | 
| 
      
 39 
     | 
    
         
            +
                  opts.separator "Gubed is a Ruby breakpoint manager that helps you find, manage, and remove"
         
     | 
| 
      
 40 
     | 
    
         
            +
                  opts.separator "debugging breakpoints (binding.pry, debugger, etc.) in your Ruby projects."
         
     | 
| 
      
 41 
     | 
    
         
            +
                  opts.separator ""
         
     | 
| 
      
 42 
     | 
    
         
            +
                  opts.separator "Options:"
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  opts.on("-h", "--help", "Show this help message") do
         
     | 
| 
      
 45 
     | 
    
         
            +
                    puts opts
         
     | 
| 
      
 46 
     | 
    
         
            +
                    exit
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  opts.on("-v", "--version", "Show version") do
         
     | 
| 
      
 50 
     | 
    
         
            +
                    puts "Gubed version #{Gubed::VERSION}"
         
     | 
| 
      
 51 
     | 
    
         
            +
                    exit
         
     | 
| 
      
 52 
     | 
    
         
            +
                  end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  opts.separator ""
         
     | 
| 
      
 55 
     | 
    
         
            +
                  opts.separator "Examples:"
         
     | 
| 
      
 56 
     | 
    
         
            +
                  opts.separator "  gubed                    # Scan current directory"
         
     | 
| 
      
 57 
     | 
    
         
            +
                  opts.separator "  gubed /path/to/project   # Scan specific directory"
         
     | 
| 
      
 58 
     | 
    
         
            +
                  opts.separator ""
         
     | 
| 
      
 59 
     | 
    
         
            +
                  opts.separator "Supported breakpoint types:"
         
     | 
| 
      
 60 
     | 
    
         
            +
                  opts.separator "  - binding.pry"
         
     | 
| 
      
 61 
     | 
    
         
            +
                  opts.separator "  - binding.irb"
         
     | 
| 
      
 62 
     | 
    
         
            +
                  opts.separator "  - binding.break"
         
     | 
| 
      
 63 
     | 
    
         
            +
                  opts.separator "  - debugger"
         
     | 
| 
      
 64 
     | 
    
         
            +
                  opts.separator "  - byebug"
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
            end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            GubedCLI.new.run if $0 == __FILE__ || File.basename($0) == "gubed"
         
     | 
| 
         @@ -0,0 +1,196 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "io/console"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Gubed
         
     | 
| 
      
 6 
     | 
    
         
            +
              class BreakpointManager
         
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(root_path = ".")
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @scanner = BreakpointScanner.new(root_path)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @breakpoints = []
         
     | 
| 
      
 10 
     | 
    
         
            +
                  @current_index = 0
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @message = nil
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def run
         
     | 
| 
      
 15 
     | 
    
         
            +
                  refresh_breakpoints
         
     | 
| 
      
 16 
     | 
    
         
            +
                  return puts "No breakpoints found." if @breakpoints.empty?
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  loop do
         
     | 
| 
      
 19 
     | 
    
         
            +
                    show_list
         
     | 
| 
      
 20 
     | 
    
         
            +
                    puts @message if @message
         
     | 
| 
      
 21 
     | 
    
         
            +
                    input = get_input
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    case input
         
     | 
| 
      
 24 
     | 
    
         
            +
                    when "q"
         
     | 
| 
      
 25 
     | 
    
         
            +
                      break if exit_program?(input)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    when "r"
         
     | 
| 
      
 27 
     | 
    
         
            +
                      refresh_breakpoints
         
     | 
| 
      
 28 
     | 
    
         
            +
                      @current_index = 0
         
     | 
| 
      
 29 
     | 
    
         
            +
                    when "t"
         
     | 
| 
      
 30 
     | 
    
         
            +
                      toggle_comment
         
     | 
| 
      
 31 
     | 
    
         
            +
                    when "d"
         
     | 
| 
      
 32 
     | 
    
         
            +
                      delete_breakpoint
         
     | 
| 
      
 33 
     | 
    
         
            +
                    when "v"
         
     | 
| 
      
 34 
     | 
    
         
            +
                      show_context
         
     | 
| 
      
 35 
     | 
    
         
            +
                    when "g"
         
     | 
| 
      
 36 
     | 
    
         
            +
                      prompt_for_breakpoint
         
     | 
| 
      
 37 
     | 
    
         
            +
                    when "j"
         
     | 
| 
      
 38 
     | 
    
         
            +
                      move_down
         
     | 
| 
      
 39 
     | 
    
         
            +
                    when "k"
         
     | 
| 
      
 40 
     | 
    
         
            +
                      move_up
         
     | 
| 
      
 41 
     | 
    
         
            +
                    when "h", "?"
         
     | 
| 
      
 42 
     | 
    
         
            +
                      show_help
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                private
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def refresh_breakpoints
         
     | 
| 
      
 50 
     | 
    
         
            +
                  print "Scanning..."
         
     | 
| 
      
 51 
     | 
    
         
            +
                  @breakpoints = @scanner.scan
         
     | 
| 
      
 52 
     | 
    
         
            +
                  puts " found #{@breakpoints.length} breakpoints"
         
     | 
| 
      
 53 
     | 
    
         
            +
                  @current_index = [@current_index, @breakpoints.length - 1].min if @breakpoints.any?
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                def show_list
         
     | 
| 
      
 57 
     | 
    
         
            +
                  system("clear") || system("cls")
         
     | 
| 
      
 58 
     | 
    
         
            +
                  puts "Gubed - Ruby Breakpoint Manager"
         
     | 
| 
      
 59 
     | 
    
         
            +
                  puts "=" * 40
         
     | 
| 
      
 60 
     | 
    
         
            +
                  puts
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  if @breakpoints.empty?
         
     | 
| 
      
 63 
     | 
    
         
            +
                    puts "No breakpoints found."
         
     | 
| 
      
 64 
     | 
    
         
            +
                    return
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  width = @breakpoints.length.to_s.length
         
     | 
| 
      
 68 
     | 
    
         
            +
                  @breakpoints.each_with_index do |bp, index|
         
     | 
| 
      
 69 
     | 
    
         
            +
                    marker = (index == @current_index) ? ">" : " "
         
     | 
| 
      
 70 
     | 
    
         
            +
                    status = bp.commented? ? "[#]" : "[ ]"
         
     | 
| 
      
 71 
     | 
    
         
            +
                    number = (index + 1).to_s.rjust(width)
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                    puts "#{marker} #{number}. #{status} #{bp.type} #{bp.location}"
         
     | 
| 
      
 74 
     | 
    
         
            +
                  end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                  puts
         
     | 
| 
      
 77 
     | 
    
         
            +
                  puts "Commands: [j]down [k]up [g]oto [v]iew [t]oggle [d]elete [r]efresh [q]uit [h]elp"
         
     | 
| 
      
 78 
     | 
    
         
            +
                  puts "Selected: #{@current_index + 1} of #{@breakpoints.length}"
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                def get_input
         
     | 
| 
      
 82 
     | 
    
         
            +
                  $stdin.getch
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                def prompt_for_breakpoint
         
     | 
| 
      
 86 
     | 
    
         
            +
                  print "Go to breakpoint: "
         
     | 
| 
      
 87 
     | 
    
         
            +
                  input = gets.chomp
         
     | 
| 
      
 88 
     | 
    
         
            +
                  return if input.empty?
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                  num = input.to_i
         
     | 
| 
      
 91 
     | 
    
         
            +
                  if num.between?(1, @breakpoints.length)
         
     | 
| 
      
 92 
     | 
    
         
            +
                    @current_index = num - 1
         
     | 
| 
      
 93 
     | 
    
         
            +
                  else
         
     | 
| 
      
 94 
     | 
    
         
            +
                    @message = "Invalid selection: #{num}."
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
                end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                def move_down
         
     | 
| 
      
 99 
     | 
    
         
            +
                  @current_index = (@current_index + 1) % @breakpoints.length
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                def move_up
         
     | 
| 
      
 103 
     | 
    
         
            +
                  @current_index = (@current_index - 1) % @breakpoints.length
         
     | 
| 
      
 104 
     | 
    
         
            +
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                def show_context
         
     | 
| 
      
 107 
     | 
    
         
            +
                  return if @breakpoints.empty?
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                  bp = @breakpoints[@current_index]
         
     | 
| 
      
 110 
     | 
    
         
            +
                  lines = File.readlines(bp.file)
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                  puts
         
     | 
| 
      
 113 
     | 
    
         
            +
                  puts "Context for #{bp.location}:"
         
     | 
| 
      
 114 
     | 
    
         
            +
                  puts "-" * 40
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                  start_line = [bp.line_number - 6, 1].max
         
     | 
| 
      
 117 
     | 
    
         
            +
                  end_line = [bp.line_number + 4, lines.length].min
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                  (start_line..end_line).each do |line_num|
         
     | 
| 
      
 120 
     | 
    
         
            +
                    line_index = line_num - 1
         
     | 
| 
      
 121 
     | 
    
         
            +
                    content = lines[line_index].rstrip
         
     | 
| 
      
 122 
     | 
    
         
            +
                    marker = (line_num == bp.line_number) ? ">>> " : "    "
         
     | 
| 
      
 123 
     | 
    
         
            +
                    puts "#{marker}#{line_num}: #{content}"
         
     | 
| 
      
 124 
     | 
    
         
            +
                  end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                  puts
         
     | 
| 
      
 127 
     | 
    
         
            +
                  print "Press Enter to continue..."
         
     | 
| 
      
 128 
     | 
    
         
            +
                  gets
         
     | 
| 
      
 129 
     | 
    
         
            +
                end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                def toggle_comment
         
     | 
| 
      
 132 
     | 
    
         
            +
                  return if @breakpoints.empty?
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                  bp = @breakpoints[@current_index]
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                  modify_line(bp) do |line|
         
     | 
| 
      
 137 
     | 
    
         
            +
                    if bp.commented?
         
     | 
| 
      
 138 
     | 
    
         
            +
                      line.sub(/^(\s*)#\s*/, '\1')
         
     | 
| 
      
 139 
     | 
    
         
            +
                    else
         
     | 
| 
      
 140 
     | 
    
         
            +
                      line.sub(/^(\s*)/, '\1# ')
         
     | 
| 
      
 141 
     | 
    
         
            +
                    end
         
     | 
| 
      
 142 
     | 
    
         
            +
                  end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                  refresh_breakpoints
         
     | 
| 
      
 145 
     | 
    
         
            +
                end
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                def delete_breakpoint
         
     | 
| 
      
 148 
     | 
    
         
            +
                  return if @breakpoints.empty?
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                  bp = @breakpoints[@current_index]
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                  print "Delete breakpoint at #{bp.location}? (y/N): "
         
     | 
| 
      
 153 
     | 
    
         
            +
                  response = gets.chomp.downcase
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                  return unless response == "y" || response == "yes"
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
                  lines = File.readlines(bp.file)
         
     | 
| 
      
 158 
     | 
    
         
            +
                  lines.delete_at(bp.line_number - 1)
         
     | 
| 
      
 159 
     | 
    
         
            +
                  File.write(bp.file, lines.join)
         
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
                  refresh_breakpoints
         
     | 
| 
      
 162 
     | 
    
         
            +
                  @current_index = [@current_index, @breakpoints.length - 1].min if @breakpoints.any?
         
     | 
| 
      
 163 
     | 
    
         
            +
                end
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                def exit_program?(input)
         
     | 
| 
      
 166 
     | 
    
         
            +
                  print "Press #{(input == "\e") ? "esc" : input} again to exit or any other key to continue: "
         
     | 
| 
      
 167 
     | 
    
         
            +
                  response = $stdin.getch
         
     | 
| 
      
 168 
     | 
    
         
            +
                  true if response == input
         
     | 
| 
      
 169 
     | 
    
         
            +
                end
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                def modify_line(breakpoint)
         
     | 
| 
      
 172 
     | 
    
         
            +
                  lines = File.readlines(breakpoint.file)
         
     | 
| 
      
 173 
     | 
    
         
            +
                  lines[breakpoint.line_number - 1] = yield(lines[breakpoint.line_number - 1])
         
     | 
| 
      
 174 
     | 
    
         
            +
                  File.write(breakpoint.file, lines.join)
         
     | 
| 
      
 175 
     | 
    
         
            +
                end
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                def show_help
         
     | 
| 
      
 178 
     | 
    
         
            +
                  puts
         
     | 
| 
      
 179 
     | 
    
         
            +
                  puts "Commands:"
         
     | 
| 
      
 180 
     | 
    
         
            +
                  puts "  j          - Move selection down"
         
     | 
| 
      
 181 
     | 
    
         
            +
                  puts "  k          - Move selection up"
         
     | 
| 
      
 182 
     | 
    
         
            +
                  puts "  g          - Go to a specific breakpoint by number"
         
     | 
| 
      
 183 
     | 
    
         
            +
                  puts "  v          - Show context around breakpoint"
         
     | 
| 
      
 184 
     | 
    
         
            +
                  puts "  t          - Toggle line comment on selected breakpoint"
         
     | 
| 
      
 185 
     | 
    
         
            +
                  puts "  d          - Delete selected breakpoint"
         
     | 
| 
      
 186 
     | 
    
         
            +
                  puts "  r          - Rescan for breakpoints"
         
     | 
| 
      
 187 
     | 
    
         
            +
                  puts "  q          - Exit program"
         
     | 
| 
      
 188 
     | 
    
         
            +
                  puts "  h, ?       - Show this help"
         
     | 
| 
      
 189 
     | 
    
         
            +
                  puts
         
     | 
| 
      
 190 
     | 
    
         
            +
                  puts "Legend: [ ] = Active, [#] = Commented"
         
     | 
| 
      
 191 
     | 
    
         
            +
                  puts
         
     | 
| 
      
 192 
     | 
    
         
            +
                  print "Press Enter to continue..."
         
     | 
| 
      
 193 
     | 
    
         
            +
                  gets
         
     | 
| 
      
 194 
     | 
    
         
            +
                end
         
     | 
| 
      
 195 
     | 
    
         
            +
              end
         
     | 
| 
      
 196 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,93 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require "find"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Gubed
         
     | 
| 
      
 6 
     | 
    
         
            +
              Breakpoint = Data.define(:file, :line_number, :content, :type) do
         
     | 
| 
      
 7 
     | 
    
         
            +
                def initialize(file:, line_number:, content:, type:)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  super(file: file, line_number: line_number, content: content.strip, type: type)
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                def commented?
         
     | 
| 
      
 12 
     | 
    
         
            +
                  content.start_with?("#")
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                def location
         
     | 
| 
      
 16 
     | 
    
         
            +
                  "#{file}:#{line_number}"
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              class BreakpointScanner
         
     | 
| 
      
 21 
     | 
    
         
            +
                BREAKPOINT_PATTERNS = {
         
     | 
| 
      
 22 
     | 
    
         
            +
                  "binding.pry" => /^\s*(?:#\s*)?binding\.pry\b/,
         
     | 
| 
      
 23 
     | 
    
         
            +
                  "binding.irb" => /^\s*(?:#\s*)?binding\.irb\b/,
         
     | 
| 
      
 24 
     | 
    
         
            +
                  "binding.break" => /^\s*(?:#\s*)?binding\.break\b/,
         
     | 
| 
      
 25 
     | 
    
         
            +
                  "debugger" => /^\s*(?:#\s*)?debugger\b/,
         
     | 
| 
      
 26 
     | 
    
         
            +
                  "byebug" => /^\s*(?:#\s*)?byebug\b/,
         
     | 
| 
      
 27 
     | 
    
         
            +
                  "debug" => /^\s*(?:#\s*)?(?:require\s+['"]debug['"];\s*)?binding\.break\b/
         
     | 
| 
      
 28 
     | 
    
         
            +
                }.freeze
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                RUBY_FILE_EXTENSIONS = %w[.rb .rake .gemspec].freeze
         
     | 
| 
      
 31 
     | 
    
         
            +
                DIR_TO_SKIP = %w[.git vendor node_modules tmp].freeze
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def initialize(root_path = ".")
         
     | 
| 
      
 34 
     | 
    
         
            +
                  @root_path = File.expand_path(root_path)
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                def scan
         
     | 
| 
      
 38 
     | 
    
         
            +
                  breakpoints = []
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  Find.find(@root_path) do |path|
         
     | 
| 
      
 41 
     | 
    
         
            +
                    if File.directory?(path)
         
     | 
| 
      
 42 
     | 
    
         
            +
                      Find.prune if DIR_TO_SKIP.any? { |dir| path.include?(dir) }
         
     | 
| 
      
 43 
     | 
    
         
            +
                      next
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                    next unless ruby_file?(path)
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                    breakpoints.concat(scan_file(path))
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  breakpoints.sort_by(&:location)
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                private
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                def ruby_file?(path)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  RUBY_FILE_EXTENSIONS.any? { |ext| path.end_with?(ext) } ||
         
     | 
| 
      
 58 
     | 
    
         
            +
                    (File.executable?(path) && ruby_shebang?(path))
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def ruby_shebang?(path)
         
     | 
| 
      
 62 
     | 
    
         
            +
                  first_line = begin
         
     | 
| 
      
 63 
     | 
    
         
            +
                    File.open(path, &:readline).strip
         
     | 
| 
      
 64 
     | 
    
         
            +
                  rescue
         
     | 
| 
      
 65 
     | 
    
         
            +
                    ""
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
                  first_line.include?("ruby")
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                def scan_file(file_path)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  breakpoints = []
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  File.foreach(file_path).each_with_index do |line, index|
         
     | 
| 
      
 74 
     | 
    
         
            +
                    BREAKPOINT_PATTERNS.each do |type, pattern|
         
     | 
| 
      
 75 
     | 
    
         
            +
                      if line.match(pattern)
         
     | 
| 
      
 76 
     | 
    
         
            +
                        breakpoints << Breakpoint.new(
         
     | 
| 
      
 77 
     | 
    
         
            +
                          file: file_path,
         
     | 
| 
      
 78 
     | 
    
         
            +
                          line_number: index + 1,
         
     | 
| 
      
 79 
     | 
    
         
            +
                          content: line.chomp,
         
     | 
| 
      
 80 
     | 
    
         
            +
                          type: type
         
     | 
| 
      
 81 
     | 
    
         
            +
                        )
         
     | 
| 
      
 82 
     | 
    
         
            +
                        break
         
     | 
| 
      
 83 
     | 
    
         
            +
                      end
         
     | 
| 
      
 84 
     | 
    
         
            +
                    end
         
     | 
| 
      
 85 
     | 
    
         
            +
                  end
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                  breakpoints
         
     | 
| 
      
 88 
     | 
    
         
            +
                rescue => e
         
     | 
| 
      
 89 
     | 
    
         
            +
                  puts "Warning: Could not scan #{file_path}: #{e.message}"
         
     | 
| 
      
 90 
     | 
    
         
            +
                  []
         
     | 
| 
      
 91 
     | 
    
         
            +
                end
         
     | 
| 
      
 92 
     | 
    
         
            +
              end
         
     | 
| 
      
 93 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/gubed.rb
    ADDED
    
    
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,59 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: gubed
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.0
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Thomas Countz
         
     | 
| 
      
 8 
     | 
    
         
            +
            bindir: exe
         
     | 
| 
      
 9 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 10 
     | 
    
         
            +
            date: 1980-01-02 00:00:00.000000000 Z
         
     | 
| 
      
 11 
     | 
    
         
            +
            dependencies: []
         
     | 
| 
      
 12 
     | 
    
         
            +
            description: Gubed is a standalone command-line tool for finding and managing debugger
         
     | 
| 
      
 13 
     | 
    
         
            +
              breakpoints (binding.pry, debugger, etc.) in Ruby codebases. Install globally with
         
     | 
| 
      
 14 
     | 
    
         
            +
              'gem install gubed' and use in any project.
         
     | 
| 
      
 15 
     | 
    
         
            +
            email:
         
     | 
| 
      
 16 
     | 
    
         
            +
            - thomascountz@gmail.com
         
     | 
| 
      
 17 
     | 
    
         
            +
            executables:
         
     | 
| 
      
 18 
     | 
    
         
            +
            - gubed
         
     | 
| 
      
 19 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 20 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 21 
     | 
    
         
            +
            files:
         
     | 
| 
      
 22 
     | 
    
         
            +
            - CHANGELOG.md
         
     | 
| 
      
 23 
     | 
    
         
            +
            - LICENSE
         
     | 
| 
      
 24 
     | 
    
         
            +
            - LICENSE.txt
         
     | 
| 
      
 25 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 26 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 27 
     | 
    
         
            +
            - examples/calculator.rb
         
     | 
| 
      
 28 
     | 
    
         
            +
            - examples/sample_app.rb
         
     | 
| 
      
 29 
     | 
    
         
            +
            - exe/gubed
         
     | 
| 
      
 30 
     | 
    
         
            +
            - lib/gubed.rb
         
     | 
| 
      
 31 
     | 
    
         
            +
            - lib/gubed/breakpoint_manager.rb
         
     | 
| 
      
 32 
     | 
    
         
            +
            - lib/gubed/breakpoint_scanner.rb
         
     | 
| 
      
 33 
     | 
    
         
            +
            - lib/gubed/version.rb
         
     | 
| 
      
 34 
     | 
    
         
            +
            homepage: https://github.com/thomascountz/gubed
         
     | 
| 
      
 35 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 36 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 37 
     | 
    
         
            +
            metadata:
         
     | 
| 
      
 38 
     | 
    
         
            +
              allowed_push_host: https://rubygems.org
         
     | 
| 
      
 39 
     | 
    
         
            +
              homepage_uri: https://github.com/thomascountz/gubed
         
     | 
| 
      
 40 
     | 
    
         
            +
              source_code_uri: https://github.com/thomascountz/gubed
         
     | 
| 
      
 41 
     | 
    
         
            +
              changelog_uri: https://github.com/thomascountz/gubed/blob/main/CHANGELOG.md
         
     | 
| 
      
 42 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 43 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 44 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 45 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 46 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 47 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 48 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 49 
     | 
    
         
            +
                  version: 3.2.0
         
     | 
| 
      
 50 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 51 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 52 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 53 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 54 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 55 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 56 
     | 
    
         
            +
            rubygems_version: 3.6.9
         
     | 
| 
      
 57 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 58 
     | 
    
         
            +
            summary: Ruby CLI for managing and editing debugger breakpoints
         
     | 
| 
      
 59 
     | 
    
         
            +
            test_files: []
         
     |