-
-
Save headius/a378320ecb89f9fdf2f11ce1019d631d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 1c8c4b0aa128ef6cd0c9bea2f1cba69c2e663a91 | |
Author: Charles Oliver Nutter <headius@headius.com> | |
Date: Wed Mar 17 16:20:58 2021 -0500 | |
Switch to io-console gem | |
diff --git a/lib/pom.rb b/lib/pom.rb | |
index 3cf217d3ab..d5401ff24d 100644 | |
--- a/lib/pom.rb | |
+++ b/lib/pom.rb | |
@@ -18,6 +18,7 @@ default_gems = [ | |
['cmath', '1.0.0'], | |
['csv', '1.0.0'], | |
['fileutils', '1.1.0'], | |
+ ['io-console', '0.5.9'], | |
['ipaddr', '1.2.0'], | |
['jar-dependencies', '${jar-dependencies.version}'], | |
['jruby-readline', '1.3.7'], | |
diff --git a/lib/pom.xml b/lib/pom.xml | |
index 6ee28c0967..8094a3f6e1 100644 | |
--- a/lib/pom.xml | |
+++ b/lib/pom.xml | |
@@ -70,6 +70,19 @@ DO NOT MODIFIY - GENERATED CODE | |
</exclusion> | |
</exclusions> | |
</dependency> | |
+ <dependency> | |
+ <groupId>rubygems</groupId> | |
+ <artifactId>io-console</artifactId> | |
+ <version>0.5.9</version> | |
+ <type>gem</type> | |
+ <scope>provided</scope> | |
+ <exclusions> | |
+ <exclusion> | |
+ <artifactId>jar-dependencies</artifactId> | |
+ <groupId>rubygems</groupId> | |
+ </exclusion> | |
+ </exclusions> | |
+ </dependency> | |
<dependency> | |
<groupId>rubygems</groupId> | |
<artifactId>ipaddr</artifactId> | |
@@ -328,6 +341,7 @@ DO NOT MODIFIY - GENERATED CODE | |
<include>specifications/cmath-1.0.0*</include> | |
<include>specifications/csv-1.0.0*</include> | |
<include>specifications/fileutils-1.1.0*</include> | |
+ <include>specifications/io-console-0.5.9*</include> | |
<include>specifications/ipaddr-1.2.0*</include> | |
<include>specifications/jar-dependencies-${jar-dependencies.version}*</include> | |
<include>specifications/jruby-readline-1.3.7*</include> | |
@@ -349,6 +363,7 @@ DO NOT MODIFIY - GENERATED CODE | |
<include>gems/cmath-1.0.0*/**/*</include> | |
<include>gems/csv-1.0.0*/**/*</include> | |
<include>gems/fileutils-1.1.0*/**/*</include> | |
+ <include>gems/io-console-0.5.9*/**/*</include> | |
<include>gems/ipaddr-1.2.0*/**/*</include> | |
<include>gems/jar-dependencies-${jar-dependencies.version}*/**/*</include> | |
<include>gems/jruby-readline-1.3.7*/**/*</include> | |
@@ -370,6 +385,7 @@ DO NOT MODIFIY - GENERATED CODE | |
<include>cache/cmath-1.0.0*</include> | |
<include>cache/csv-1.0.0*</include> | |
<include>cache/fileutils-1.1.0*</include> | |
+ <include>cache/io-console-0.5.9*</include> | |
<include>cache/ipaddr-1.2.0*</include> | |
<include>cache/jar-dependencies-${jar-dependencies.version}*</include> | |
<include>cache/jruby-readline-1.3.7*</include> | |
diff --git a/lib/ruby/stdlib/io/console.rb b/lib/ruby/stdlib/io/console.rb | |
index 82ae83cc29..e0a71a1374 100644 | |
--- a/lib/ruby/stdlib/io/console.rb | |
+++ b/lib/ruby/stdlib/io/console.rb | |
@@ -1,5 +1,5 @@ | |
-if RUBY_ENGINE == 'jruby' | |
- require 'io/console/jruby' | |
+if RUBY_ENGINE == 'ruby' || RUBY_ENGINE == 'truffleruby' | |
+ require_relative 'console.so' | |
else | |
- require 'io/console.so' | |
-end | |
\ No newline at end of file | |
+ require_relative 'console/ffi/console' | |
+end | |
diff --git a/lib/ruby/stdlib/io/console/jruby/bsd_console.rb b/lib/ruby/stdlib/io/console/ffi/bsd_console.rb | |
similarity index 99% | |
rename from lib/ruby/stdlib/io/console/jruby/bsd_console.rb | |
rename to lib/ruby/stdlib/io/console/ffi/bsd_console.rb | |
index d32804c520..1238fd92dc 100644 | |
--- a/lib/ruby/stdlib/io/console/jruby/bsd_console.rb | |
+++ b/lib/ruby/stdlib/io/console/ffi/bsd_console.rb | |
@@ -138,7 +138,7 @@ module IO::LibC | |
:c_oflag, :tcflag_t, | |
:c_cflag, :tcflag_t, | |
:c_lflag, :tcflag_t, | |
- :cc_c, [ :uchar, NCCS ], | |
+ :c_cc, [ :uchar, NCCS ], | |
:c_ispeed, :speed_t, | |
:c_ospeed, :speed_t | |
end | |
diff --git a/lib/ruby/stdlib/io/console/jruby/common.rb b/lib/ruby/stdlib/io/console/ffi/common.rb | |
similarity index 91% | |
rename from lib/ruby/stdlib/io/console/jruby/common.rb | |
rename to lib/ruby/stdlib/io/console/ffi/common.rb | |
index 10f7fc0396..d45601ab1c 100644 | |
--- a/lib/ruby/stdlib/io/console/jruby/common.rb | |
+++ b/lib/ruby/stdlib/io/console/ffi/common.rb | |
@@ -1,7 +1,7 @@ | |
# Methods common to all backend impls | |
class IO | |
- def getch(*) | |
- raw do | |
+ def getch(*, **opts) | |
+ raw(**opts) do | |
getc | |
end | |
end | |
@@ -32,4 +32,4 @@ class IO | |
str | |
end | |
end | |
-end | |
\ No newline at end of file | |
+end | |
diff --git a/lib/ruby/stdlib/io/console/jruby.rb b/lib/ruby/stdlib/io/console/ffi/console.rb | |
similarity index 90% | |
rename from lib/ruby/stdlib/io/console/jruby.rb | |
rename to lib/ruby/stdlib/io/console/ffi/console.rb | |
index d6dfe1e8d9..9538215352 100644 | |
--- a/lib/ruby/stdlib/io/console/jruby.rb | |
+++ b/lib/ruby/stdlib/io/console/ffi/console.rb | |
@@ -21,11 +21,11 @@ | |
require 'rbconfig' | |
-require_relative 'jruby/common' | |
+require_relative 'common' | |
# If Windows, always use the stub version | |
if RbConfig::CONFIG['host_os'] =~ /(mswin)|(win32)|(ming)/ | |
- require_relative 'jruby/stub_console' | |
+ require_relative 'stub_console' | |
else | |
# If Linux or BSD, try to load the native version | |
@@ -33,7 +33,7 @@ else | |
begin | |
# Attempt to load the native Linux and BSD console logic | |
- require_relative 'jruby/native_console' | |
+ require_relative 'native_console' | |
ready = true | |
rescue Exception => ex | |
@@ -48,7 +48,7 @@ else | |
if !ready | |
begin | |
- require_relative 'jruby/stty_console' | |
+ require_relative 'stty_console' | |
ready = true | |
rescue Exception | |
@@ -61,7 +61,7 @@ else | |
# If still not ready, just use stubbed version | |
if !ready | |
- require_relative 'jruby/stub_console' | |
+ require_relative 'stub_console' | |
end | |
end | |
diff --git a/lib/ruby/stdlib/io/console/jruby/linux_console.rb b/lib/ruby/stdlib/io/console/ffi/linux_console.rb | |
similarity index 98% | |
rename from lib/ruby/stdlib/io/console/jruby/linux_console.rb | |
rename to lib/ruby/stdlib/io/console/ffi/linux_console.rb | |
index bb6e43cd9e..6172c8ca62 100644 | |
--- a/lib/ruby/stdlib/io/console/jruby/linux_console.rb | |
+++ b/lib/ruby/stdlib/io/console/ffi/linux_console.rb | |
@@ -163,7 +163,7 @@ module IO::LibC | |
TCSANOW = 0 | |
TCSADRAIN = 1 | |
TCSAFLUSH = 2 | |
- NCCS = 19 | |
+ NCCS = 32 | |
class Termios < FFI::Struct | |
layout \ | |
:c_iflag, :tcflag_t, | |
@@ -171,7 +171,7 @@ module IO::LibC | |
:c_cflag, :tcflag_t, | |
:c_lflag, :tcflag_t, | |
:c_line, :uchar, | |
- :cc_c, [ :uchar, NCCS ], | |
+ :c_cc, [ :uchar, NCCS ], | |
:c_ispeed, :speed_t, | |
:c_ospeed, :speed_t | |
end | |
diff --git a/lib/ruby/stdlib/io/console/jruby/native_console.rb b/lib/ruby/stdlib/io/console/ffi/native_console.rb | |
similarity index 59% | |
rename from lib/ruby/stdlib/io/console/jruby/native_console.rb | |
rename to lib/ruby/stdlib/io/console/ffi/native_console.rb | |
index 792e4b1ae5..1c499efa6f 100644 | |
--- a/lib/ruby/stdlib/io/console/jruby/native_console.rb | |
+++ b/lib/ruby/stdlib/io/console/ffi/native_console.rb | |
@@ -13,38 +13,47 @@ class IO | |
def ttymode | |
termios = LibC::Termios.new | |
if LibC.tcgetattr(self.fileno, termios) != 0 | |
- raise SystemCallError.new("tcgetattr", FFI.errno) | |
+ raise SystemCallError.new(path, FFI.errno) | |
end | |
if block_given? | |
yield tmp = termios.dup | |
- if LibC.tcsetattr(self.fileno, LibC::TCSADRAIN, tmp) != 0 | |
- raise SystemCallError.new("tcsetattr", FFI.errno) | |
+ if LibC.tcsetattr(self.fileno, LibC::TCSANOW, tmp) != 0 | |
+ raise SystemCallError.new(path, FFI.errno) | |
end | |
end | |
termios | |
end | |
private :ttymode | |
- def ttymode_yield(block, &setup) | |
+ def ttymode_yield(block, **opts, &setup) | |
begin | |
- orig_termios = ttymode { |t| setup.call(t) } | |
+ orig_termios = ttymode { |t| setup.call(t, **opts) } | |
block.call(self) | |
ensure | |
- if orig_termios && LibC.tcsetattr(self.fileno, LibC::TCSADRAIN, orig_termios) != 0 | |
- raise SystemCallError.new("tcsetattr", FFI.errno) | |
+ if orig_termios && LibC.tcsetattr(self.fileno, LibC::TCSANOW, orig_termios) != 0 | |
+ raise SystemCallError.new(path, FFI.errno) | |
end | |
end | |
end | |
private :ttymode_yield | |
- TTY_RAW = Proc.new do |t| | |
+ TTY_RAW = Proc.new do |t, min: 1, time: nil, intr: nil| | |
LibC.cfmakeraw(t) | |
t[:c_lflag] &= ~(LibC::ECHOE|LibC::ECHOK) | |
+ if min >= 0 | |
+ t[:c_cc][LibC::VMIN] = min | |
+ end | |
+ t[:c_cc][LibC::VTIME] = (time&.to_i || 0) * 10 | |
+ if intr | |
+ t[:c_iflag] |= LibC::BRKINT | |
+ t[:c_lflag] |= LibC::ISIG | |
+ t[:c_oflag] |= LibC::OPOST | |
+ end | |
end | |
- def raw(*, &block) | |
- ttymode_yield(block, &TTY_RAW) | |
+ def raw(*, **kwargs, &block) | |
+ ttymode_yield(block, **kwargs, &TTY_RAW) | |
end | |
def raw!(*) | |
@@ -93,13 +102,25 @@ class IO | |
end | |
def winsize=(size) | |
+ size = size.to_ary unless size.kind_of?(Array) | |
+ sizelen = size.size | |
+ | |
+ if sizelen != 2 && sizelen != 4 | |
+ raise ArgumentError.new("wrong number of arguments (given #{sizelen}, expected 2 or 4)") | |
+ end | |
+ | |
+ row, col, xpixel, ypixel = size | |
+ | |
ws = LibC::Winsize.new | |
if LibC.ioctl(self.fileno, LibC::TIOCGWINSZ, :pointer, ws.pointer) != 0 | |
raise SystemCallError.new("ioctl(TIOCGWINSZ)", FFI.errno) | |
end | |
- ws[:ws_row] = size[0] | |
- ws[:ws_col] = size[1] | |
+ ws[:ws_row] = row | |
+ ws[:ws_col] = col | |
+ ws[:ws_xpixel] = xpixel&.to_i || 0 | |
+ ws[:ws_ypixel] = ypixel&.to_i || 0 | |
+ | |
if LibC.ioctl(self.fileno, LibC::TIOCSWINSZ, :pointer, ws.pointer) != 0 | |
raise SystemCallError.new("ioctl(TIOCSWINSZ)", FFI.errno) | |
end | |
@@ -117,6 +138,80 @@ class IO | |
raise SystemCallError.new("tcflush(TCIOFLUSH)", FFI.errno) unless LibC.tcflush(self.fileno, LibC::TCIOFLUSH) == 0 | |
end | |
+ def cursor | |
+ raw do | |
+ syswrite "\e[6n" | |
+ | |
+ return nil if getbyte != 0x1b | |
+ return nil if getbyte != ?[.ord | |
+ | |
+ num = 0 | |
+ result = [] | |
+ | |
+ while b = getbyte | |
+ c = b.to_i | |
+ if c == ?;.ord | |
+ result.push num | |
+ num = 0 | |
+ elsif c >= ?0.ord && c <= ?9.ord | |
+ num = num * 10 + c - ?0.ord | |
+ #elsif opt && c == opt | |
+ else | |
+ last = c | |
+ result.push num | |
+ b = last.chr | |
+ return nil unless b == ?R | |
+ break | |
+ end | |
+ end | |
+ | |
+ result.map(&:pred) | |
+ end | |
+ end | |
+ | |
+ def cursor=(pos) | |
+ pos = pos.to_ary if !pos.kind_of?(Array) | |
+ | |
+ raise "expected 2D coordinates" unless pos.size == 2 | |
+ | |
+ x, y = pos | |
+ syswrite(format("\x1b[%d;%dH", x + 1, y + 1)) | |
+ | |
+ self | |
+ end | |
+ | |
+ def cursor_down(n) | |
+ raw do | |
+ syswrite "\x1b[#{n}B" | |
+ end | |
+ | |
+ self | |
+ end | |
+ | |
+ def cursor_right(n) | |
+ raw do | |
+ syswrite "\x1b[#{n}C" | |
+ end | |
+ | |
+ self | |
+ end | |
+ | |
+ def cursor_left(n) | |
+ raw do | |
+ syswrite "\x1b[#{n}D" | |
+ end | |
+ | |
+ self | |
+ end | |
+ | |
+ def cursor_up(n) | |
+ raw do | |
+ syswrite "\x1b[#{n}A" | |
+ end | |
+ | |
+ self | |
+ end | |
+ | |
# TODO: Windows version uses "conin$" and "conout$" instead of /dev/tty | |
def self.console(sym = nil, *args) | |
raise TypeError, "expected Symbol, got #{sym.class}" unless sym.nil? || sym.kind_of?(Symbol) | |
@@ -141,8 +236,13 @@ class IO | |
end | |
end | |
- if !con && $stdin.tty? | |
- con = File.open('/dev/tty', 'r+') | |
+ if !con | |
+ begin | |
+ con = File.open('/dev/tty', 'r+') | |
+ rescue | |
+ return nil | |
+ end | |
+ | |
con.sync = true | |
@console = con | |
end | |
diff --git a/lib/ruby/stdlib/io/console/jruby/stty_console.rb b/lib/ruby/stdlib/io/console/ffi/stty_console.rb | |
similarity index 78% | |
rename from lib/ruby/stdlib/io/console/jruby/stty_console.rb | |
rename to lib/ruby/stdlib/io/console/ffi/stty_console.rb | |
index 1832a9a85a..95a22a0e56 100644 | |
--- a/lib/ruby/stdlib/io/console/jruby/stty_console.rb | |
+++ b/lib/ruby/stdlib/io/console/ffi/stty_console.rb | |
@@ -68,7 +68,20 @@ class IO | |
end | |
def winsize=(size) | |
- stty("rows #{size[0]} cols #{size[1]}") | |
+ size = size.to_ary unless size.kind_of?(Array) | |
+ sizelen = size.size | |
+ | |
+ if sizelen != 2 && sizelen != 4 | |
+ raise ArgumentError.new("wrong number of arguments (given #{sizelen}, expected 2 or 4)") | |
+ end | |
+ | |
+ row, col, xpixel, ypixel = size | |
+ | |
+ if sizelen == 4 | |
+ warn "stty io/console does not support pixel winsize" | |
+ end | |
+ | |
+ stty("rows #{row} cols #{col}") | |
end | |
def iflush | |
@@ -79,4 +92,4 @@ class IO | |
def ioflush | |
end | |
-end | |
\ No newline at end of file | |
+end | |
diff --git a/lib/ruby/stdlib/io/console/jruby/stub_console.rb b/lib/ruby/stdlib/io/console/ffi/stub_console.rb | |
similarity index 99% | |
rename from lib/ruby/stdlib/io/console/jruby/stub_console.rb | |
rename to lib/ruby/stdlib/io/console/ffi/stub_console.rb | |
index 2ebe36ca8c..d2407b69e6 100644 | |
--- a/lib/ruby/stdlib/io/console/jruby/stub_console.rb | |
+++ b/lib/ruby/stdlib/io/console/ffi/stub_console.rb | |
@@ -42,4 +42,4 @@ class IO | |
def ioflush | |
end | |
-end | |
\ No newline at end of file | |
+end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment