Module: TTY::Screen
- Defined in:
- lib/tty/screen.rb,
lib/tty/screen/version.rb
Overview
Responsible for detecting terminal screen size
Constant Summary collapse
- DEFAULT_SIZE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
The default terminal screen size
[27, 80].freeze
- STDOUT_HANDLE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
The standard output handle
0xFFFFFFF5
- TIOCGWINSZ =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
The get window size control code for Linux
0x5413
- TIOCGWINSZ_PPC =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
The get window size control code for FreeBSD and macOS
0x40087468
- TIOCGWINSZ_SOL =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
The get window size control code for Solaris
0x5468
- VERSION =
"0.8.2"
Class Attribute Summary collapse
-
.env ⇒ Enumerable
The environment variables.
-
.output ⇒ IO
The output stream with standard error as default.
Class Method Summary collapse
-
.cols ⇒ Integer
Detect terminal screen width.
-
.columns ⇒ Integer
Detect terminal screen width.
-
.height ⇒ Integer
Detect terminal screen height.
-
.ioctl?(control, buf) ⇒ Boolean
private
Check if the ioctl call gets window size on any standard stream.
- .jruby? ⇒ Object
-
.lines ⇒ Integer
Detect terminal screen height.
-
.private_module_function(name) ⇒ void
private
Define module method as private.
-
.rows ⇒ Integer
Detect terminal screen height.
-
.size(verbose: false) ⇒ Array(Integer, Integer)
Detect terminal screen size.
-
.size_from_ansicon ⇒ Array(Integer, Integer)?
private
Detect terminal screen size from the ANSICON environment variable.
-
.size_from_default ⇒ Array(Integer, Integer)
private
Detect terminal screen size from default.
-
.size_from_env ⇒ Array(Integer, Integer)?
private
Detect terminal screen size from environment variables.
-
.size_from_io_console(verbose: false) ⇒ Array(Integer, Integer)?
private
Detect terminal screen size from io-console.
-
.size_from_ioctl ⇒ Array(Integer, Integer)?
private
Detect terminal screen size from ioctl.
-
.size_from_java(verbose: false) ⇒ Array(Integer, Integer)?
private
Detect terminal screen size from Java.
-
.size_from_readline(verbose: false) ⇒ Array(Integer, Integer)?
private
Detect terminal screen size from readline.
-
.size_from_stty ⇒ Array(Integer, Integer)?
private
Detect terminal screen size from stty.
-
.size_from_tput ⇒ Array(Integer, Integer)?
private
Detect terminal screen size from tput.
-
.size_from_win_api(verbose: false) ⇒ Array(Integer, Integer)?
private
Detect terminal screen size from Windows API.
-
.width ⇒ Integer
Detect terminal screen width.
- .windows? ⇒ Object
Instance Method Summary collapse
-
#command_exist?(command) ⇒ Boolean
private
Check if a command exists.
-
#nonzero_column?(column) ⇒ Boolean
private
Check if a number is non-zero.
-
#run_command(*args) ⇒ String?
private
Run command capturing the standard output.
Class Attribute Details
.env ⇒ Enumerable
The environment variables
81 82 83 |
# File 'lib/tty/screen.rb', line 81 def env @env end |
.output ⇒ IO
The output stream with standard error as default
94 95 96 |
# File 'lib/tty/screen.rb', line 94 def output @output end |
Class Method Details
.cols ⇒ Integer
Detect terminal screen width
134 135 136 |
# File 'lib/tty/screen.rb', line 134 def width size[1] end |
.columns ⇒ Integer
Detect terminal screen width
133 134 135 |
# File 'lib/tty/screen.rb', line 133 def width size[1] end |
.height ⇒ Integer
Detect terminal screen height
146 147 148 |
# File 'lib/tty/screen.rb', line 146 def height size[0] end |
.ioctl?(control, buf) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Check if the ioctl call gets window size on any standard stream
331 332 333 334 335 336 337 |
# File 'lib/tty/screen.rb', line 331 def ioctl?(control, buf) ($stdout.ioctl(control, buf) >= 0) || ($stdin.ioctl(control, buf) >= 0) || ($stderr.ioctl(control, buf) >= 0) rescue SystemCallError false end |
.jruby? ⇒ Object
.lines ⇒ Integer
Detect terminal screen height
152 153 154 |
# File 'lib/tty/screen.rb', line 152 def height size[0] end |
.private_module_function(name) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Define module method as private
28 29 30 31 |
# File 'lib/tty/screen.rb', line 28 def self.private_module_function(name) module_function(name) private_class_method(name) end |
.rows ⇒ Integer
Detect terminal screen height
151 152 153 |
# File 'lib/tty/screen.rb', line 151 def height size[0] end |
.size(verbose: false) ⇒ Array(Integer, Integer)
Detect terminal screen size
106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/tty/screen.rb', line 106 def size(verbose: false) size_from_java(verbose: verbose) || size_from_win_api(verbose: verbose) || size_from_ioctl || size_from_io_console(verbose: verbose) || size_from_readline(verbose: verbose) || size_from_tput || size_from_stty || size_from_env || size_from_ansicon || size_from_default end |
.size_from_ansicon ⇒ Array(Integer, Integer)?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Detect terminal screen size from the ANSICON environment variable
426 427 428 429 430 431 |
# File 'lib/tty/screen.rb', line 426 def size_from_ansicon return unless env["ANSICON"] =~ /\((.*)x(.*)\)/ size = [::Regexp.last_match(2).to_i, ::Regexp.last_match(1).to_i] size if nonzero_column?(size[1]) end |
.size_from_default ⇒ Array(Integer, Integer)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Detect terminal screen size from default
161 162 163 |
# File 'lib/tty/screen.rb', line 161 def size_from_default DEFAULT_SIZE end |
.size_from_env ⇒ Array(Integer, Integer)?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Detect terminal screen size from environment variables
After executing Ruby code, when the user changes terminal screen size during code runtime, the code will not be notified, and hence will not see the new size reflected in its copy of LINES and COLUMNS environment variables.
412 413 414 415 416 417 |
# File 'lib/tty/screen.rb', line 412 def size_from_env return unless env["COLUMNS"] =~ /^\d+$/ size = [(env["LINES"] || env["ROWS"]).to_i, env["COLUMNS"].to_i] size if nonzero_column?(size[1]) end |
.size_from_io_console(verbose: false) ⇒ Array(Integer, Integer)?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Detect terminal screen size from io-console
On Windows, the io-console falls back to reading environment variables. This means any user changes to the terminal screen size will not be reflected in the runtime of the Ruby application.
249 250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/tty/screen.rb', line 249 def size_from_io_console(verbose: false) return unless output.tty? require "io/console" unless IO.method_defined?(:winsize) return unless output.respond_to?(:winsize) size = output.winsize size if nonzero_column?(size[1]) rescue Errno::EOPNOTSUPP # no support for winsize on output rescue LoadError warn "no native io/console support or io-console gem" if verbose end |
.size_from_ioctl ⇒ Array(Integer, Integer)?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Detect terminal screen size from ioctl
308 309 310 311 312 313 314 315 316 317 318 |
# File 'lib/tty/screen.rb', line 308 def size_from_ioctl buffer = Array.new(TIOCGWINSZ_BUF_LEN, 0).pack(TIOCGWINSZ_BUF_FMT) if ioctl?(TIOCGWINSZ, buffer) || ioctl?(TIOCGWINSZ_PPC, buffer) || ioctl?(TIOCGWINSZ_SOL, buffer) rows, cols, = buffer.unpack(TIOCGWINSZ_BUF_FMT) [rows, cols] if nonzero_column?(cols) end end |
.size_from_java(verbose: false) ⇒ Array(Integer, Integer)?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Detect terminal screen size from Java
221 222 223 224 225 226 227 228 229 230 |
# File 'lib/tty/screen.rb', line 221 def size_from_java(verbose: false) require "java" java_import "jline.TerminalFactory" terminal = TerminalFactory.get size = [terminal.get_height, terminal.get_width] size if nonzero_column?(size[1]) rescue warn "failed to import java terminal package" if verbose end |
.size_from_readline(verbose: false) ⇒ Array(Integer, Integer)?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Detect terminal screen size from readline
353 354 355 356 357 358 359 360 361 362 363 364 |
# File 'lib/tty/screen.rb', line 353 def size_from_readline(verbose: false) return unless output.tty? require "readline" unless defined?(::Readline) return unless ::Readline.respond_to?(:get_screen_size) size = ::Readline.get_screen_size size if nonzero_column?(size[1]) rescue LoadError warn "no readline gem" if verbose rescue NotImplementedError end |
.size_from_stty ⇒ Array(Integer, Integer)?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Detect terminal screen size from stty
390 391 392 393 394 395 396 397 398 |
# File 'lib/tty/screen.rb', line 390 def size_from_stty return unless output.tty? && command_exist?("stty") out = run_command("stty", "size") return unless out size = out.split.map(&:to_i) size if nonzero_column?(size[1]) end |
.size_from_tput ⇒ Array(Integer, Integer)?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Detect terminal screen size from tput
373 374 375 376 377 378 379 380 381 |
# File 'lib/tty/screen.rb', line 373 def size_from_tput return unless output.tty? && command_exist?("tput") lines = run_command("tput", "lines") return unless lines cols = run_command("tput", "cols") [lines.to_i, cols.to_i] if nonzero_column?(cols) end |
.size_from_win_api(verbose: false) ⇒ Array(Integer, Integer)?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Detect terminal screen size from Windows API
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/tty/screen.rb', line 183 def size_from_win_api(verbose: false) require "fiddle" unless defined?(Fiddle) kernel32 = Fiddle::Handle.new("kernel32") get_std_handle = Fiddle::Function.new( kernel32["GetStdHandle"], [-Fiddle::TYPE_INT], Fiddle::TYPE_INT) get_console_buffer_info = Fiddle::Function.new( kernel32["GetConsoleScreenBufferInfo"], [Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT) format = "SSSSSssssSS" buffer = ([0] * format.size).pack(format) stdout_handle = get_std_handle.(STDOUT_HANDLE) get_console_buffer_info.(stdout_handle, buffer) _, _, _, _, _, left, top, right, bottom, = buffer.unpack(format) size = [bottom - top + 1, right - left + 1] size if nonzero_column?(size[1] - 1) rescue LoadError warn "no native fiddle module found" if verbose rescue Fiddle::DLError # non windows platform or no kernel32 lib end |
.width ⇒ Integer
Detect terminal screen width
128 129 130 |
# File 'lib/tty/screen.rb', line 128 def width size[1] end |
.windows? ⇒ Object
Instance Method Details
#command_exist?(command) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Check if a command exists
442 443 444 445 446 447 448 449 |
# File 'lib/tty/screen.rb', line 442 def command_exist?(command) exts = env.fetch("PATHEXT", "").split(::File::PATH_SEPARATOR) env.fetch("PATH", "").split(::File::PATH_SEPARATOR).any? do |dir| file = ::File.join(dir, command) ::File.exist?(file) || exts.any? { |ext| ::File.exist?("#{file}#{ext}") } end end |
#nonzero_column?(column) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Check if a number is non-zero
476 477 478 |
# File 'lib/tty/screen.rb', line 476 def nonzero_column?(column) column.to_i > 0 end |
#run_command(*args) ⇒ String?
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Run command capturing the standard output
461 462 463 464 465 |
# File 'lib/tty/screen.rb', line 461 def run_command(*args) %x(#{args.join(" ")}) rescue IOError, SystemCallError nil end |