lib/irb.rb in irb-1.1.0.pre.2 vs lib/irb.rb in irb-1.1.0.pre.3

- old
+ new

@@ -8,10 +8,11 @@ # -- # # # require "e2mmap" +require "ripper" require "irb/init" require "irb/context" require "irb/extend-command" @@ -408,10 +409,39 @@ raise exception, "abort then interrupt!" end end class Irb + ASSIGNMENT_NODE_TYPES = [ + # Local, instance, global, class, constant, instance, and index assignment: + # "foo = bar", + # "@foo = bar", + # "$foo = bar", + # "@@foo = bar", + # "::Foo = bar", + # "a::Foo = bar", + # "Foo = bar" + # "foo.bar = 1" + # "foo[1] = bar" + :assign, + + # Operation assignment: + # "foo += bar" + # "foo -= bar" + # "foo ||= bar" + # "foo &&= bar" + :opassign, + + # Multiple assignment: + # "foo, bar = 1, 2 + :massign, + ] + # Note: instance and index assignment expressions could also be written like: + # "foo.bar=(1)" and "foo.[]=(1, bar)", when expressed that way, the former + # be parsed as :assign and echo will be suppressed, but the latter is + # parsed as a :method_add_arg and the output won't be suppressed + # Creates a new irb session def initialize(workspace = nil, input_method = nil, output_method = nil) @context = Context.new(self, workspace, input_method, output_method) @context.main.extend ExtendCommandBundle @signal_status = :IN_IRB @@ -496,11 +526,11 @@ @scanner.each_top_level_statement do |line, line_no| signal_status(:IN_EVAL) do begin line.untaint @context.evaluate(line, line_no, exception: exc) - output_value if @context.echo? + output_value if @context.echo? && (@context.echo_on_assignment? || !assignment_expression?(line)) rescue Interrupt => exc rescue SystemExit, SignalException raise rescue Exception => exc else @@ -715,10 +745,22 @@ end end format("#<%s: %s>", self.class, ary.join(", ")) end + def assignment_expression?(line) + # Try to parse the line and check if the last of possibly multiple + # expressions is an assignment type. + + # If the expression is invalid, Ripper.sexp should return nil which will + # result in false being returned. Any valid expression should return an + # s-expression where the second selement of the top level array is an + # array of parsed expressions. The first element of each expression is the + # expression's type. + ASSIGNMENT_NODE_TYPES.include?(Ripper.sexp(line)&.dig(1,-1,0)) + end + ATTR_TTY = "\e[%sm" def ATTR_TTY.[](*a) self % a.join(";"); end ATTR_PLAIN = "" def ATTR_PLAIN.[](*) self; end end @@ -803,10 +845,10 @@ # Cooked potato: true # # # See IRB@IRB+Usage for more information. def irb - IRB.setup(eval("__FILE__"), argv: []) + IRB.setup(source_location[0], argv: []) workspace = IRB::WorkSpace.new(self) STDOUT.print(workspace.code_around_binding) IRB::Irb.new(workspace).run(IRB.conf) end end