Skip to content

Instantly share code, notes, and snippets.

@headius

headius/.diff Secret

Created March 17, 2021 21:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save headius/a378320ecb89f9fdf2f11ce1019d631d to your computer and use it in GitHub Desktop.
Save headius/a378320ecb89f9fdf2f11ce1019d631d to your computer and use it in GitHub Desktop.
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