class IO
Public Class Methods
Returns an File instance opened console.
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.
You must require ‘io/console’ to use this method.
static VALUE console_dev(int argc, VALUE *argv, VALUE klass) { VALUE con = 0; VALUE sym = 0; rb_check_arity(argc, 0, UNLIMITED_ARGUMENTS); if (argc) { Check_Type(sym = argv[0], T_SYMBOL); } // Force the class to be File. if (klass == rb_cIO) klass = rb_cFile; if (console_dev_get(klass, &con)) { if (!RB_TYPE_P(con, T_FILE) || RTEST(rb_io_closed_p(con))) { console_dev_remove(klass); con = 0; } } if (sym) { if (sym == ID2SYM(id_close) && argc == 1) { if (con) { rb_io_close(con); console_dev_remove(klass); con = 0; } return Qnil; } } if (!con) { #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H || defined HAVE_SGTTY_H # define CONSOLE_DEVICE "/dev/tty" #elif defined _WIN32 # define CONSOLE_DEVICE "con$" # define CONSOLE_DEVICE_FOR_READING "conin$" # define CONSOLE_DEVICE_FOR_WRITING "conout$" #endif #ifndef CONSOLE_DEVICE_FOR_READING # define CONSOLE_DEVICE_FOR_READING CONSOLE_DEVICE #endif #ifdef CONSOLE_DEVICE_FOR_WRITING VALUE out; #endif int fd; VALUE path = rb_obj_freeze(rb_str_new2(CONSOLE_DEVICE)); #ifdef CONSOLE_DEVICE_FOR_WRITING fd = rb_cloexec_open(CONSOLE_DEVICE_FOR_WRITING, O_RDWR, 0); if (fd < 0) return Qnil; out = rb_io_open_descriptor(klass, fd, FMODE_WRITABLE | FMODE_SYNC, path, Qnil, NULL); #endif fd = rb_cloexec_open(CONSOLE_DEVICE_FOR_READING, O_RDWR, 0); if (fd < 0) { #ifdef CONSOLE_DEVICE_FOR_WRITING rb_io_close(out); #endif return Qnil; } con = rb_io_open_descriptor(klass, fd, FMODE_READWRITE | FMODE_SYNC, path, Qnil, NULL); #ifdef CONSOLE_DEVICE_FOR_WRITING rb_io_set_write_io(con, out); #endif console_dev_set(klass, con); } if (sym) { return rb_f_send(argc, argv, con); } return con; }
fallback to console window size
# File io/console/lib/console/size.rb, line 3 def IO.default_console_size [ ENV["LINES"].to_i.nonzero? || 25, ENV["COLUMNS"].to_i.nonzero? || 80, ] end
Public Instance Methods
Beeps on the output console.
You must require ‘io/console’ to use this method.
static VALUE console_beep(VALUE io) { #ifdef _WIN32 MessageBeep(0); #else int fd = GetWriteFD(io); if (write(fd, "\a", 1) < 0) sys_fail(io); #endif return io; }
Yields while console input events are queued.
This method is Windows only.
You must require ‘io/console’ to use this method.
static VALUE console_check_winsize_changed(VALUE io) { HANDLE h; DWORD num; h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(io)); while (GetNumberOfConsoleInputEvents(h, &num) && num > 0) { INPUT_RECORD rec; if (ReadConsoleInput(h, &rec, 1, &num)) { if (rec.EventType == WINDOW_BUFFER_SIZE_EVENT) { rb_yield(Qnil); } } } return io; }
Clears the entire screen and moves the cursor top-left corner.
You must require ‘io/console’ to use this method.
static VALUE console_clear_screen(VALUE io) { console_erase_screen(io, INT2FIX(2)); console_goto(io, INT2FIX(0), INT2FIX(0)); return io; }
Returns a data represents the current console mode.
You must require ‘io/console’ to use this method.
static VALUE console_conmode_get(VALUE io) { conmode t; int fd = GetReadFD(io); if (!getattr(fd, &t)) sys_fail(io); return conmode_new(cConmode, &t); }
Sets the console mode to mode
.
You must require ‘io/console’ to use this method.
static VALUE console_conmode_set(VALUE io, VALUE mode) { conmode *t, r; int fd = GetReadFD(io); TypedData_Get_Struct(mode, conmode, &conmode_type, t); r = *t; if (!setattr(fd, &r)) sys_fail(io); return mode; }
Yields self
within cooked mode.
STDIN.cooked(&:gets)
will read and return a line with echo back and line editing.
You must require ‘io/console’ to use this method.
static VALUE console_cooked(VALUE io) { return ttymode(io, rb_yield, io, set_cookedmode, NULL); }
Enables cooked mode.
If the terminal mode needs to be back, use io.cooked { … }.
You must require ‘io/console’ to use this method.
static VALUE console_set_cooked(VALUE io) { conmode t; int fd = GetReadFD(io); if (!getattr(fd, &t)) sys_fail(io); set_cookedmode(&t, NULL); if (!setattr(fd, &t)) sys_fail(io); return io; }
Returns the current cursor position as a two-element array of integers (row, column)
io.cursor # => [3, 5]
You must require ‘io/console’ to use this method.
static VALUE console_cursor_pos(VALUE io) { #ifdef _WIN32 rb_console_size_t ws; int fd = GetWriteFD(io); if (!GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), &ws)) { rb_syserr_fail(LAST_ERROR, 0); } return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.Y), UINT2NUM(ws.dwCursorPosition.X)); #else static const struct query_args query = {"\033[6n", 0}; VALUE resp = console_vt_response(0, 0, io, &query); VALUE row, column, term; unsigned int r, c; if (!RB_TYPE_P(resp, T_ARRAY) || RARRAY_LEN(resp) != 3) return Qnil; term = RARRAY_AREF(resp, 2); if (!RB_TYPE_P(term, T_STRING) || RSTRING_LEN(term) != 1) return Qnil; if (RSTRING_PTR(term)[0] != 'R') return Qnil; row = RARRAY_AREF(resp, 0); column = RARRAY_AREF(resp, 1); rb_ary_resize(resp, 2); r = NUM2UINT(row) - 1; c = NUM2UINT(column) - 1; RARRAY_ASET(resp, 0, INT2NUM(r)); RARRAY_ASET(resp, 1, INT2NUM(c)); return resp; #endif }
Same as io.goto(line, column)
See IO#goto
.
You must require ‘io/console’ to use this method.
static VALUE console_cursor_set(VALUE io, VALUE cpos) { cpos = rb_convert_type(cpos, T_ARRAY, "Array", "to_ary"); if (RARRAY_LEN(cpos) != 2) rb_raise(rb_eArgError, "expected 2D coordinate"); return console_goto(io, RARRAY_AREF(cpos, 0), RARRAY_AREF(cpos, 1)); }
Moves the cursor down n
lines.
You must require ‘io/console’ to use this method.
static VALUE console_cursor_down(VALUE io, VALUE val) { return console_move(io, +NUM2INT(val), 0); }
Moves the cursor left n
columns.
You must require ‘io/console’ to use this method.
static VALUE console_cursor_left(VALUE io, VALUE val) { return console_move(io, 0, -NUM2INT(val)); }
Moves the cursor right n
columns.
You must require ‘io/console’ to use this method.
static VALUE console_cursor_right(VALUE io, VALUE val) { return console_move(io, 0, +NUM2INT(val)); }
Moves the cursor up n
lines.
You must require ‘io/console’ to use this method.
static VALUE console_cursor_up(VALUE io, VALUE val) { return console_move(io, -NUM2INT(val), 0); }
Enables/disables echo back. On some platforms, all combinations of this flags and raw/cooked mode may not be valid.
You must require ‘io/console’ to use this method.
static VALUE console_set_echo(VALUE io, VALUE f) { conmode t; int fd = GetReadFD(io); if (!getattr(fd, &t)) sys_fail(io); if (RTEST(f)) set_echo(&t, NULL); else set_noecho(&t, NULL); if (!setattr(fd, &t)) sys_fail(io); return io; }
Returns true
if echo back is enabled.
You must require ‘io/console’ to use this method.
static VALUE console_echo_p(VALUE io) { conmode t; int fd = GetReadFD(io); if (!getattr(fd, &t)) sys_fail(io); return echo_p(&t) ? Qtrue : Qfalse; }
Erases the line at the cursor corresponding to mode
. mode
may be either: 0: after cursor 1: before and cursor 2: entire line
You must require ‘io/console’ to use this method.
static VALUE console_erase_line(VALUE io, VALUE val) { int mode = mode_in_range(val, 2, "line erase"); #ifdef _WIN32 HANDLE h; rb_console_size_t ws; COORD *pos = &ws.dwCursorPosition; DWORD w; h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io)); if (!GetConsoleScreenBufferInfo(h, &ws)) { rb_syserr_fail(LAST_ERROR, 0); } w = winsize_col(&ws); switch (mode) { case 0: /* after cursor */ w -= pos->X; break; case 1: /* before *and* cursor */ w = pos->X + 1; pos->X = 0; break; case 2: /* entire line */ pos->X = 0; break; } constat_clear(h, ws.wAttributes, w, *pos); return io; #else rb_io_write(io, rb_sprintf(CSI "%dK", mode)); #endif return io; }
Erases the screen at the cursor corresponding to mode
. mode
may be either: 0: after cursor 1: before and cursor 2: entire screen
You must require ‘io/console’ to use this method.
static VALUE console_erase_screen(VALUE io, VALUE val) { int mode = mode_in_range(val, 3, "screen erase"); #ifdef _WIN32 HANDLE h; rb_console_size_t ws; COORD *pos = &ws.dwCursorPosition; DWORD w; h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io)); if (!GetConsoleScreenBufferInfo(h, &ws)) { rb_syserr_fail(LAST_ERROR, 0); } w = winsize_col(&ws); switch (mode) { case 0: /* erase after cursor */ w = (w * (ws.srWindow.Bottom - pos->Y + 1) - pos->X); break; case 1: /* erase before *and* cursor */ w = (w * (pos->Y - ws.srWindow.Top) + pos->X + 1); pos->X = 0; pos->Y = ws.srWindow.Top; break; case 2: /* erase entire screen */ w = (w * winsize_row(&ws)); pos->X = 0; pos->Y = ws.srWindow.Top; break; case 3: /* erase entire screen */ w = (w * ws.dwSize.Y); pos->X = 0; pos->Y = 0; break; } constat_clear(h, ws.wAttributes, w, *pos); #else rb_io_write(io, rb_sprintf(CSI "%dJ", mode)); #endif return io; }
Reads and returns a character in raw mode.
See IO#raw
for details on the parameters.
You must require ‘io/console’ to use this method.
static VALUE console_getch(int argc, VALUE *argv, VALUE io) { rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts); #ifndef _WIN32 return ttymode(io, getc_call, io, set_rawmode, optp); #else rb_io_t *fptr; VALUE str; wint_t c; int len; char buf[8]; wint_t wbuf[2]; # ifndef HAVE_RB_IO_WAIT struct timeval *to = NULL, tv; # else VALUE timeout = Qnil; # endif GetOpenFile(io, fptr); if (optp) { if (optp->vtime) { # ifndef HAVE_RB_IO_WAIT to = &tv; # else struct timeval tv; # endif tv.tv_sec = optp->vtime / 10; tv.tv_usec = (optp->vtime % 10) * 100000; # ifdef HAVE_RB_IO_WAIT timeout = rb_fiber_scheduler_make_timeout(&tv); # endif } switch (optp->vmin) { case 1: /* default */ break; case 0: /* return nil when timed out */ if (optp->vtime) break; /* fallthru */ default: rb_warning("min option larger than 1 ignored"); } if (optp->intr) { # ifndef HAVE_RB_IO_WAIT int w = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, to); if (w < 0) rb_eof_error(); if (!(w & RB_WAITFD_IN)) return Qnil; # else VALUE result = rb_io_wait(io, RB_INT2NUM(RUBY_IO_READABLE), timeout); if (!RTEST(result)) return Qnil; # endif } else if (optp->vtime) { rb_warning("Non-zero vtime option ignored if intr flag is unset"); } } len = (int)(VALUE)rb_thread_call_without_gvl(nogvl_getch, wbuf, RUBY_UBF_IO, 0); switch (len) { case 0: return Qnil; case 2: buf[0] = (char)wbuf[0]; c = wbuf[1]; len = 1; do { buf[len++] = (unsigned char)c; } while ((c >>= CHAR_BIT) && len < (int)sizeof(buf)); return rb_str_new(buf, len); default: c = wbuf[0]; len = rb_uv_to_utf8(buf, c); str = rb_utf8_str_new(buf, len); return rb_str_conv_enc(str, NULL, rb_default_external_encoding()); } #endif }
Reads and returns a line without echo back. Prints prompt
unless it is nil
.
The newline character that terminates the read line is removed from the returned string, see String#chomp!.
You must require ‘io/console’ to use this method.
require 'io/console' IO::console.getpass("Enter password:") Enter password: # => "mypassword"
static VALUE console_getpass(int argc, VALUE *argv, VALUE io) { VALUE str, wio; rb_check_arity(argc, 0, 1); wio = rb_io_get_write_io(io); if (wio == io && io == rb_stdin) wio = rb_stderr; prompt(argc, argv, wio); rb_io_flush(wio); str = rb_ensure(getpass_call, io, puts_call, wio); return str_chomp(str); }
Set the cursor position at line
and column
.
You must require ‘io/console’ to use this method.
static VALUE console_goto(VALUE io, VALUE y, VALUE x) { #ifdef _WIN32 COORD pos; int fd = GetWriteFD(io); pos.X = NUM2UINT(x); pos.Y = NUM2UINT(y); if (!SetConsoleCursorPosition((HANDLE)rb_w32_get_osfhandle(fd), pos)) { rb_syserr_fail(LAST_ERROR, 0); } #else rb_io_write(io, rb_sprintf(CSI "%d;%dH", NUM2UINT(y)+1, NUM2UINT(x)+1)); #endif return io; }
Set the cursor position at column
in the same line of the current position.
You must require ‘io/console’ to use this method.
static VALUE console_goto_column(VALUE io, VALUE val) { #ifdef _WIN32 HANDLE h; rb_console_size_t ws; COORD *pos = &ws.dwCursorPosition; h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io)); if (!GetConsoleScreenBufferInfo(h, &ws)) { rb_syserr_fail(LAST_ERROR, 0); } pos->X = NUM2INT(val); if (!SetConsoleCursorPosition(h, *pos)) { rb_syserr_fail(LAST_ERROR, 0); } #else rb_io_write(io, rb_sprintf(CSI "%dG", NUM2UINT(val)+1)); #endif return io; }
Flushes input buffer in kernel.
You must require ‘io/console’ to use this method.
static VALUE console_iflush(VALUE io) { #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H int fd = GetReadFD(io); if (tcflush(fd, TCIFLUSH)) sys_fail(io); #endif return io; }
Flushes input and output buffers in kernel.
You must require ‘io/console’ to use this method.
static VALUE console_ioflush(VALUE io) { #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H int fd1 = GetReadFD(io); int fd2 = GetWriteFD(io); if (fd2 != -1 && fd1 != fd2) { if (tcflush(fd1, TCIFLUSH)) sys_fail(io); if (tcflush(fd2, TCOFLUSH)) sys_fail(io); } else { if (tcflush(fd1, TCIOFLUSH)) sys_fail(io); } #endif return io; }
Yields self
with disabling echo back.
STDIN.noecho(&:gets)
will read and return a line without echo back.
You must require ‘io/console’ to use this method.
static VALUE console_noecho(VALUE io) { return ttymode(io, rb_yield, io, set_noecho, NULL); }
Yields self
in non-blocking mode.
When false
is given as an argument, self
is yielded in blocking mode. The original mode is restored after the block is executed.
static VALUE rb_io_nonblock_block(int argc, VALUE *argv, VALUE self) { int nb = 1; int descriptor = rb_io_descriptor(self); if (argc > 0) { VALUE v; rb_scan_args(argc, argv, "01", &v); nb = RTEST(v); } int current_flags = get_fcntl_flags(descriptor); int restore[2] = {descriptor, current_flags}; if (!io_nonblock_set(descriptor, current_flags, nb)) return rb_yield(self); return rb_ensure(rb_yield, self, io_nonblock_restore, (VALUE)restore); }
Enables non-blocking mode on a stream when set to true
, and blocking mode when set to false
.
This method set or clear O_NONBLOCK flag for the file descriptor in ios.
The behavior of most IO
methods is not affected by this flag because they retry system calls to complete their task after EAGAIN and partial read/write. (An exception is IO#syswrite which doesn’t retry.)
This method can be used to clear non-blocking mode of standard I/O. Since nonblocking methods (read_nonblock, etc.) set non-blocking mode but they doesn’t clear it, this method is usable as follows.
END { STDOUT.nonblock = false } STDOUT.write_nonblock("foo")
Since the flag is shared across processes and many non-Ruby commands doesn’t expect standard I/O with non-blocking mode, it would be safe to clear the flag before Ruby program exits.
For example following Ruby program leaves STDIN/STDOUT/STDER non-blocking mode. (STDIN, STDOUT and STDERR are connected to a terminal. So making one of them nonblocking-mode effects other two.) Thus cat command try to read from standard input and it causes “Resource temporarily unavailable” error (EAGAIN).
% ruby -e ' STDOUT.write_nonblock("foo\n")'; cat foo cat: -: Resource temporarily unavailable
Clearing the flag makes the behavior of cat command normal. (cat command waits input from standard input.)
% ruby -rio/nonblock -e ' END { STDOUT.nonblock = false } STDOUT.write_nonblock("foo") '; cat foo
static VALUE rb_io_nonblock_set(VALUE self, VALUE value) { if (RTEST(value)) { rb_io_t *fptr; GetOpenFile(self, fptr); rb_io_set_nonblock(fptr); } else { int descriptor = rb_io_descriptor(self); io_nonblock_set(descriptor, get_fcntl_flags(descriptor), RTEST(value)); } return self; }
Returns true
if an IO
object is in non-blocking mode.
static VALUE rb_io_nonblock_p(VALUE io) { if (get_fcntl_flags(rb_io_descriptor(io)) & O_NONBLOCK) return Qtrue; return Qfalse; }
Returns number of bytes that can be read without blocking. Returns zero if no information available.
You must require ‘io/wait’ to use this method.
static VALUE io_nread(VALUE io) { rb_io_t *fptr; int len; ioctl_arg n; GetOpenFile(io, fptr); rb_io_check_readable(fptr); len = rb_io_read_pending(fptr); if (len > 0) return INT2FIX(len); #ifdef HAVE_RB_IO_DESCRIPTOR int fd = rb_io_descriptor(io); #else int fd = fptr->fd; #endif if (!FIONREAD_POSSIBLE_P(fd)) return INT2FIX(0); if (ioctl(fd, FIONREAD, &n)) return INT2FIX(0); if (n > 0) return ioctl_arg2num(n); return INT2FIX(0); }
Flushes output buffer in kernel.
You must require ‘io/console’ to use this method.
static VALUE console_oflush(VALUE io) { int fd = GetWriteFD(io); #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H if (tcflush(fd, TCOFLUSH)) sys_fail(io); #endif (void)fd; return io; }
Returns true
if key
is pressed. key
may be a virtual key code or its name (String or Symbol) with out “VK_” prefix.
This method is Windows only.
You must require ‘io/console’ to use this method.
static VALUE console_key_pressed_p(VALUE io, VALUE k) { int vk = -1; if (FIXNUM_P(k)) { vk = NUM2UINT(k); } else { const struct vktable *t; const char *kn; if (SYMBOL_P(k)) { k = rb_sym2str(k); kn = RSTRING_PTR(k); } else { kn = StringValuePtr(k); } t = console_win32_vk(kn, RSTRING_LEN(k)); if (!t || (vk = (short)t->vk) == -1) { rb_raise(rb_eArgError, "unknown virtual key code: % "PRIsVALUE, k); } } return GetKeyState(vk) & 0x80 ? Qtrue : Qfalse; }
Yields self
within raw mode, and returns the result of the block.
STDIN.raw(&:gets)
will read and return a line without echo back and line editing.
The parameter min
specifies the minimum number of bytes that should be received when a read operation is performed. (default: 1)
The parameter time
specifies the timeout in seconds with a precision of 1/10 of a second. (default: 0)
If the parameter intr
is true
, enables break, interrupt, quit, and suspend special characters.
Refer to the manual page of termios for further details.
You must require ‘io/console’ to use this method.
static VALUE console_raw(int argc, VALUE *argv, VALUE io) { rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts); return ttymode(io, rb_yield, io, set_rawmode, optp); }
Enables raw mode, and returns io
.
If the terminal mode needs to be back, use io.raw { ... }
.
See IO#raw
for details on the parameters.
You must require ‘io/console’ to use this method.
static VALUE console_set_raw(int argc, VALUE *argv, VALUE io) { conmode t; rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts); int fd = GetReadFD(io); if (!getattr(fd, &t)) sys_fail(io); set_rawmode(&t, optp); if (!setattr(fd, &t)) sys_fail(io); return io; }
Returns a truthy value if input available without blocking, or a falsy value.
You must require ‘io/wait’ to use this method.
static VALUE io_ready_p(VALUE io) { rb_io_t *fptr; #ifndef HAVE_RB_IO_WAIT struct timeval tv = {0, 0}; #endif GetOpenFile(io, fptr); rb_io_check_readable(fptr); if (rb_io_read_pending(fptr)) return Qtrue; #ifndef HAVE_RB_IO_WAIT return wait_for_single_fd(fptr, RB_WAITFD_IN, &tv) ? Qtrue : Qfalse; #else return io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0), 1); #endif }
Scrolls the entire scrolls backward n
lines.
You must require ‘io/console’ to use this method.
static VALUE console_scroll_backward(VALUE io, VALUE val) { return console_scroll(io, -NUM2INT(val)); }
Scrolls the entire scrolls forward n
lines.
You must require ‘io/console’ to use this method.
static VALUE console_scroll_forward(VALUE io, VALUE val) { return console_scroll(io, +NUM2INT(val)); }
Returns name of associated terminal (tty) if io
is not a tty. Returns nil
otherwise.
static VALUE console_ttyname(VALUE io) { int fd = rb_io_descriptor(io); if (!isatty(fd)) return Qnil; # if defined _WIN32 return rb_usascii_str_new_lit("con"); # elif defined HAVE_TTYNAME_R { char termname[1024], *tn = termname; size_t size = sizeof(termname); int e; if (ttyname_r(fd, tn, size) == 0) return rb_interned_str_cstr(tn); if ((e = errno) == ERANGE) { VALUE s = rb_str_new(0, size); while (1) { tn = RSTRING_PTR(s); size = rb_str_capacity(s); if (ttyname_r(fd, tn, size) == 0) { return rb_str_to_interned_str(rb_str_resize(s, strlen(tn))); } if ((e = errno) != ERANGE) break; if ((size *= 2) >= INT_MAX/2) break; rb_str_resize(s, size); } } rb_syserr_fail_str(e, rb_sprintf("ttyname_r(%d)", fd)); UNREACHABLE_RETURN(Qnil); } # elif defined HAVE_TTYNAME { const char *tn = ttyname(fd); if (!tn) { int e = errno; rb_syserr_fail_str(e, rb_sprintf("ttyname(%d)", fd)); } return rb_interned_str_cstr(tn); } # else # error No ttyname function # endif }
Waits until the IO
becomes ready for the specified events and returns the subset of events that become ready, or a falsy value when times out.
The events can be a bit mask of IO::READABLE
, IO::WRITABLE
or IO::PRIORITY
.
Returns a truthy value immediately when buffered data is available.
Optional parameter mode
is one of :read
, :write
, or :read_write
.
You must require ‘io/wait’ to use this method.
static VALUE io_wait(int argc, VALUE *argv, VALUE io) { #ifndef HAVE_RB_IO_WAIT rb_io_t *fptr; struct timeval timerec; struct timeval *tv = NULL; int event = 0; int i; GetOpenFile(io, fptr); for (i = 0; i < argc; ++i) { if (SYMBOL_P(argv[i])) { event |= wait_mode_sym(argv[i]); } else { *(tv = &timerec) = rb_time_interval(argv[i]); } } /* rb_time_interval() and might_mode() might convert the argument */ rb_io_check_closed(fptr); if (!event) event = RB_WAITFD_IN; if ((event & RB_WAITFD_IN) && rb_io_read_pending(fptr)) return Qtrue; if (wait_for_single_fd(fptr, event, tv)) return io; return Qnil; #else VALUE timeout = Qundef; rb_io_event_t events = 0; int i, return_io = 0; /* The documented signature for this method is actually incorrect. * A single timeout is allowed in any position, and multiple symbols can be given. * Whether this is intentional or not, I don't know, and as such I consider this to * be a legacy/slow path. */ if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) { /* We'd prefer to return the actual mask, but this form would return the io itself: */ return_io = 1; /* Slow/messy path: */ for (i = 0; i < argc; i += 1) { if (RB_SYMBOL_P(argv[i])) { events |= wait_mode_sym(argv[i]); } else if (timeout == Qundef) { rb_time_interval(timeout = argv[i]); } else { rb_raise(rb_eArgError, "timeout given more than once"); } } if (timeout == Qundef) timeout = Qnil; if (events == 0) { events = RUBY_IO_READABLE; } } else /* argc == 2 and neither are symbols */ { /* This is the fast path: */ events = io_event_from_value(argv[0]); timeout = argv[1]; } if (events & RUBY_IO_READABLE) { rb_io_t *fptr = NULL; RB_IO_POINTER(io, fptr); if (rb_io_read_pending(fptr)) { /* This was the original behaviour: */ if (return_io) return Qtrue; /* New behaviour always returns an event mask: */ else return RB_INT2NUM(RUBY_IO_READABLE); } } return io_wait_event(io, events, timeout, return_io); #endif }
Waits until IO
is priority and returns a truthy value or a falsy value when times out. Priority data is sent and received using the Socket::MSG_OOB flag and is typically limited to streams.
You must require ‘io/wait’ to use this method.
static VALUE io_wait_priority(int argc, VALUE *argv, VALUE io) { rb_io_t *fptr = NULL; RB_IO_POINTER(io, fptr); rb_io_check_readable(fptr); if (rb_io_read_pending(fptr)) return Qtrue; rb_check_arity(argc, 0, 1); VALUE timeout = argc == 1 ? argv[0] : Qnil; return io_wait_event(io, RUBY_IO_PRIORITY, timeout, 1); }
Waits until IO
is readable and returns a truthy value, or a falsy value when times out. Returns a truthy value immediately when buffered data is available.
You must require ‘io/wait’ to use this method.
static VALUE io_wait_readable(int argc, VALUE *argv, VALUE io) { rb_io_t *fptr; #ifndef HAVE_RB_IO_WAIT struct timeval timerec; struct timeval *tv; #endif GetOpenFile(io, fptr); rb_io_check_readable(fptr); #ifndef HAVE_RB_IO_WAIT tv = get_timeout(argc, argv, &timerec); #endif if (rb_io_read_pending(fptr)) return Qtrue; #ifndef HAVE_RB_IO_WAIT if (wait_for_single_fd(fptr, RB_WAITFD_IN, tv)) { return io; } return Qnil; #else rb_check_arity(argc, 0, 1); VALUE timeout = (argc == 1 ? argv[0] : Qnil); return io_wait_event(io, RUBY_IO_READABLE, timeout, 1); #endif }
Waits until IO
is writable and returns a truthy value or a falsy value when times out.
You must require ‘io/wait’ to use this method.
static VALUE io_wait_writable(int argc, VALUE *argv, VALUE io) { rb_io_t *fptr; #ifndef HAVE_RB_IO_WAIT struct timeval timerec; struct timeval *tv; #endif GetOpenFile(io, fptr); rb_io_check_writable(fptr); #ifndef HAVE_RB_IO_WAIT tv = get_timeout(argc, argv, &timerec); if (wait_for_single_fd(fptr, RB_WAITFD_OUT, tv)) { return io; } return Qnil; #else rb_check_arity(argc, 0, 1); VALUE timeout = (argc == 1 ? argv[0] : Qnil); return io_wait_event(io, RUBY_IO_WRITABLE, timeout, 1); #endif }
Returns console size.
You must require ‘io/console’ to use this method.
static VALUE console_winsize(VALUE io) { rb_console_size_t ws; int fd = GetWriteFD(io); if (!getwinsize(fd, &ws)) sys_fail(io); return rb_assoc_new(INT2NUM(winsize_row(&ws)), INT2NUM(winsize_col(&ws))); }
Tries to set console size. The effect depends on the platform and the running environment.
You must require ‘io/console’ to use this method.
static VALUE console_set_winsize(VALUE io, VALUE size) { rb_console_size_t ws; #if defined _WIN32 HANDLE wh; int newrow, newcol; BOOL ret; #endif VALUE row, col, xpixel, ypixel; const VALUE *sz; long sizelen; int fd; size = rb_Array(size); if ((sizelen = RARRAY_LEN(size)) != 2 && sizelen != 4) { rb_raise(rb_eArgError, "wrong number of arguments (given %ld, expected 2 or 4)", sizelen); } sz = RARRAY_CONST_PTR(size); row = sz[0], col = sz[1], xpixel = ypixel = Qnil; if (sizelen == 4) xpixel = sz[2], ypixel = sz[3]; fd = GetWriteFD(io); #if defined TIOCSWINSZ ws.ws_row = ws.ws_col = ws.ws_xpixel = ws.ws_ypixel = 0; #define SET(m) ws.ws_##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m) SET(row); SET(col); SET(xpixel); SET(ypixel); #undef SET if (!setwinsize(fd, &ws)) sys_fail(io); #elif defined _WIN32 wh = (HANDLE)rb_w32_get_osfhandle(fd); #define SET(m) new##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m) SET(row); SET(col); #undef SET if (!NIL_P(xpixel)) (void)NUM2UINT(xpixel); if (!NIL_P(ypixel)) (void)NUM2UINT(ypixel); if (!GetConsoleScreenBufferInfo(wh, &ws)) { rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo"); } ws.dwSize.X = newcol; ret = SetConsoleScreenBufferSize(wh, ws.dwSize); ws.srWindow.Left = 0; ws.srWindow.Top = 0; ws.srWindow.Right = newcol-1; ws.srWindow.Bottom = newrow-1; if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) { rb_syserr_fail(LAST_ERROR, "SetConsoleWindowInfo"); } /* retry when shrinking buffer after shrunk window */ if (!ret && !SetConsoleScreenBufferSize(wh, ws.dwSize)) { rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo"); } /* remove scrollbar if possible */ if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) { rb_syserr_fail(LAST_ERROR, "SetConsoleWindowInfo"); } #endif return io; }