diff --git a/Rakefile b/Rakefile index c67301a..4b6f891 100644 --- a/Rakefile +++ b/Rakefile @@ -30,9 +30,10 @@ task :build => jruby_version_file task :test => jruby_version_file if RUBY_ENGINE == "jruby" Rake::TestTask.new(:test) do |t| - if extask + backend = ENV["IO_CONSOLE_BACKEND"] + if extask and !backend t.libs = [extask.lib_dir.chomp("/"+File.dirname(name))] - elsif RUBY_ENGINE == "jruby" + elsif RUBY_ENGINE == "jruby" or backend t.libs.unshift "jruby/lib" end t.libs << "lib" diff --git a/ext/io/console/console.c b/ext/io/console/console.c index 04d0f70..eb1c876 100644 --- a/ext/io/console/console.c +++ b/ext/io/console/console.c @@ -2135,10 +2135,17 @@ puts_call(VALUE io) return rb_io_write(io, rb_default_rs); } +static VALUE +funcall_with_rs(VALUE obj, ID mid) +{ + const VALUE rs = rb_default_rs; /* rvalue in TruffleRuby */ + return rb_funcallv(obj, mid, 1, &rs); +} + static VALUE gets_call(VALUE io) { - return rb_funcallv(io, id_gets, 0, 0); + return funcall_with_rs(io, id_gets); } static VALUE @@ -2161,8 +2168,7 @@ static VALUE str_chomp(VALUE str) { if (!NIL_P(str)) { - const VALUE rs = rb_default_rs; /* rvalue in TruffleRuby */ - rb_funcallv(str, id_chomp_bang, 1, &rs); + funcall_with_rs(str, id_chomp_bang); } return str; } diff --git a/jruby/lib/io/console.rb b/jruby/lib/io/console.rb index b804a93..a9cb2ce 100644 --- a/jruby/lib/io/console.rb +++ b/jruby/lib/io/console.rb @@ -37,6 +37,9 @@ class Mode end backends = [] +ENV["IO_CONSOLE_BACKEND"]&.then do |be| + backends.concat(be.split(",").map {|b| b.split(":")}) +end&.first || # If Linux or BSD, try to load the native version case RbConfig::CONFIG['host_os'] when /darwin|openbsd|freebsd|netbsd/i diff --git a/jruby/lib/io/console/common.rb b/jruby/lib/io/console/common.rb index 1b55bac..4b3e4d6 100644 --- a/jruby/lib/io/console/common.rb +++ b/jruby/lib/io/console/common.rb @@ -6,7 +6,7 @@ module IO::Console class IO # TODO: Windows version uses "conin$" and "conout$" instead of /dev/tty - def self.console(sym = nil, *args) + def self.console(sym = nil, *args, **opts) raise TypeError, "expected Symbol, got #{sym.class}" unless sym.nil? || sym.kind_of?(Symbol) # klass = self == IO ? File : self @@ -44,7 +44,7 @@ def self.console(sym = nil, *args) end return nil unless con - return con.send(sym, *args) if sym + return con.send(sym, *args, **opts) if sym return con end @@ -58,14 +58,11 @@ def getpass(prompt = nil) wio = self == $stdin ? $stderr : self wio.write(prompt) if prompt begin - str = nil - noecho do - str = gets - end + str = noecho {gets("\n")} ensure - puts($/) + puts end - str&.chomp + str&.chomp("\n") end def input_pending? @@ -164,8 +161,8 @@ def getch(*) def getpass(prompt = nil) write(prompt) if prompt - str = gets&.chomp - puts($/) + str = gets("\n")&.chomp("\n") + puts str end end diff --git a/test/io/console/test_io_console.rb b/test/io/console/test_io_console.rb index ffc5b50..af207c8 100644 --- a/test/io/console/test_io_console.rb +++ b/test/io/console/test_io_console.rb @@ -26,14 +26,14 @@ def test_version end begin - PATHS = $LOADED_FEATURES.grep(%r"/io/console(?:\.#{RbConfig::CONFIG['DLEXT']}|\.rb|/\w+\.rb)\z") {$`} + paths = $LOADED_FEATURES.grep(%r"/io/console(?:\.#{RbConfig::CONFIG['DLEXT']}|\.rb|/\w+\.rb)\z") {$`} rescue Encoding::CompatibilityError $stderr.puts "test_io_console.rb debug" $LOADED_FEATURES.each{|path| $stderr.puts [path, path.encoding].inspect} raise end - PATHS.uniq! - INCLUDE_OPTS = "-I#{PATHS.join(File::PATH_SEPARATOR)}" + paths.uniq! + INCLUDE_OPTS = "-I#{paths.join(File::PATH_SEPARATOR)}".freeze # FreeBSD seems to hang on TTOU when running parallel tests # tested on FreeBSD 11.x. @@ -75,6 +75,7 @@ def test_bad_keyword end TTY_ENHANCED = IO.instance_method(:tty?).arity != 0 + TTY_MODE_STTY = IO.private_method_defined?(:_io_console_stty) def test_tty? pend "not supported" unless TTY_ENHANCED @@ -348,7 +349,9 @@ def test_getpass assert_equal("\r\n", r.gets) assert_equal("\"asdf\"", r.gets.chomp) end + end + def test_getpass_eof run_pty("p IO.console.getpass('> ')") do |r, w| assert_equal("> ", r.readpartial(10)) sleep 0.1 @@ -357,7 +360,9 @@ def test_getpass assert_equal("\r\n", r.gets) assert_equal("\"asdf\"", r.gets.chomp) end + end + def test_getpass_rs run_pty("$VERBOSE, $/ = nil, '.'; p IO.console.getpass('> ')") do |r, w| assert_equal("> ", r.readpartial(10)) sleep 0.1 @@ -380,7 +385,7 @@ def test_getpass_empty end def test_iflush - pend "stty cannot flush terminal queues" if IO.private_method_defined?(:_io_console_stty) + pend "stty cannot flush terminal queues" if TTY_MODE_STTY helper {|m, s| m.print "a" @@ -403,7 +408,7 @@ def test_oflush end def test_ioflush - pend "stty cannot flush terminal queues" if IO.private_method_defined?(:_io_console_stty) + pend "stty cannot flush terminal queues" if TTY_MODE_STTY helper {|m, s| m.print "a" diff --git a/test/io/console/test_ractor.rb b/test/io/console/test_ractor.rb index dff0c67..374db1f 100644 --- a/test/io/console/test_ractor.rb +++ b/test/io/console/test_ractor.rb @@ -5,7 +5,7 @@ class TestIOConsoleInRactor < Test::Unit::TestCase def test_ractor ext = "/io/console.#{RbConfig::CONFIG['DLEXT']}" - path = $".find {|path| path.end_with?(ext)} + path = $".find {|path| path.end_with?(ext)} || "io/console" assert_in_out_err(%W[-r#{path}], "#{<<~"begin;"}\n#{<<~'end;'}", ["true"], []) begin; class Ractor