Class: IO

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

Defined Under Namespace

Modules: generic_readable Classes: ConsoleMode

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)

      ]



1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
# File 'ext/io/console/console.c', line 1703

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

.default_console_sizeObject

fallback to console window size



3
4
5
6
7
8
# File 'lib/io/console/size.rb', line 3

def IO.default_console_size
  [
    ENV["LINES"].to_i.nonzero? || 25,
    ENV["COLUMNS"].to_i.nonzero? || 80,
  ]
end

Instance Method Details

#beepObject

Beeps on the output console.

You must require ‘io/console’ to use this method.



1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
# File 'ext/io/console/console.c', line 1070

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.

This method is Windows only.

You must require ‘io/console’ to use this method.

Yields:

Returns:



976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
# File 'ext/io/console/console.c', line 976

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_screenIO

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

You must require ‘io/console’ to use this method.

Returns:



1596
1597
1598
1599
1600
1601
1602
# File 'ext/io/console/console.c', line 1596

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

#console_modeObject

Returns a data represents the current console mode.

You must require ‘io/console’ to use this method.



773
774
775
776
777
778
779
780
781
782
# File 'ext/io/console/console.c', line 773

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.



792
793
794
795
796
797
798
799
800
801
802
803
804
# File 'ext/io/console/console.c', line 792

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)


495
496
497
498
499
# File 'ext/io/console/console.c', line 495

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.



511
512
513
514
515
516
517
518
519
520
# File 'ext/io/console/console.c', line 511

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)


1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
# File 'ext/io/console/console.c', line 1264

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.



1496
1497
1498
1499
1500
1501
1502
# File 'ext/io/console/console.c', line 1496

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:



1526
1527
1528
1529
1530
# File 'ext/io/console/console.c', line 1526

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:



1540
1541
1542
1543
1544
# File 'ext/io/console/console.c', line 1540

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:



1554
1555
1556
1557
1558
# File 'ext/io/console/console.c', line 1554

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:



1512
1513
1514
1515
1516
# File 'ext/io/console/console.c', line 1512

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.



666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
# File 'ext/io/console/console.c', line 666

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)


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

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:



1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
# File 'ext/io/console/console.c', line 1397

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:



1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
# File 'ext/io/console/console.c', line 1444

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)


561
562
563
564
565
566
567
568
569
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
# File 'ext/io/console/console.c', line 561

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)


1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
# File 'ext/io/console/console.c', line 1847

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:



1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
# File 'ext/io/console/console.c', line 1302

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:



1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
# File 'ext/io/console/console.c', line 1363

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

#iflushObject

Flushes input buffer in kernel.

You must require ‘io/console’ to use this method.



1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
# File 'ext/io/console/console.c', line 1005

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

#ioflushObject

Flushes input and output buffers in kernel.

You must require ‘io/console’ to use this method.



1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
# File 'ext/io/console/console.c', line 1043

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


650
651
652
653
654
# File 'ext/io/console/console.c', line 650

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.



1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
# File 'ext/io/console/console.c', line 1024

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)


1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
# File 'ext/io/console/console.c', line 1151

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)


452
453
454
455
456
457
# File 'ext/io/console/console.c', line 452

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:



471
472
473
474
475
476
477
478
479
480
481
# File 'ext/io/console/console.c', line 471

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:



1582
1583
1584
1585
1586
# File 'ext/io/console/console.c', line 1582

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:



1568
1569
1570
1571
1572
# File 'ext/io/console/console.c', line 1568

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

#ttynameString?

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

Returns:

  • (String, nil)


1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
# File 'ext/io/console/console.c', line 1887

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
}

#winsizeArray

Returns console size.

You must require ‘io/console’ to use this method.

Returns:

  • (Array)


834
835
836
837
838
839
840
841
# File 'ext/io/console/console.c', line 834

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.



855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
# File 'ext/io/console/console.c', line 855

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