mirror of
https://github.com/ruby/ruby.git
synced 2026-08-07 01:37:15 +08:00
[ruby/io-console] Accept multiple mode arguments
https://github.com/ruby/io-console/commit/d140425f9f
This commit is contained in:
parent
f407596837
commit
d1bfedce7f
@ -1914,52 +1914,59 @@ console_ttyname(VALUE io)
|
||||
# define console_ttyname rb_f_notimplement
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
platform_none,
|
||||
#ifdef HAVE_RB_PREPEND_MODULE
|
||||
platform_any,
|
||||
typedef enum {
|
||||
platform_default,
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
platform_cygwin,
|
||||
platform_msys,
|
||||
#endif
|
||||
platform_any,
|
||||
|
||||
platform_default_bit = 1U << platform_default,
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
platform_cygwin_bit = 1U << platform_cygwin,
|
||||
platform_msys_bit = 1U << platform_msys,
|
||||
#endif
|
||||
platform_max
|
||||
platform_any_bit = (1U << platform_any) - 1 /* all bits */
|
||||
} console_platform_t;
|
||||
|
||||
#ifdef HAVE_RB_PREPEND_MODULE
|
||||
/*
|
||||
* call-seq:
|
||||
* io.tty?([mode]) -> true or false
|
||||
* io.tty?([mode, ...]) -> true or false
|
||||
*
|
||||
* Returns +true+ if the stream is associated with a terminal device (tty),
|
||||
* +false+ otherwise.
|
||||
*
|
||||
* If non-nil +mode+ is given, platform dependent tty is also checked
|
||||
* in addition to the default tty.
|
||||
* If one or more +type+s are given, returns +true+ if the stream is
|
||||
* associated with any of the specified tty types.
|
||||
*
|
||||
* - +:any+ : Returns +true+ for any known kind of tty.
|
||||
* - +: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.
|
||||
*/
|
||||
static VALUE
|
||||
console_platform_tty_p(int argc, VALUE *argv, VALUE io)
|
||||
{
|
||||
VALUE ret;
|
||||
console_platform_t mode = platform_none;
|
||||
VALUE ret = Qfalse;
|
||||
int mode = 0;
|
||||
|
||||
if (rb_check_arity(argc, 0, 1)) {
|
||||
VALUE m = argv[0];
|
||||
if (!NIL_P(m)) {
|
||||
if (argc > 0) {
|
||||
int i;
|
||||
for (i = 0; i < argc; ++i) {
|
||||
VALUE m = argv[i];
|
||||
if (NIL_P(m)) continue;
|
||||
Check_Type(m, T_SYMBOL);
|
||||
if (m == ID2SYM(rb_intern("any"))) {
|
||||
mode = platform_any;
|
||||
mode |= platform_any_bit;
|
||||
}
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
else if (m == ID2SYM(rb_intern("cygwin"))) {
|
||||
mode = platform_cygwin;
|
||||
mode |= platform_cygwin_bit;
|
||||
}
|
||||
else if (m == ID2SYM(rb_intern("msys"))) {
|
||||
mode = platform_msys;
|
||||
mode |= platform_msys_bit;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
@ -1967,37 +1974,34 @@ console_platform_tty_p(int argc, VALUE *argv, VALUE io)
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = rb_call_super(0, 0);
|
||||
if (mode != platform_none && !RTEST(ret)) {
|
||||
if ((mode & platform_default_bit) || (mode == 0)) {
|
||||
ret = rb_call_super(0, 0);
|
||||
}
|
||||
if ((mode & ~platform_default_bit) && !RTEST(ret)) {
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
HANDLE h;
|
||||
union {
|
||||
FILE_NAME_INFO info;
|
||||
WCHAR rest[MAX_PATH];
|
||||
} buffer;
|
||||
WCHAR *const name = buffer.info.FileName;
|
||||
const WCHAR *ptr;
|
||||
DWORD len;
|
||||
if (mode & (platform_cygwin_bit | platform_msys_bit)) {
|
||||
struct {
|
||||
FILE_NAME_INFO info;
|
||||
WCHAR rest[MAX_PATH];
|
||||
} buffer;
|
||||
|
||||
h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(io));
|
||||
if (GetFileType(h) != FILE_TYPE_PIPE) return Qfalse;
|
||||
if (!GetFileInformationByHandleEx(h, FileNameInfo, &buffer, sizeof(buffer))) return Qfalse;
|
||||
len = buffer.info.FileNameLength / sizeof(WCHAR);
|
||||
name[len] = L'\0';
|
||||
# define skip_platform_tty_prefix(type) \
|
||||
(memcmp(name, L"\\" #type "-", sizeof(L"\\" #type)) == 0 ? \
|
||||
&name[rb_strlen_lit(L"\\" #type "-")] : 0)
|
||||
if (mode == platform_cygwin || mode == platform_any) {
|
||||
ptr = skip_platform_tty_prefix(cygwin);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mode == platform_msys || mode == platform_any) {
|
||||
ptr = skip_platform_tty_prefix(msys);
|
||||
}
|
||||
else {
|
||||
return Qfalse;
|
||||
}
|
||||
if (!ptr) return Qfalse;
|
||||
if (wcsstr(ptr, L"-pty")) ret = Qtrue;
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
|
||||
@ -61,16 +61,32 @@ class TestIO_Console < Test::Unit::TestCase
|
||||
end
|
||||
end
|
||||
|
||||
TTY_ENHANCED = IO.instance_method(:tty?).arity != 0
|
||||
|
||||
def test_tty?
|
||||
omit "not supported" if IO.instance_method(:tty?).arity == 0
|
||||
assert_include([true, false], STDIN.tty?(:any))
|
||||
pend "not supported" unless TTY_ENHANCED
|
||||
|
||||
tty = STDIN.tty?(:any)
|
||||
assert_include([true, false], tty)
|
||||
assert_equal(tty, STDIN.tty?(:any, :any))
|
||||
end
|
||||
|
||||
def test_tty_non_tty
|
||||
pend "not supported" unless TTY_ENHANCED
|
||||
|
||||
File.open(IO::NULL) do |f|
|
||||
assert_not_predicate(f, :tty?)
|
||||
assert_not_operator(f, :tty?, :any)
|
||||
assert_not_send([f, :tty?, :any, :any])
|
||||
|
||||
assert_raise(TypeError) {f.tty?("any")}
|
||||
assert_raise(ArgumentError) {f.tty?(:unknown)}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
|
||||
defined?(PTY) and defined?(IO.console) and \
|
||||
class TestIO_Console
|
||||
Bug6116 = '[ruby-dev:45309]'
|
||||
|
||||
def test_raw
|
||||
@ -250,6 +266,19 @@ defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
|
||||
}
|
||||
end
|
||||
|
||||
def test_tty_on_pty
|
||||
pend "not supported" unless TTY_ENHANCED
|
||||
|
||||
helper {|_, s|
|
||||
assert_predicate(s, :tty?)
|
||||
assert_operator(s, :tty?, :any)
|
||||
assert_send([s, :tty?, :any, :any])
|
||||
|
||||
assert_raise(TypeError) {s.tty?("any")}
|
||||
assert_raise(ArgumentError) {s.tty?(:unknown)}
|
||||
}
|
||||
end
|
||||
|
||||
def test_getpass
|
||||
run_pty("p IO.console.getpass('> ')") do |r, w|
|
||||
assert_equal("> ", r.readpartial(10))
|
||||
@ -503,7 +532,8 @@ defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
|
||||
end
|
||||
end
|
||||
|
||||
defined?(IO.console) and IO.console and TestIO_Console.class_eval do
|
||||
defined?(IO.console) and IO.console and \
|
||||
class TestIO_Console
|
||||
def test_get_winsize_console
|
||||
s = IO.console.winsize
|
||||
assert_kind_of(Array, s)
|
||||
@ -613,8 +643,8 @@ defined?(IO.console) and IO.console and TestIO_Console.class_eval do
|
||||
end
|
||||
end
|
||||
|
||||
defined?(IO.console) and IO.console and IO.console.respond_to?(:pressed?) and
|
||||
TestIO_Console.class_eval do
|
||||
defined?(IO.console) and IO.console and IO.console.respond_to?(:pressed?) and \
|
||||
class TestIO_Console
|
||||
def test_pressed_valid
|
||||
assert_include([true, false], IO.console.pressed?("HOME"))
|
||||
assert_include([true, false], IO.console.pressed?(:"HOME"))
|
||||
@ -628,7 +658,7 @@ defined?(IO.console) and IO.console and IO.console.respond_to?(:pressed?) and
|
||||
end
|
||||
end
|
||||
|
||||
TestIO_Console.class_eval do
|
||||
class TestIO_Console
|
||||
def test_stringio_getch
|
||||
assert_ruby_status %w"--disable=gems -rstringio -rio/console", %q{
|
||||
abort unless StringIO.method_defined?(:getch)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user