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:
parent
3723ac22d2
commit
714ec98ec4
2 changed files with 70 additions and 26 deletions
|
@ -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>
|
||||
|
||||
* ext/io/console/console.c (console_cooked, console_set_cooked):
|
||||
|
|
|
@ -91,8 +91,37 @@ getattr(int fd, conmode *t)
|
|||
|
||||
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
|
||||
set_rawmode(conmode *t)
|
||||
set_rawmode(conmode *t, void *arg)
|
||||
{
|
||||
#ifdef HAVE_CFMAKERAW
|
||||
cfmakeraw(t);
|
||||
|
@ -108,10 +137,17 @@ set_rawmode(conmode *t)
|
|||
#elif defined _WIN32
|
||||
*t = 0;
|
||||
#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
|
||||
set_cookedmode(conmode *t)
|
||||
set_cookedmode(conmode *t, void *arg)
|
||||
{
|
||||
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
|
||||
t->c_iflag |= (BRKINT|ISTRIP|ICRNL|IXON);
|
||||
|
@ -126,7 +162,7 @@ set_cookedmode(conmode *t)
|
|||
}
|
||||
|
||||
static void
|
||||
set_noecho(conmode *t)
|
||||
set_noecho(conmode *t, void *arg)
|
||||
{
|
||||
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
|
||||
t->c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
|
||||
|
@ -138,7 +174,7 @@ set_noecho(conmode *t)
|
|||
}
|
||||
|
||||
static void
|
||||
set_echo(conmode *t)
|
||||
set_echo(conmode *t, void *arg)
|
||||
{
|
||||
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
|
||||
t->c_lflag |= (ECHO | ECHOE | ECHOK | ECHONL);
|
||||
|
@ -162,12 +198,12 @@ echo_p(conmode *t)
|
|||
}
|
||||
|
||||
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;
|
||||
if (!getattr(fd, t)) return 0;
|
||||
r = *t;
|
||||
setter(&r);
|
||||
setter(&r, arg);
|
||||
return setattr(fd, &r);
|
||||
}
|
||||
|
||||
|
@ -195,7 +231,7 @@ get_write_fd(const rb_io_t *fptr)
|
|||
#define FD_PER_IO 2
|
||||
|
||||
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;
|
||||
int status = -1;
|
||||
|
@ -207,7 +243,7 @@ ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *))
|
|||
GetOpenFile(io, fptr);
|
||||
fd[0] = GetReadFD(fptr);
|
||||
if (fd[0] != -1) {
|
||||
if (set_ttymode(fd[0], t+0, setter)) {
|
||||
if (set_ttymode(fd[0], t+0, setter, arg)) {
|
||||
status = 0;
|
||||
}
|
||||
else {
|
||||
|
@ -217,7 +253,7 @@ ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *))
|
|||
}
|
||||
fd[1] = GetWriteFD(fptr);
|
||||
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;
|
||||
}
|
||||
else {
|
||||
|
@ -253,7 +289,7 @@ ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *))
|
|||
|
||||
/*
|
||||
* call-seq:
|
||||
* io.raw {|io| }
|
||||
* io.raw(min: nil, time: nil) {|io| }
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
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:
|
||||
* io.raw!
|
||||
* io.raw!(min: nil, time: nil)
|
||||
*
|
||||
* Enables raw mode.
|
||||
*
|
||||
* If the terminal mode needs to be back, use io.raw { ... }.
|
||||
*/
|
||||
static VALUE
|
||||
console_set_raw(VALUE io)
|
||||
console_set_raw(int argc, VALUE *argv, VALUE io)
|
||||
{
|
||||
conmode t;
|
||||
rb_io_t *fptr;
|
||||
int fd;
|
||||
rawmode_arg_t opts, *optp = rawmode_opt(argc, argv, &opts);
|
||||
|
||||
GetOpenFile(io, fptr);
|
||||
fd = GetReadFD(fptr);
|
||||
if (!getattr(fd, &t)) rb_sys_fail(0);
|
||||
set_rawmode(&t);
|
||||
set_rawmode(&t, optp);
|
||||
if (!setattr(fd, &t)) rb_sys_fail(0);
|
||||
return io;
|
||||
}
|
||||
|
@ -303,7 +341,7 @@ console_set_raw(VALUE io)
|
|||
static VALUE
|
||||
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);
|
||||
fd = GetReadFD(fptr);
|
||||
if (!getattr(fd, &t)) rb_sys_fail(0);
|
||||
set_cookedmode(&t);
|
||||
set_cookedmode(&t, NULL);
|
||||
if (!setattr(fd, &t)) rb_sys_fail(0);
|
||||
return io;
|
||||
}
|
||||
|
@ -337,14 +375,15 @@ getc_call(VALUE io)
|
|||
|
||||
/*
|
||||
* call-seq:
|
||||
* io.getch -> char
|
||||
* io.getch(min: nil, time: nil) -> char
|
||||
*
|
||||
* Reads and returns a character in raw mode.
|
||||
*/
|
||||
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
|
||||
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);
|
||||
if (!getattr(fd, &t)) rb_sys_fail(0);
|
||||
if (RTEST(f))
|
||||
set_echo(&t);
|
||||
set_echo(&t, NULL);
|
||||
else
|
||||
set_noecho(&t);
|
||||
set_noecho(&t, NULL);
|
||||
if (!setattr(fd, &t)) rb_sys_fail(0);
|
||||
return io;
|
||||
}
|
||||
|
@ -665,11 +704,11 @@ Init_console(void)
|
|||
void
|
||||
InitVM_console(void)
|
||||
{
|
||||
rb_define_method(rb_cIO, "raw", console_raw, 0);
|
||||
rb_define_method(rb_cIO, "raw!", console_set_raw, 0);
|
||||
rb_define_method(rb_cIO, "raw", console_raw, -1);
|
||||
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_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_echo_p, 0);
|
||||
rb_define_method(rb_cIO, "noecho", console_noecho, 0);
|
||||
|
|
Loading…
Add table
Reference in a new issue