ruby-changes:65738
From: aycabta <ko1@a...>
Date: Sat, 3 Apr 2021 01:19:24 +0900 (JST)
Subject: [ruby-changes:65738] ab89c45b90 (master): [ruby/irb] Evaluate each toplevel statement
https://git.ruby-lang.org/ruby.git/commit/?id=ab89c45b90 From ab89c45b906380353d1b399781170cafe1d7b503 Mon Sep 17 00:00:00 2001 From: aycabta <aycabta@g...> Date: Fri, 26 Mar 2021 22:46:40 +0900 Subject: [ruby/irb] Evaluate each toplevel statement https://github.com/ruby/irb/commit/bc1b1d8bc3 --- lib/irb/input-method.rb | 8 +-- lib/irb/ruby-lex.rb | 69 +++++++++++++++++++++-- test/irb/yamatanooroti/test_rendering.rb | 96 ++++++++++++++++++++++++++++---- 3 files changed, 151 insertions(+), 22 deletions(-) diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb index df73cee..1854567 100644 --- a/lib/irb/input-method.rb +++ b/lib/irb/input-method.rb @@ -316,13 +316,7 @@ module IRB https://github.com/ruby/ruby/blob/trunk/lib/irb/input-method.rb#L316 Reline.output = @stdout Reline.prompt_proc = @prompt_proc Reline.auto_indent_proc = @auto_indent_proc if @auto_indent_proc - - l = readmultiline(@prompt, false) do |line| - next false if Reline::IOGate.in_pasting? - @check_termination_proc.call(line) - end - - if l + if l = readmultiline(@prompt, false, &@check_termination_proc) HISTORY.push(l) if !l.empty? @line[@line_no += 1] = l + "\n" else diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb index 586ac39..82df06d 100644 --- a/lib/irb/ruby-lex.rb +++ b/lib/irb/ruby-lex.rb @@ -47,12 +47,26 @@ class RubyLex https://github.com/ruby/ruby/blob/trunk/lib/irb/ruby-lex.rb#L47 @io = io if @io.respond_to?(:check_termination) @io.check_termination do |code| - code.gsub!(/\s*\z/, '').concat("\n") - ltype, indent, continue, code_block_open = check_state(code) - if ltype or indent > 0 or continue or code_block_open - false + if Reline::IOGate.in_pasting? + lex = RubyLex.new + rest = lex.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 - true + code.gsub!(/\s*\z/, '').concat("\n") + ltype, indent, continue, code_block_open = check_state(code) + if ltype or indent > 0 or continue or code_block_open + false + else + true + end end end end @@ -739,5 +753,50 @@ class RubyLex https://github.com/ruby/ruby/blob/trunk/lib/irb/ruby-lex.rb#L753 nil end end + + def check_termination_in_prev_line(code) + tokens = self.class.ripper_lex_without_warning(code) + past_first_newline = false + index = tokens.rindex do |t| + # traverse first token before last line + if past_first_newline + if t.tok.include?("\n") + true + end + elsif t.tok.include?("\n") + past_first_newline = true + false + else + false + end + end + if index + first_token = nil + last_line_tokens = tokens[(index + 1)..(tokens.size - 1)] + last_line_tokens.each do |t| + unless [:on_sp, :on_ignored_sp, :on_comment].include?(t.event) + first_token = t + break + end + end + if first_token.nil? + return false + elsif first_token && first_token.state == Ripper::EXPR_DOT + return false + else + tokens_without_last_line = tokens[0..index] + ltype = process_literal_type(tokens_without_last_line) + indent = process_nesting_level(tokens_without_last_line) + continue = process_continue(tokens_without_last_line) + code_block_open = check_code_block(tokens_without_last_line.map(&:tok).join(''), tokens_without_last_line) + if ltype or indent > 0 or continue or code_block_open + return false + else + return last_line_tokens.map(&:tok).join('') + end + end + end + false + end end # :startdoc: diff --git a/test/irb/yamatanooroti/test_rendering.rb b/test/irb/yamatanooroti/test_rendering.rb index 171bfea..8f55b38 100644 --- a/test/irb/yamatanooroti/test_rendering.rb +++ b/test/irb/yamatanooroti/test_rendering.rb @@ -49,6 +49,7 @@ begin https://github.com/ruby/ruby/blob/trunk/test/irb/yamatanooroti/test_rendering.rb#L49 start_terminal(25, 80, %W{ruby -I#{@pwd}/lib -I#{@pwd}/../reline/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') write(<<~EOC) class A + def inspect; '#<A>'; end def a; self; end def b; true; end end @@ -63,17 +64,92 @@ begin https://github.com/ruby/ruby/blob/trunk/test/irb/yamatanooroti/test_rendering.rb#L64 assert_screen(<<~EOC) start IRB irb(main):001:1* class A - irb(main):002:1* def a; self; end - irb(main):003:1* def b; true; end - irb(main):004:0> end - irb(main):005:0* - irb(main):006:0> a = A.new - irb(main):007:0* - irb(main):008:0> a - irb(main):009:0> .a - irb(main):010:0> .b + irb(main):002:1* def inspect; '#<A>'; end + irb(main):003:1* def a; self; end + irb(main):004:1* def b; true; end + irb(main):005:0> end + => :b + irb(main):006:0> + irb(main):007:0> a = A.new + => #<A> + irb(main):008:0> + irb(main):009:0> a + irb(main):010:0> .a + irb(main):011:0> .b => true - irb(main):011:0> + irb(main):012:0> + EOC + end + + def test_evaluate_each_toplevel_statement_by_multiline_paste + write_irbrc <<~'LINES' + puts 'start IRB' + LINES + start_terminal(40, 80, %W{ruby -I#{@pwd}/lib -I#{@pwd}/../reline/lib #{@pwd}/exe/irb}, startup_message: 'start IRB') + write(<<~EOC) + class A + def inspect; '#<A>'; end + def b; self; end + def c; true; end + end + + a = A.new + + a + .b + # aaa + .c + + (a) + &.b() + + + class A def b; self; end; def c; true; end; end; + a = A.new + a + .b + # aaa + .c + (a) + &.b() + EOC + close + assert_screen(<<~EOC) + start IRB + irb(main):001:1* class A + irb(main):002:1* def inspect; '#<A>'; end + irb(main):003:1* def b; self; end + irb(main):004:1* def c; true; end + irb(main):005:0> end + => :c + irb(main):006:0> + irb(main):007:0> a = A.new + => #<A> + irb(main):008:0> + irb(main):009:0> a + irb(main):010:0> .b + irb(main):011:0> # aaa + irb(main):012:0> .c + => true + irb(main):013:0> + irb(main):014:0> (a) + irb(main):015:0> &.b() + => #<A> + irb(main):016:0> + irb(main):017:0> + irb(main):018:0> class A def b; self; end; def c; true; end; end; + => :c + irb(main):019:0> a = A.new + => #<A> + irb(main):020:0> a + irb(main):021:0> .b + irb(main):022:0> # aaa + irb(main):023:0> .c + => true + irb(main):024:0> (a) + irb(main):025:0> &.b() + => #<A> + irb(main):026:0> EOC end -- cgit v1.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/