summaryrefslogtreecommitdiff
path: root/ext/io/console
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2019-09-09 23:51:44 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2019-09-10 08:18:03 +0900
commite8be056af92b2f13162567c057322a2c16797b79 (patch)
tree27779bf718092a1da48c5e48d620bf1a402609e0 /ext/io/console
parent3d9c7c28358110076abb2d77365eef805ddb896c (diff)
[ruby/io-console] Added relative cursor move methods
https://github.com/ruby/io-console/commit/21d340e4a2
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2440
Diffstat (limited to 'ext/io/console')
-rw-r--r--ext/io/console/console.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/ext/io/console/console.c b/ext/io/console/console.c
index db40c1b014f..a99846cc24b 100644
--- a/ext/io/console/console.c
+++ b/ext/io/console/console.c
@@ -799,6 +799,27 @@ console_cursor_pos(VALUE io)
return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.X), UINT2NUM(ws.dwCursorPosition.Y));
}
+static VALUE
+console_move(VALUE io, int x, int y)
+{
+ rb_io_t *fptr;
+ HANDLE h;
+ rb_console_size_t ws;
+ COORD *pos = &ws.dwCursorPosition;
+
+ GetOpenFile(io, fptr);
+ h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(fptr));
+ if (!GetConsoleScreenBufferInfo(h, &ws)) {
+ rb_syserr_fail(LAST_ERROR, 0);
+ }
+ pos->X += x;
+ pos->Y += y;
+ if (!SetConsoleCursorPosition(h, *pos)) {
+ rb_syserr_fail(LAST_ERROR, 0);
+ }
+ return io;
+}
+
#include "win32_vk.inc"
static VALUE
@@ -889,6 +910,19 @@ console_goto(VALUE io, VALUE x, VALUE y)
rb_io_write(io, rb_sprintf("\x1b[%d;%dH", NUM2UINT(y), NUM2UINT(x)));
return io;
}
+
+static VALUE
+console_move(VALUE io, int x, int y)
+{
+ if (x || y) {
+ VALUE s = rb_str_new_cstr("");
+ if (y) rb_str_catf(s, "\x1b[%d%c", y < 0 ? -y : y, y < 0 ? 'A' : 'B');
+ if (x) rb_str_catf(s, "\x1b[%d%c", x < 0 ? -x : x, x < 0 ? 'D' : 'C');
+ rb_io_write(io, s);
+ rb_io_flush(io);
+ }
+ return io;
+}
# define console_key_pressed_p rb_f_notimplement
#endif
@@ -900,6 +934,38 @@ console_cursor_set(VALUE io, VALUE cpos)
return console_goto(io, RARRAY_AREF(cpos, 0), RARRAY_AREF(cpos, 1));
}
+static VALUE
+console_cursor_up(VALUE io, VALUE val)
+{
+ return console_move(io, 0, -NUM2INT(val));
+}
+
+static VALUE
+console_cursor_down(VALUE io, VALUE val)
+{
+ return console_move(io, 0, +NUM2INT(val));
+}
+
+static VALUE
+console_cursor_left(VALUE io, VALUE val)
+{
+ return console_move(io, -NUM2INT(val), 0);
+}
+
+static VALUE
+console_cursor_right(VALUE io, VALUE val)
+{
+ return console_move(io, +NUM2INT(val), 0);
+}
+
+static VALUE
+console_clear_screen(VALUE io)
+{
+ console_erase_screen(io, INT2FIX(2));
+ console_goto(io, INT2FIX(1), INT2FIX(1));
+ return io;
+}
+
/*
* call-seq:
* IO.console -> #<File:/dev/tty>
@@ -1124,6 +1190,10 @@ InitVM_console(void)
rb_define_method(rb_cIO, "goto", console_goto, 2);
rb_define_method(rb_cIO, "cursor", console_cursor_pos, 0);
rb_define_method(rb_cIO, "cursor=", console_cursor_set, 1);
+ rb_define_method(rb_cIO, "cursor_up", console_cursor_up, 1);
+ rb_define_method(rb_cIO, "cursor_down", console_cursor_down, 1);
+ rb_define_method(rb_cIO, "cursor_left", console_cursor_left, 1);
+ rb_define_method(rb_cIO, "cursor_right", console_cursor_right, 1);
rb_define_method(rb_cIO, "pressed?", console_key_pressed_p, 1);
#if ENABLE_IO_GETPASS
rb_define_method(rb_cIO, "getpass", console_getpass, -1);