Class: IO

Inherits:
Object
  • Object
show all
Defined in:
(unknown)

Defined Under Namespace

Modules: generic_readable, platform_tty

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.console#<File:/dev/tty .console(sym, *args) ⇒ Object

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.

Overloads:

  • .console#<File:/dev/tty

    Returns ].

    Returns:

    • (#<File:/dev/tty)

      ]



2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
# File 'ext/io/console/console.c', line 2118

static VALUE
console_dev(int argc, VALUE *argv, VALUE klass)
{
    VALUE con = 0;
    VALUE sym = 0;

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

Instance Method Details

#beepObject

Beeps on the output console.

You must require 'io/console' to use this method.



1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
# File 'ext/io/console/console.c', line 1437

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

Yields while console input events are queued.

Deprecated because it discards queued input events other than window buffer size changes. Use IO#console_input_events instead to preserve all events.

This method is Windows only.

You must require 'io/console' to use this method.

Yields:

  • []

Returns:



1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
# File 'ext/io/console/console.c', line 1339

static VALUE
console_check_winsize_changed(VALUE io)
{
    HANDLE h;
    DWORD num;

    rb_category_warn(RB_WARN_CATEGORY_DEPRECATED,
         "IO#check_winsize_changed is deprecated; "
         "use IO#console_input_events instead");
    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_screenIO

Clears the entire screen and moves the cursor top-left corner.

You must require 'io/console' to use this method.

Returns:



2011
2012
2013
2014
2015
2016
2017
# File 'ext/io/console/console.c', line 2011

static VALUE
console_clear_screen(VALUE io)
{
    console_erase_screen(io, INT2FIX(2));
    console_goto(io, INT2FIX(0), INT2FIX(0));
    return io;
}

#console_input_events([max_events], timeout: nil) ⇒ Array

Reads up to max_events console input events, preserving their order. The default is one event. Blocks until at least one event is available, or for timeout seconds if specified. Returns an empty Array on timeout.

Each event is returned as a Hash. The :type and remaining keys are:

  • :key : :key_down, :repeat_count, :virtual_key_code, :virtual_scan_code, :unicode_char, and :control_key_state.
  • :mouse : :position ([row, column]), :button_state, :control_key_state, and :event_flags.
  • :window_buffer_size : :size ([rows, columns]).
  • :menu : :command_id.
  • :focus : :set_focus.

This method is Windows only.

You must require 'io/console' to use this method.

Returns:

  • (Array)


1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
# File 'ext/io/console/console.c', line 1282

static VALUE
console_input_events(int argc, VALUE *argv, VALUE io)
{
    VALUE vmax = Qnil, vopts = Qnil, vtimeout = Qundef;
    VALUE values[1];
    ID keywords[1] = {id_timeout};
    DWORD max_events = 1;
    read_console_input_args_t args;

    rb_scan_args(argc, argv, "01:", &vmax, &vopts);
    if (rb_get_kwargs(vopts, keywords, 0, 1, values)) {
  vtimeout = values[0];
    }
    if (!NIL_P(vmax)) {
  max_events = NUM2UINT(vmax);
  if (max_events == 0) rb_raise(rb_eArgError, "max_events must be positive");
    }

    args.timeout = INFINITE;
    if (!NIL_OR_UNDEF_P(vtimeout)) {
  struct timeval timeout = rb_time_interval(vtimeout);
  uint64_t milliseconds = (uint64_t)timeout.tv_sec * 1000;
  milliseconds += ((uint64_t)timeout.tv_usec + 999) / 1000;
  args.timeout = milliseconds < INFINITE ? (DWORD)milliseconds : INFINITE - 1;
    }

    args.handles[console_input_handle] =
  (HANDLE)rb_w32_get_osfhandle(GetReadFD(io));
    args.records = ALLOC_N(INPUT_RECORD, max_events);
    args.handles[console_input_wakeup] = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (!args.handles[console_input_wakeup]) {
  int error = LAST_ERROR;
  xfree(args.records);
  rb_syserr_fail(error, 0);
    }
    args.length = max_events;
    args.count = 0;
    args.wait_result = WAIT_FAILED;
    args.error = ERROR_SUCCESS;
    args.result = FALSE;
    return rb_ensure(console_input_events_read, (VALUE)&args,
         console_input_events_ensure, (VALUE)&args);
}

#console_modeObject

Returns a data represents the current console mode.

You must require 'io/console' to use this method.



942
943
944
945
946
947
948
949
950
951
# File 'ext/io/console/console.c', line 942

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) ⇒ Object

Sets the console mode to mode.

You must require 'io/console' to use this method.



961
962
963
964
965
966
967
968
969
970
971
972
973
# File 'ext/io/console/console.c', line 961

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| ... } ⇒ Object

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.

Yields:

  • (io)


504
505
506
507
508
# File 'ext/io/console/console.c', line 504

static VALUE
console_cooked(VALUE io)
{
    return ttymode(io, rb_yield, io, set_cookedmode, NULL);
}

#cooked!Object

Enables cooked mode.

If the terminal mode needs to be back, use io.cooked { ... }.

You must require 'io/console' to use this method.



520
521
522
523
524
525
526
527
528
529
# File 'ext/io/console/console.c', line 520

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

#cursorArray

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.

Returns:

  • (Array)


1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
# File 'ext/io/console/console.c', line 1631

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 - ws.srWindow.Top), 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=(cpos) ⇒ Object

Same as io.goto(line, column)

See IO#goto.

You must require 'io/console' to use this method.



1911
1912
1913
1914
1915
1916
1917
# File 'ext/io/console/console.c', line 1911

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

Moves the cursor down n lines.

You must require 'io/console' to use this method.

Returns:



1941
1942
1943
1944
1945
# File 'ext/io/console/console.c', line 1941

static VALUE
console_cursor_down(VALUE io, VALUE val)
{
    return console_move(io, +NUM2INT(val), 0);
}

#cursor_left(n) ⇒ IO

Moves the cursor left n columns.

You must require 'io/console' to use this method.

Returns:



1955
1956
1957
1958
1959
# File 'ext/io/console/console.c', line 1955

static VALUE
console_cursor_left(VALUE io, VALUE val)
{
    return console_move(io, 0, -NUM2INT(val));
}

#cursor_right(n) ⇒ IO

Moves the cursor right n columns.

You must require 'io/console' to use this method.

Returns:



1969
1970
1971
1972
1973
# File 'ext/io/console/console.c', line 1969

static VALUE
console_cursor_right(VALUE io, VALUE val)
{
    return console_move(io, 0, +NUM2INT(val));
}

#cursor_up(n) ⇒ IO

Moves the cursor up n lines.

You must require 'io/console' to use this method.

Returns:



1927
1928
1929
1930
1931
# File 'ext/io/console/console.c', line 1927

static VALUE
console_cursor_up(VALUE io, VALUE val)
{
    return console_move(io, -NUM2INT(val), 0);
}

#echo=(flag) ⇒ Object

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.



712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
# File 'ext/io/console/console.c', line 712

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?Boolean

Returns true if echo back is enabled.

You must require 'io/console' to use this method.

Returns:

  • (Boolean)


738
739
740
741
742
743
744
745
746
# File 'ext/io/console/console.c', line 738

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

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.

Returns:



1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
# File 'ext/io/console/console.c', line 1812

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

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.

Returns:



1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
# File 'ext/io/console/console.c', line 1859

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) ⇒ String?

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.

Returns:

  • (String, nil)


570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
# File 'ext/io/console/console.c', line 570

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

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"

Returns:

  • (String)


2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
# File 'ext/io/console/console.c', line 2268

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

Set the cursor position at line and column.

You must require 'io/console' to use this method.

Returns:



1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
# File 'ext/io/console/console.c', line 1717

static VALUE
console_goto(VALUE io, VALUE y, VALUE x)
{
#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 = NUM2UINT(x);
    pos->Y = ws.srWindow.Top + NUM2UINT(y);
    if (!SetConsoleCursorPosition(h, *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

Set the cursor position at column in the same line of the current position.

You must require 'io/console' to use this method.

Returns:



1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
# File 'ext/io/console/console.c', line 1778

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

#hide_cursorIO

Hides the cursor.

You must require 'io/console' to use this method.

Returns:



1689
1690
1691
1692
1693
# File 'ext/io/console/console.c', line 1689

static VALUE
console_hide_cursor(VALUE io)
{
    return console_cursor_visibility(io, 0);
}

#iflushObject

Flushes input buffer in kernel.

You must require 'io/console' to use this method.



1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
# File 'ext/io/console/console.c', line 1372

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

#input_pending?Boolean

Returns whether input can be read without blocking.

You must require 'io/console' to use this method.

Returns:

  • (Boolean)


655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
# File 'ext/io/console/console.c', line 655

static VALUE
console_input_pending_p(VALUE io)
{
    rb_io_t *fptr;

    GetOpenFile(io, fptr);
    if (rb_io_read_pending(fptr)) return Qtrue;
#ifdef _WIN32
    {
  DWORD mode;
  HANDLE h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(io));

  if (GetConsoleMode(h, &mode)) return _kbhit() ? Qtrue : Qfalse;
    }
#endif
#if defined HAVE_RB_IO_WAIT
    return RTEST(rb_io_wait(io, RB_INT2NUM(RUBY_IO_READABLE), INT2FIX(0))) ? Qtrue : Qfalse;
#else
    {
  struct timeval timeout = {0, 0};
  int result;

  result = rb_wait_for_single_fd(fptr->fd, RB_WAITFD_IN, &timeout);
  if (result < 0) sys_fail(io);
  return (result & RB_WAITFD_IN) ? Qtrue : Qfalse;
    }
#endif
}

#ioflushObject

Flushes input and output buffers in kernel.

You must require 'io/console' to use this method.



1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
# File 'ext/io/console/console.c', line 1410

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

#tty?([mode, ...]) ⇒ Object

Returns true if the stream is associated with a terminal device (tty), false otherwise.

If one or more +type+s are given, returns true if the stream is associated with any of the specified tty types.

  • nil : Returns the result of the default tty check, as if no type were given. It can be combined with other types.
  • :any : Returns true for any known kind of tty, including the default tty.
  • :cygwin : Returns true for cygwin tty, on Windows.
  • :msys : Returns true for msys2 tty, on Windows.


2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
# File 'ext/io/console/console.c', line 2391

static VALUE
console_platform_tty_p(int argc, VALUE *argv, VALUE io)
{
    VALUE ret = Qfalse;
    int mode = 0;

    if (argc > 0) {
  int i;
  for (i = 0; i < argc; ++i) {
      VALUE m = argv[i];
      if (NIL_P(m)) {
    mode |= platform_default_bit;
    continue;
      }
      Check_Type(m, T_SYMBOL);
      if (m == ID2SYM(rb_intern("any"))) {
    mode |= platform_any_bit;
      }
#if defined _WIN32
      else if (m == ID2SYM(rb_intern("cygwin"))) {
    mode |= platform_cygwin_bit;
      }
      else if (m == ID2SYM(rb_intern("msys"))) {
    mode |= platform_msys_bit;
      }
#endif
      else {
    rb_raise(rb_eArgError, "unknown tty type: %+" PRIsVALUE, m);
      }
  }
    }
    if ((mode & platform_default_bit) || (mode == 0)) {
  ret = rb_call_super(0, 0);
    }
    if ((mode & ~platform_default_bit) && !RTEST(ret)) {
#if defined _WIN32
  if (mode & (platform_cygwin_bit | platform_msys_bit)) {
      struct {
    FILE_NAME_INFO info;
    WCHAR rest[MAX_PATH];
      } buffer;

      HANDLE h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(io));
      if ((GetFileType(h) == FILE_TYPE_PIPE) &&
    GetFileInformationByHandleEx(h, FileNameInfo, &buffer, sizeof(buffer))) {
    WCHAR *const name = buffer.info.FileName;
    DWORD len = buffer.info.FileNameLength / sizeof(WCHAR);
    name[len] = L'\0';
# define tty_pipe_p(type)      (memcmp(name, L"\\" #type "-", sizeof(L"\\" #type)) == 0 &&       wcsstr(&name[rb_strlen_lit("\\" #type "-")], L"-pty") != NULL)
    if (!ret && (mode & platform_cygwin_bit)) {
        ret = tty_pipe_p(cygwin);
    }
    if (!ret && (mode & platform_msys_bit)) {
        ret = tty_pipe_p(msys);
    }
      }
  }
#endif
    }
    return ret;
}

#noecho {|io| ... } ⇒ Object

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.

Yields:

  • (io)


696
697
698
699
700
# File 'ext/io/console/console.c', line 696

static VALUE
console_noecho(VALUE io)
{
    return ttymode(io, rb_yield, io, set_noecho, NULL);
}

#oflushObject

Flushes output buffer in kernel.

You must require 'io/console' to use this method.



1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
# File 'ext/io/console/console.c', line 1391

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) ⇒ Boolean

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.

Returns:

  • (Boolean)


1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
# File 'ext/io/console/console.c', line 1518

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| ... } ⇒ Object

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.

Yields:

  • (io)


461
462
463
464
465
466
# File 'ext/io/console/console.c', line 461

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

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.

Returns:



480
481
482
483
484
485
486
487
488
489
490
# File 'ext/io/console/console.c', line 480

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

#scroll_backward(n) ⇒ IO

Scrolls the entire scrolls backward n lines.

You must require 'io/console' to use this method.

Returns:



1997
1998
1999
2000
2001
# File 'ext/io/console/console.c', line 1997

static VALUE
console_scroll_backward(VALUE io, VALUE val)
{
    return console_scroll(io, -NUM2INT(val));
}

#scroll_forward(n) ⇒ IO

Scrolls the entire scrolls forward n lines.

You must require 'io/console' to use this method.

Returns:



1983
1984
1985
1986
1987
# File 'ext/io/console/console.c', line 1983

static VALUE
console_scroll_forward(VALUE io, VALUE val)
{
    return console_scroll(io, +NUM2INT(val));
}

#show_cursorIO

Shows the cursor.

You must require 'io/console' to use this method.

Returns:



1703
1704
1705
1706
1707
# File 'ext/io/console/console.c', line 1703

static VALUE
console_show_cursor(VALUE io)
{
    return console_cursor_visibility(io, 1);
}

#tty?([mode, ...]) ⇒ Boolean

Returns true if the stream is associated with a terminal device (tty), false otherwise.

If one or more +type+s are given, returns true if the stream is associated with any of the specified tty types.

  • nil : Returns the result of the default tty check, as if no type were given. It can be combined with other types.
  • :any : Returns true for any known kind of tty, including the default tty.
  • :cygwin : Returns true for cygwin tty, on Windows.
  • :msys : Returns true for msys2 tty, on Windows.

Returns:

  • (Boolean)


2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
# File 'ext/io/console/console.c', line 2391

static VALUE
console_platform_tty_p(int argc, VALUE *argv, VALUE io)
{
    VALUE ret = Qfalse;
    int mode = 0;

    if (argc > 0) {
  int i;
  for (i = 0; i < argc; ++i) {
      VALUE m = argv[i];
      if (NIL_P(m)) {
    mode |= platform_default_bit;
    continue;
      }
      Check_Type(m, T_SYMBOL);
      if (m == ID2SYM(rb_intern("any"))) {
    mode |= platform_any_bit;
      }
#if defined _WIN32
      else if (m == ID2SYM(rb_intern("cygwin"))) {
    mode |= platform_cygwin_bit;
      }
      else if (m == ID2SYM(rb_intern("msys"))) {
    mode |= platform_msys_bit;
      }
#endif
      else {
    rb_raise(rb_eArgError, "unknown tty type: %+" PRIsVALUE, m);
      }
  }
    }
    if ((mode & platform_default_bit) || (mode == 0)) {
  ret = rb_call_super(0, 0);
    }
    if ((mode & ~platform_default_bit) && !RTEST(ret)) {
#if defined _WIN32
  if (mode & (platform_cygwin_bit | platform_msys_bit)) {
      struct {
    FILE_NAME_INFO info;
    WCHAR rest[MAX_PATH];
      } buffer;

      HANDLE h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(io));
      if ((GetFileType(h) == FILE_TYPE_PIPE) &&
    GetFileInformationByHandleEx(h, FileNameInfo, &buffer, sizeof(buffer))) {
    WCHAR *const name = buffer.info.FileName;
    DWORD len = buffer.info.FileNameLength / sizeof(WCHAR);
    name[len] = L'\0';
# define tty_pipe_p(type)      (memcmp(name, L"\\" #type "-", sizeof(L"\\" #type)) == 0 &&       wcsstr(&name[rb_strlen_lit("\\" #type "-")], L"-pty") != NULL)
    if (!ret && (mode & platform_cygwin_bit)) {
        ret = tty_pipe_p(cygwin);
    }
    if (!ret && (mode & platform_msys_bit)) {
        ret = tty_pipe_p(msys);
    }
      }
  }
#endif
    }
    return ret;
}

#ttynameString?

Returns name of associated terminal (tty) if io is a tty. Returns nil otherwise.

Returns:

  • (String, nil)


2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
# File 'ext/io/console/console.c', line 2308

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
    {
# ifdef TTYNAME_R_RETURNS_CHAR_P
#   define ttyname_r(fd, name, size) (ttyname_r(fd, name, size) == NULL ? errno : 0)
# endif
  char termname[1024], *tn = termname;
  size_t size = sizeof(termname);
  int e;
  if ((e = ttyname_r(fd, tn, size)) == 0)
      return rb_interned_str_cstr(tn);
  if (e == ERANGE) {
      VALUE s = rb_str_new(0, size);
      while (1) {
    tn = RSTRING_PTR(s);
    size = rb_str_capacity(s);
    if ((e = ttyname_r(fd, tn, size)) == 0) {
        return rb_str_to_interned_str(rb_str_resize(s, strlen(tn)));
    }
    if (e != 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
}

#winsizeArray

Returns console size.

You must require 'io/console' to use this method.

Returns:

  • (Array)


1003
1004
1005
1006
1007
1008
1009
1010
# File 'ext/io/console/console.c', line 1003

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=(size) ⇒ Object

Tries to set console size. The effect depends on the platform and the running environment.

You must require 'io/console' to use this method.



1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
# File 'ext/io/console/console.c', line 1024

static VALUE
console_set_winsize(VALUE io, VALUE size)
{
    rb_console_size_t ws;
#if defined _WIN32
    HANDLE wh;
    int newrow, newcol;
    COORD oldsize;
    SMALL_RECT oldwindow;
#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");
    }
    oldsize = ws.dwSize;
    oldwindow = ws.srWindow;
    if (ws.srWindow.Right + 1 < newcol) {
        ws.dwSize.X = newcol;
    }
    if (ws.dwSize.Y < newrow) {
        ws.dwSize.Y = newrow;
    }
    /* expand screen buffer first if needed */
    if (!SetConsoleScreenBufferSize(wh, ws.dwSize)) {
        rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo");
    }
    /* refresh ws for new dwMaximumWindowSize */
    if (!GetConsoleScreenBufferInfo(wh, &ws)) {
        rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo");
    }
    /* check new size before modifying buffer content */
    if (newrow <= 0 || newcol <= 0 ||
        newrow > ws.dwMaximumWindowSize.Y ||
        newcol > ws.dwMaximumWindowSize.X) {
        SetConsoleScreenBufferSize(wh, oldsize);
        /* remove scrollbar if possible */
        SetConsoleWindowInfo(wh, TRUE, &oldwindow);
        rb_raise(rb_eArgError, "out of range winsize: [%d, %d]", newrow, newcol);
    }
    /* shrink screen buffer width */
    ws.dwSize.X = newcol;
    /* shrink screen buffer height if window height were the same */
    if (oldsize.Y == ws.srWindow.Bottom - ws.srWindow.Top + 1) {
        ws.dwSize.Y = newrow;
    }
    ws.srWindow.Left = 0;
    ws.srWindow.Right = newcol - 1;
    ws.srWindow.Bottom = ws.srWindow.Top + newrow -1;
    if (ws.dwCursorPosition.Y > ws.srWindow.Bottom) {
        console_scroll(io, ws.dwCursorPosition.Y - ws.srWindow.Bottom);
        ws.dwCursorPosition.Y = ws.srWindow.Bottom;
        console_goto(io, INT2FIX(ws.dwCursorPosition.Y), INT2FIX(ws.dwCursorPosition.X));
    }
    if (ws.srWindow.Bottom > ws.dwSize.Y - 1) {
        console_scroll(io, ws.srWindow.Bottom - (ws.dwSize.Y - 1));
        ws.dwCursorPosition.Y -= ws.srWindow.Bottom - (ws.dwSize.Y - 1);
        console_goto(io, INT2FIX(ws.dwCursorPosition.Y), INT2FIX(ws.dwCursorPosition.X));
  ws.srWindow.Bottom = ws.dwSize.Y - 1;
    }
    ws.srWindow.Top = ws.srWindow.Bottom - (newrow - 1);
    /* perform changes to winsize */
    if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) {
        int last_error = LAST_ERROR;
        SetConsoleScreenBufferSize(wh, oldsize);
  rb_syserr_fail(last_error, "SetConsoleWindowInfo");
    }
    /* perform screen buffer shrinking if necessary */
    if ((ws.dwSize.Y < oldsize.Y || ws.dwSize.X < oldsize.X) &&
        !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;
}