Module: TTY::Screen
- Defined in:
- lib/tty/screen.rb,
lib/tty/screen/version.rb
Overview
Used for detecting screen properties
Constant Summary collapse
- DEFAULT_SIZE =
Default terminal size
[27, 80].freeze
- STDOUT_HANDLE =
0xFFFFFFF5
- TIOCGWINSZ =
linux
0x5413
- TIOCGWINSZ_PPC =
macos, freedbsd, netbsd, openbsd
0x40087468
- TIOCGWINSZ_SOL =
solaris
0x5468
- VERSION =
"0.8.1"
Class Attribute Summary collapse
-
.env ⇒ Object
Holds the environment variables.
-
.output ⇒ Object
Specifies an output stream.
Class Method Summary collapse
- .cols ⇒ Object
- .columns ⇒ Object
- .height ⇒ Object
-
.ioctl?(control, buf) ⇒ Boolean
private
Check if ioctl can be called and any of the streams is attached to a terminal.
- .jruby? ⇒ Object
- .lines ⇒ Object
-
.private_module_function(name) ⇒ Object
Helper to define private functions.
- .rows ⇒ Object
-
.size(verbose: false) ⇒ Array[Integer, Integer]
Get terminal rows and columns.
-
.size_from_ansicon ⇒ Object
private
Detect terminal size from Windows ANSICON.
-
.size_from_default ⇒ Array[Integer, Integer]
private
Default size for the terminal.
-
.size_from_env ⇒ nil, Array[Integer, Integer]
private
Detect terminal size from environment.
-
.size_from_io_console(verbose: false) ⇒ nil, Array[Integer, Integer]
private
Detect screen size by loading io/console lib.
-
.size_from_ioctl ⇒ nil, Array[Integer, Integer]
private
Read terminal size from Unix ioctl.
- .size_from_java(verbose: false) ⇒ Object
-
.size_from_readline(verbose: false) ⇒ Object
private
Detect screen size using Readline.
-
.size_from_stty ⇒ Object
private
Detect terminal size from stty utility.
-
.size_from_tput ⇒ Object
private
Detect terminal size from tput utility.
- .size_from_win_api(verbose: false) ⇒ Object
- .width ⇒ Object
- .windows? ⇒ Object
Instance Method Summary collapse
-
#command_exist?(command) ⇒ Boolean
private
Check if command exists.
-
#nonzero_column?(column) ⇒ Boolean
private
Check if number is non zero.
-
#run_command(*args) ⇒ Object
private
Runs command silently capturing the output.
Class Attribute Details
.env ⇒ Object
Holds the environment variables
48 49 50 |
# File 'lib/tty/screen.rb', line 48 def env @env end |
.output ⇒ Object
Specifies an output stream
52 53 54 |
# File 'lib/tty/screen.rb', line 52 def output @output end |
Class Method Details
.cols ⇒ Object
81 82 83 |
# File 'lib/tty/screen.rb', line 81 def width size[1] end |
.columns ⇒ Object
80 81 82 |
# File 'lib/tty/screen.rb', line 80 def width size[1] end |
.height ⇒ Object
85 86 87 |
# File 'lib/tty/screen.rb', line 85 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 ioctl can be called and any of the streams is attached to a terminal.
215 216 217 218 219 220 221 |
# File 'lib/tty/screen.rb', line 215 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 ⇒ Object
91 92 93 |
# File 'lib/tty/screen.rb', line 91 def height size[0] end |
.private_module_function(name) ⇒ Object
Helper to define private functions
16 17 18 19 |
# File 'lib/tty/screen.rb', line 16 def self.private_module_function(name) module_function(name) private_class_method(name) end |
.rows ⇒ Object
90 91 92 |
# File 'lib/tty/screen.rb', line 90 def height size[0] end |
.size(verbose: false) ⇒ Array[Integer, Integer]
Get terminal rows and columns
61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/tty/screen.rb', line 61 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 ⇒ Object
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 size from Windows ANSICON
293 294 295 296 297 298 |
# File 'lib/tty/screen.rb', line 293 def size_from_ansicon return unless @env["ANSICON"] =~ /\((.*)x(.*)\)/ size = [$2, $1].map(&: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.
Default size for the terminal
100 101 102 |
# File 'lib/tty/screen.rb', line 100 def size_from_default DEFAULT_SIZE end |
.size_from_env ⇒ nil, 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 size from environment
After executing Ruby code if the user changes terminal dimensions during code runtime, the code won’t be notified, and hence won’t see the new dimensions reflected in its copy of LINES and COLUMNS environment variables.
282 283 284 285 286 287 |
# File 'lib/tty/screen.rb', line 282 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) ⇒ nil, 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 screen size by loading io/console lib
On Windows io_console falls back to reading environment variables. This means any user changes to the terminal size won’t be reflected in the runtime of the Ruby app.
171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/tty/screen.rb', line 171 def size_from_io_console(verbose: false) require "io/console" unless IO.method_defined?(:winsize) return unless @output.tty? && @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 ⇒ nil, 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.
Read terminal size from Unix ioctl
195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/tty/screen.rb', line 195 def size_from_ioctl format = "SSSS" buffer = ([0] * format.size).pack(format) if ioctl?(TIOCGWINSZ, buffer) || ioctl?(TIOCGWINSZ_PPC, buffer) || ioctl?(TIOCGWINSZ_SOL, buffer) rows, cols, = buffer.unpack(format)[0..1] return [rows, cols] if nonzero_column?(cols) end end |
.size_from_java(verbose: false) ⇒ Object
147 148 149 150 151 152 153 154 155 156 |
# File 'lib/tty/screen.rb', line 147 def size_from_java(verbose: false) require "java" java_import "jline.TerminalFactory" terminal = TerminalFactory.get size = [terminal.get_height, terminal.get_width] return size if nonzero_column?(size[1]) rescue warn "failed to import java terminal package" if verbose end |
.size_from_readline(verbose: false) ⇒ Object
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 screen size using Readline
231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/tty/screen.rb', line 231 def size_from_readline(verbose: false) 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 ⇒ Object
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 size from stty utility
261 262 263 264 265 266 267 268 269 |
# File 'lib/tty/screen.rb', line 261 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 ⇒ Object
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 size from tput utility
247 248 249 250 251 252 253 254 255 |
# File 'lib/tty/screen.rb', line 247 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?(lines) end |
.size_from_win_api(verbose: false) ⇒ Object
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/tty/screen.rb', line 113 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] return 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 ⇒ Object
75 76 77 |
# File 'lib/tty/screen.rb', line 75 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 command exists
306 307 308 309 310 311 312 |
# File 'lib/tty/screen.rb', line 306 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 number is non zero
return [Boolean]
330 331 332 |
# File 'lib/tty/screen.rb', line 330 def nonzero_column?(column) column.to_i > 0 end |
#run_command(*args) ⇒ Object
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.
Runs command silently capturing the output
318 319 320 321 322 |
# File 'lib/tty/screen.rb', line 318 def run_command(*args) %x(#{args.join(" ")}) rescue IOError, SystemCallError nil end |