1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* ext/io/console/console.c (console_raw, console_set_raw)

(console_getch): optional parameters.  [EXPERIMENTAL]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33786 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2011-11-18 08:18:18 +00:00
parent 3723ac22d2
commit 714ec98ec4
2 changed files with 70 additions and 26 deletions

View file

@ -1,3 +1,8 @@
Fri Nov 18 17:18:16 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/io/console/console.c (console_raw, console_set_raw)
(console_getch): optional parameters. [EXPERIMENTAL]
Fri Nov 18 16:12:11 2011 Nobuyoshi Nakada <nobu@ruby-lang.org> Fri Nov 18 16:12:11 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/io/console/console.c (console_cooked, console_set_cooked): * ext/io/console/console.c (console_cooked, console_set_cooked):

View file

@ -91,8 +91,37 @@ getattr(int fd, conmode *t)
static ID id_getc, id_console; static ID id_getc, id_console;
typedef struct {
int vmin;
int vtime;
} rawmode_arg_t;
static rawmode_arg_t *
rawmode_opt(int argc, VALUE *argv, rawmode_arg_t *opts)
{
rawmode_arg_t *optp = NULL;
VALUE vopts;
rb_scan_args(argc, argv, "0:", &vopts);
if (!NIL_P(vopts)) {
VALUE vmin = rb_hash_aref(vopts, ID2SYM(rb_intern("min")));
VALUE vtime = rb_hash_aref(vopts, ID2SYM(rb_intern("time")));
VALUE v10 = INT2FIX(10);
if (!NIL_P(vmin)) {
vmin = rb_funcall3(vmin, '*', 1, &v10);
opts->vmin = NUM2INT(vmin);
optp = opts;
}
if (!NIL_P(vtime)) {
vtime = rb_funcall3(vtime, '*', 1, &v10);
opts->vtime = NUM2INT(vtime);
optp = opts;
}
}
return optp;
}
static void static void
set_rawmode(conmode *t) set_rawmode(conmode *t, void *arg)
{ {
#ifdef HAVE_CFMAKERAW #ifdef HAVE_CFMAKERAW
cfmakeraw(t); cfmakeraw(t);
@ -108,10 +137,17 @@ set_rawmode(conmode *t)
#elif defined _WIN32 #elif defined _WIN32
*t = 0; *t = 0;
#endif #endif
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
if (arg) {
const rawmode_arg_t *r = arg;
if (r->vmin >= 0) t->c_cc[VMIN] = r->vmin;
if (r->vtime >= 0) t->c_cc[VTIME] = r->vtime;
}
#endif
} }
static void static void
set_cookedmode(conmode *t) set_cookedmode(conmode *t, void *arg)
{ {
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
t->c_iflag |= (BRKINT|ISTRIP|ICRNL|IXON); t->c_iflag |= (BRKINT|ISTRIP|ICRNL|IXON);
@ -126,7 +162,7 @@ set_cookedmode(conmode *t)
} }
static void static void
set_noecho(conmode *t) set_noecho(conmode *t, void *arg)
{ {
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
t->c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); t->c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
@ -138,7 +174,7 @@ set_noecho(conmode *t)
} }
static void static void
set_echo(conmode *t) set_echo(conmode *t, void *arg)
{ {
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
t->c_lflag |= (ECHO | ECHOE | ECHOK | ECHONL); t->c_lflag |= (ECHO | ECHOE | ECHOK | ECHONL);
@ -162,12 +198,12 @@ echo_p(conmode *t)
} }
static int static int
set_ttymode(int fd, conmode *t, void (*setter)(conmode *)) set_ttymode(int fd, conmode *t, void (*setter)(conmode *, void *), void *arg)
{ {
conmode r; conmode r;
if (!getattr(fd, t)) return 0; if (!getattr(fd, t)) return 0;
r = *t; r = *t;
setter(&r); setter(&r, arg);
return setattr(fd, &r); return setattr(fd, &r);
} }
@ -195,7 +231,7 @@ get_write_fd(const rb_io_t *fptr)
#define FD_PER_IO 2 #define FD_PER_IO 2
static VALUE static VALUE
ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *)) ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *, void *), void *arg)
{ {
rb_io_t *fptr; rb_io_t *fptr;
int status = -1; int status = -1;
@ -207,7 +243,7 @@ ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *))
GetOpenFile(io, fptr); GetOpenFile(io, fptr);
fd[0] = GetReadFD(fptr); fd[0] = GetReadFD(fptr);
if (fd[0] != -1) { if (fd[0] != -1) {
if (set_ttymode(fd[0], t+0, setter)) { if (set_ttymode(fd[0], t+0, setter, arg)) {
status = 0; status = 0;
} }
else { else {
@ -217,7 +253,7 @@ ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *))
} }
fd[1] = GetWriteFD(fptr); fd[1] = GetWriteFD(fptr);
if (fd[1] != -1 && fd[1] != fd[0]) { if (fd[1] != -1 && fd[1] != fd[0]) {
if (set_ttymode(fd[1], t+1, setter)) { if (set_ttymode(fd[1], t+1, setter, arg)) {
status = 0; status = 0;
} }
else { else {
@ -253,7 +289,7 @@ ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *))
/* /*
* call-seq: * call-seq:
* io.raw {|io| } * io.raw(min: nil, time: nil) {|io| }
* *
* Yields +self+ within raw mode. * Yields +self+ within raw mode.
* *
@ -262,30 +298,32 @@ ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *))
* will read and return a line with echo back and line editing. * will read and return a line with echo back and line editing.
*/ */
static VALUE static VALUE
console_raw(VALUE io) console_raw(int argc, VALUE *argv, VALUE io)
{ {
return ttymode(io, rb_yield, set_rawmode); rawmode_arg_t opts, *optp = rawmode_opt(argc, argv, &opts);
return ttymode(io, rb_yield, set_rawmode, optp);
} }
/* /*
* call-seq: * call-seq:
* io.raw! * io.raw!(min: nil, time: nil)
* *
* Enables raw mode. * Enables raw mode.
* *
* If the terminal mode needs to be back, use io.raw { ... }. * If the terminal mode needs to be back, use io.raw { ... }.
*/ */
static VALUE static VALUE
console_set_raw(VALUE io) console_set_raw(int argc, VALUE *argv, VALUE io)
{ {
conmode t; conmode t;
rb_io_t *fptr; rb_io_t *fptr;
int fd; int fd;
rawmode_arg_t opts, *optp = rawmode_opt(argc, argv, &opts);
GetOpenFile(io, fptr); GetOpenFile(io, fptr);
fd = GetReadFD(fptr); fd = GetReadFD(fptr);
if (!getattr(fd, &t)) rb_sys_fail(0); if (!getattr(fd, &t)) rb_sys_fail(0);
set_rawmode(&t); set_rawmode(&t, optp);
if (!setattr(fd, &t)) rb_sys_fail(0); if (!setattr(fd, &t)) rb_sys_fail(0);
return io; return io;
} }
@ -303,7 +341,7 @@ console_set_raw(VALUE io)
static VALUE static VALUE
console_cooked(VALUE io) console_cooked(VALUE io)
{ {
return ttymode(io, rb_yield, set_cookedmode); return ttymode(io, rb_yield, set_cookedmode, NULL);
} }
/* /*
@ -324,7 +362,7 @@ console_set_cooked(VALUE io)
GetOpenFile(io, fptr); GetOpenFile(io, fptr);
fd = GetReadFD(fptr); fd = GetReadFD(fptr);
if (!getattr(fd, &t)) rb_sys_fail(0); if (!getattr(fd, &t)) rb_sys_fail(0);
set_cookedmode(&t); set_cookedmode(&t, NULL);
if (!setattr(fd, &t)) rb_sys_fail(0); if (!setattr(fd, &t)) rb_sys_fail(0);
return io; return io;
} }
@ -337,14 +375,15 @@ getc_call(VALUE io)
/* /*
* call-seq: * call-seq:
* io.getch -> char * io.getch(min: nil, time: nil) -> char
* *
* Reads and returns a character in raw mode. * Reads and returns a character in raw mode.
*/ */
static VALUE static VALUE
console_getch(VALUE io) console_getch(int argc, VALUE *argv, VALUE io)
{ {
return ttymode(io, getc_call, set_rawmode); rawmode_arg_t opts, *optp = rawmode_opt(argc, argv, &opts);
return ttymode(io, getc_call, set_rawmode, optp);
} }
/* /*
@ -360,7 +399,7 @@ console_getch(VALUE io)
static VALUE static VALUE
console_noecho(VALUE io) console_noecho(VALUE io)
{ {
return ttymode(io, rb_yield, set_noecho); return ttymode(io, rb_yield, set_noecho, NULL);
} }
/* /*
@ -380,9 +419,9 @@ console_set_echo(VALUE io, VALUE f)
fd = GetReadFD(fptr); fd = GetReadFD(fptr);
if (!getattr(fd, &t)) rb_sys_fail(0); if (!getattr(fd, &t)) rb_sys_fail(0);
if (RTEST(f)) if (RTEST(f))
set_echo(&t); set_echo(&t, NULL);
else else
set_noecho(&t); set_noecho(&t, NULL);
if (!setattr(fd, &t)) rb_sys_fail(0); if (!setattr(fd, &t)) rb_sys_fail(0);
return io; return io;
} }
@ -665,11 +704,11 @@ Init_console(void)
void void
InitVM_console(void) InitVM_console(void)
{ {
rb_define_method(rb_cIO, "raw", console_raw, 0); rb_define_method(rb_cIO, "raw", console_raw, -1);
rb_define_method(rb_cIO, "raw!", console_set_raw, 0); rb_define_method(rb_cIO, "raw!", console_set_raw, -1);
rb_define_method(rb_cIO, "cooked", console_cooked, 0); rb_define_method(rb_cIO, "cooked", console_cooked, 0);
rb_define_method(rb_cIO, "cooked!", console_set_cooked, 0); rb_define_method(rb_cIO, "cooked!", console_set_cooked, 0);
rb_define_method(rb_cIO, "getch", console_getch, 0); rb_define_method(rb_cIO, "getch", console_getch, -1);
rb_define_method(rb_cIO, "echo=", console_set_echo, 1); rb_define_method(rb_cIO, "echo=", console_set_echo, 1);
rb_define_method(rb_cIO, "echo?", console_echo_p, 0); rb_define_method(rb_cIO, "echo?", console_echo_p, 0);
rb_define_method(rb_cIO, "noecho", console_noecho, 0); rb_define_method(rb_cIO, "noecho", console_noecho, 0);