aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorStan Lo <stan001212@gmail.com>2023-08-13 16:23:00 +0100
committergit <svn-admin@ruby-lang.org>2023-08-13 15:23:04 +0000
commit9099d62ac77cdca548bc4110e2cb03057ef0ac8f (patch)
tree01349988ebf73ea94eb7b740b8e78ba424082135 /lib
parent3af5badae85851ba50e497c297b478cf88a6061a (diff)
downloadruby-9099d62ac77cdca548bc4110e2cb03057ef0ac8f.tar.gz
[ruby/irb] Move IO configuration to IRB::Irb
(https://github.com/ruby/irb/pull/681) It shouldn't be `RubyLex`'s responsibility to handle IO. So this moves the configuration to `IRB::Irb`. https://github.com/ruby/irb/commit/daff750076
Diffstat (limited to 'lib')
-rw-r--r--lib/irb.rb54
-rw-r--r--lib/irb/ruby-lex.rb57
2 files changed, 55 insertions, 56 deletions
diff --git a/lib/irb.rb b/lib/irb.rb
index e0025ab3e8..c3631715da 100644
--- a/lib/irb.rb
+++ b/lib/irb.rb
@@ -537,7 +537,7 @@ module IRB
end
end
- @scanner.configure_io(@context.io)
+ configure_io
@scanner.each_top_level_statement do |line, line_no, is_assignment|
signal_status(:IN_EVAL) do
@@ -564,6 +564,58 @@ module IRB
end
end
+ def configure_io
+ if @context.io.respond_to?(:check_termination)
+ @context.io.check_termination do |code|
+ if Reline::IOGate.in_pasting?
+ rest = @scanner.check_termination_in_prev_line(code)
+ if rest
+ Reline.delete_text
+ rest.bytes.reverse_each do |c|
+ Reline.ungetc(c)
+ end
+ true
+ else
+ false
+ end
+ else
+ # Accept any single-line input for symbol aliases or commands that transform args
+ next true if @scanner.single_line_command?(code)
+
+ _tokens, _opens, terminated = @scanner.check_code_state(code)
+ terminated
+ end
+ end
+ end
+ if @context.io.respond_to?(:dynamic_prompt)
+ @context.io.dynamic_prompt do |lines|
+ lines << '' if lines.empty?
+ tokens = RubyLex.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join, context: @context)
+ line_results = IRB::NestingParser.parse_by_line(tokens)
+ tokens_until_line = []
+ line_results.map.with_index do |(line_tokens, _prev_opens, next_opens, _min_depth), line_num_offset|
+ line_tokens.each do |token, _s|
+ # Avoid appending duplicated token. Tokens that include "\n" like multiline tstring_content can exist in multiple lines.
+ tokens_until_line << token if token != tokens_until_line.last
+ end
+ continue = @scanner.should_continue?(tokens_until_line)
+ @scanner.prompt(next_opens, continue, line_num_offset)
+ end
+ end
+ end
+
+ if @context.io.respond_to?(:auto_indent) and @context.auto_indent_mode
+ @context.io.auto_indent do |lines, line_index, byte_pointer, is_newline|
+ next nil if lines == [nil] # Workaround for exit IRB with CTRL+d
+ next nil if !is_newline && lines[line_index]&.byteslice(0, byte_pointer)&.match?(/\A\s*\z/)
+
+ code = lines[0..line_index].map { |l| "#{l}\n" }.join
+ tokens = RubyLex.ripper_lex_without_warning(code, context: @context)
+ @scanner.process_indent_level(tokens, lines, line_index, is_newline)
+ end
+ end
+ end
+
def evaluate_line(line, line_no)
# Transform a non-identifier alias (@, $) or keywords (next, break)
command, args = line.split(/\s/, 2)
diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb
index 92e993ecef..7d4f8a514c 100644
--- a/lib/irb/ruby-lex.rb
+++ b/lib/irb/ruby-lex.rb
@@ -74,59 +74,6 @@ class RubyLex
@input = block
end
- def configure_io(io)
- @io = io
- if @io.respond_to?(:check_termination)
- @io.check_termination do |code|
- if Reline::IOGate.in_pasting?
- rest = check_termination_in_prev_line(code)
- if rest
- Reline.delete_text
- rest.bytes.reverse_each do |c|
- Reline.ungetc(c)
- end
- true
- else
- false
- end
- else
- # Accept any single-line input for symbol aliases or commands that transform args
- next true if single_line_command?(code)
-
- _tokens, _opens, terminated = check_code_state(code)
- terminated
- end
- end
- end
- if @io.respond_to?(:dynamic_prompt)
- @io.dynamic_prompt do |lines|
- lines << '' if lines.empty?
- tokens = self.class.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join, context: @context)
- line_results = IRB::NestingParser.parse_by_line(tokens)
- tokens_until_line = []
- line_results.map.with_index do |(line_tokens, _prev_opens, next_opens, _min_depth), line_num_offset|
- line_tokens.each do |token, _s|
- # Avoid appending duplicated token. Tokens that include "\n" like multiline tstring_content can exist in multiple lines.
- tokens_until_line << token if token != tokens_until_line.last
- end
- continue = should_continue?(tokens_until_line)
- prompt(next_opens, continue, line_num_offset)
- end
- end
- end
-
- if @io.respond_to?(:auto_indent) and @context.auto_indent_mode
- @io.auto_indent do |lines, line_index, byte_pointer, is_newline|
- next nil if lines == [nil] # Workaround for exit IRB with CTRL+d
- next nil if !is_newline && lines[line_index]&.byteslice(0, byte_pointer)&.match?(/\A\s*\z/)
-
- code = lines[0..line_index].map { |l| "#{l}\n" }.join
- tokens = self.class.ripper_lex_without_warning(code, context: @context)
- process_indent_level(tokens, lines, line_index, is_newline)
- end
- end
- end
-
def set_prompt(&block)
@prompt = block
end
@@ -240,7 +187,7 @@ class RubyLex
save_prompt_to_context_io([], false, 0)
# multiline
- return @input.call if @io.respond_to?(:check_termination)
+ return @input.call if @context.io.respond_to?(:check_termination)
# nomultiline
code = ''
@@ -270,7 +217,7 @@ class RubyLex
break unless code
if code != "\n"
- code.force_encoding(@io.encoding)
+ code.force_encoding(@context.io.encoding)
yield code, @line_no, assignment_expression?(code)
end
@line_no += code.count("\n")