Skip to content
This repository was archived by the owner on Mar 12, 2023. It is now read-only.

Commit 5613d82

Browse files
authored
Merge pull request #78 from nguyenquangminh0711/refactor/isolate-pry
Refactor REPL manager
2 parents f6244b5 + 08eadd9 commit 5613d82

32 files changed

+1158
-447
lines changed

Gemfile

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# frozen_string_literal: true
22

3-
source 'http://rubygems.org'
3+
source 'https://rubygems.org'
44

55
gemspec
66

@@ -20,6 +20,7 @@ gem 'tty-markdown', '~>0.7.0'
2020
group :test do
2121
gem 'activerecord'
2222
gem 'parallel_tests'
23+
gem 'reline', require: false
2324
gem 'rspec-retry'
2425
gem 'simplecov', require: false
2526
gem 'sqlite3'

lib/ruby_jard.rb

+5-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@
1313
require 'ruby_jard/keys'
1414
require 'ruby_jard/key_binding'
1515
require 'ruby_jard/key_bindings'
16-
require 'ruby_jard/repl_proxy'
16+
require 'ruby_jard/repl_processor'
17+
require 'ruby_jard/repl_manager'
18+
require 'ruby_jard/repl_interceptor'
19+
require 'ruby_jard/repl_state'
20+
require 'ruby_jard/repl_sequence'
1721
require 'ruby_jard/screen_manager'
1822
require 'ruby_jard/reflection'
1923

lib/ruby_jard/commands/continue_command.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ def process
1616
end
1717
end
1818

19-
Pry::Commands.add_command(RubyJard::Commands::ContinueCommand)
20-
Pry::Commands.alias_command 'c', 'continue'
19+
RubyJard::PryProxy::Commands.add_command(RubyJard::Commands::ContinueCommand)
20+
RubyJard::PryProxy::Commands.alias_command 'c', 'continue'

lib/ruby_jard/commands/down_command.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@ def process
1919
end
2020
end
2121

22-
Pry::Commands.add_command(RubyJard::Commands::DownCommand)
22+
RubyJard::PryProxy::Commands.add_command(RubyJard::Commands::DownCommand)

lib/ruby_jard/commands/exit_command.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ def process
1616
end
1717
end
1818

19-
Pry::Commands.add_command(RubyJard::Commands::ExitCommand)
19+
RubyJard::PryProxy::Commands.add_command(RubyJard::Commands::ExitCommand)

lib/ruby_jard/commands/frame_command.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,4 @@ def process
2626
end
2727
end
2828

29-
Pry::Commands.add_command(RubyJard::Commands::FrameCommand)
29+
RubyJard::PryProxy::Commands.add_command(RubyJard::Commands::FrameCommand)

lib/ruby_jard/commands/help_command.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,4 @@ def help_text_with_sub_commands(commands)
9393
end
9494
end
9595

96-
Pry::Commands.add_command(RubyJard::Commands::HelpCommand)
96+
RubyJard::PryProxy::Commands.add_command(RubyJard::Commands::HelpCommand)

lib/ruby_jard/commands/jard_command.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,4 @@ def process
4949
end
5050
end
5151

52-
Pry::Commands.add_command(RubyJard::Commands::JardCommand)
52+
RubyJard::PryProxy::Commands.add_command(RubyJard::Commands::JardCommand)

lib/ruby_jard/commands/list_command.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ def process
1616
end
1717
end
1818

19-
Pry::Commands.add_command(RubyJard::Commands::ListCommand)
20-
Pry::Commands.alias_command 'l', 'list'
21-
Pry::Commands.alias_command 'whereami', 'list'
19+
RubyJard::PryProxy::Commands.add_command(RubyJard::Commands::ListCommand)
20+
RubyJard::PryProxy::Commands.alias_command 'l', 'list'
21+
RubyJard::PryProxy::Commands.alias_command 'whereami', 'list'

lib/ruby_jard/commands/next_command.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ def process
2020
end
2121
end
2222

23-
Pry::Commands.add_command(RubyJard::Commands::NextCommand)
24-
Pry::Commands.alias_command 'n', 'next'
23+
RubyJard::PryProxy::Commands.add_command(RubyJard::Commands::NextCommand)
24+
RubyJard::PryProxy::Commands.alias_command 'n', 'next'

lib/ruby_jard/commands/skip_command.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ def process
2727
end
2828
end
2929

30-
Pry::Commands.add_command(RubyJard::Commands::SkipCommand)
30+
RubyJard::PryProxy::Commands.add_command(RubyJard::Commands::SkipCommand)

lib/ruby_jard/commands/step_command.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ def process
2020
end
2121
end
2222

23-
Pry::Commands.add_command(RubyJard::Commands::StepCommand)
24-
Pry::Commands.alias_command 's', 'step'
23+
RubyJard::PryProxy::Commands.add_command(RubyJard::Commands::StepCommand)
24+
RubyJard::PryProxy::Commands.alias_command 's', 'step'

lib/ruby_jard/commands/step_out_command.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ def process
2020
end
2121
end
2222

23-
Pry::Commands.add_command(RubyJard::Commands::StepOutCommand)
24-
Pry::Commands.alias_command 'so', 'step-out'
23+
RubyJard::PryProxy::Commands.add_command(RubyJard::Commands::StepOutCommand)
24+
RubyJard::PryProxy::Commands.alias_command 'so', 'step-out'

lib/ruby_jard/commands/up_command.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ def process
2020
end
2121
end
2222

23-
Pry::Commands.add_command(RubyJard::Commands::UpCommand)
23+
RubyJard::PryProxy::Commands.add_command(RubyJard::Commands::UpCommand)

lib/ruby_jard/pager.rb

+3-3
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,8 @@ class JardPageTracker < Pry::Pager::PageTracker
3939
# Pager using GNU Less
4040
class LessPager < Pry::Pager::NullPager
4141
def initialize(pry_instance, force_open: false, pager_start_at_the_end: false, prompt: nil)
42-
super(pry_instance.output)
4342
@pry_instance = pry_instance
44-
@console = pry_instance.console
43+
@console = RubyJard::Session.instance.screen_manager.console
4544
@buffer = ''
4645

4746
@pager_start_at_the_end = pager_start_at_the_end
@@ -52,10 +51,11 @@ def initialize(pry_instance, force_open: false, pager_start_at_the_end: false, p
5251
# from /dev/tty), in which, the same as RubyJard::Console.output
5352
# - Otherwise, it writes directly into pry's REPL output.
5453
# That's why there should be two output here
55-
@tty_output = @console.redirected? ? @console.output : pry_instance.output
54+
@tty_output = @console.redirected? ? @console.output : @pry_instance.output
5655
@window_width, @window_height = @console.screen_size
5756
@tracker = JardPageTracker.new(@window_height, @window_width)
5857
@pager = force_open ? open_pager : nil
58+
super(@pry_instance.output)
5959
end
6060

6161
def write(str)

lib/ruby_jard/pry_proxy.rb

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# frozen_string_literal: true
2+
3+
module RubyJard
4+
# Proxy for Pry::REPL. Implement support for ::Readline only
5+
class PryReplProxy < Pry::REPL
6+
def read_line(current_prompt)
7+
handle_read_errors do
8+
Pry::InputLock.for(:all).interruptible_region do
9+
input.readline(current_prompt, false)
10+
end
11+
end
12+
end
13+
end
14+
15+
# Proxy for Pry instance. Safely overidding some attributes
16+
class PryProxy < ::Pry
17+
# Some commands overlaps with Jard, Ruby, and even cause confusion for
18+
# users. It's better ignore or re-implement those commands.
19+
PRY_EXCLUDED_COMMANDS = [
20+
'pry-backtrace', # Redundant method for normal user
21+
'watch', # Conflict with byebug and jard watch
22+
'edit', # Sorry, but a file should not be editted while debugging, as it made breakpoints shifted
23+
'play', # What if the played files or methods include jard again?
24+
'stat', # Included in jard UI
25+
'backtrace', # Re-implemented later
26+
'break', # Re-implemented later
27+
'exit-all', # Conflicted with continue
28+
'exit-program', # We already have `exit` native command
29+
'!pry', # No need to complicate things
30+
'jump-to', # No need to complicate things
31+
'nesting', # No need to complicate things
32+
'switch-to', # No need to complicate things
33+
'disable-pry' # No need to complicate things
34+
].freeze
35+
36+
Commands = Pry::CommandSet.new
37+
38+
attr_reader :console
39+
40+
def initialize(options = {})
41+
@redirected_input = options[:redirected_input]
42+
@redirected_output = options[:redirected_output]
43+
@original_input = options[:original_input]
44+
@original_output = options[:original_output]
45+
@state_hooks = options[:state_hooks] || {}
46+
options = options.merge(
47+
input: ::Readline,
48+
output: @redirected_output,
49+
prompt: pry_jard_prompt,
50+
commands: pry_command_set,
51+
quiet: true,
52+
hooks: pry_hooks
53+
)
54+
super(options)
55+
end
56+
57+
def handle_line(line, *args)
58+
command = RubyJard::ReplSequence.detect(line)
59+
if command.nil?
60+
super(line, *args)
61+
else
62+
super(command, *args)
63+
end
64+
ensure
65+
exec_hook :after_handle_line, *args, self
66+
end
67+
68+
def start(target = nil)
69+
::Readline.input = @redirected_input
70+
::Readline.output = @redirected_output
71+
PryReplProxy.new(self, target: target).start
72+
end
73+
74+
def stop
75+
::Readline.input = @original_input
76+
::Readline.output = @original_output
77+
end
78+
79+
def pager
80+
RubyJard::Pager.new(self)
81+
end
82+
83+
def line_buffer
84+
Readline.line_buffer
85+
end
86+
87+
private
88+
89+
def pry_jard_prompt
90+
Pry::Prompt.new(
91+
:jard,
92+
'Custom pry promt for Jard', [
93+
proc do |_context, _nesting, _pry_instance|
94+
'jard >> '
95+
end,
96+
proc do |_context, _nesting, _pry_instance|
97+
'jard *> '
98+
end
99+
]
100+
)
101+
end
102+
103+
def pry_command_set
104+
set = Pry::CommandSet.new
105+
set.import_from(
106+
Pry::Commands,
107+
*(Pry::Commands.list_commands - PRY_EXCLUDED_COMMANDS)
108+
)
109+
set.import_from(
110+
PryProxy::Commands,
111+
*PryProxy::Commands.list_commands
112+
)
113+
set
114+
end
115+
116+
def pry_hooks
117+
hooks = Pry::Hooks.default
118+
hooks.add_hook(:after_read, :jard_proxy_acquire_lock) do |_read_string, _pry|
119+
@state_hooks[:after_read]&.call
120+
end
121+
hooks.add_hook(:after_handle_line, :jard_proxy_release_lock) do
122+
@state_hooks[:after_handle_line]&.call
123+
end
124+
hooks.add_hook(:before_pager, :jard_proxy_before_pager) do
125+
@state_hooks[:before_pager]&.call
126+
end
127+
hooks.add_hook(:after_pager, :jard_proxy_after_pager) do
128+
@state_hooks[:after_pager]&.call
129+
end
130+
end
131+
end
132+
end
133+
134+
RubyJard::PryProxy.init
135+
136+
require 'ruby_jard/commands/base_command'
137+
require 'ruby_jard/commands/validation_helpers'
138+
require 'ruby_jard/commands/color_helpers'
139+
require 'ruby_jard/commands/continue_command'
140+
require 'ruby_jard/commands/exit_command'
141+
require 'ruby_jard/commands/up_command'
142+
require 'ruby_jard/commands/down_command'
143+
require 'ruby_jard/commands/next_command'
144+
require 'ruby_jard/commands/step_command'
145+
require 'ruby_jard/commands/step_out_command'
146+
require 'ruby_jard/commands/frame_command'
147+
require 'ruby_jard/commands/list_command'
148+
require 'ruby_jard/commands/skip_command'
149+
require 'ruby_jard/commands/jard_command'
150+
require 'ruby_jard/commands/help_command'

0 commit comments

Comments
 (0)