Class: IO
| Relationships & Source Files | |
| Namespace Children | |
|
Modules:
| |
| Inherits: | Object |
| Defined in: | ext/io/console/console.c |
Class Method Summary
-
.console ⇒ #<File:/dev/tty
Returns an File instance opened console.
-
.default_console_size
fallback to console window size.
Instance Attribute Summary
-
#console_mode ⇒ mode
rw
Returns a data represents the current console mode.
-
#console_mode=(mode)
rw
Sets the console mode to
mode. -
#cursor ⇒ Array, column
rw
Returns the current cursor position as a two-element array of integers (row, column).
-
#cursor=([line, column]) ⇒ IO
rw
Same as io.goto(line, column).
-
#echo=(flag)
rw
Enables/disables echo back.
-
#echo? ⇒ Boolean
rw
Returns
trueif echo back is enabled. -
#input_pending? ⇒ Boolean
readonly
Returns whether input can be read without blocking.
-
#winsize ⇒ Array, columns
rw
Returns console size.
-
#winsize=([rows, columns])
rw
Tries to set console size.
Instance Method Summary
-
#beep
Beeps on the output console.
-
#check_winsize_changed ⇒ IO
Yields while console input events are queued.
-
#clear_screen ⇒ IO
Clears the entire screen and moves the cursor top-left corner.
-
#console_input_events([max_events], timeout: nil) ⇒ Array
Reads up to
max_eventsconsole input events, preserving their order. -
#cooked {|io| ... }
Yields
selfwithin cooked mode. -
#cooked!
Enables cooked mode.
-
#cursor_down(n) ⇒ IO
Moves the cursor down
nlines. -
#cursor_left(n) ⇒ IO
Moves the cursor left
ncolumns. -
#cursor_right(n) ⇒ IO
Moves the cursor right
ncolumns. -
#cursor_up(n) ⇒ IO
Moves the cursor up
nlines. -
#erase_line(mode) ⇒ IO
Erases the line at the cursor corresponding to
mode. -
#erase_screen(mode) ⇒ IO
Erases the screen at the cursor corresponding to
mode. -
#getch(min: nil, time: nil, intr: nil) ⇒ String?
Reads and returns a character in raw mode.
-
#getpass(prompt = nil) ⇒ String
Reads and returns a line without echo back.
-
#goto(line, column) ⇒ IO
Set the cursor position at
lineandcolumn. -
#goto_column(column) ⇒ IO
Set the cursor position at
columnin the same line of the current position. -
#hide_cursor ⇒ IO
Hides the cursor.
-
#iflush
Flushes input buffer in kernel.
-
#ioflush
Flushes input and output buffers in kernel.
-
#isatty([mode, ...]) ⇒ Boolean
Alias for #tty?.
-
#noecho {|io| ... }
Yields
selfwith disabling echo back. -
#oflush
Flushes output buffer in kernel.
-
#pressed?(key) ⇒ Boolean
Returns
trueifkeyis pressed. -
#raw(min: nil, time: nil, intr: nil) {|io| ... }
Yields
selfwithin raw mode, and returns the result of the block. -
#raw!(min: nil, time: nil, intr: nil) ⇒ IO
Enables raw mode, and returns
io. -
#scroll_backward(n) ⇒ IO
Scrolls the entire scrolls backward
nlines. -
#scroll_forward(n) ⇒ IO
Scrolls the entire scrolls forward
nlines. -
#show_cursor ⇒ IO
Shows the cursor.
-
#tty?([mode, ...]) ⇒ Boolean
(also: #isatty)
Returns
trueif the stream is associated with a terminal device (tty),falseotherwise. -
#ttyname ⇒ String?
Returns name of associated terminal (tty) if
iois not a tty.
Class Method Details
.console ⇒ #<File:/dev/tty
.console(sym, *args)
File:/dev/tty
.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.
# File 'ext/io/console/console.c', line 2045
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_size
fallback to console window size
# File 'ext/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
Instance Attribute Details
#console_mode ⇒ mode (rw)
Returns a data represents the current console mode.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 869
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) (rw)
Sets the console mode to mode.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 888
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;
}
#cursor ⇒ Array, column (rw)
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.
# File 'ext/io/console/console.c', line 1558
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=([line, column]) ⇒ IO (rw)
# File 'ext/io/console/console.c', line 1838
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));
}
#echo=(flag) (rw)
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.
# File 'ext/io/console/console.c', line 698
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 (rw)
Returns true if echo back is enabled.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 724
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;
}
#input_pending? ⇒ Boolean (readonly)
Returns whether input can be read without blocking.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 641
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
}
#winsize ⇒ Array, columns (rw)
Returns console size.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 930
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]) (rw)
Tries to set console size. The effect depends on the platform and the running environment.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 951
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;
}
Instance Method Details
#beep
Beeps on the output console.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 1364
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 #console_input_events instead to preserve all events.
This method is Windows only.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 1266
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_screen ⇒ IO
Clears the entire screen and moves the cursor top-left corner.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 1938
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.
# File 'ext/io/console/console.c', line 1209
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);
}
#cooked {|io| ... }
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.
# File 'ext/io/console/console.c', line 490
static VALUE
console_cooked(VALUE io)
{
return ttymode(io, rb_yield, io, set_cookedmode, NULL);
}
#cooked!
Enables cooked mode.
If the terminal mode needs to be back, use io.cooked { ... }.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 506
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_down(n) ⇒ IO
Moves the cursor down n lines.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 1868
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.
# File 'ext/io/console/console.c', line 1882
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.
# File 'ext/io/console/console.c', line 1896
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.
# File 'ext/io/console/console.c', line 1854
static VALUE
console_cursor_up(VALUE io, VALUE val)
{
return console_move(io, -NUM2INT(val), 0);
}
#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.
# File 'ext/io/console/console.c', line 1739
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.
# File 'ext/io/console/console.c', line 1786
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 #raw for details on the parameters.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 556
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"
# File 'ext/io/console/console.c', line 2189
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.
# File 'ext/io/console/console.c', line 1644
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.
# File 'ext/io/console/console.c', line 1705
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_cursor ⇒ IO
Hides the cursor.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 1616
static VALUE
console_hide_cursor(VALUE io)
{
return console_cursor_visibility(io, 0);
}
#iflush
Flushes input buffer in kernel.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 1299
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
Flushes input and output buffers in kernel.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 1337
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, ...]) ⇒ Boolean
#isatty([mode, ...]) ⇒ Boolean
Boolean
#isatty([mode, ...]) ⇒ Boolean
Alias for #tty?.
#noecho {|io| ... }
Yields self with disabling echo back.
STDIN.noecho(&:gets)
will read and return a line without echo back.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 682
static VALUE
console_noecho(VALUE io)
{
return ttymode(io, rb_yield, io, set_noecho, NULL);
}
#oflush
Flushes output buffer in kernel.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 1318
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.
# File 'ext/io/console/console.c', line 1445
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| ... }
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.
# File 'ext/io/console/console.c', line 447
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 #raw for details on the parameters.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 466
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.
# File 'ext/io/console/console.c', line 1924
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.
# File 'ext/io/console/console.c', line 1910
static VALUE
console_scroll_forward(VALUE io, VALUE val)
{
return console_scroll(io, +NUM2INT(val));
}
#show_cursor ⇒ IO
Shows the cursor.
You must require 'io/console' to use this method.
# File 'ext/io/console/console.c', line 1630
static VALUE
console_show_cursor(VALUE io)
{
return console_cursor_visibility(io, 1);
}
#tty?([mode, ...]) ⇒ Boolean Also known as: #isatty
Returns true if the stream is associated with a terminal device (tty),
false otherwise.
If one or more types 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: Returnstruefor any known kind of tty, including the default tty.:cygwin: Returnstruefor cygwin tty, on Windows.:msys: Returnstruefor msys2 tty, on Windows.
# File 'ext/io/console/console.c', line 2309
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;
}
#ttyname ⇒ String?
Returns name of associated terminal (tty) if io is not a tty.
Returns nil otherwise.
# File 'ext/io/console/console.c', line 2229
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
}