Skip to content
This repository was archived by the owner on Mar 12, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/rspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.5
ruby-version: 3.2
- name: Install dependencies
run: bundle install
- name: Checking offenses
Expand All @@ -28,7 +28,7 @@ jobs:
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.5
ruby-version: 3.2
- name: Install dependencies
run: bundle install
- name: Testing docs
Expand All @@ -38,7 +38,7 @@ jobs:
strategy:
fail-fast: false
matrix:
ruby: [2.5, 2.6, 2.7.2, head]
ruby: [3.2, 3.3, 3.4, 4.0, head]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand Down Expand Up @@ -73,7 +73,7 @@ jobs:
strategy:
fail-fast: false
matrix:
ruby: [2.5, 2.6, 2.7.2, head]
ruby: [3.2, 3.3, 3.4, 4.0, head]
env:
CI_PLATFORM: "macos"
runs-on: macos-latest
Expand Down
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,6 @@ RSpec/MultipleMemoizedHelpers:
Enabled: false

AllCops:
TargetRubyVersion: 2.5
TargetRubyVersion: 3.2
Exclude:
- '**/*_example.rb'
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
# Changelog
## [0.3.2-beta2]
Ruby 3.5 compatibility release.
- Add gem `benchmark` to gemspec
- Add gem `ostruct` to gemspec
- Update dependency `byebug`

## [0.3.2-beta1]
Ruby 3.4 compatibility release for testing.

### Features
- Ruby 3.4 support and compatibility
- Updated CI to test against Ruby 3.0-3.4

### Bug fixes
- Fix Ruby 3.4.6 Reline interceptor compatibility
- Fix Ruby 3.4.6 compatibility in path classifier

## [0.3.1]
This release fixes bunch of bugs, and performance issues reported by the users after beta launch. No new features are introduced.
Expand Down
74 changes: 74 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

Ruby Jard is a terminal-based debugger for Ruby that provides a rich UI wrapping around Byebug. It offers features like highlighted source code, stacktrace visualization, variable exploration, and multi-thread debugging.

## Development Commands

### Testing
- `bundle exec rspec` - Run all tests
- `bundle exec rspec spec/path/to/specific_spec.rb` - Run specific test file
- `bundle exec parallel_rspec spec/` - Run tests in parallel

### Code Quality
- `bundle exec rubocop` - Run linting
- `bundle exec rubocop -a` - Auto-fix linting issues

### Build & Install
- `bundle install` - Install dependencies
- `rake build` - Build the gem
- `rake install` - Install the gem locally
- `rake release` - Release the gem (maintainers only)

## Architecture Overview

### Core Components

**Session Management (`lib/ruby_jard/session.rb`)**
- Entry point for debugging sessions
- Manages the lifecycle of debugging contexts

**REPL System**
- `repl_manager.rb` - Manages REPL interactions
- `repl_processor.rb` - Processes commands and input
- `repl_interceptor.rb` - Intercepts and handles debugging flow
- `repl_state.rb` - Tracks REPL state

**Screen & Layout System**
- `screen_manager.rb` - Manages multiple debug screens
- `screen_renderer.rb` - Renders screen content
- `layout_*.rb` files - Different layout configurations (wide, narrow, tiny)
- `screens/` directory - Individual screen implementations (source, variables, backtrace, etc.)

**Inspection System** (`lib/ruby_jard/inspectors/`)
- Modular object inspection with specialized inspectors for different data types
- `base.rb` - Base inspector class
- Type-specific inspectors for arrays, hashes, objects, strings, etc.

**Command System** (`lib/ruby_jard/commands/`)
- Debugging commands like step, next, continue, frame navigation
- Each command is a separate class inheriting from `base_command.rb`

### Key Design Patterns

- **Configuration-driven**: Uses `config.rb` for user customization
- **Modular screens**: Each debug view is a separate screen class
- **Responsive layouts**: Multiple layout templates adapt to terminal size
- **Command pattern**: Debug commands are individual classes
- **Decorator pattern**: Used for colorizing and formatting output

### Integration Points

- **Byebug Integration**: Core debugging functionality via Byebug gem
- **Pry Integration**: REPL functionality via Pry gem
- **TTY Integration**: Terminal UI via tty-screen gem

### Development Notes

- The codebase uses frozen string literals throughout
- Main entry point is the `jard` method added to Kernel module
- Debugging state is managed through thread-local variables
- UI rendering is optimized for different terminal sizes and capabilities
6 changes: 3 additions & 3 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ if Gem.path.all? { |path| Dir[File.join(path, 'gems/jard_merge_sort*')].empty? }
puts `gem install ./spec/examples/jard_merge_sort/jard_merge_sort-0.1.0.gem`
end

gem 'byebug', '~> 11.1.0'
gem 'byebug', '~> 12.0'
gem 'jard_merge_sort', require: false
gem 'rake', '~> 12.0'
gem 'rspec', '~> 3.0'
gem 'rubocop', '~> 0.89.1'
gem 'rubocop-rspec', '~> 1.43.1', require: false
gem 'rubocop', '~> 1.81', '>= 1.81.7'
gem 'rubocop-rspec', '~> 3.7', require: false
gem 'tty-markdown', '~>0.7.0'

group :test do
Expand Down
32 changes: 19 additions & 13 deletions lib/ruby_jard/path_classifier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class PathClassifier
GEM_PATTERN = /(.*)-(\d+\.\d+[.\d]*[.\d]*[-.\w]*)/i.freeze
STDLIB_PATTERN = /(.*)\.rb$/.freeze
INTERNAL_PATTERN = /<internal:[^>]+>/.freeze
EVALUATION_SIGNATURE = '(eval)'
EVALUATION_PATTERN = /^\(eval.*\)$/.freeze
RUBY_SCRIPT_SIGNATURE = '-e'

TYPES = [
Expand Down Expand Up @@ -80,27 +80,33 @@ def try_classify_internal(path)
end

def try_classify_stdlib(path)
lib_dir = RbConfig::CONFIG['rubylibdir'].to_s.strip
lib_dirs = [
RbConfig::CONFIG['rubylibdir'],
RbConfig::CONFIG['sitelibdir']
].compact.map(&:strip).reject(&:empty?)

return false if lib_dir.empty?
return false unless path.start_with?(lib_dir)
lib_dirs.each do |lib_dir|
next unless path.start_with?(lib_dir)

splitted_path =
path[lib_dir.length..-1]
.split('/')
.reject(&:empty?)
lib_name = splitted_path.first
match = STDLIB_PATTERN.match(lib_name)
lib_name = match[1] if match
splitted_path =
path[lib_dir.length..-1]
.split('/')
.reject(&:empty?)
lib_name = splitted_path.first
match = STDLIB_PATTERN.match(lib_name)
lib_name = match[1] if match

[true, lib_name, splitted_path.join('/')]
return [true, lib_name, splitted_path.join('/')]
end

false
rescue NameError
# RbConfig is not available
false
end

def try_classify_evaluation(path)
path == EVALUATION_SIGNATURE
path =~ EVALUATION_PATTERN
end

def try_classify_ruby_script(path)
Expand Down
19 changes: 16 additions & 3 deletions lib/ruby_jard/repl_interceptor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,22 @@ def redirected_output

def interceptable?
return false unless defined?(PTY)
return false if defined?(Reline) && Readline == Reline
return false if RubyJard::Reflection.instance.call_method(::Readline, :input=).source_location != nil
return false if RubyJard::Reflection.instance.call_method(::Readline, :output=).source_location != nil

# In Ruby 3.4+, Reline is the default Readline implementation and should work fine
if RUBY_VERSION >= '3.4.0'
# Allow forwardable delegation in Ruby 3.4+ (methods will have source_location in forwardable.rb)
input_location = RubyJard::Reflection.instance.call_method(::Readline, :input=).source_location
output_location = RubyJard::Reflection.instance.call_method(::Readline, :output=).source_location

# Only reject if patched by non-standard sources (not forwardable.rb)
return false if input_location && !input_location[0].include?('forwardable.rb')
return false if output_location && !output_location[0].include?('forwardable.rb')
else
# Original logic for older Ruby versions
return false if defined?(Reline) && Readline == Reline
return false if RubyJard::Reflection.instance.call_method(::Readline, :input=).source_location != nil
return false if RubyJard::Reflection.instance.call_method(::Readline, :output=).source_location != nil
end

true
end
Expand Down
2 changes: 1 addition & 1 deletion lib/ruby_jard/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

# Semantic versionn
module RubyJard
VERSION = '0.3.1'
VERSION = '0.3.2.beta2'
end
10 changes: 7 additions & 3 deletions ruby_jard.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
editors.'
spec.homepage = 'https://github.com/nguyenquangminh0711/ruby_jard'
spec.license = 'MIT'
spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
spec.required_ruby_version = Gem::Requirement.new('>= 3.2.0', '< 4.1.0')

spec.metadata['allowed_push_host'] = 'https://rubygems.org'

Expand All @@ -32,7 +32,11 @@ Gem::Specification.new do |spec|
spec.executables = []
spec.require_paths = ['lib']

spec.add_runtime_dependency 'byebug', '>= 9.1', '< 12.0'
spec.add_runtime_dependency 'pry', '~> 0.13.0'
spec.add_runtime_dependency 'benchmark', '~> 0.5.0'
spec.add_runtime_dependency 'bigdecimal', '~> 3.2', '>= 3.2.3'
spec.add_runtime_dependency 'byebug', '~> 12.0'
spec.add_runtime_dependency 'mutex_m', '~> 0.3.0'
spec.add_runtime_dependency 'ostruct', '~> 0.6.3'
spec.add_runtime_dependency 'pry', '~> 0.14.0'
spec.add_runtime_dependency 'tty-screen', '~> 0.8.1'
end
1 change: 1 addition & 0 deletions spec/helpers/integration_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def start
'-c', @dir,
'-t', @target,
'-n', 'main',
'-e', 'RUBYOPT=-W0',
@command
)
sleep 0.5
Expand Down
8 changes: 4 additions & 4 deletions spec/ruby_jard/path_classifier_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

require 'uri'
require 'unicode_normalize/normalize'

RSpec.describe RubyJard::PathClassifier do
subject(:classifier) { described_class.new }
Expand Down Expand Up @@ -28,7 +28,7 @@
end

context 'when input path is in current dir which is also gem path' do
let(:dir) { Gem.path.first }
let(:dir) { Gem.path.find { |path| Dir.exist?(path) } }

it 'returns source tree' do
Dir.chdir(dir) do
Expand Down Expand Up @@ -99,8 +99,8 @@

context 'when input path is a standard lib sub folder' do
it 'returns stdlib, and relative path' do
expect(classifier.classify(URI::HTTP.method(:build).source_location.first)).to eq(
[:stdlib, 'uri', 'uri/http.rb']
expect(classifier.classify(UnicodeNormalize.method(:normalize).source_location.first)).to eq(
[:stdlib, 'unicode_normalize', 'unicode_normalize/normalize.rb']
)
end
end
Expand Down