class IO - io: Ruby Standard Library Documentation

# class IO

### Public Class Methods

console → #<File:/dev/tty> click to toggle source
console(sym, *args)

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;
    }

console_size()
Alias for: default_console_size
default_console_size() click to toggle source

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

Also aliased as: console_size

### Public Instance Methods

beep click to toggle source

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;
    }

check_winsize_changed { ... } → io click to toggle source

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;
    }

clear_screen → io click to toggle source

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;
    }

console_mode → mode click to toggle source

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);
    }

console_mode = mode click to toggle source

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;
    }

cooked {|io| } click to toggle source

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);
    }

cooked! click to toggle source

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;
    }

cursor → [row, column] click to toggle source

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
    }

cursor = [line, column] → io click to toggle source

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));
    }

cursor_down(n) → io click to toggle source

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);
    }

cursor_left(n) → io click to toggle source

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));
    }

cursor_right(n) → io click to toggle source

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));
    }

cursor_up(n) → io click to toggle source

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);
    }

echo = flag click to toggle source

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;
    }

echo? → true or false click to toggle source

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;
    }

erase_line(mode) → io click to toggle source

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;
    }

erase_screen(mode) → io click to toggle source

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;
    }

getch(min: nil, time: nil, intr: nil) → char click to toggle source

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
    }

getpass(prompt=nil) → string click to toggle source

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);
    }

goto(line, column) → io click to toggle source

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;
    }

goto_column(column) → io click to toggle source

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;
    }

iflush click to toggle source

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;
    }

ioflush click to toggle source

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;
    }

noecho {|io| } click to toggle source

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);
    }

nonblock {|io| } → object click to toggle source
nonblock(boolean) {|io| } → object

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);
    }

nonblock = boolean → boolean click to toggle source

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;
    }

nonblock? → boolean click to toggle source

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;
    }

nread → int click to toggle source

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);
    }

oflush click to toggle source

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;
    }

pressed?(key) → bool click to toggle source

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;
    }

raw(min: nil, time: nil, intr: nil) {|io| } click to toggle source

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);
    }

raw!(min: nil, time: nil, intr: nil) → io click to toggle source

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;
    }

ready? → truthy or falsy click to toggle source

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
    }

scroll_backward(n) → io click to toggle source

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));
    }

scroll_forward(n) → io click to toggle source

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));
    }

ttyname → string or nil click to toggle source

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
    }

wait(events, timeout) → event mask, false or nil click to toggle source
wait(timeout = nil, mode = :read) → self, true, or false

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
    }

wait_priority → truthy or falsy click to toggle source
wait_priority(timeout) → truthy or falsy

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);
    }

wait_readable → truthy or falsy click to toggle source
wait_readable(timeout) → truthy or falsy

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
    }

wait_writable → truthy or falsy click to toggle source
wait_writable(timeout) → truthy or falsy

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
    }

winsize → [rows, columns] click to toggle source

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)));
    }

winsize = [rows, columns] click to toggle source

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;
    }