From 241e06173fd68b8e827aafc72a5113ee566c40fa Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Wed, 1 May 2024 18:40:49 +0300 Subject: [PATCH] Switch to StdioInputMethod when TERM is 'dumb' (#907) * Switch to StdioInputMethod when TERM is 'dumb' This works around Reline's misbehavior on low-capability terminals, such as when IRB is launched inside Emacs (ruby/reline#616). It should also resolve #68 and resolve #113 which were filed out of similar need. * Add special env for testing See discussion in #907. --------- Co-authored-by: tomoya ishida --- lib/irb.rb | 7 +++++-- lib/irb/context.rb | 9 +++++++-- test/irb/helper.rb | 4 +++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/irb.rb b/lib/irb.rb index 45a59087b..5a064cfce 100644 --- a/lib/irb.rb +++ b/lib/irb.rb @@ -311,7 +311,9 @@ # ### Input Method # # The IRB input method determines how command input is to be read; by default, -# the input method for a session is IRB::RelineInputMethod. +# the input method for a session is IRB::RelineInputMethod. Unless the +# value of the TERM environment variable is 'dumb', in which case the +# most simplistic input method is used. # # You can set the input method by: # @@ -329,7 +331,8 @@ # IRB::ReadlineInputMethod. # * `--nosingleline` or `--multiline` sets the input method to # IRB::RelineInputMethod. -# +# * `--nosingleline` together with `--nomultiline` sets the +# input to IRB::StdioInputMethod. # # # Method `conf.use_multiline?` and its synonym `conf.use_reline` return: diff --git a/lib/irb/context.rb b/lib/irb/context.rb index 22e855f1e..173f3dae5 100644 --- a/lib/irb/context.rb +++ b/lib/irb/context.rb @@ -85,7 +85,7 @@ def initialize(irb, workspace = nil, input_method = nil) @io = nil case use_multiline? when nil - if STDIN.tty? && IRB.conf[:PROMPT_MODE] != :INF_RUBY && !use_singleline? + if term_interactive? && IRB.conf[:PROMPT_MODE] != :INF_RUBY && !use_singleline? # Both of multiline mode and singleline mode aren't specified. @io = RelineInputMethod.new(build_completor) else @@ -99,7 +99,7 @@ def initialize(irb, workspace = nil, input_method = nil) unless @io case use_singleline? when nil - if (defined?(ReadlineInputMethod) && STDIN.tty? && + if (defined?(ReadlineInputMethod) && term_interactive? && IRB.conf[:PROMPT_MODE] != :INF_RUBY) @io = ReadlineInputMethod.new else @@ -151,6 +151,11 @@ def initialize(irb, workspace = nil, input_method = nil) @command_aliases = @user_aliases.merge(KEYWORD_ALIASES) end + private def term_interactive? + return true if ENV['TEST_IRB_FORCE_INTERACTIVE'] + STDIN.tty? && ENV['TERM'] != 'dumb' + end + # because all input will eventually be evaluated as Ruby code, # command names that conflict with Ruby keywords need special workaround # we can remove them once we implemented a better command system for IRB diff --git a/test/irb/helper.rb b/test/irb/helper.rb index 591bd05b7..acaf6277f 100644 --- a/test/irb/helper.rb +++ b/test/irb/helper.rb @@ -121,7 +121,9 @@ def run_ruby_file(&block) @envs["XDG_CONFIG_HOME"] ||= tmp_dir @envs["IRBRC"] = nil unless @envs.key?("IRBRC") - PTY.spawn(@envs.merge("TERM" => "dumb"), *cmd) do |read, write, pid| + envs_for_spawn = @envs.merge('TERM' => 'dumb', 'TEST_IRB_FORCE_INTERACTIVE' => 'true') + + PTY.spawn(envs_for_spawn, *cmd) do |read, write, pid| Timeout.timeout(TIMEOUT_SEC) do while line = safe_gets(read) lines << line