io-console 0.5.7-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +46 -0
- data/jruby/io/console.rb +67 -0
- data/jruby/io/console/bsd_console.rb +166 -0
- data/jruby/io/console/common.rb +35 -0
- data/jruby/io/console/linux_console.rb +200 -0
- data/jruby/io/console/native_console.rb +153 -0
- data/jruby/io/console/stty_console.rb +82 -0
- data/jruby/io/console/stub_console.rb +45 -0
- data/lib/io/console/size.rb +23 -0
- metadata +55 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 1493164f1796b8bd1a67e9263d12de32cce6fc7135c6f4eb3603ea19ee3d1152
|
|
4
|
+
data.tar.gz: a1c28fb7e965635d4b039aa5ff672833818116885daae8a6b3224d153144df2f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 1a8a824c8cdefab44e2e6276faedc1911e035f9fccf2853e09fe2ae35484fdf9aaa61bbfee474aac55b41d7cdd2f210037fc13c188ba453fb2c2d92cdc59799a
|
|
7
|
+
data.tar.gz: 82cdc2b38f9ab9975766cfd36920373fb7af1fd9bb1fb6166963551a0ffc2feb03f252d9fd57fd3864b5314f60821098bfab9ad9cdd678d222859eb8b5057388
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
|
|
2
|
+
|
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
|
4
|
+
modification, are permitted provided that the following conditions
|
|
5
|
+
are met:
|
|
6
|
+
1. Redistributions of source code must retain the above copyright
|
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
|
10
|
+
documentation and/or other materials provided with the distribution.
|
|
11
|
+
|
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
13
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
14
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
15
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
16
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
17
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
18
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
19
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
20
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
21
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
22
|
+
SUCH DAMAGE.
|
data/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# IO.console
|
|
2
|
+
|
|
3
|
+
Add console capabilities to IO instances.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add this line to your application's Gemfile:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'io-console'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
And then execute:
|
|
14
|
+
|
|
15
|
+
$ bundle
|
|
16
|
+
|
|
17
|
+
Or install it yourself as:
|
|
18
|
+
|
|
19
|
+
$ gem install io-console
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
require 'io/console'
|
|
25
|
+
|
|
26
|
+
IO.console -> #<File:/dev/tty>
|
|
27
|
+
IO.console(sym, *args)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Returns a File instance opened console.
|
|
31
|
+
|
|
32
|
+
If `sym` is given, it will be sent to the opened console with `args` and the result will be returned instead of the console IO itself.
|
|
33
|
+
|
|
34
|
+
## Development
|
|
35
|
+
|
|
36
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
37
|
+
|
|
38
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
39
|
+
|
|
40
|
+
## Contributing
|
|
41
|
+
|
|
42
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/io-console.
|
|
43
|
+
|
|
44
|
+
## License
|
|
45
|
+
|
|
46
|
+
The gem is available as open source under the terms of the [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause).
|
data/jruby/io/console.rb
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# This implementation of io/console is a little hacky. It shells out to `stty`
|
|
2
|
+
# for most operations, which does not work on Windows, in secured environments,
|
|
3
|
+
# and so on. In addition, because on Java 6 we can't actually launch
|
|
4
|
+
# subprocesses with tty control, stty will not actually manipulate the
|
|
5
|
+
# controlling terminal.
|
|
6
|
+
#
|
|
7
|
+
# For platforms where shelling to stty does not work, most operations will
|
|
8
|
+
# just be pass-throughs. This allows them to function, but does not actually
|
|
9
|
+
# change any tty flags.
|
|
10
|
+
#
|
|
11
|
+
# Finally, since we're using stty to shell out, we can only manipulate stdin/
|
|
12
|
+
# stdout tty rather than manipulating whatever terminal is actually associated
|
|
13
|
+
# with the IO we're calling against. This will produce surprising results if
|
|
14
|
+
# anyone is actually using io/console against non-stdio ttys...but that case
|
|
15
|
+
# seems like it would be pretty rare.
|
|
16
|
+
#
|
|
17
|
+
# Note: we are incorporating this into 1.7.0 since RubyGems uses io/console
|
|
18
|
+
# when pushing gems, in order to mask the password entry. Worst case is that
|
|
19
|
+
# we don't actually disable echo and the password is shown...we will try to
|
|
20
|
+
# do a better version of this in 1.7.1.
|
|
21
|
+
|
|
22
|
+
require 'rbconfig'
|
|
23
|
+
|
|
24
|
+
require_relative 'console/common'
|
|
25
|
+
|
|
26
|
+
# If Windows, always use the stub version
|
|
27
|
+
if RbConfig::CONFIG['host_os'] =~ /(mswin)|(win32)|(ming)/
|
|
28
|
+
require_relative 'console/stub_console'
|
|
29
|
+
else
|
|
30
|
+
|
|
31
|
+
# If Linux or BSD, try to load the native version
|
|
32
|
+
if RbConfig::CONFIG['host_os'].downcase =~ /darwin|openbsd|freebsd|netbsd|linux/
|
|
33
|
+
begin
|
|
34
|
+
|
|
35
|
+
# Attempt to load the native Linux and BSD console logic
|
|
36
|
+
require_relative 'console/native_console'
|
|
37
|
+
ready = true
|
|
38
|
+
|
|
39
|
+
rescue Exception => ex
|
|
40
|
+
|
|
41
|
+
warn "failed to load native console support: #{ex}" if $VERBOSE
|
|
42
|
+
ready = false
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Native failed, try to use stty
|
|
48
|
+
if !ready
|
|
49
|
+
begin
|
|
50
|
+
|
|
51
|
+
require_relative 'console/stty_console'
|
|
52
|
+
ready = true
|
|
53
|
+
|
|
54
|
+
rescue Exception
|
|
55
|
+
|
|
56
|
+
warn "failed to load stty console support: #{ex}" if $VERBOSE
|
|
57
|
+
ready = false
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# If still not ready, just use stubbed version
|
|
63
|
+
if !ready
|
|
64
|
+
require_relative 'console/stub_console'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
require 'ffi'
|
|
2
|
+
|
|
3
|
+
module IO::LibC
|
|
4
|
+
extend FFI::Library
|
|
5
|
+
ffi_lib FFI::Library::LIBC
|
|
6
|
+
|
|
7
|
+
if RbConfig::CONFIG['host_os'].downcase =~ /darwin/
|
|
8
|
+
typedef :ulong, :tcflag_t
|
|
9
|
+
typedef :ulong, :speed_t
|
|
10
|
+
else
|
|
11
|
+
typedef :uint, :tcflag_t
|
|
12
|
+
typedef :uint, :speed_t
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Special Control Characters
|
|
16
|
+
VEOF = 0 # ICANON
|
|
17
|
+
VEOL = 1 # ICANON
|
|
18
|
+
VEOL2 = 2 # ICANON together with IEXTEN
|
|
19
|
+
VERASE = 3 # ICANON
|
|
20
|
+
VWERASE = 4 # ICANON together with IEXTEN
|
|
21
|
+
VKILL = 5 # ICANON
|
|
22
|
+
VREPRINT = 6 # ICANON together with IEXTEN
|
|
23
|
+
VINTR = 8 # ISIG
|
|
24
|
+
VQUIT = 9 # ISIG
|
|
25
|
+
VSUSP = 10 # ISIG
|
|
26
|
+
VDSUSP = 11 # ISIG together with IEXTEN
|
|
27
|
+
VSTART = 12 # IXON, IXOFF
|
|
28
|
+
VSTOP = 13 # IXON, IXOFF
|
|
29
|
+
VLNEXT = 14 # IEXTEN
|
|
30
|
+
VDISCARD = 15 # IEXTEN
|
|
31
|
+
VMIN = 16 # !ICANON
|
|
32
|
+
VTIME = 17 # !ICANON
|
|
33
|
+
VSTATUS = 18 # ICANON together with IEXTEN
|
|
34
|
+
NCCS = 20
|
|
35
|
+
|
|
36
|
+
# Input flags - software input processing
|
|
37
|
+
IGNBRK = 0x00000001 # ignore BREAK condition
|
|
38
|
+
BRKINT = 0x00000002 # map BREAK to SIGINTR
|
|
39
|
+
IGNPAR = 0x00000004 # ignore (discard) parity errors
|
|
40
|
+
PARMRK = 0x00000008 # mark parity and framing errors
|
|
41
|
+
INPCK = 0x00000010 # enable checking of parity errors
|
|
42
|
+
ISTRIP = 0x00000020 # strip 8th bit off chars
|
|
43
|
+
INLCR = 0x00000040 # map NL into CR
|
|
44
|
+
IGNCR = 0x00000080 # ignore CR
|
|
45
|
+
ICRNL = 0x00000100 # map CR to NL (ala CRMOD)
|
|
46
|
+
IXON = 0x00000200 # enable output flow control
|
|
47
|
+
IXOFF = 0x00000400 # enable input flow control
|
|
48
|
+
IXANY = 0x00000800 # any char will restart after stop
|
|
49
|
+
IMAXBEL = 0x00002000 # ring bell on input queue full
|
|
50
|
+
IUTF8 = 0x00004000 # maintain state for UTF-8 VERASE
|
|
51
|
+
|
|
52
|
+
# Output flags - software output processing
|
|
53
|
+
OPOST = 0x00000001 # enable following output processing
|
|
54
|
+
ONLCR = 0x00000002 # map NL to CR-NL (ala CRMOD)
|
|
55
|
+
OXTABS = 0x00000004 # expand tabs to spaces
|
|
56
|
+
ONOEOT = 0x00000008 # discard EOT's (^D) on output)
|
|
57
|
+
OCRNL = 0x00000010 # map CR to NL on output
|
|
58
|
+
ONOCR = 0x00000020 # no CR output at column 0
|
|
59
|
+
ONLRET = 0x00000040 # NL performs CR function
|
|
60
|
+
|
|
61
|
+
# Control flags - hardware control of terminal
|
|
62
|
+
CIGNORE = 0x00000001 # ignore control flags
|
|
63
|
+
CSIZE = 0x00000300 # character size mask
|
|
64
|
+
CS5 = 0x00000000 # 5 bits (pseudo)
|
|
65
|
+
CS6 = 0x00000100 # 6 bits
|
|
66
|
+
CS7 = 0x00000200 # 7 bits
|
|
67
|
+
CS8 = 0x00000300 # 8 bits
|
|
68
|
+
CSTOPB = 0x00000400 # send 2 stop bits
|
|
69
|
+
CREAD = 0x00000800 # enable receiver
|
|
70
|
+
PARENB = 0x00001000 # parity enable
|
|
71
|
+
PARODD = 0x00002000 # odd parity, else even
|
|
72
|
+
HUPCL = 0x00004000 # hang up on last close
|
|
73
|
+
CLOCAL = 0x00008000 # ignore modem status lines
|
|
74
|
+
CCTS_OFLOW = 0x00010000 # CTS flow control of output
|
|
75
|
+
CRTS_IFLOW = 0x00020000 # RTS flow control of input
|
|
76
|
+
CDTR_IFLOW = 0x00040000 # DTR flow control of input
|
|
77
|
+
CDSR_OFLOW = 0x00080000 # DSR flow control of output
|
|
78
|
+
CCAR_OFLOW = 0x00100000 # DCD flow control of output
|
|
79
|
+
CRTSCTS = CCTS_OFLOW | CRTS_IFLOW
|
|
80
|
+
MDMBUF = 0x00100000 # old name for CCAR_OFLOW
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# "Local" flags - dumping ground for other state
|
|
84
|
+
ECHOKE = 0x00000001 # visual erase for line kill
|
|
85
|
+
ECHOE = 0x00000002 # visually erase chars
|
|
86
|
+
ECHOK = 0x00000004 # echo NL after line kill
|
|
87
|
+
ECHO = 0x00000008 # enable echoing
|
|
88
|
+
ECHONL = 0x00000010 # echo NL even if ECHO is off
|
|
89
|
+
ECHOPRT = 0x00000020 # visual erase mode for hardcopy
|
|
90
|
+
ECHOCTL = 0x00000040 # echo control chars as ^(Char)
|
|
91
|
+
ISIG = 0x00000080 # enable signals INTR, QUIT, [D]SUSP
|
|
92
|
+
ICANON = 0x00000100 # canonicalize input lines
|
|
93
|
+
ALTWERASE = 0x00000200 # use alternate WERASE algorithm
|
|
94
|
+
IEXTEN = 0x00000400 # enable DISCARD and LNEXT
|
|
95
|
+
EXTPROC = 0x00000800 # external processing
|
|
96
|
+
TOSTOP = 0x00400000 # stop background jobs from output
|
|
97
|
+
FLUSHO = 0x00800000 # output being flushed (state)
|
|
98
|
+
NOKERNINFO = 0x02000000 # no kernel output from VSTATUS
|
|
99
|
+
PENDIN = 0x20000000 # XXX retype pending input (state)
|
|
100
|
+
NOFLSH = 0x80000000 # don't flush after interrupt
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# Commands passed to tcsetattr() for setting the termios structure.
|
|
104
|
+
TCSANOW = 0 # make change immediate
|
|
105
|
+
TCSADRAIN = 1 # drain output, then change
|
|
106
|
+
TCSAFLUSH = 2 # drain output, flush input
|
|
107
|
+
TCSASOFT = 0x10 # flag - don't alter h.w. state
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
TCIFLUSH = 1
|
|
111
|
+
TCOFLUSH = 2
|
|
112
|
+
TCIOFLUSH = 3
|
|
113
|
+
TCOOFF = 1
|
|
114
|
+
TCOON = 2
|
|
115
|
+
TCIOFF = 3
|
|
116
|
+
TCION = 4
|
|
117
|
+
|
|
118
|
+
IOCPARM_MASK = 0x1fff
|
|
119
|
+
IOC_OUT = 0x40000000
|
|
120
|
+
IOC_IN = 0x80000000
|
|
121
|
+
|
|
122
|
+
def self._IOC(inout,group,num,len)
|
|
123
|
+
inout | ((len & IOCPARM_MASK) << 16) | ((group.ord << 8) | num)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def self._IOR(g,n,t)
|
|
127
|
+
self._IOC(IOC_OUT, g, n, find_type(t).size)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def self._IOW(g,n,t)
|
|
131
|
+
self._IOC(IOC_IN, g, n, find_type(t).size)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class Termios < FFI::Struct
|
|
136
|
+
layout \
|
|
137
|
+
:c_iflag, :tcflag_t,
|
|
138
|
+
:c_oflag, :tcflag_t,
|
|
139
|
+
:c_cflag, :tcflag_t,
|
|
140
|
+
:c_lflag, :tcflag_t,
|
|
141
|
+
:cc_c, [ :uchar, NCCS ],
|
|
142
|
+
:c_ispeed, :speed_t,
|
|
143
|
+
:c_ospeed, :speed_t
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
class Winsize < FFI::Struct
|
|
147
|
+
layout \
|
|
148
|
+
:ws_row, :ushort,
|
|
149
|
+
:ws_col, :ushort,
|
|
150
|
+
:ws_xpixel, :ushort,
|
|
151
|
+
:ws_ypixel, :ushort
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
TIOCGWINSZ = _IOR('t', 104, Winsize) # get window size
|
|
155
|
+
TIOCSWINSZ = _IOW('t', 103, Winsize) # set window size
|
|
156
|
+
|
|
157
|
+
attach_function :tcsetattr, [ :int, :int, Termios ], :int
|
|
158
|
+
attach_function :tcgetattr, [ :int, Termios ], :int
|
|
159
|
+
attach_function :cfgetispeed, [ Termios ], :speed_t
|
|
160
|
+
attach_function :cfgetospeed, [ Termios ], :speed_t
|
|
161
|
+
attach_function :cfsetispeed, [ Termios, :speed_t ], :int
|
|
162
|
+
attach_function :cfsetospeed, [ Termios, :speed_t ], :int
|
|
163
|
+
attach_function :cfmakeraw, [ Termios ], :int
|
|
164
|
+
attach_function :tcflush, [ :int, :int ], :int
|
|
165
|
+
attach_function :ioctl, [ :int, :ulong, :varargs ], :int
|
|
166
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Methods common to all backend impls
|
|
2
|
+
class IO
|
|
3
|
+
def getch(*)
|
|
4
|
+
raw do
|
|
5
|
+
getc
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def getpass(prompt = nil)
|
|
10
|
+
wio = self == $stdin ? $stderr : self
|
|
11
|
+
wio.write(prompt) if prompt
|
|
12
|
+
begin
|
|
13
|
+
str = nil
|
|
14
|
+
noecho do
|
|
15
|
+
str = gets
|
|
16
|
+
end
|
|
17
|
+
ensure
|
|
18
|
+
puts($/)
|
|
19
|
+
end
|
|
20
|
+
str.chomp
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module GenericReadable
|
|
24
|
+
def getch(*)
|
|
25
|
+
getc
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def getpass(prompt = nil)
|
|
29
|
+
write(prompt) if prompt
|
|
30
|
+
str = gets.chomp
|
|
31
|
+
puts($/)
|
|
32
|
+
str
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
require 'ffi'
|
|
2
|
+
|
|
3
|
+
raise LoadError.new("native console only supported on i386, x86_64 and powerpc64") unless FFI::Platform::ARCH =~ /i386|x86_64|powerpc64/
|
|
4
|
+
|
|
5
|
+
module IO::LibC
|
|
6
|
+
extend FFI::Library
|
|
7
|
+
ffi_lib FFI::Library::LIBC
|
|
8
|
+
|
|
9
|
+
typedef :uint, :tcflag_t
|
|
10
|
+
typedef :uint, :speed_t
|
|
11
|
+
|
|
12
|
+
VINTR = 0
|
|
13
|
+
VQUIT = 1
|
|
14
|
+
VERASE = 2
|
|
15
|
+
VKILL = 3
|
|
16
|
+
VEOF = 4
|
|
17
|
+
VTIME = 5
|
|
18
|
+
VMIN = 6
|
|
19
|
+
VSWTC = 7
|
|
20
|
+
VSTART = 8
|
|
21
|
+
VSTOP = 9
|
|
22
|
+
VSUSP = 10
|
|
23
|
+
VEOL = 11
|
|
24
|
+
VREPRINT = 12
|
|
25
|
+
VDISCARD = 13
|
|
26
|
+
VWERASE = 14
|
|
27
|
+
VLNEXT = 15
|
|
28
|
+
VEOL2 = 16
|
|
29
|
+
|
|
30
|
+
# c_iflag bits
|
|
31
|
+
IGNBRK = 0000001
|
|
32
|
+
BRKINT = 0000002
|
|
33
|
+
IGNPAR = 0000004
|
|
34
|
+
PARMRK = 0000010
|
|
35
|
+
INPCK = 0000020
|
|
36
|
+
ISTRIP = 0000040
|
|
37
|
+
INLCR = 0000100
|
|
38
|
+
IGNCR = 0000200
|
|
39
|
+
ICRNL = 0000400
|
|
40
|
+
IUCLC = 0001000
|
|
41
|
+
IXON = 0002000
|
|
42
|
+
IXANY = 0004000
|
|
43
|
+
IXOFF = 0010000
|
|
44
|
+
IMAXBEL = 0020000
|
|
45
|
+
IUTF8 = 0040000
|
|
46
|
+
|
|
47
|
+
# c_oflag bits
|
|
48
|
+
OPOST = 0000001
|
|
49
|
+
OLCUC = 0000002
|
|
50
|
+
ONLCR = 0000004
|
|
51
|
+
OCRNL = 0000010
|
|
52
|
+
ONOCR = 0000020
|
|
53
|
+
ONLRET = 0000040
|
|
54
|
+
OFILL = 0000100
|
|
55
|
+
OFDEL = 0000200
|
|
56
|
+
NLDLY = 0000400
|
|
57
|
+
NL0 = 0000000
|
|
58
|
+
NL1 = 0000400
|
|
59
|
+
CRDLY = 0003000
|
|
60
|
+
CR0 = 0000000
|
|
61
|
+
CR1 = 0001000
|
|
62
|
+
CR2 = 0002000
|
|
63
|
+
CR3 = 0003000
|
|
64
|
+
TABDLY = 0014000
|
|
65
|
+
TAB0 = 0000000
|
|
66
|
+
TAB1 = 0004000
|
|
67
|
+
TAB2 = 0010000
|
|
68
|
+
TAB3 = 0014000
|
|
69
|
+
XTABS = 0014000
|
|
70
|
+
BSDLY = 0020000
|
|
71
|
+
BS0 = 0000000
|
|
72
|
+
BS1 = 0020000
|
|
73
|
+
VTDLY = 0040000
|
|
74
|
+
VT0 = 0000000
|
|
75
|
+
VT1 = 0040000
|
|
76
|
+
FFDLY = 0100000
|
|
77
|
+
FF0 = 0000000
|
|
78
|
+
FF1 = 0100000
|
|
79
|
+
|
|
80
|
+
# c_cflag bit meaning
|
|
81
|
+
CBAUD = 0010017
|
|
82
|
+
B0 = 0000000
|
|
83
|
+
B50 = 0000001
|
|
84
|
+
B75 = 0000002
|
|
85
|
+
B110 = 0000003
|
|
86
|
+
B134 = 0000004
|
|
87
|
+
B150 = 0000005
|
|
88
|
+
B200 = 0000006
|
|
89
|
+
B300 = 0000007
|
|
90
|
+
B600 = 0000010
|
|
91
|
+
B1200 = 0000011
|
|
92
|
+
B1800 = 0000012
|
|
93
|
+
B2400 = 0000013
|
|
94
|
+
B4800 = 0000014
|
|
95
|
+
B9600 = 0000015
|
|
96
|
+
B19200 = 0000016
|
|
97
|
+
B38400 = 0000017
|
|
98
|
+
EXTA = B19200
|
|
99
|
+
EXTB = B38400
|
|
100
|
+
CSIZE = 0000060
|
|
101
|
+
CS5 = 0000000
|
|
102
|
+
CS6 = 0000020
|
|
103
|
+
CS7 = 0000040
|
|
104
|
+
CS8 = 0000060
|
|
105
|
+
CSTOPB = 0000100
|
|
106
|
+
CREAD = 0000200
|
|
107
|
+
PARENB = 0000400
|
|
108
|
+
PARODD = 0001000
|
|
109
|
+
HUPCL = 0002000
|
|
110
|
+
CLOCAL = 0004000
|
|
111
|
+
CBAUDEX = 0010000
|
|
112
|
+
BOTHER = 0010000
|
|
113
|
+
B57600 = 0010001
|
|
114
|
+
B115200 = 0010002
|
|
115
|
+
B230400 = 0010003
|
|
116
|
+
B460800 = 0010004
|
|
117
|
+
B500000 = 0010005
|
|
118
|
+
B576000 = 0010006
|
|
119
|
+
B921600 = 0010007
|
|
120
|
+
B1000000 = 0010010
|
|
121
|
+
B1152000 = 0010011
|
|
122
|
+
B1500000 = 0010012
|
|
123
|
+
B2000000 = 0010013
|
|
124
|
+
B2500000 = 0010014
|
|
125
|
+
B3000000 = 0010015
|
|
126
|
+
B3500000 = 0010016
|
|
127
|
+
B4000000 = 0010017
|
|
128
|
+
CIBAUD = 002003600000
|
|
129
|
+
CMSPAR = 010000000000
|
|
130
|
+
CRTSCTS = 020000000000
|
|
131
|
+
|
|
132
|
+
IBSHIFT = 16
|
|
133
|
+
|
|
134
|
+
# c_lflag bits
|
|
135
|
+
ISIG = 0000001
|
|
136
|
+
ICANON = 0000002
|
|
137
|
+
XCASE = 0000004
|
|
138
|
+
ECHO = 0000010
|
|
139
|
+
ECHOE = 0000020
|
|
140
|
+
ECHOK = 0000040
|
|
141
|
+
ECHONL = 0000100
|
|
142
|
+
NOFLSH = 0000200
|
|
143
|
+
TOSTOP = 0000400
|
|
144
|
+
ECHOCTL = 0001000
|
|
145
|
+
ECHOPRT = 0002000
|
|
146
|
+
ECHOKE = 0004000
|
|
147
|
+
FLUSHO = 0010000
|
|
148
|
+
PENDIN = 0040000
|
|
149
|
+
IEXTEN = 0100000
|
|
150
|
+
|
|
151
|
+
# tcflow() and TCXONC use these
|
|
152
|
+
TCOOFF = 0
|
|
153
|
+
TCOON = 1
|
|
154
|
+
TCIOFF = 2
|
|
155
|
+
TCION = 3
|
|
156
|
+
|
|
157
|
+
# tcflush() and TCFLSH use these
|
|
158
|
+
TCIFLUSH = 0
|
|
159
|
+
TCOFLUSH = 1
|
|
160
|
+
TCIOFLUSH = 2
|
|
161
|
+
|
|
162
|
+
# tcsetattr uses these
|
|
163
|
+
TCSANOW = 0
|
|
164
|
+
TCSADRAIN = 1
|
|
165
|
+
TCSAFLUSH = 2
|
|
166
|
+
NCCS = 32
|
|
167
|
+
class Termios < FFI::Struct
|
|
168
|
+
layout \
|
|
169
|
+
:c_iflag, :tcflag_t,
|
|
170
|
+
:c_oflag, :tcflag_t,
|
|
171
|
+
:c_cflag, :tcflag_t,
|
|
172
|
+
:c_lflag, :tcflag_t,
|
|
173
|
+
:c_line, :uchar,
|
|
174
|
+
:cc_c, [ :uchar, NCCS ],
|
|
175
|
+
:c_ispeed, :speed_t,
|
|
176
|
+
:c_ospeed, :speed_t
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
class Winsize < FFI::Struct
|
|
180
|
+
layout \
|
|
181
|
+
:ws_row, :ushort,
|
|
182
|
+
:ws_col, :ushort,
|
|
183
|
+
:ws_xpixel, :ushort,
|
|
184
|
+
:ws_ypixel, :ushort
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
TIOCGWINSZ = 0x5413
|
|
189
|
+
TIOCSWINSZ = 0x5414
|
|
190
|
+
|
|
191
|
+
attach_function :tcsetattr, [ :int, :int, Termios ], :int
|
|
192
|
+
attach_function :tcgetattr, [ :int, Termios ], :int
|
|
193
|
+
attach_function :cfgetispeed, [ Termios ], :speed_t
|
|
194
|
+
attach_function :cfgetospeed, [ Termios ], :speed_t
|
|
195
|
+
attach_function :cfsetispeed, [ Termios, :speed_t ], :int
|
|
196
|
+
attach_function :cfsetospeed, [ Termios, :speed_t ], :int
|
|
197
|
+
attach_function :cfmakeraw, [ Termios ], :int
|
|
198
|
+
attach_function :tcflush, [ :int, :int ], :int
|
|
199
|
+
attach_function :ioctl, [ :int, :ulong, :varargs ], :int
|
|
200
|
+
end
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Load appropriate native bits for BSD or Linux
|
|
2
|
+
case RbConfig::CONFIG['host_os'].downcase
|
|
3
|
+
when /darwin|openbsd|freebsd|netbsd/
|
|
4
|
+
require_relative 'bsd_console'
|
|
5
|
+
when /linux/
|
|
6
|
+
require_relative 'linux_console'
|
|
7
|
+
else
|
|
8
|
+
raise LoadError.new("no native io/console support")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Common logic that uses native calls for console
|
|
12
|
+
class IO
|
|
13
|
+
def ttymode
|
|
14
|
+
termios = LibC::Termios.new
|
|
15
|
+
if LibC.tcgetattr(self.fileno, termios) != 0
|
|
16
|
+
raise SystemCallError.new("tcgetattr", FFI.errno)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
if block_given?
|
|
20
|
+
yield tmp = termios.dup
|
|
21
|
+
if LibC.tcsetattr(self.fileno, LibC::TCSADRAIN, tmp) != 0
|
|
22
|
+
raise SystemCallError.new("tcsetattr", FFI.errno)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
termios
|
|
26
|
+
end
|
|
27
|
+
private :ttymode
|
|
28
|
+
|
|
29
|
+
def ttymode_yield(block, &setup)
|
|
30
|
+
begin
|
|
31
|
+
orig_termios = ttymode { |t| setup.call(t) }
|
|
32
|
+
block.call(self)
|
|
33
|
+
ensure
|
|
34
|
+
if orig_termios && LibC.tcsetattr(self.fileno, LibC::TCSADRAIN, orig_termios) != 0
|
|
35
|
+
raise SystemCallError.new("tcsetattr", FFI.errno)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
private :ttymode_yield
|
|
40
|
+
|
|
41
|
+
TTY_RAW = Proc.new do |t|
|
|
42
|
+
LibC.cfmakeraw(t)
|
|
43
|
+
t[:c_lflag] &= ~(LibC::ECHOE|LibC::ECHOK)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def raw(*, &block)
|
|
47
|
+
ttymode_yield(block, &TTY_RAW)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def raw!(*)
|
|
51
|
+
ttymode(&TTY_RAW)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
TTY_COOKED = Proc.new do |t|
|
|
55
|
+
t[:c_iflag] |= (LibC::BRKINT|LibC::ISTRIP|LibC::ICRNL|LibC::IXON)
|
|
56
|
+
t[:c_oflag] |= LibC::OPOST
|
|
57
|
+
t[:c_lflag] |= (LibC::ECHO|LibC::ECHOE|LibC::ECHOK|LibC::ECHONL|LibC::ICANON|LibC::ISIG|LibC::IEXTEN)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def cooked(*, &block)
|
|
61
|
+
ttymode_yield(block, &TTY_COOKED)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def cooked!(*)
|
|
65
|
+
ttymode(&TTY_COOKED)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
TTY_ECHO = LibC::ECHO | LibC::ECHOE | LibC::ECHOK | LibC::ECHONL
|
|
69
|
+
def echo=(echo)
|
|
70
|
+
ttymode do |t|
|
|
71
|
+
if echo
|
|
72
|
+
t[:c_lflag] |= TTY_ECHO
|
|
73
|
+
else
|
|
74
|
+
t[:c_lflag] &= ~TTY_ECHO
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def echo?
|
|
80
|
+
(ttymode[:c_lflag] & (LibC::ECHO | LibC::ECHONL)) != 0
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def noecho(&block)
|
|
84
|
+
ttymode_yield(block) { |t| t[:c_lflag] &= ~(TTY_ECHO) }
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def winsize
|
|
88
|
+
ws = LibC::Winsize.new
|
|
89
|
+
if LibC.ioctl(self.fileno, LibC::TIOCGWINSZ, :pointer, ws.pointer) != 0
|
|
90
|
+
raise SystemCallError.new("ioctl(TIOCGWINSZ)", FFI.errno)
|
|
91
|
+
end
|
|
92
|
+
[ ws[:ws_row], ws[:ws_col] ]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def winsize=(size)
|
|
96
|
+
ws = LibC::Winsize.new
|
|
97
|
+
if LibC.ioctl(self.fileno, LibC::TIOCGWINSZ, :pointer, ws.pointer) != 0
|
|
98
|
+
raise SystemCallError.new("ioctl(TIOCGWINSZ)", FFI.errno)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
ws[:ws_row] = size[0]
|
|
102
|
+
ws[:ws_col] = size[1]
|
|
103
|
+
if LibC.ioctl(self.fileno, LibC::TIOCSWINSZ, :pointer, ws.pointer) != 0
|
|
104
|
+
raise SystemCallError.new("ioctl(TIOCSWINSZ)", FFI.errno)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def iflush
|
|
109
|
+
raise SystemCallError.new("tcflush(TCIFLUSH)", FFI.errno) unless LibC.tcflush(self.fileno, LibC::TCIFLUSH) == 0
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def oflush
|
|
113
|
+
raise SystemCallError.new("tcflush(TCOFLUSH)", FFI.errno) unless LibC.tcflush(self.fileno, LibC::TCOFLUSH) == 0
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def ioflush
|
|
117
|
+
raise SystemCallError.new("tcflush(TCIOFLUSH)", FFI.errno) unless LibC.tcflush(self.fileno, LibC::TCIOFLUSH) == 0
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# TODO: Windows version uses "conin$" and "conout$" instead of /dev/tty
|
|
121
|
+
def self.console(sym = nil, *args)
|
|
122
|
+
raise TypeError, "expected Symbol, got #{sym.class}" unless sym.nil? || sym.kind_of?(Symbol)
|
|
123
|
+
|
|
124
|
+
# klass = self == IO ? File : self
|
|
125
|
+
if defined?(@console) # using ivar instead of hidden const as in MRI
|
|
126
|
+
con = @console
|
|
127
|
+
# MRI checks IO internals : (!RB_TYPE_P(con, T_FILE) || (!(fptr = RFILE(con)->fptr) || GetReadFD(fptr) == -1))
|
|
128
|
+
if !con.kind_of?(File) || (con.kind_of?(IO) && (con.closed? || !FileTest.readable?(con)))
|
|
129
|
+
remove_instance_variable :@console
|
|
130
|
+
con = nil
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
if sym
|
|
135
|
+
if sym == :close
|
|
136
|
+
if con
|
|
137
|
+
con.close
|
|
138
|
+
remove_instance_variable :@console if defined?(@console)
|
|
139
|
+
end
|
|
140
|
+
return nil
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
if !con && $stdin.tty?
|
|
145
|
+
con = File.open('/dev/tty', 'r+')
|
|
146
|
+
con.sync = true
|
|
147
|
+
@console = con
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
return con.send(sym, *args) if sym
|
|
151
|
+
return con
|
|
152
|
+
end
|
|
153
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# attempt to call stty; if failure, raise error
|
|
2
|
+
`stty 2> /dev/null`
|
|
3
|
+
if $?.exitstatus != 0
|
|
4
|
+
raise "stty command returned nonzero exit status"
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
warn "io/console on JRuby shells out to stty for most operations"
|
|
8
|
+
|
|
9
|
+
# Non-Windows assumes stty command is available
|
|
10
|
+
class IO
|
|
11
|
+
if RbConfig::CONFIG['host_os'].downcase =~ /linux/ && File.exists?("/proc/#{Process.pid}/fd")
|
|
12
|
+
def stty(*args)
|
|
13
|
+
`stty #{args.join(' ')} < /proc/#{Process.pid}/fd/#{fileno}`
|
|
14
|
+
end
|
|
15
|
+
else
|
|
16
|
+
def stty(*args)
|
|
17
|
+
`stty #{args.join(' ')}`
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def raw(*)
|
|
22
|
+
saved = stty('-g')
|
|
23
|
+
stty('raw')
|
|
24
|
+
yield self
|
|
25
|
+
ensure
|
|
26
|
+
stty(saved)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def raw!(*)
|
|
30
|
+
stty('raw')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def cooked(*)
|
|
34
|
+
saved = stty('-g')
|
|
35
|
+
stty('-raw')
|
|
36
|
+
yield self
|
|
37
|
+
ensure
|
|
38
|
+
stty(saved)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def cooked!(*)
|
|
42
|
+
stty('-raw')
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def echo=(echo)
|
|
46
|
+
stty(echo ? 'echo' : '-echo')
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def echo?
|
|
50
|
+
(stty('-a') =~ / -echo /) ? false : true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def noecho
|
|
54
|
+
saved = stty('-g')
|
|
55
|
+
stty('-echo')
|
|
56
|
+
yield self
|
|
57
|
+
ensure
|
|
58
|
+
stty(saved)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Not all systems return same format of stty -a output
|
|
62
|
+
IEEE_STD_1003_2 = '(?<rows>\d+) rows; (?<columns>\d+) columns'
|
|
63
|
+
UBUNTU = 'rows (?<rows>\d+); columns (?<columns>\d+)'
|
|
64
|
+
|
|
65
|
+
def winsize
|
|
66
|
+
match = stty('-a').match(/#{IEEE_STD_1003_2}|#{UBUNTU}/)
|
|
67
|
+
[match[:rows].to_i, match[:columns].to_i]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def winsize=(size)
|
|
71
|
+
stty("rows #{size[0]} cols #{size[1]}")
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def iflush
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def oflush
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def ioflush
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
warn "io/console not supported; tty will not be manipulated" if $VERBOSE
|
|
2
|
+
|
|
3
|
+
# Windows version is always stubbed for now
|
|
4
|
+
class IO
|
|
5
|
+
def raw(*)
|
|
6
|
+
yield self
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def raw!(*)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def cooked(*)
|
|
13
|
+
yield self
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def cooked!(*)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def echo=(echo)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def echo?
|
|
23
|
+
true
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def noecho
|
|
27
|
+
yield self
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def winsize
|
|
31
|
+
[25, 80]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def winsize=(size)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def iflush
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def oflush
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def ioflush
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: false
|
|
2
|
+
# fallback to console window size
|
|
3
|
+
def IO.default_console_size
|
|
4
|
+
[
|
|
5
|
+
ENV["LINES"].to_i.nonzero? || 25,
|
|
6
|
+
ENV["COLUMNS"].to_i.nonzero? || 80,
|
|
7
|
+
]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
begin
|
|
11
|
+
require 'io/console'
|
|
12
|
+
rescue LoadError
|
|
13
|
+
class << IO
|
|
14
|
+
alias console_size default_console_size
|
|
15
|
+
end
|
|
16
|
+
else
|
|
17
|
+
# returns console window size
|
|
18
|
+
def IO.console_size
|
|
19
|
+
console.winsize
|
|
20
|
+
rescue NoMethodError
|
|
21
|
+
default_console_size
|
|
22
|
+
end
|
|
23
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: io-console
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.5.7
|
|
5
|
+
platform: java
|
|
6
|
+
authors:
|
|
7
|
+
- Nobu Nakada
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2021-01-16 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: add console capabilities to IO instances.
|
|
14
|
+
email: nobu@ruby-lang.org
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- LICENSE.txt
|
|
20
|
+
- README.md
|
|
21
|
+
- jruby/io/console.rb
|
|
22
|
+
- jruby/io/console/bsd_console.rb
|
|
23
|
+
- jruby/io/console/common.rb
|
|
24
|
+
- jruby/io/console/linux_console.rb
|
|
25
|
+
- jruby/io/console/native_console.rb
|
|
26
|
+
- jruby/io/console/stty_console.rb
|
|
27
|
+
- jruby/io/console/stub_console.rb
|
|
28
|
+
- lib/io/console/size.rb
|
|
29
|
+
homepage: https://github.com/ruby/io-console
|
|
30
|
+
licenses:
|
|
31
|
+
- Ruby
|
|
32
|
+
- BSD-2-Clause
|
|
33
|
+
metadata:
|
|
34
|
+
source_code_url: https://github.com/ruby/io-console
|
|
35
|
+
post_install_message:
|
|
36
|
+
rdoc_options: []
|
|
37
|
+
require_paths:
|
|
38
|
+
- jruby
|
|
39
|
+
- lib
|
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
41
|
+
requirements:
|
|
42
|
+
- - ">="
|
|
43
|
+
- !ruby/object:Gem::Version
|
|
44
|
+
version: 2.4.0
|
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
46
|
+
requirements:
|
|
47
|
+
- - ">="
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '0'
|
|
50
|
+
requirements: []
|
|
51
|
+
rubygems_version: 3.2.3
|
|
52
|
+
signing_key:
|
|
53
|
+
specification_version: 4
|
|
54
|
+
summary: Console interface
|
|
55
|
+
test_files: []
|