From 62890333ac49cf33ed1a1661d60b12fb57ca0f3e Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 7 Aug 2026 10:52:21 +0900 Subject: [PATCH] Introduce the `IO::Console` namespace Isolate console modes and version information from `IO` into a common namespace. --- Rakefile | 6 ++++-- ext/io/console/console.c | 17 +++++++++++++++-- lib/ffi/io/console.rb | 12 ++++++++++++ lib/ffi/io/console/bsd_console.rb | 2 +- lib/ffi/io/console/linux_console.rb | 2 +- lib/ffi/io/console/native_console.rb | 10 +++++++--- test/io/console/test_io_console.rb | 13 ++++++++++++- 7 files changed, 52 insertions(+), 10 deletions(-) diff --git a/Rakefile b/Rakefile index b594fc9..0294c44 100644 --- a/Rakefile +++ b/Rakefile @@ -15,8 +15,10 @@ end ffi_version_file = "lib/ffi/#{name}/version.rb" task ffi_version_file => "#{name.tr('/', '-')}.gemspec" do |t| version = <<~RUBY - class IO::ConsoleMode - VERSION = "#{Bundler::GemHelper.instance.gemspec.version}" + class IO + module Console + VERSION = "#{Bundler::GemHelper.instance.gemspec.version}" + end end RUBY unless (File.read(t.name) rescue nil) == version diff --git a/ext/io/console/console.c b/ext/io/console/console.c index 05a4d68..80944aa 100644 --- a/ext/io/console/console.c +++ b/ext/io/console/console.c @@ -2102,8 +2102,21 @@ InitVM_console(void) } { /* :nodoc: */ - cConmode = rb_define_class_under(rb_cIO, "ConsoleMode", rb_cObject); - rb_define_const(cConmode, "VERSION", rb_obj_freeze(rb_str_new_cstr(IO_CONSOLE_VERSION))); + VALUE mConsole = rb_define_module_under(rb_cIO, "Console"); + VALUE version = rb_obj_freeze(rb_str_new_cstr(IO_CONSOLE_VERSION)); + ID cid, deprecate_constant = rb_intern_const("deprecate_constant"); + rb_define_const(mConsole, "VERSION", version); + /* :nodoc: */ + cConmode = rb_define_class_under(mConsole, "Mode", rb_cObject); + + /* old internal names; do not use */ + cid = rb_intern_const("ConsoleMode"); + rb_const_set(rb_cIO, cid, cConmode); + rb_funcall(rb_cIO, deprecate_constant, 1, ID2SYM(cid)); + cid = rb_intern_const("VERSION"); + rb_const_set(cConmode, cid, version); + rb_funcall(cConmode, deprecate_constant, 1, ID2SYM(cid)); + rb_define_alloc_func(cConmode, conmode_alloc); rb_undef_method(cConmode, "initialize"); rb_define_method(cConmode, "initialize_copy", conmode_init_copy, 1); diff --git a/lib/ffi/io/console.rb b/lib/ffi/io/console.rb index fb69ff8..f217838 100644 --- a/lib/ffi/io/console.rb +++ b/lib/ffi/io/console.rb @@ -24,6 +24,18 @@ require_relative 'console/version' require_relative 'console/common' +class IO + module Console + class Mode + VERSION = Console::VERSION + deprecate_constant :VERSION + end + end + + ConsoleMode = Console::Mode + deprecate_constant :ConsoleMode +end + libs = [] # If Linux or BSD, try to load the native version case RbConfig::CONFIG['host_os'].downcase diff --git a/lib/ffi/io/console/bsd_console.rb b/lib/ffi/io/console/bsd_console.rb index 79da09e..4ab9369 100644 --- a/lib/ffi/io/console/bsd_console.rb +++ b/lib/ffi/io/console/bsd_console.rb @@ -6,7 +6,7 @@ raise LoadError.new("native console on MacOS only supported on #{tested_platforms.join(', ')}") end -module IO::LibC +module IO::Console::LibC extend FFI::Library ffi_lib FFI::Library::LIBC diff --git a/lib/ffi/io/console/linux_console.rb b/lib/ffi/io/console/linux_console.rb index c2f30da..02ef924 100644 --- a/lib/ffi/io/console/linux_console.rb +++ b/lib/ffi/io/console/linux_console.rb @@ -6,7 +6,7 @@ warn "native console only tested on #{tested_platforms.join(', ')}" end -module IO::LibC +module IO::Console::LibC extend FFI::Library ffi_lib FFI::Library::LIBC diff --git a/lib/ffi/io/console/native_console.rb b/lib/ffi/io/console/native_console.rb index 09aacb6..211bbbc 100644 --- a/lib/ffi/io/console/native_console.rb +++ b/lib/ffi/io/console/native_console.rb @@ -1,5 +1,5 @@ # Common logic that uses native calls for console -class IO +module IO::Console def ttymode termios = LibC::Termios.new if LibC.tcgetattr(self.fileno, termios) != 0 @@ -88,7 +88,7 @@ def noecho(&block) ttymode_yield(block) { |t| t[:c_lflag] &= ~(TTY_ECHO) } end - class ConsoleMode + class Mode attr_reader :termios def initialize(t) @@ -120,7 +120,7 @@ def raw(min: 1, time: nil, intr: nil) end def console_mode - ConsoleMode.new(ttymode) + Mode.new(ttymode) end def console_mode=(mode) @@ -173,3 +173,7 @@ def ioflush raise SystemCallError.new("tcflush(TCIOFLUSH)", FFI.errno) unless LibC.tcflush(self.fileno, LibC::TCIOFLUSH) == 0 end end + +class IO + include Console +end diff --git a/test/io/console/test_io_console.rb b/test/io/console/test_io_console.rb index 83cb4e7..9f5911e 100644 --- a/test/io/console/test_io_console.rb +++ b/test/io/console/test_io_console.rb @@ -8,6 +8,14 @@ class TestIO_Console < Test::Unit::TestCase HOST_OS = RbConfig::CONFIG['host_os'] + + def test_version + assert_kind_of(String, IO::Console::VERSION) + EnvUtil.suppress_warning do + assert_same(IO::Console::VERSION, IO::Console::Mode::VERSION) + end + end + private def host_os?(os) HOST_OS =~ os end @@ -274,7 +282,10 @@ def test_console_mode helper {|m, s| begin original = s.console_mode - assert_kind_of(IO::ConsoleMode, original) + assert_kind_of(IO::Console::Mode, original) + EnvUtil.suppress_warning do + assert_same(IO::Console::Mode, IO.const_get(:ConsoleMode)) + end noecho = original.dup noecho.echo = false