类 IO
公共类方法
返回一个打开的控制台 File 实例。
如果给定了 sym
,它将与 args
一起发送到打开的控制台,并将返回结果,而不是控制台 IO
本身。
您必须使用 ‘io/console’ 来使用此方法。
static VALUE console_dev(int argc, VALUE *argv, VALUE klass) { VALUE con = 0; VALUE sym = 0; rb_check_arity(argc, 0, UNLIMITED_ARGUMENTS); if (argc) { Check_Type(sym = argv[0], T_SYMBOL); } // Force the class to be File. if (klass == rb_cIO) klass = rb_cFile; if (rb_const_defined(klass, id_console)) { con = rb_const_get(klass, id_console); if (!RB_TYPE_P(con, T_FILE) || RTEST(rb_io_closed_p(con))) { rb_const_remove(klass, id_console); con = 0; } } if (sym) { if (sym == ID2SYM(id_close) && argc == 1) { if (con) { rb_io_close(con); rb_const_remove(klass, id_console); 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; rb_io_t *ofptr; #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 rb_const_set(klass, id_console, con); } if (sym) { return rb_f_send(argc, argv, con); } return con; }
回退到控制台窗口大小
# File io/console/lib/console/size.rb, line 3 def IO.default_console_size [ ENV["LINES"].to_i.nonzero? || 25, ENV["COLUMNS"].to_i.nonzero? || 80, ] end
公共实例方法
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; }
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; }
static VALUE console_clear_screen(VALUE io) { console_erase_screen(io, INT2FIX(2)); console_goto(io, INT2FIX(0), INT2FIX(0)); return io; }
返回表示当前控制台模式的数据。
您必须使用 ‘io/console’ 来使用此方法。
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); }
将控制台模式设置为 mode
。
您必须使用 ‘io/console’ 来使用此方法。
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 模式下返回 self
。
STDIN.cooked(&:gets)
将读取并返回一行,并回显和进行行编辑。
您必须使用 ‘io/console’ 来使用此方法。
static VALUE console_cooked(VALUE io) { return ttymode(io, rb_yield, io, set_cookedmode, NULL); }
启用 cooked 模式。
如果需要将终端模式恢复,请使用 io.cooked { … }。
您必须使用 ‘io/console’ 来使用此方法。
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; }
返回当前光标位置,以包含两个整数元素的数组表示(行,列)。
io.cursor # => [3, 5]
您必须使用 ‘io/console’ 来使用此方法。
static VALUE console_cursor_pos(VALUE io) { #ifdef _WIN32 rb_console_size_t ws; int fd = GetWriteFD(io); if (!GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), &ws)) { rb_syserr_fail(LAST_ERROR, 0); } return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.Y), UINT2NUM(ws.dwCursorPosition.X)); #else static const struct query_args query = {"\033[6n", 0}; VALUE resp = console_vt_response(0, 0, io, &query); VALUE row, column, term; unsigned int r, c; if (!RB_TYPE_P(resp, T_ARRAY) || RARRAY_LEN(resp) != 3) return Qnil; term = RARRAY_AREF(resp, 2); if (!RB_TYPE_P(term, T_STRING) || RSTRING_LEN(term) != 1) return Qnil; if (RSTRING_PTR(term)[0] != 'R') return Qnil; row = RARRAY_AREF(resp, 0); column = RARRAY_AREF(resp, 1); rb_ary_resize(resp, 2); r = NUM2UINT(row) - 1; c = NUM2UINT(column) - 1; RARRAY_ASET(resp, 0, INT2NUM(r)); RARRAY_ASET(resp, 1, INT2NUM(c)); return resp; #endif }
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)); }
static VALUE console_cursor_down(VALUE io, VALUE val) { return console_move(io, +NUM2INT(val), 0); }
static VALUE console_cursor_left(VALUE io, VALUE val) { return console_move(io, 0, -NUM2INT(val)); }
static VALUE console_cursor_right(VALUE io, VALUE val) { return console_move(io, 0, +NUM2INT(val)); }
static VALUE console_cursor_up(VALUE io, VALUE val) { return console_move(io, -NUM2INT(val), 0); }
启用/禁用回显。在某些平台上,此标志和 raw/cooked 模式的所有组合可能无效。
您必须使用 ‘io/console’ 来使用此方法。
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; }
如果启用了回显,则返回 true
。
您必须使用 ‘io/console’ 来使用此方法。
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; }
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("\x1b[%dK", mode)); #endif return io; }
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("\x1b[%dJ", mode)); #endif return io; }
在 raw 模式下读取并返回一个字符。
有关参数的详细信息,请参见 IO#raw
。
您必须使用 ‘io/console’ 来使用此方法。
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 }
读取并返回一行,不回显。除非为 nil
,否则打印 prompt
。
从返回的字符串中删除终止读取行的换行符,请参见 String#chomp!。
您必须使用 ‘io/console’ 来使用此方法。
require 'io/console' IO::console.getpass("Enter password:") Enter password: # => "mypassword"
static VALUE console_getpass(int argc, VALUE *argv, VALUE io) { VALUE str, wio; rb_check_arity(argc, 0, 1); wio = rb_io_get_write_io(io); if (wio == io && io == rb_stdin) wio = rb_stderr; prompt(argc, argv, wio); rb_io_flush(wio); str = rb_ensure(getpass_call, io, puts_call, wio); return str_chomp(str); }
static VALUE console_goto(VALUE io, VALUE y, VALUE x) { #ifdef _WIN32 COORD pos; int fd = GetWriteFD(io); pos.X = NUM2UINT(x); pos.Y = NUM2UINT(y); if (!SetConsoleCursorPosition((HANDLE)rb_w32_get_osfhandle(fd), pos)) { rb_syserr_fail(LAST_ERROR, 0); } #else rb_io_write(io, rb_sprintf("\x1b[%d;%dH", NUM2UINT(y)+1, NUM2UINT(x)+1)); #endif return io; }
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("\x1b[%dG", NUM2UINT(val)+1)); #endif return io; }
刷新内核中的输入缓冲区。
您必须使用 ‘io/console’ 来使用此方法。
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; }
在内核中刷新输入和输出缓冲区。
您必须使用 ‘io/console’ 来使用此方法。
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; }
禁用回显,并返回 self
。
STDIN.noecho(&:gets)
将读取并返回一行,不回显。
您必须使用 ‘io/console’ 来使用此方法。
static VALUE console_noecho(VALUE io) { return ttymode(io, rb_yield, io, set_noecho, NULL); }
在非阻塞模式下返回 self
。
当参数为 false
时,self
将在阻塞模式下返回。在代码块执行完毕后,将恢复原始模式。
static VALUE rb_io_nonblock_block(int argc, VALUE *argv, VALUE self) { int nb = 1; int descriptor = rb_io_descriptor(self); if (argc > 0) { VALUE v; rb_scan_args(argc, argv, "01", &v); nb = RTEST(v); } int current_flags = get_fcntl_flags(descriptor); int restore[2] = {descriptor, current_flags}; if (!io_nonblock_set(descriptor, current_flags, nb)) return rb_yield(self); return rb_ensure(rb_yield, self, io_nonblock_restore, (VALUE)restore); }
当设置为 true
时,在流上启用非阻塞模式,当设置为 false
时,启用阻塞模式。
此方法在 ios 中设置或清除文件描述符的 O_NONBLOCK 标志。
大多数 IO
方法的行为不受此标志影响,因为它们在 EAGAIN 和部分读写后会重试系统调用以完成任务。(IO#syswrite 是一个例外,它不会重试。)
此方法可用于清除标准 I/O 的非阻塞模式。由于非阻塞方法(read_nonblock 等)会设置非阻塞模式,但不会清除它,因此此方法可用于以下情况。
END { STDOUT.nonblock = false } STDOUT.write_nonblock("foo")
由于该标志在进程之间共享,并且许多非 Ruby 命令不期望标准 I/O 处于非阻塞模式,因此在 Ruby 程序退出之前清除该标志是安全的。
例如,以下 Ruby 程序将 STDIN/STDOUT/STDER 留在非阻塞模式下。(STDIN、STDOUT 和 STDERR 连接到终端。因此,使其中一个处于非阻塞模式会影响另外两个。)因此,cat 命令尝试从标准输入读取,并导致“资源暂时不可用”错误(EAGAIN)。
% ruby -e ' STDOUT.write_nonblock("foo\n")'; cat foo cat: -: Resource temporarily unavailable
清除该标志将使 cat 命令的行为正常。(cat 命令将等待来自标准输入的输入。)
% ruby -rio/nonblock -e ' END { STDOUT.nonblock = false } STDOUT.write_nonblock("foo") '; cat foo
static VALUE rb_io_nonblock_set(VALUE self, VALUE value) { if (RTEST(value)) { rb_io_t *fptr; GetOpenFile(self, fptr); rb_io_set_nonblock(fptr); } else { int descriptor = rb_io_descriptor(self); io_nonblock_set(descriptor, get_fcntl_flags(descriptor), RTEST(value)); } return self; }
如果 IO
对象处于非阻塞模式,则返回 true
。
static VALUE rb_io_nonblock_p(VALUE io) { if (get_fcntl_flags(rb_io_descriptor(io)) & O_NONBLOCK) return Qtrue; return Qfalse; }
返回可以在不阻塞的情况下读取的字节数。如果无可用信息,则返回零。
您必须要求‘io/wait’才能使用此方法。
static VALUE io_nread(VALUE io) { rb_io_t *fptr; int len; ioctl_arg n; GetOpenFile(io, fptr); rb_io_check_readable(fptr); len = rb_io_read_pending(fptr); if (len > 0) return INT2FIX(len); #ifdef HAVE_RB_IO_DESCRIPTOR int fd = rb_io_descriptor(io); #else int fd = fptr->fd; #endif if (!FIONREAD_POSSIBLE_P(fd)) return INT2FIX(0); if (ioctl(fd, FIONREAD, &n)) return INT2FIX(0); if (n > 0) return ioctl_arg2num(n); return INT2FIX(0); }
刷新内核中的输出缓冲区。
您必须使用 ‘io/console’ 来使用此方法。
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; }
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; }
在原始模式下 yield self
,并返回块的结果。
STDIN.raw(&:gets)
将读取并返回一行,不回显也不进行行编辑。
参数 min
指定执行读取操作时应接收的最小字节数。(默认值:1)
参数 time
指定以秒为单位的超时时间,精度为 1/10 秒。(默认值:0)
如果参数 intr
为 true
,则启用 break、interrupt、quit 和 suspend 特殊字符。
有关更多详细信息,请参阅 termios 手册页。
您必须使用 ‘io/console’ 来使用此方法。
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); }
启用原始模式,并返回 io
。
如果需要恢复终端模式,请使用 io.raw { ... }
。
有关参数的详细信息,请参见 IO#raw
。
您必须使用 ‘io/console’ 来使用此方法。
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; }
如果输入可用且不阻塞,则返回真值,否则返回假值。
您必须要求‘io/wait’才能使用此方法。
static VALUE io_ready_p(VALUE io) { rb_io_t *fptr; #ifndef HAVE_RB_IO_WAIT struct timeval tv = {0, 0}; #endif GetOpenFile(io, fptr); rb_io_check_readable(fptr); if (rb_io_read_pending(fptr)) return Qtrue; #ifndef HAVE_RB_IO_WAIT return wait_for_single_fd(fptr, RB_WAITFD_IN, &tv) ? Qtrue : Qfalse; #else return io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0), 1); #endif }
static VALUE console_scroll_backward(VALUE io, VALUE val) { return console_scroll(io, -NUM2INT(val)); }
static VALUE console_scroll_forward(VALUE io, VALUE val) { return console_scroll(io, +NUM2INT(val)); }
等待直到 IO
准备好处理指定的事件,并返回已准备好的事件子集,或在超时时返回假值。
事件可以是 IO::READABLE
、IO::WRITABLE
或 IO::PRIORITY
的位掩码。
当缓冲数据可用时立即返回真值。
可选参数 mode
可以是 :read
、:write
或 :read_write
之一。
您必须要求‘io/wait’才能使用此方法。
static VALUE io_wait(int argc, VALUE *argv, VALUE io) { #ifndef HAVE_RB_IO_WAIT rb_io_t *fptr; struct timeval timerec; struct timeval *tv = NULL; int event = 0; int i; GetOpenFile(io, fptr); for (i = 0; i < argc; ++i) { if (SYMBOL_P(argv[i])) { event |= wait_mode_sym(argv[i]); } else { *(tv = &timerec) = rb_time_interval(argv[i]); } } /* rb_time_interval() and might_mode() might convert the argument */ rb_io_check_closed(fptr); if (!event) event = RB_WAITFD_IN; if ((event & RB_WAITFD_IN) && rb_io_read_pending(fptr)) return Qtrue; if (wait_for_single_fd(fptr, event, tv)) return io; return Qnil; #else VALUE timeout = Qundef; rb_io_event_t events = 0; int i, return_io = 0; /* The documented signature for this method is actually incorrect. * A single timeout is allowed in any position, and multiple symbols can be given. * Whether this is intentional or not, I don't know, and as such I consider this to * be a legacy/slow path. */ if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) { /* We'd prefer to return the actual mask, but this form would return the io itself: */ return_io = 1; /* Slow/messy path: */ for (i = 0; i < argc; i += 1) { if (RB_SYMBOL_P(argv[i])) { events |= wait_mode_sym(argv[i]); } else if (timeout == Qundef) { rb_time_interval(timeout = argv[i]); } else { rb_raise(rb_eArgError, "timeout given more than once"); } } if (timeout == Qundef) timeout = Qnil; if (events == 0) { events = RUBY_IO_READABLE; } } else /* argc == 2 and neither are symbols */ { /* This is the fast path: */ events = io_event_from_value(argv[0]); timeout = argv[1]; } if (events & RUBY_IO_READABLE) { rb_io_t *fptr = NULL; RB_IO_POINTER(io, fptr); if (rb_io_read_pending(fptr)) { /* This was the original behaviour: */ if (return_io) return Qtrue; /* New behaviour always returns an event mask: */ else return RB_INT2NUM(RUBY_IO_READABLE); } } return io_wait_event(io, events, timeout, return_io); #endif }
等待直到 IO
处于优先级状态,并返回真值,或在超时时返回假值。优先级数据使用 Socket::MSG_OOB 标志发送和接收,通常限于流。
您必须要求‘io/wait’才能使用此方法。
static VALUE io_wait_priority(int argc, VALUE *argv, VALUE io) { rb_io_t *fptr = NULL; RB_IO_POINTER(io, fptr); rb_io_check_readable(fptr); if (rb_io_read_pending(fptr)) return Qtrue; rb_check_arity(argc, 0, 1); VALUE timeout = argc == 1 ? argv[0] : Qnil; return io_wait_event(io, RUBY_IO_PRIORITY, timeout, 1); }
等待直到 IO
可读并返回真值,或在超时时返回假值。当有缓冲数据可用时,立即返回真值。
您必须要求‘io/wait’才能使用此方法。
static VALUE io_wait_readable(int argc, VALUE *argv, VALUE io) { rb_io_t *fptr; #ifndef HAVE_RB_IO_WAIT struct timeval timerec; struct timeval *tv; #endif GetOpenFile(io, fptr); rb_io_check_readable(fptr); #ifndef HAVE_RB_IO_WAIT tv = get_timeout(argc, argv, &timerec); #endif if (rb_io_read_pending(fptr)) return Qtrue; #ifndef HAVE_RB_IO_WAIT if (wait_for_single_fd(fptr, RB_WAITFD_IN, tv)) { return io; } return Qnil; #else rb_check_arity(argc, 0, 1); VALUE timeout = (argc == 1 ? argv[0] : Qnil); return io_wait_event(io, RUBY_IO_READABLE, timeout, 1); #endif }
等待直到 IO
可写并返回真值,或在超时时返回假值。
您必须要求‘io/wait’才能使用此方法。
static VALUE io_wait_writable(int argc, VALUE *argv, VALUE io) { rb_io_t *fptr; #ifndef HAVE_RB_IO_WAIT struct timeval timerec; struct timeval *tv; #endif GetOpenFile(io, fptr); rb_io_check_writable(fptr); #ifndef HAVE_RB_IO_WAIT tv = get_timeout(argc, argv, &timerec); if (wait_for_single_fd(fptr, RB_WAITFD_OUT, tv)) { return io; } return Qnil; #else rb_check_arity(argc, 0, 1); VALUE timeout = (argc == 1 ? argv[0] : Qnil); return io_wait_event(io, RUBY_IO_WRITABLE, timeout, 1); #endif }
返回控制台大小。
您必须使用 ‘io/console’ 来使用此方法。
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))); }
尝试设置控制台大小。效果取决于平台和运行环境。
您必须使用 ‘io/console’ 来使用此方法。
static VALUE console_set_winsize(VALUE io, VALUE size) { rb_console_size_t ws; #if defined _WIN32 HANDLE wh; int newrow, newcol; BOOL ret; #endif VALUE row, col, xpixel, ypixel; const VALUE *sz; long sizelen; int fd; size = rb_Array(size); if ((sizelen = RARRAY_LEN(size)) != 2 && sizelen != 4) { rb_raise(rb_eArgError, "wrong number of arguments (given %ld, expected 2 or 4)", sizelen); } sz = RARRAY_CONST_PTR(size); row = sz[0], col = sz[1], xpixel = ypixel = Qnil; if (sizelen == 4) xpixel = sz[2], ypixel = sz[3]; fd = GetWriteFD(io); #if defined TIOCSWINSZ ws.ws_row = ws.ws_col = ws.ws_xpixel = ws.ws_ypixel = 0; #define SET(m) ws.ws_##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m) SET(row); SET(col); SET(xpixel); SET(ypixel); #undef SET if (!setwinsize(fd, &ws)) sys_fail(io); #elif defined _WIN32 wh = (HANDLE)rb_w32_get_osfhandle(fd); #define SET(m) new##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m) SET(row); SET(col); #undef SET if (!NIL_P(xpixel)) (void)NUM2UINT(xpixel); if (!NIL_P(ypixel)) (void)NUM2UINT(ypixel); if (!GetConsoleScreenBufferInfo(wh, &ws)) { rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo"); } ws.dwSize.X = newcol; ret = SetConsoleScreenBufferSize(wh, ws.dwSize); ws.srWindow.Left = 0; ws.srWindow.Top = 0; ws.srWindow.Right = newcol-1; ws.srWindow.Bottom = newrow-1; if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) { rb_syserr_fail(LAST_ERROR, "SetConsoleWindowInfo"); } /* retry when shrinking buffer after shrunk window */ if (!ret && !SetConsoleScreenBufferSize(wh, ws.dwSize)) { rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo"); } /* remove scrollbar if possible */ if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) { rb_syserr_fail(LAST_ERROR, "SetConsoleWindowInfo"); } #endif return io; }