Skip to content

Commit

Permalink
Fix size detection from IO to skip loading io-console on non-TTY output
Browse files Browse the repository at this point in the history
  • Loading branch information
piotrmurach committed Nov 30, 2023
1 parent 314fbdc commit a40f254
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Fixed
* Fix ioctl call test to stub terminal size encoding for big-endian systems
* Fix to skip terminal size detection from readline on non-TTY output
* Fix size detection from IO to skip loading io-console on non-TTY output

## [v0.8.1] - 2020-07-17

Expand Down
7 changes: 4 additions & 3 deletions lib/tty/screen.rb
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,12 @@ def size_from_java(verbose: false); nil end
#
# @api private
def size_from_io_console(verbose: false)
require "io/console" unless IO.method_defined?(:winsize)
return unless output.tty?

return unless @output.tty? && @output.respond_to?(:winsize)
require "io/console" unless IO.method_defined?(:winsize)
return unless output.respond_to?(:winsize)

size = @output.winsize
size = output.winsize
size if nonzero_column?(size[1])
rescue Errno::EOPNOTSUPP
# no support for winsize on output
Expand Down
64 changes: 48 additions & 16 deletions spec/unit/screen_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,35 +60,67 @@ def java_import(*args); end
end

describe "#size_from_io_console" do
it "calcualtes the size" do
old_output = screen.output
screen.output = StringIO.new
it "doesn't detect size on non-tty output" do
allow(screen.output).to receive(:tty?).and_return(false)

allow(IO).to receive(:method_defined?).with(:winsize) { true }
allow(screen.output).to receive(:tty?) { true }
allow(screen.output).to receive(:respond_to?) { true }
allow(screen.output).to receive(:winsize) { [100, 200] }
expect(screen.size_from_io_console).to eq(nil)
expect(screen.output).to have_received(:tty?)
end

expect(screen.size_from_io_console).to eq([100, 200])
expect(screen.output).to have_received(:winsize)
it "doesn't detect size when the io/console fails to load" do
allow(screen.output).to receive(:tty?).and_return(true)
allow(IO).to receive(:method_defined?).with(:winsize).and_return(false)
allow(screen).to receive(:require).with("io/console").and_raise(LoadError)

screen.output = old_output
expect(screen.size_from_io_console).to eq(nil)
expect(IO).to have_received(:method_defined?).with(:winsize)
expect(screen).to have_received(:require).with("io/console")
end

it "doesn't calculate size if io/console not available" do
it "warns in verbose mode when the io/console fails to load" do
allow(screen.output).to receive(:tty?).and_return(true)
allow(IO).to receive(:method_defined?).with(:winsize).and_return(false)
allow(screen).to receive(:require).with("io/console").and_raise(LoadError)

expect {
screen.size_from_io_console(verbose: true)
}.to output("no native io/console support or io-console gem\n").to_stderr
end

it "doesn't detect size when the winsize method is missing" do
allow(screen.output).to receive(:tty?).and_return(true)
allow(IO).to receive(:method_defined?).with(:winsize).and_return(true)
allow(screen.output).to receive(:respond_to?)
.with(:winsize).and_return(false)

expect(screen.size_from_io_console).to eq(nil)
expect(screen.output).to have_received(:respond_to?).with(:winsize)
end

it "doesn't detect size when the winsize method raises an error" do
allow(IO).to receive(:method_defined?).with(:winsize).and_return(true)
allow(screen.output).to receive_messages(tty?: true, respond_to?: true)
allow(screen.output).to receive(:winsize).and_raise(Errno::EOPNOTSUPP)

expect(screen.size_from_io_console).to eq(nil)
expect(screen.output).to have_received(:winsize)
end

it "doesn't calculate size if it is run without a console" do
allow(IO).to receive(:method_defined?).with(:winsize) { true }
allow(screen).to receive(:require).with("io/console") { true }
allow(screen.output).to receive(:tty?) { true }
allow(screen.output).to receive(:respond_to?).with(:winsize) { false }
it "detects no columns" do
allow(IO).to receive(:method_defined?).with(:winsize).and_return(true)
allow(screen.output).to receive_messages(
tty?: true, respond_to?: true, winsize: [51, 0])

expect(screen.size_from_io_console).to eq(nil)
expect(screen.output).to have_received(:winsize)
end

it "detects size" do
allow(IO).to receive(:method_defined?).with(:winsize).and_return(true)
allow(screen.output).to receive_messages(
tty?: true, respond_to?: true, winsize: [51, 211])

expect(screen.size_from_io_console).to eq([51, 211])
end
end

Expand Down

0 comments on commit a40f254

Please sign in to comment.