From 86f490378f199a7bbe135ba774ee292d296e1476 Mon Sep 17 00:00:00 2001 From: "Pedro D. Garcia Lopez" Date: Mon, 27 Nov 2023 22:17:06 +0000 Subject: [PATCH] add the ability to store last eval in variable. --- lib/web_console/evaluator.rb | 14 ++++++++++++-- lib/web_console/railtie.rb | 6 ++++++ test/web_console/evaluator_test.rb | 16 ++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/lib/web_console/evaluator.rb b/lib/web_console/evaluator.rb index dc91d061..4c719bed 100644 --- a/lib/web_console/evaluator.rb +++ b/lib/web_console/evaluator.rb @@ -7,6 +7,8 @@ module WebConsole # difference of a regular +Binding+ eval is that +Evaluator+ will always # return a string and will format exception output. class Evaluator + # stores last evalutation in this variable for futher use. + cattr_accessor :last_evaluation_variable, default: '_' # Cleanses exceptions raised inside #eval. cattr_reader :cleaner, default: begin cleaner = ActiveSupport::BacktraceCleaner.new @@ -14,6 +16,7 @@ class Evaluator cleaner end + def initialize(binding = TOPLEVEL_BINDING) @binding = binding end @@ -21,16 +24,23 @@ def initialize(binding = TOPLEVEL_BINDING) def eval(input) # Binding#source_location is available since Ruby 2.6. if @binding.respond_to? :source_location - "=> #{@binding.eval(input, *@binding.source_location).inspect}\n" + output = "=> #{@binding.eval(input, *@binding.source_location).inspect}\n" else - "=> #{@binding.eval(input).inspect}\n" + output = "=> #{@binding.eval(input).inspect}\n" end + set_last_eval(input) + output rescue Exception => exc format_exception(exc) end private + def set_last_eval(input) + return if input.blank? + @binding.eval("#{last_evaluation_variable} = #{input}") + end + def format_exception(exc) backtrace = cleaner.clean(Array(exc.backtrace) - caller) diff --git a/lib/web_console/railtie.rb b/lib/web_console/railtie.rb index 9bc8fdc6..42a941e3 100644 --- a/lib/web_console/railtie.rb +++ b/lib/web_console/railtie.rb @@ -84,5 +84,11 @@ def web_console_permissions initializer "i18n.load_path" do config.i18n.load_path.concat(Dir[File.expand_path("../locales/*.yml", __FILE__)]) end + + initializer 'web_console.last_evaluation_variable' do + if last_evaluation_variable = config.web_console.last_evaluation_variable + Evaluator.last_evaluation_variable = last_evaluation_variable + end + end end end diff --git a/test/web_console/evaluator_test.rb b/test/web_console/evaluator_test.rb index c5b603c8..b53fec8e 100644 --- a/test/web_console/evaluator_test.rb +++ b/test/web_console/evaluator_test.rb @@ -66,6 +66,22 @@ def backtrace END end + test "Evaluator preserve the last value in the _ variable" do + @repl.class.last_evaluation_variable = "_" + assert_equal "=> 42\n", @repl.eval("foo = 42") + assert_equal "=> 42\n", @repl.eval("_") + assert_equal "=> 50\n", @repl.eval("_ + 8") + assert_equal "=> 50\n", @repl.eval("_") + end + + test "last evaluation variable can be configured" do + assert_equal "=> 42\n", @repl.eval("foo = 42") + assert_equal "=> 42\n", @repl.eval("_") + @repl.class.last_evaluation_variable = "$_last_value" + assert_equal "=> 42\n", @repl.eval("foo = 42") + assert_equal "=> 42\n", @repl.eval("$_last_value") + end + private def current_trace