io-console 0.5.11 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.document +5 -0
- data/ext/io/console/console.c +493 -356
- data/ext/io/console/extconf.rb +6 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea376ca7a23381cc7ad476248aa32fc95ff2fe19be07170f6eb4031b42e897ab
|
4
|
+
data.tar.gz: 321d946b43b46f279bb28d08c173c48b05e9c9a087d51cbcf1715153c772cda1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88f4b33458250ec0e9039c9187d144fb9c851753c39b7e5191db26e2b8a898ce5ac6d6897330c93ae8eab1c6a4cd800a7af9f36ce83fd20b6caedfc52a12ed50
|
7
|
+
data.tar.gz: 4235ecf65e5e0b81c196d62a0a95649f708a29e2c300d645e99301dd3b6a470dc30b3cad6e2151b8ebf69c15c797962f62f55d6cdb935179f0656d2e450939af
|
data/.document
ADDED
data/ext/io/console/console.c
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
/*
|
3
3
|
* console IO module
|
4
4
|
*/
|
5
|
+
|
6
|
+
static const char *const
|
7
|
+
IO_CONSOLE_VERSION = "0.7.2";
|
8
|
+
|
5
9
|
#include "ruby.h"
|
6
10
|
#include "ruby/io.h"
|
7
11
|
#include "ruby/thread.h"
|
@@ -75,10 +79,10 @@ getattr(int fd, conmode *t)
|
|
75
79
|
#define SET_LAST_ERROR (0)
|
76
80
|
#endif
|
77
81
|
|
78
|
-
|
79
|
-
|
80
|
-
static ID
|
81
|
-
|
82
|
+
#define CSI "\x1b\x5b"
|
83
|
+
|
84
|
+
static ID id_getc, id_console, id_close;
|
85
|
+
static ID id_gets, id_flush, id_chomp_bang;
|
82
86
|
|
83
87
|
#if defined HAVE_RUBY_FIBER_SCHEDULER_H
|
84
88
|
# include "ruby/fiber/scheduler.h"
|
@@ -87,7 +91,41 @@ extern VALUE rb_scheduler_timeout(struct timeval *timeout);
|
|
87
91
|
# define rb_fiber_scheduler_make_timeout rb_scheduler_timeout
|
88
92
|
#endif
|
89
93
|
|
90
|
-
#
|
94
|
+
#ifndef HAVE_RB_IO_DESCRIPTOR
|
95
|
+
static int
|
96
|
+
io_descriptor_fallback(VALUE io)
|
97
|
+
{
|
98
|
+
rb_io_t *fptr;
|
99
|
+
GetOpenFile(io, fptr);
|
100
|
+
return fptr->fd;
|
101
|
+
}
|
102
|
+
#define rb_io_descriptor io_descriptor_fallback
|
103
|
+
#endif
|
104
|
+
|
105
|
+
#ifndef HAVE_RB_IO_PATH
|
106
|
+
static VALUE
|
107
|
+
io_path_fallback(VALUE io)
|
108
|
+
{
|
109
|
+
rb_io_t *fptr;
|
110
|
+
GetOpenFile(io, fptr);
|
111
|
+
return fptr->pathv;
|
112
|
+
}
|
113
|
+
#define rb_io_path io_path_fallback
|
114
|
+
#endif
|
115
|
+
|
116
|
+
#ifndef HAVE_RB_IO_GET_WRITE_IO
|
117
|
+
static VALUE
|
118
|
+
io_get_write_io_fallback(VALUE io)
|
119
|
+
{
|
120
|
+
rb_io_t *fptr;
|
121
|
+
GetOpenFile(io, fptr);
|
122
|
+
VALUE wio = fptr->tied_io_for_writing;
|
123
|
+
return wio ? wio : io;
|
124
|
+
}
|
125
|
+
#define rb_io_get_write_io io_get_write_io_fallback
|
126
|
+
#endif
|
127
|
+
|
128
|
+
#define sys_fail(io) rb_sys_fail_str(rb_io_path(io))
|
91
129
|
|
92
130
|
#ifndef HAVE_RB_F_SEND
|
93
131
|
#ifndef RB_PASS_CALLED_KEYWORDS
|
@@ -112,18 +150,34 @@ rb_f_send(int argc, VALUE *argv, VALUE recv)
|
|
112
150
|
}
|
113
151
|
#endif
|
114
152
|
|
153
|
+
enum rawmode_opt_ids {
|
154
|
+
kwd_min,
|
155
|
+
kwd_time,
|
156
|
+
kwd_intr,
|
157
|
+
rawmode_opt_id_count
|
158
|
+
};
|
159
|
+
static ID rawmode_opt_ids[rawmode_opt_id_count];
|
160
|
+
|
115
161
|
typedef struct {
|
116
162
|
int vmin;
|
117
163
|
int vtime;
|
118
164
|
int intr;
|
119
165
|
} rawmode_arg_t;
|
120
166
|
|
167
|
+
#ifndef UNDEF_P
|
168
|
+
# define UNDEF_P(obj) ((obj) == Qundef)
|
169
|
+
#endif
|
170
|
+
#ifndef NIL_OR_UNDEF_P
|
171
|
+
# define NIL_OR_UNDEF_P(obj) (NIL_P(obj) || UNDEF_P(obj))
|
172
|
+
#endif
|
173
|
+
|
121
174
|
static rawmode_arg_t *
|
122
175
|
rawmode_opt(int *argcp, VALUE *argv, int min_argc, int max_argc, rawmode_arg_t *opts)
|
123
176
|
{
|
124
177
|
int argc = *argcp;
|
125
178
|
rawmode_arg_t *optp = NULL;
|
126
179
|
VALUE vopts = Qnil;
|
180
|
+
VALUE optvals[rawmode_opt_id_count];
|
127
181
|
#ifdef RB_SCAN_ARGS_PASS_CALLED_KEYWORDS
|
128
182
|
argc = rb_scan_args(argc, argv, "*:", NULL, &vopts);
|
129
183
|
#else
|
@@ -138,19 +192,20 @@ rawmode_opt(int *argcp, VALUE *argv, int min_argc, int max_argc, rawmode_arg_t *
|
|
138
192
|
}
|
139
193
|
#endif
|
140
194
|
rb_check_arity(argc, min_argc, max_argc);
|
141
|
-
if (
|
142
|
-
|
143
|
-
VALUE
|
144
|
-
VALUE
|
195
|
+
if (rb_get_kwargs(vopts, rawmode_opt_ids,
|
196
|
+
0, rawmode_opt_id_count, optvals)) {
|
197
|
+
VALUE vmin = optvals[kwd_min];
|
198
|
+
VALUE vtime = optvals[kwd_time];
|
199
|
+
VALUE intr = optvals[kwd_intr];
|
145
200
|
/* default values by `stty raw` */
|
146
201
|
opts->vmin = 1;
|
147
202
|
opts->vtime = 0;
|
148
203
|
opts->intr = 0;
|
149
|
-
if (!
|
204
|
+
if (!NIL_OR_UNDEF_P(vmin)) {
|
150
205
|
opts->vmin = NUM2INT(vmin);
|
151
206
|
optp = opts;
|
152
207
|
}
|
153
|
-
if (!
|
208
|
+
if (!NIL_OR_UNDEF_P(vtime)) {
|
154
209
|
VALUE v10 = INT2FIX(10);
|
155
210
|
vtime = rb_funcall3(vtime, '*', 1, &v10);
|
156
211
|
opts->vtime = NUM2INT(vtime);
|
@@ -165,6 +220,7 @@ rawmode_opt(int *argcp, VALUE *argv, int min_argc, int max_argc, rawmode_arg_t *
|
|
165
220
|
opts->intr = 0;
|
166
221
|
optp = opts;
|
167
222
|
break;
|
223
|
+
case Qundef:
|
168
224
|
case Qnil:
|
169
225
|
break;
|
170
226
|
default:
|
@@ -275,33 +331,21 @@ set_ttymode(int fd, conmode *t, void (*setter)(conmode *, void *), void *arg)
|
|
275
331
|
return setattr(fd, &r);
|
276
332
|
}
|
277
333
|
|
278
|
-
#define GetReadFD(
|
279
|
-
|
280
|
-
static inline int
|
281
|
-
get_write_fd(const rb_io_t *fptr)
|
282
|
-
{
|
283
|
-
VALUE wio = fptr->tied_io_for_writing;
|
284
|
-
rb_io_t *ofptr;
|
285
|
-
if (!wio) return fptr->fd;
|
286
|
-
GetOpenFile(wio, ofptr);
|
287
|
-
return ofptr->fd;
|
288
|
-
}
|
289
|
-
#define GetWriteFD(fptr) get_write_fd(fptr)
|
334
|
+
#define GetReadFD(io) rb_io_descriptor(io)
|
335
|
+
#define GetWriteFD(io) rb_io_descriptor(rb_io_get_write_io(io))
|
290
336
|
|
291
337
|
#define FD_PER_IO 2
|
292
338
|
|
293
339
|
static VALUE
|
294
340
|
ttymode(VALUE io, VALUE (*func)(VALUE), VALUE farg, void (*setter)(conmode *, void *), void *arg)
|
295
341
|
{
|
296
|
-
rb_io_t *fptr;
|
297
342
|
int status = -1;
|
298
343
|
int error = 0;
|
299
344
|
int fd[FD_PER_IO];
|
300
345
|
conmode t[FD_PER_IO];
|
301
346
|
VALUE result = Qnil;
|
302
347
|
|
303
|
-
|
304
|
-
fd[0] = GetReadFD(fptr);
|
348
|
+
fd[0] = GetReadFD(io);
|
305
349
|
if (fd[0] != -1) {
|
306
350
|
if (set_ttymode(fd[0], t+0, setter, arg)) {
|
307
351
|
status = 0;
|
@@ -311,7 +355,7 @@ ttymode(VALUE io, VALUE (*func)(VALUE), VALUE farg, void (*setter)(conmode *, vo
|
|
311
355
|
fd[0] = -1;
|
312
356
|
}
|
313
357
|
}
|
314
|
-
fd[1] = GetWriteFD(
|
358
|
+
fd[1] = GetWriteFD(io);
|
315
359
|
if (fd[1] != -1 && fd[1] != fd[0]) {
|
316
360
|
if (set_ttymode(fd[1], t+1, setter, arg)) {
|
317
361
|
status = 0;
|
@@ -324,14 +368,13 @@ ttymode(VALUE io, VALUE (*func)(VALUE), VALUE farg, void (*setter)(conmode *, vo
|
|
324
368
|
if (status == 0) {
|
325
369
|
result = rb_protect(func, farg, &status);
|
326
370
|
}
|
327
|
-
|
328
|
-
if (fd[0] != -1 && fd[0] == GetReadFD(fptr)) {
|
371
|
+
if (fd[0] != -1 && fd[0] == GetReadFD(io)) {
|
329
372
|
if (!setattr(fd[0], t+0)) {
|
330
373
|
error = errno;
|
331
374
|
status = -1;
|
332
375
|
}
|
333
376
|
}
|
334
|
-
if (fd[1] != -1 && fd[1] != fd[0] && fd[1] == GetWriteFD(
|
377
|
+
if (fd[1] != -1 && fd[1] != fd[0] && fd[1] == GetWriteFD(io)) {
|
335
378
|
if (!setattr(fd[1], t+1)) {
|
336
379
|
error = errno;
|
337
380
|
status = -1;
|
@@ -417,15 +460,11 @@ static VALUE
|
|
417
460
|
console_set_raw(int argc, VALUE *argv, VALUE io)
|
418
461
|
{
|
419
462
|
conmode t;
|
420
|
-
rb_io_t *fptr;
|
421
|
-
int fd;
|
422
463
|
rawmode_arg_t opts, *optp = rawmode_opt(&argc, argv, 0, 0, &opts);
|
423
|
-
|
424
|
-
|
425
|
-
fd = GetReadFD(fptr);
|
426
|
-
if (!getattr(fd, &t)) sys_fail_fptr(fptr);
|
464
|
+
int fd = GetReadFD(io);
|
465
|
+
if (!getattr(fd, &t)) sys_fail(io);
|
427
466
|
set_rawmode(&t, optp);
|
428
|
-
if (!setattr(fd, &t))
|
467
|
+
if (!setattr(fd, &t)) sys_fail(io);
|
429
468
|
return io;
|
430
469
|
}
|
431
470
|
|
@@ -461,14 +500,10 @@ static VALUE
|
|
461
500
|
console_set_cooked(VALUE io)
|
462
501
|
{
|
463
502
|
conmode t;
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
GetOpenFile(io, fptr);
|
468
|
-
fd = GetReadFD(fptr);
|
469
|
-
if (!getattr(fd, &t)) sys_fail_fptr(fptr);
|
503
|
+
int fd = GetReadFD(io);
|
504
|
+
if (!getattr(fd, &t)) sys_fail(io);
|
470
505
|
set_cookedmode(&t, NULL);
|
471
|
-
if (!setattr(fd, &t))
|
506
|
+
if (!setattr(fd, &t)) sys_fail(io);
|
472
507
|
return io;
|
473
508
|
}
|
474
509
|
|
@@ -620,17 +655,17 @@ static VALUE
|
|
620
655
|
console_set_echo(VALUE io, VALUE f)
|
621
656
|
{
|
622
657
|
conmode t;
|
623
|
-
|
624
|
-
|
658
|
+
int fd = GetReadFD(io);
|
659
|
+
|
660
|
+
if (!getattr(fd, &t)) sys_fail(io);
|
625
661
|
|
626
|
-
GetOpenFile(io, fptr);
|
627
|
-
fd = GetReadFD(fptr);
|
628
|
-
if (!getattr(fd, &t)) sys_fail_fptr(fptr);
|
629
662
|
if (RTEST(f))
|
630
|
-
|
663
|
+
set_echo(&t, NULL);
|
631
664
|
else
|
632
|
-
|
633
|
-
|
665
|
+
set_noecho(&t, NULL);
|
666
|
+
|
667
|
+
if (!setattr(fd, &t)) sys_fail(io);
|
668
|
+
|
634
669
|
return io;
|
635
670
|
}
|
636
671
|
|
@@ -646,12 +681,9 @@ static VALUE
|
|
646
681
|
console_echo_p(VALUE io)
|
647
682
|
{
|
648
683
|
conmode t;
|
649
|
-
|
650
|
-
int fd;
|
684
|
+
int fd = GetReadFD(io);
|
651
685
|
|
652
|
-
|
653
|
-
fd = GetReadFD(fptr);
|
654
|
-
if (!getattr(fd, &t)) sys_fail_fptr(fptr);
|
686
|
+
if (!getattr(fd, &t)) sys_fail(io);
|
655
687
|
return echo_p(&t) ? Qtrue : Qfalse;
|
656
688
|
}
|
657
689
|
|
@@ -730,12 +762,9 @@ static VALUE
|
|
730
762
|
console_conmode_get(VALUE io)
|
731
763
|
{
|
732
764
|
conmode t;
|
733
|
-
|
734
|
-
int fd;
|
765
|
+
int fd = GetReadFD(io);
|
735
766
|
|
736
|
-
|
737
|
-
fd = GetReadFD(fptr);
|
738
|
-
if (!getattr(fd, &t)) sys_fail_fptr(fptr);
|
767
|
+
if (!getattr(fd, &t)) sys_fail(io);
|
739
768
|
|
740
769
|
return conmode_new(cConmode, &t);
|
741
770
|
}
|
@@ -752,14 +781,12 @@ static VALUE
|
|
752
781
|
console_conmode_set(VALUE io, VALUE mode)
|
753
782
|
{
|
754
783
|
conmode *t, r;
|
755
|
-
|
756
|
-
int fd;
|
784
|
+
int fd = GetReadFD(io);
|
757
785
|
|
758
786
|
TypedData_Get_Struct(mode, conmode, &conmode_type, t);
|
759
787
|
r = *t;
|
760
|
-
|
761
|
-
fd
|
762
|
-
if (!setattr(fd, &r)) sys_fail_fptr(fptr);
|
788
|
+
|
789
|
+
if (!setattr(fd, &r)) sys_fail(io);
|
763
790
|
|
764
791
|
return mode;
|
765
792
|
}
|
@@ -795,13 +822,9 @@ typedef CONSOLE_SCREEN_BUFFER_INFO rb_console_size_t;
|
|
795
822
|
static VALUE
|
796
823
|
console_winsize(VALUE io)
|
797
824
|
{
|
798
|
-
rb_io_t *fptr;
|
799
|
-
int fd;
|
800
825
|
rb_console_size_t ws;
|
801
|
-
|
802
|
-
|
803
|
-
fd = GetWriteFD(fptr);
|
804
|
-
if (!getwinsize(fd, &ws)) sys_fail_fptr(fptr);
|
826
|
+
int fd = GetWriteFD(io);
|
827
|
+
if (!getwinsize(fd, &ws)) sys_fail(io);
|
805
828
|
return rb_assoc_new(INT2NUM(winsize_row(&ws)), INT2NUM(winsize_col(&ws)));
|
806
829
|
}
|
807
830
|
|
@@ -817,7 +840,6 @@ console_winsize(VALUE io)
|
|
817
840
|
static VALUE
|
818
841
|
console_set_winsize(VALUE io, VALUE size)
|
819
842
|
{
|
820
|
-
rb_io_t *fptr;
|
821
843
|
rb_console_size_t ws;
|
822
844
|
#if defined _WIN32
|
823
845
|
HANDLE wh;
|
@@ -826,20 +848,17 @@ console_set_winsize(VALUE io, VALUE size)
|
|
826
848
|
#endif
|
827
849
|
VALUE row, col, xpixel, ypixel;
|
828
850
|
const VALUE *sz;
|
829
|
-
int fd;
|
830
851
|
long sizelen;
|
852
|
+
int fd;
|
831
853
|
|
832
|
-
GetOpenFile(io, fptr);
|
833
854
|
size = rb_Array(size);
|
834
855
|
if ((sizelen = RARRAY_LEN(size)) != 2 && sizelen != 4) {
|
835
|
-
|
836
|
-
"wrong number of arguments (given %ld, expected 2 or 4)",
|
837
|
-
sizelen);
|
856
|
+
rb_raise(rb_eArgError, "wrong number of arguments (given %ld, expected 2 or 4)", sizelen);
|
838
857
|
}
|
839
858
|
sz = RARRAY_CONST_PTR(size);
|
840
859
|
row = sz[0], col = sz[1], xpixel = ypixel = Qnil;
|
841
860
|
if (sizelen == 4) xpixel = sz[2], ypixel = sz[3];
|
842
|
-
fd = GetWriteFD(
|
861
|
+
fd = GetWriteFD(io);
|
843
862
|
#if defined TIOCSWINSZ
|
844
863
|
ws.ws_row = ws.ws_col = ws.ws_xpixel = ws.ws_ypixel = 0;
|
845
864
|
#define SET(m) ws.ws_##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m)
|
@@ -848,7 +867,7 @@ console_set_winsize(VALUE io, VALUE size)
|
|
848
867
|
SET(xpixel);
|
849
868
|
SET(ypixel);
|
850
869
|
#undef SET
|
851
|
-
if (!setwinsize(fd, &ws))
|
870
|
+
if (!setwinsize(fd, &ws)) sys_fail(io);
|
852
871
|
#elif defined _WIN32
|
853
872
|
wh = (HANDLE)rb_w32_get_osfhandle(fd);
|
854
873
|
#define SET(m) new##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m)
|
@@ -883,15 +902,23 @@ console_set_winsize(VALUE io, VALUE size)
|
|
883
902
|
#endif
|
884
903
|
|
885
904
|
#ifdef _WIN32
|
905
|
+
/*
|
906
|
+
* call-seq:
|
907
|
+
* io.check_winsize_changed { ... } -> io
|
908
|
+
*
|
909
|
+
* Yields while console input events are queued.
|
910
|
+
*
|
911
|
+
* This method is Windows only.
|
912
|
+
*
|
913
|
+
* You must require 'io/console' to use this method.
|
914
|
+
*/
|
886
915
|
static VALUE
|
887
916
|
console_check_winsize_changed(VALUE io)
|
888
917
|
{
|
889
|
-
rb_io_t *fptr;
|
890
918
|
HANDLE h;
|
891
919
|
DWORD num;
|
892
920
|
|
893
|
-
|
894
|
-
h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(fptr));
|
921
|
+
h = (HANDLE)rb_w32_get_osfhandle(GetReadFD(io));
|
895
922
|
while (GetNumberOfConsoleInputEvents(h, &num) && num > 0) {
|
896
923
|
INPUT_RECORD rec;
|
897
924
|
if (ReadConsoleInput(h, &rec, 1, &num)) {
|
@@ -917,15 +944,11 @@ console_check_winsize_changed(VALUE io)
|
|
917
944
|
static VALUE
|
918
945
|
console_iflush(VALUE io)
|
919
946
|
{
|
920
|
-
rb_io_t *fptr;
|
921
|
-
int fd;
|
922
|
-
|
923
|
-
GetOpenFile(io, fptr);
|
924
|
-
fd = GetReadFD(fptr);
|
925
947
|
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
|
926
|
-
|
948
|
+
int fd = GetReadFD(io);
|
949
|
+
if (tcflush(fd, TCIFLUSH)) sys_fail(io);
|
927
950
|
#endif
|
928
|
-
|
951
|
+
|
929
952
|
return io;
|
930
953
|
}
|
931
954
|
|
@@ -940,13 +963,9 @@ console_iflush(VALUE io)
|
|
940
963
|
static VALUE
|
941
964
|
console_oflush(VALUE io)
|
942
965
|
{
|
943
|
-
|
944
|
-
int fd;
|
945
|
-
|
946
|
-
GetOpenFile(io, fptr);
|
947
|
-
fd = GetWriteFD(fptr);
|
966
|
+
int fd = GetWriteFD(io);
|
948
967
|
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
|
949
|
-
if (tcflush(fd, TCOFLUSH))
|
968
|
+
if (tcflush(fd, TCOFLUSH)) sys_fail(io);
|
950
969
|
#endif
|
951
970
|
(void)fd;
|
952
971
|
return io;
|
@@ -963,40 +982,38 @@ console_oflush(VALUE io)
|
|
963
982
|
static VALUE
|
964
983
|
console_ioflush(VALUE io)
|
965
984
|
{
|
966
|
-
rb_io_t *fptr;
|
967
985
|
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
|
968
|
-
int fd1
|
969
|
-
|
986
|
+
int fd1 = GetReadFD(io);
|
987
|
+
int fd2 = GetWriteFD(io);
|
970
988
|
|
971
|
-
GetOpenFile(io, fptr);
|
972
|
-
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
|
973
|
-
fd1 = GetReadFD(fptr);
|
974
|
-
fd2 = GetWriteFD(fptr);
|
975
989
|
if (fd2 != -1 && fd1 != fd2) {
|
976
|
-
|
977
|
-
|
990
|
+
if (tcflush(fd1, TCIFLUSH)) sys_fail(io);
|
991
|
+
if (tcflush(fd2, TCOFLUSH)) sys_fail(io);
|
978
992
|
}
|
979
993
|
else {
|
980
|
-
|
994
|
+
if (tcflush(fd1, TCIOFLUSH)) sys_fail(io);
|
981
995
|
}
|
982
996
|
#endif
|
997
|
+
|
983
998
|
return io;
|
984
999
|
}
|
985
1000
|
|
1001
|
+
/*
|
1002
|
+
* call-seq:
|
1003
|
+
* io.beep
|
1004
|
+
*
|
1005
|
+
* Beeps on the output console.
|
1006
|
+
*
|
1007
|
+
* You must require 'io/console' to use this method.
|
1008
|
+
*/
|
986
1009
|
static VALUE
|
987
1010
|
console_beep(VALUE io)
|
988
1011
|
{
|
989
|
-
rb_io_t *fptr;
|
990
|
-
int fd;
|
991
|
-
|
992
|
-
GetOpenFile(io, fptr);
|
993
|
-
fd = GetWriteFD(fptr);
|
994
1012
|
#ifdef _WIN32
|
995
|
-
(void)fd;
|
996
1013
|
MessageBeep(0);
|
997
1014
|
#else
|
998
|
-
|
999
|
-
|
1015
|
+
int fd = GetWriteFD(io);
|
1016
|
+
if (write(fd, "\a", 1) < 0) sys_fail(io);
|
1000
1017
|
#endif
|
1001
1018
|
return io;
|
1002
1019
|
}
|
@@ -1017,79 +1034,6 @@ mode_in_range(VALUE val, int high, const char *modename)
|
|
1017
1034
|
}
|
1018
1035
|
|
1019
1036
|
#if defined _WIN32
|
1020
|
-
static VALUE
|
1021
|
-
console_goto(VALUE io, VALUE y, VALUE x)
|
1022
|
-
{
|
1023
|
-
rb_io_t *fptr;
|
1024
|
-
int fd;
|
1025
|
-
COORD pos;
|
1026
|
-
|
1027
|
-
GetOpenFile(io, fptr);
|
1028
|
-
fd = GetWriteFD(fptr);
|
1029
|
-
pos.X = NUM2UINT(x);
|
1030
|
-
pos.Y = NUM2UINT(y);
|
1031
|
-
if (!SetConsoleCursorPosition((HANDLE)rb_w32_get_osfhandle(fd), pos)) {
|
1032
|
-
rb_syserr_fail(LAST_ERROR, 0);
|
1033
|
-
}
|
1034
|
-
return io;
|
1035
|
-
}
|
1036
|
-
|
1037
|
-
static VALUE
|
1038
|
-
console_cursor_pos(VALUE io)
|
1039
|
-
{
|
1040
|
-
rb_io_t *fptr;
|
1041
|
-
int fd;
|
1042
|
-
rb_console_size_t ws;
|
1043
|
-
|
1044
|
-
GetOpenFile(io, fptr);
|
1045
|
-
fd = GetWriteFD(fptr);
|
1046
|
-
if (!GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), &ws)) {
|
1047
|
-
rb_syserr_fail(LAST_ERROR, 0);
|
1048
|
-
}
|
1049
|
-
return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.Y), UINT2NUM(ws.dwCursorPosition.X));
|
1050
|
-
}
|
1051
|
-
|
1052
|
-
static VALUE
|
1053
|
-
console_move(VALUE io, int y, int x)
|
1054
|
-
{
|
1055
|
-
rb_io_t *fptr;
|
1056
|
-
HANDLE h;
|
1057
|
-
rb_console_size_t ws;
|
1058
|
-
COORD *pos = &ws.dwCursorPosition;
|
1059
|
-
|
1060
|
-
GetOpenFile(io, fptr);
|
1061
|
-
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(fptr));
|
1062
|
-
if (!GetConsoleScreenBufferInfo(h, &ws)) {
|
1063
|
-
rb_syserr_fail(LAST_ERROR, 0);
|
1064
|
-
}
|
1065
|
-
pos->X += x;
|
1066
|
-
pos->Y += y;
|
1067
|
-
if (!SetConsoleCursorPosition(h, *pos)) {
|
1068
|
-
rb_syserr_fail(LAST_ERROR, 0);
|
1069
|
-
}
|
1070
|
-
return io;
|
1071
|
-
}
|
1072
|
-
|
1073
|
-
static VALUE
|
1074
|
-
console_goto_column(VALUE io, VALUE val)
|
1075
|
-
{
|
1076
|
-
rb_io_t *fptr;
|
1077
|
-
HANDLE h;
|
1078
|
-
rb_console_size_t ws;
|
1079
|
-
COORD *pos = &ws.dwCursorPosition;
|
1080
|
-
|
1081
|
-
GetOpenFile(io, fptr);
|
1082
|
-
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(fptr));
|
1083
|
-
if (!GetConsoleScreenBufferInfo(h, &ws)) {
|
1084
|
-
rb_syserr_fail(LAST_ERROR, 0);
|
1085
|
-
}
|
1086
|
-
pos->X = NUM2INT(val);
|
1087
|
-
if (!SetConsoleCursorPosition(h, *pos)) {
|
1088
|
-
rb_syserr_fail(LAST_ERROR, 0);
|
1089
|
-
}
|
1090
|
-
return io;
|
1091
|
-
}
|
1092
|
-
|
1093
1037
|
static void
|
1094
1038
|
constat_clear(HANDLE handle, WORD attr, DWORD len, COORD pos)
|
1095
1039
|
{
|
@@ -1099,87 +1043,13 @@ constat_clear(HANDLE handle, WORD attr, DWORD len, COORD pos)
|
|
1099
1043
|
FillConsoleOutputCharacterW(handle, L' ', len, pos, &written);
|
1100
1044
|
}
|
1101
1045
|
|
1102
|
-
static VALUE
|
1103
|
-
console_erase_line(VALUE io, VALUE val)
|
1104
|
-
{
|
1105
|
-
rb_io_t *fptr;
|
1106
|
-
HANDLE h;
|
1107
|
-
rb_console_size_t ws;
|
1108
|
-
COORD *pos = &ws.dwCursorPosition;
|
1109
|
-
DWORD w;
|
1110
|
-
int mode = mode_in_range(val, 2, "line erase");
|
1111
|
-
|
1112
|
-
GetOpenFile(io, fptr);
|
1113
|
-
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(fptr));
|
1114
|
-
if (!GetConsoleScreenBufferInfo(h, &ws)) {
|
1115
|
-
rb_syserr_fail(LAST_ERROR, 0);
|
1116
|
-
}
|
1117
|
-
w = winsize_col(&ws);
|
1118
|
-
switch (mode) {
|
1119
|
-
case 0: /* after cursor */
|
1120
|
-
w -= pos->X;
|
1121
|
-
break;
|
1122
|
-
case 1: /* before *and* cursor */
|
1123
|
-
w = pos->X + 1;
|
1124
|
-
pos->X = 0;
|
1125
|
-
break;
|
1126
|
-
case 2: /* entire line */
|
1127
|
-
pos->X = 0;
|
1128
|
-
break;
|
1129
|
-
}
|
1130
|
-
constat_clear(h, ws.wAttributes, w, *pos);
|
1131
|
-
return io;
|
1132
|
-
}
|
1133
|
-
|
1134
|
-
static VALUE
|
1135
|
-
console_erase_screen(VALUE io, VALUE val)
|
1136
|
-
{
|
1137
|
-
rb_io_t *fptr;
|
1138
|
-
HANDLE h;
|
1139
|
-
rb_console_size_t ws;
|
1140
|
-
COORD *pos = &ws.dwCursorPosition;
|
1141
|
-
DWORD w;
|
1142
|
-
int mode = mode_in_range(val, 3, "screen erase");
|
1143
|
-
|
1144
|
-
GetOpenFile(io, fptr);
|
1145
|
-
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(fptr));
|
1146
|
-
if (!GetConsoleScreenBufferInfo(h, &ws)) {
|
1147
|
-
rb_syserr_fail(LAST_ERROR, 0);
|
1148
|
-
}
|
1149
|
-
w = winsize_col(&ws);
|
1150
|
-
switch (mode) {
|
1151
|
-
case 0: /* erase after cursor */
|
1152
|
-
w = (w * (ws.srWindow.Bottom - pos->Y + 1) - pos->X);
|
1153
|
-
break;
|
1154
|
-
case 1: /* erase before *and* cursor */
|
1155
|
-
w = (w * (pos->Y - ws.srWindow.Top) + pos->X + 1);
|
1156
|
-
pos->X = 0;
|
1157
|
-
pos->Y = ws.srWindow.Top;
|
1158
|
-
break;
|
1159
|
-
case 2: /* erase entire screen */
|
1160
|
-
w = (w * winsize_row(&ws));
|
1161
|
-
pos->X = 0;
|
1162
|
-
pos->Y = ws.srWindow.Top;
|
1163
|
-
break;
|
1164
|
-
case 3: /* erase entire screen */
|
1165
|
-
w = (w * ws.dwSize.Y);
|
1166
|
-
pos->X = 0;
|
1167
|
-
pos->Y = 0;
|
1168
|
-
break;
|
1169
|
-
}
|
1170
|
-
constat_clear(h, ws.wAttributes, w, *pos);
|
1171
|
-
return io;
|
1172
|
-
}
|
1173
|
-
|
1174
1046
|
static VALUE
|
1175
1047
|
console_scroll(VALUE io, int line)
|
1176
1048
|
{
|
1177
|
-
rb_io_t *fptr;
|
1178
1049
|
HANDLE h;
|
1179
1050
|
rb_console_size_t ws;
|
1180
1051
|
|
1181
|
-
|
1182
|
-
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(fptr));
|
1052
|
+
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
|
1183
1053
|
if (!GetConsoleScreenBufferInfo(h, &ws)) {
|
1184
1054
|
rb_syserr_fail(LAST_ERROR, 0);
|
1185
1055
|
}
|
@@ -1203,6 +1073,17 @@ console_scroll(VALUE io, int line)
|
|
1203
1073
|
|
1204
1074
|
#include "win32_vk.inc"
|
1205
1075
|
|
1076
|
+
/*
|
1077
|
+
* call-seq:
|
1078
|
+
* io.pressed?(key) -> bool
|
1079
|
+
*
|
1080
|
+
* Returns +true+ if +key+ is pressed. +key+ may be a virtual key
|
1081
|
+
* code or its name (String or Symbol) with out "VK_" prefix.
|
1082
|
+
*
|
1083
|
+
* This method is Windows only.
|
1084
|
+
*
|
1085
|
+
* You must require 'io/console' to use this method.
|
1086
|
+
*/
|
1206
1087
|
static VALUE
|
1207
1088
|
console_key_pressed_p(VALUE io, VALUE k)
|
1208
1089
|
{
|
@@ -1238,23 +1119,11 @@ static int
|
|
1238
1119
|
direct_query(VALUE io, const struct query_args *query)
|
1239
1120
|
{
|
1240
1121
|
if (RB_TYPE_P(io, T_FILE)) {
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
VALUE s = rb_str_new_cstr(query->qstr);
|
1247
|
-
rb_io_write(wio, s);
|
1248
|
-
rb_io_flush(wio);
|
1249
|
-
return 1;
|
1250
|
-
}
|
1251
|
-
if (write(fptr->fd, query->qstr, strlen(query->qstr)) != -1) {
|
1252
|
-
return 1;
|
1253
|
-
}
|
1254
|
-
if (fptr->fd == 0 &&
|
1255
|
-
write(1, query->qstr, strlen(query->qstr)) != -1) {
|
1256
|
-
return 1;
|
1257
|
-
}
|
1122
|
+
VALUE wio = rb_io_get_write_io(io);
|
1123
|
+
VALUE s = rb_str_new_cstr(query->qstr);
|
1124
|
+
rb_io_write(wio, s);
|
1125
|
+
rb_io_flush(wio);
|
1126
|
+
return 1;
|
1258
1127
|
}
|
1259
1128
|
return 0;
|
1260
1129
|
}
|
@@ -1304,9 +1173,41 @@ console_vt_response(int argc, VALUE *argv, VALUE io, const struct query_args *qa
|
|
1304
1173
|
return ret;
|
1305
1174
|
}
|
1306
1175
|
|
1176
|
+
static VALUE
|
1177
|
+
console_scroll(VALUE io, int line)
|
1178
|
+
{
|
1179
|
+
if (line) {
|
1180
|
+
VALUE s = rb_sprintf(CSI "%d%c", line < 0 ? -line : line,
|
1181
|
+
line < 0 ? 'T' : 'S');
|
1182
|
+
rb_io_write(io, s);
|
1183
|
+
}
|
1184
|
+
return io;
|
1185
|
+
}
|
1186
|
+
|
1187
|
+
# define console_key_pressed_p rb_f_notimplement
|
1188
|
+
#endif
|
1189
|
+
|
1190
|
+
/*
|
1191
|
+
* call-seq:
|
1192
|
+
* io.cursor -> [row, column]
|
1193
|
+
*
|
1194
|
+
* Returns the current cursor position as a two-element array of integers (row, column)
|
1195
|
+
*
|
1196
|
+
* io.cursor # => [3, 5]
|
1197
|
+
*
|
1198
|
+
* You must require 'io/console' to use this method.
|
1199
|
+
*/
|
1307
1200
|
static VALUE
|
1308
1201
|
console_cursor_pos(VALUE io)
|
1309
1202
|
{
|
1203
|
+
#ifdef _WIN32
|
1204
|
+
rb_console_size_t ws;
|
1205
|
+
int fd = GetWriteFD(io);
|
1206
|
+
if (!GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), &ws)) {
|
1207
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
1208
|
+
}
|
1209
|
+
return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.Y), UINT2NUM(ws.dwCursorPosition.X));
|
1210
|
+
#else
|
1310
1211
|
static const struct query_args query = {"\033[6n", 0};
|
1311
1212
|
VALUE resp = console_vt_response(0, 0, io, &query);
|
1312
1213
|
VALUE row, column, term;
|
@@ -1323,64 +1224,205 @@ console_cursor_pos(VALUE io)
|
|
1323
1224
|
RARRAY_ASET(resp, 0, INT2NUM(r));
|
1324
1225
|
RARRAY_ASET(resp, 1, INT2NUM(c));
|
1325
1226
|
return resp;
|
1227
|
+
#endif
|
1326
1228
|
}
|
1327
1229
|
|
1230
|
+
/*
|
1231
|
+
* call-seq:
|
1232
|
+
* io.goto(line, column) -> io
|
1233
|
+
*
|
1234
|
+
* Set the cursor position at +line+ and +column+.
|
1235
|
+
*
|
1236
|
+
* You must require 'io/console' to use this method.
|
1237
|
+
*/
|
1328
1238
|
static VALUE
|
1329
1239
|
console_goto(VALUE io, VALUE y, VALUE x)
|
1330
1240
|
{
|
1331
|
-
|
1241
|
+
#ifdef _WIN32
|
1242
|
+
COORD pos;
|
1243
|
+
int fd = GetWriteFD(io);
|
1244
|
+
pos.X = NUM2UINT(x);
|
1245
|
+
pos.Y = NUM2UINT(y);
|
1246
|
+
if (!SetConsoleCursorPosition((HANDLE)rb_w32_get_osfhandle(fd), pos)) {
|
1247
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
1248
|
+
}
|
1249
|
+
#else
|
1250
|
+
rb_io_write(io, rb_sprintf(CSI "%d;%dH", NUM2UINT(y)+1, NUM2UINT(x)+1));
|
1251
|
+
#endif
|
1332
1252
|
return io;
|
1333
1253
|
}
|
1334
1254
|
|
1335
1255
|
static VALUE
|
1336
1256
|
console_move(VALUE io, int y, int x)
|
1337
1257
|
{
|
1258
|
+
#ifdef _WIN32
|
1259
|
+
HANDLE h;
|
1260
|
+
rb_console_size_t ws;
|
1261
|
+
COORD *pos = &ws.dwCursorPosition;
|
1262
|
+
|
1263
|
+
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
|
1264
|
+
if (!GetConsoleScreenBufferInfo(h, &ws)) {
|
1265
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
1266
|
+
}
|
1267
|
+
pos->X += x;
|
1268
|
+
pos->Y += y;
|
1269
|
+
if (!SetConsoleCursorPosition(h, *pos)) {
|
1270
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
1271
|
+
}
|
1272
|
+
#else
|
1338
1273
|
if (x || y) {
|
1339
1274
|
VALUE s = rb_str_new_cstr("");
|
1340
|
-
if (y) rb_str_catf(s, "
|
1341
|
-
if (x) rb_str_catf(s, "
|
1275
|
+
if (y) rb_str_catf(s, CSI "%d%c", y < 0 ? -y : y, y < 0 ? 'A' : 'B');
|
1276
|
+
if (x) rb_str_catf(s, CSI "%d%c", x < 0 ? -x : x, x < 0 ? 'D' : 'C');
|
1342
1277
|
rb_io_write(io, s);
|
1343
1278
|
rb_io_flush(io);
|
1344
1279
|
}
|
1280
|
+
#endif
|
1345
1281
|
return io;
|
1346
1282
|
}
|
1347
1283
|
|
1284
|
+
/*
|
1285
|
+
* call-seq:
|
1286
|
+
* io.goto_column(column) -> io
|
1287
|
+
*
|
1288
|
+
* Set the cursor position at +column+ in the same line of the current
|
1289
|
+
* position.
|
1290
|
+
*
|
1291
|
+
* You must require 'io/console' to use this method.
|
1292
|
+
*/
|
1348
1293
|
static VALUE
|
1349
1294
|
console_goto_column(VALUE io, VALUE val)
|
1350
1295
|
{
|
1351
|
-
|
1296
|
+
#ifdef _WIN32
|
1297
|
+
HANDLE h;
|
1298
|
+
rb_console_size_t ws;
|
1299
|
+
COORD *pos = &ws.dwCursorPosition;
|
1300
|
+
|
1301
|
+
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
|
1302
|
+
if (!GetConsoleScreenBufferInfo(h, &ws)) {
|
1303
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
1304
|
+
}
|
1305
|
+
pos->X = NUM2INT(val);
|
1306
|
+
if (!SetConsoleCursorPosition(h, *pos)) {
|
1307
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
1308
|
+
}
|
1309
|
+
#else
|
1310
|
+
rb_io_write(io, rb_sprintf(CSI "%dG", NUM2UINT(val)+1));
|
1311
|
+
#endif
|
1352
1312
|
return io;
|
1353
1313
|
}
|
1354
1314
|
|
1315
|
+
/*
|
1316
|
+
* call-seq:
|
1317
|
+
* io.erase_line(mode) -> io
|
1318
|
+
*
|
1319
|
+
* Erases the line at the cursor corresponding to +mode+.
|
1320
|
+
* +mode+ may be either:
|
1321
|
+
* 0: after cursor
|
1322
|
+
* 1: before and cursor
|
1323
|
+
* 2: entire line
|
1324
|
+
*
|
1325
|
+
* You must require 'io/console' to use this method.
|
1326
|
+
*/
|
1355
1327
|
static VALUE
|
1356
1328
|
console_erase_line(VALUE io, VALUE val)
|
1357
1329
|
{
|
1358
1330
|
int mode = mode_in_range(val, 2, "line erase");
|
1359
|
-
|
1331
|
+
#ifdef _WIN32
|
1332
|
+
HANDLE h;
|
1333
|
+
rb_console_size_t ws;
|
1334
|
+
COORD *pos = &ws.dwCursorPosition;
|
1335
|
+
DWORD w;
|
1336
|
+
|
1337
|
+
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
|
1338
|
+
if (!GetConsoleScreenBufferInfo(h, &ws)) {
|
1339
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
1340
|
+
}
|
1341
|
+
w = winsize_col(&ws);
|
1342
|
+
switch (mode) {
|
1343
|
+
case 0: /* after cursor */
|
1344
|
+
w -= pos->X;
|
1345
|
+
break;
|
1346
|
+
case 1: /* before *and* cursor */
|
1347
|
+
w = pos->X + 1;
|
1348
|
+
pos->X = 0;
|
1349
|
+
break;
|
1350
|
+
case 2: /* entire line */
|
1351
|
+
pos->X = 0;
|
1352
|
+
break;
|
1353
|
+
}
|
1354
|
+
constat_clear(h, ws.wAttributes, w, *pos);
|
1355
|
+
return io;
|
1356
|
+
#else
|
1357
|
+
rb_io_write(io, rb_sprintf(CSI "%dK", mode));
|
1358
|
+
#endif
|
1360
1359
|
return io;
|
1361
1360
|
}
|
1362
1361
|
|
1362
|
+
/*
|
1363
|
+
* call-seq:
|
1364
|
+
* io.erase_screen(mode) -> io
|
1365
|
+
*
|
1366
|
+
* Erases the screen at the cursor corresponding to +mode+.
|
1367
|
+
* +mode+ may be either:
|
1368
|
+
* 0: after cursor
|
1369
|
+
* 1: before and cursor
|
1370
|
+
* 2: entire screen
|
1371
|
+
*
|
1372
|
+
* You must require 'io/console' to use this method.
|
1373
|
+
*/
|
1363
1374
|
static VALUE
|
1364
1375
|
console_erase_screen(VALUE io, VALUE val)
|
1365
1376
|
{
|
1366
1377
|
int mode = mode_in_range(val, 3, "screen erase");
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1378
|
+
#ifdef _WIN32
|
1379
|
+
HANDLE h;
|
1380
|
+
rb_console_size_t ws;
|
1381
|
+
COORD *pos = &ws.dwCursorPosition;
|
1382
|
+
DWORD w;
|
1370
1383
|
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1384
|
+
h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
|
1385
|
+
if (!GetConsoleScreenBufferInfo(h, &ws)) {
|
1386
|
+
rb_syserr_fail(LAST_ERROR, 0);
|
1387
|
+
}
|
1388
|
+
w = winsize_col(&ws);
|
1389
|
+
switch (mode) {
|
1390
|
+
case 0: /* erase after cursor */
|
1391
|
+
w = (w * (ws.srWindow.Bottom - pos->Y + 1) - pos->X);
|
1392
|
+
break;
|
1393
|
+
case 1: /* erase before *and* cursor */
|
1394
|
+
w = (w * (pos->Y - ws.srWindow.Top) + pos->X + 1);
|
1395
|
+
pos->X = 0;
|
1396
|
+
pos->Y = ws.srWindow.Top;
|
1397
|
+
break;
|
1398
|
+
case 2: /* erase entire screen */
|
1399
|
+
w = (w * winsize_row(&ws));
|
1400
|
+
pos->X = 0;
|
1401
|
+
pos->Y = ws.srWindow.Top;
|
1402
|
+
break;
|
1403
|
+
case 3: /* erase entire screen */
|
1404
|
+
w = (w * ws.dwSize.Y);
|
1405
|
+
pos->X = 0;
|
1406
|
+
pos->Y = 0;
|
1407
|
+
break;
|
1378
1408
|
}
|
1409
|
+
constat_clear(h, ws.wAttributes, w, *pos);
|
1410
|
+
#else
|
1411
|
+
rb_io_write(io, rb_sprintf(CSI "%dJ", mode));
|
1412
|
+
#endif
|
1379
1413
|
return io;
|
1380
1414
|
}
|
1381
|
-
# define console_key_pressed_p rb_f_notimplement
|
1382
|
-
#endif
|
1383
1415
|
|
1416
|
+
/*
|
1417
|
+
* call-seq:
|
1418
|
+
* io.cursor = [line, column] -> io
|
1419
|
+
*
|
1420
|
+
* Same as <tt>io.goto(line, column)</tt>
|
1421
|
+
*
|
1422
|
+
* See IO#goto.
|
1423
|
+
*
|
1424
|
+
* You must require 'io/console' to use this method.
|
1425
|
+
*/
|
1384
1426
|
static VALUE
|
1385
1427
|
console_cursor_set(VALUE io, VALUE cpos)
|
1386
1428
|
{
|
@@ -1389,42 +1431,98 @@ console_cursor_set(VALUE io, VALUE cpos)
|
|
1389
1431
|
return console_goto(io, RARRAY_AREF(cpos, 0), RARRAY_AREF(cpos, 1));
|
1390
1432
|
}
|
1391
1433
|
|
1434
|
+
/*
|
1435
|
+
* call-seq:
|
1436
|
+
* io.cursor_up(n) -> io
|
1437
|
+
*
|
1438
|
+
* Moves the cursor up +n+ lines.
|
1439
|
+
*
|
1440
|
+
* You must require 'io/console' to use this method.
|
1441
|
+
*/
|
1392
1442
|
static VALUE
|
1393
1443
|
console_cursor_up(VALUE io, VALUE val)
|
1394
1444
|
{
|
1395
1445
|
return console_move(io, -NUM2INT(val), 0);
|
1396
1446
|
}
|
1397
1447
|
|
1448
|
+
/*
|
1449
|
+
* call-seq:
|
1450
|
+
* io.cursor_down(n) -> io
|
1451
|
+
*
|
1452
|
+
* Moves the cursor down +n+ lines.
|
1453
|
+
*
|
1454
|
+
* You must require 'io/console' to use this method.
|
1455
|
+
*/
|
1398
1456
|
static VALUE
|
1399
1457
|
console_cursor_down(VALUE io, VALUE val)
|
1400
1458
|
{
|
1401
1459
|
return console_move(io, +NUM2INT(val), 0);
|
1402
1460
|
}
|
1403
1461
|
|
1462
|
+
/*
|
1463
|
+
* call-seq:
|
1464
|
+
* io.cursor_left(n) -> io
|
1465
|
+
*
|
1466
|
+
* Moves the cursor left +n+ columns.
|
1467
|
+
*
|
1468
|
+
* You must require 'io/console' to use this method.
|
1469
|
+
*/
|
1404
1470
|
static VALUE
|
1405
1471
|
console_cursor_left(VALUE io, VALUE val)
|
1406
1472
|
{
|
1407
1473
|
return console_move(io, 0, -NUM2INT(val));
|
1408
1474
|
}
|
1409
1475
|
|
1476
|
+
/*
|
1477
|
+
* call-seq:
|
1478
|
+
* io.cursor_right(n) -> io
|
1479
|
+
*
|
1480
|
+
* Moves the cursor right +n+ columns.
|
1481
|
+
*
|
1482
|
+
* You must require 'io/console' to use this method.
|
1483
|
+
*/
|
1410
1484
|
static VALUE
|
1411
1485
|
console_cursor_right(VALUE io, VALUE val)
|
1412
1486
|
{
|
1413
1487
|
return console_move(io, 0, +NUM2INT(val));
|
1414
1488
|
}
|
1415
1489
|
|
1490
|
+
/*
|
1491
|
+
* call-seq:
|
1492
|
+
* io.scroll_forward(n) -> io
|
1493
|
+
*
|
1494
|
+
* Scrolls the entire scrolls forward +n+ lines.
|
1495
|
+
*
|
1496
|
+
* You must require 'io/console' to use this method.
|
1497
|
+
*/
|
1416
1498
|
static VALUE
|
1417
1499
|
console_scroll_forward(VALUE io, VALUE val)
|
1418
1500
|
{
|
1419
1501
|
return console_scroll(io, +NUM2INT(val));
|
1420
1502
|
}
|
1421
1503
|
|
1504
|
+
/*
|
1505
|
+
* call-seq:
|
1506
|
+
* io.scroll_backward(n) -> io
|
1507
|
+
*
|
1508
|
+
* Scrolls the entire scrolls backward +n+ lines.
|
1509
|
+
*
|
1510
|
+
* You must require 'io/console' to use this method.
|
1511
|
+
*/
|
1422
1512
|
static VALUE
|
1423
1513
|
console_scroll_backward(VALUE io, VALUE val)
|
1424
1514
|
{
|
1425
1515
|
return console_scroll(io, -NUM2INT(val));
|
1426
1516
|
}
|
1427
1517
|
|
1518
|
+
/*
|
1519
|
+
* call-seq:
|
1520
|
+
* io.clear_screen -> io
|
1521
|
+
*
|
1522
|
+
* Clears the entire screen and moves the cursor top-left corner.
|
1523
|
+
*
|
1524
|
+
* You must require 'io/console' to use this method.
|
1525
|
+
*/
|
1428
1526
|
static VALUE
|
1429
1527
|
console_clear_screen(VALUE io)
|
1430
1528
|
{
|
@@ -1433,6 +1531,38 @@ console_clear_screen(VALUE io)
|
|
1433
1531
|
return io;
|
1434
1532
|
}
|
1435
1533
|
|
1534
|
+
#ifndef HAVE_RB_IO_OPEN_DESCRIPTOR
|
1535
|
+
static VALUE
|
1536
|
+
io_open_descriptor_fallback(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, void *encoding)
|
1537
|
+
{
|
1538
|
+
rb_update_max_fd(descriptor);
|
1539
|
+
|
1540
|
+
VALUE arguments[2] = {
|
1541
|
+
INT2NUM(descriptor),
|
1542
|
+
INT2FIX(mode),
|
1543
|
+
};
|
1544
|
+
|
1545
|
+
VALUE self = rb_class_new_instance(2, arguments, klass);
|
1546
|
+
|
1547
|
+
rb_io_t *fptr;
|
1548
|
+
GetOpenFile(self, fptr);
|
1549
|
+
fptr->pathv = path;
|
1550
|
+
fptr->mode |= mode;
|
1551
|
+
|
1552
|
+
return self;
|
1553
|
+
}
|
1554
|
+
#define rb_io_open_descriptor io_open_descriptor_fallback
|
1555
|
+
#endif
|
1556
|
+
|
1557
|
+
#ifndef HAVE_RB_IO_CLOSED_P
|
1558
|
+
static VALUE
|
1559
|
+
rb_io_closed_p(VALUE io)
|
1560
|
+
{
|
1561
|
+
rb_io_t *fptr = RFILE(io)->fptr;
|
1562
|
+
return fptr->fd == -1 ? Qtrue : Qfalse;
|
1563
|
+
}
|
1564
|
+
#endif
|
1565
|
+
|
1436
1566
|
/*
|
1437
1567
|
* call-seq:
|
1438
1568
|
* IO.console -> #<File:/dev/tty>
|
@@ -1450,34 +1580,37 @@ static VALUE
|
|
1450
1580
|
console_dev(int argc, VALUE *argv, VALUE klass)
|
1451
1581
|
{
|
1452
1582
|
VALUE con = 0;
|
1453
|
-
rb_io_t *fptr;
|
1454
1583
|
VALUE sym = 0;
|
1455
1584
|
|
1456
1585
|
rb_check_arity(argc, 0, UNLIMITED_ARGUMENTS);
|
1586
|
+
|
1457
1587
|
if (argc) {
|
1458
|
-
|
1588
|
+
Check_Type(sym = argv[0], T_SYMBOL);
|
1459
1589
|
}
|
1590
|
+
|
1591
|
+
// Force the class to be File.
|
1460
1592
|
if (klass == rb_cIO) klass = rb_cFile;
|
1593
|
+
|
1461
1594
|
if (rb_const_defined(klass, id_console)) {
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1466
|
-
|
1467
|
-
}
|
1595
|
+
con = rb_const_get(klass, id_console);
|
1596
|
+
if (!RB_TYPE_P(con, T_FILE) || RTEST(rb_io_closed_p(con))) {
|
1597
|
+
rb_const_remove(klass, id_console);
|
1598
|
+
con = 0;
|
1599
|
+
}
|
1468
1600
|
}
|
1601
|
+
|
1469
1602
|
if (sym) {
|
1470
|
-
|
1471
|
-
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1603
|
+
if (sym == ID2SYM(id_close) && argc == 1) {
|
1604
|
+
if (con) {
|
1605
|
+
rb_io_close(con);
|
1606
|
+
rb_const_remove(klass, id_console);
|
1607
|
+
con = 0;
|
1608
|
+
}
|
1609
|
+
return Qnil;
|
1610
|
+
}
|
1478
1611
|
}
|
1612
|
+
|
1479
1613
|
if (!con) {
|
1480
|
-
VALUE args[2];
|
1481
1614
|
#if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H || defined HAVE_SGTTY_H
|
1482
1615
|
# define CONSOLE_DEVICE "/dev/tty"
|
1483
1616
|
#elif defined _WIN32
|
@@ -1489,44 +1622,36 @@ console_dev(int argc, VALUE *argv, VALUE klass)
|
|
1489
1622
|
# define CONSOLE_DEVICE_FOR_READING CONSOLE_DEVICE
|
1490
1623
|
#endif
|
1491
1624
|
#ifdef CONSOLE_DEVICE_FOR_WRITING
|
1492
|
-
|
1493
|
-
|
1625
|
+
VALUE out;
|
1626
|
+
rb_io_t *ofptr;
|
1494
1627
|
#endif
|
1495
|
-
|
1628
|
+
int fd;
|
1629
|
+
VALUE path = rb_obj_freeze(rb_str_new2(CONSOLE_DEVICE));
|
1496
1630
|
|
1497
1631
|
#ifdef CONSOLE_DEVICE_FOR_WRITING
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
args[1] = INT2FIX(O_WRONLY);
|
1502
|
-
args[0] = INT2NUM(fd);
|
1503
|
-
out = rb_class_new_instance(2, args, klass);
|
1632
|
+
fd = rb_cloexec_open(CONSOLE_DEVICE_FOR_WRITING, O_RDWR, 0);
|
1633
|
+
if (fd < 0) return Qnil;
|
1634
|
+
out = rb_io_open_descriptor(klass, fd, FMODE_WRITABLE | FMODE_SYNC, path, Qnil, NULL);
|
1504
1635
|
#endif
|
1505
|
-
|
1506
|
-
|
1636
|
+
fd = rb_cloexec_open(CONSOLE_DEVICE_FOR_READING, O_RDWR, 0);
|
1637
|
+
if (fd < 0) {
|
1507
1638
|
#ifdef CONSOLE_DEVICE_FOR_WRITING
|
1508
|
-
|
1639
|
+
rb_io_close(out);
|
1509
1640
|
#endif
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
args[0] = INT2NUM(fd);
|
1515
|
-
con = rb_class_new_instance(2, args, klass);
|
1516
|
-
GetOpenFile(con, fptr);
|
1517
|
-
fptr->pathv = rb_obj_freeze(rb_str_new2(CONSOLE_DEVICE));
|
1641
|
+
return Qnil;
|
1642
|
+
}
|
1643
|
+
|
1644
|
+
con = rb_io_open_descriptor(klass, fd, FMODE_READWRITE | FMODE_SYNC, path, Qnil, NULL);
|
1518
1645
|
#ifdef CONSOLE_DEVICE_FOR_WRITING
|
1519
|
-
|
1520
|
-
ofptr->pathv = fptr->pathv;
|
1521
|
-
fptr->tied_io_for_writing = out;
|
1522
|
-
ofptr->mode |= FMODE_SYNC;
|
1646
|
+
rb_io_set_write_io(con, out);
|
1523
1647
|
#endif
|
1524
|
-
|
1525
|
-
rb_const_set(klass, id_console, con);
|
1648
|
+
rb_const_set(klass, id_console, con);
|
1526
1649
|
}
|
1650
|
+
|
1527
1651
|
if (sym) {
|
1528
|
-
|
1652
|
+
return rb_f_send(argc, argv, con);
|
1529
1653
|
}
|
1654
|
+
|
1530
1655
|
return con;
|
1531
1656
|
}
|
1532
1657
|
|
@@ -1542,13 +1667,18 @@ io_getch(int argc, VALUE *argv, VALUE io)
|
|
1542
1667
|
return rb_funcallv(io, id_getc, argc, argv);
|
1543
1668
|
}
|
1544
1669
|
|
1545
|
-
#if ENABLE_IO_GETPASS
|
1546
1670
|
static VALUE
|
1547
1671
|
puts_call(VALUE io)
|
1548
1672
|
{
|
1549
1673
|
return rb_io_write(io, rb_default_rs);
|
1550
1674
|
}
|
1551
1675
|
|
1676
|
+
static VALUE
|
1677
|
+
gets_call(VALUE io)
|
1678
|
+
{
|
1679
|
+
return rb_funcallv(io, id_gets, 0, 0);
|
1680
|
+
}
|
1681
|
+
|
1552
1682
|
static VALUE
|
1553
1683
|
getpass_call(VALUE io)
|
1554
1684
|
{
|
@@ -1569,7 +1699,8 @@ static VALUE
|
|
1569
1699
|
str_chomp(VALUE str)
|
1570
1700
|
{
|
1571
1701
|
if (!NIL_P(str)) {
|
1572
|
-
|
1702
|
+
const VALUE rs = rb_default_rs; /* rvalue in TruffleRuby */
|
1703
|
+
rb_funcallv(str, id_chomp_bang, 1, &rs);
|
1573
1704
|
}
|
1574
1705
|
return str;
|
1575
1706
|
}
|
@@ -1586,6 +1717,12 @@ str_chomp(VALUE str)
|
|
1586
1717
|
* see String#chomp!.
|
1587
1718
|
*
|
1588
1719
|
* You must require 'io/console' to use this method.
|
1720
|
+
*
|
1721
|
+
* require 'io/console'
|
1722
|
+
* IO::console.getpass("Enter password:")
|
1723
|
+
* Enter password:
|
1724
|
+
* # => "mypassword"
|
1725
|
+
*
|
1589
1726
|
*/
|
1590
1727
|
static VALUE
|
1591
1728
|
console_getpass(int argc, VALUE *argv, VALUE io)
|
@@ -1596,6 +1733,7 @@ console_getpass(int argc, VALUE *argv, VALUE io)
|
|
1596
1733
|
wio = rb_io_get_write_io(io);
|
1597
1734
|
if (wio == io && io == rb_stdin) wio = rb_stderr;
|
1598
1735
|
prompt(argc, argv, wio);
|
1736
|
+
rb_io_flush(wio);
|
1599
1737
|
str = rb_ensure(getpass_call, io, puts_call, wio);
|
1600
1738
|
return str_chomp(str);
|
1601
1739
|
}
|
@@ -1613,11 +1751,10 @@ io_getpass(int argc, VALUE *argv, VALUE io)
|
|
1613
1751
|
|
1614
1752
|
rb_check_arity(argc, 0, 1);
|
1615
1753
|
prompt(argc, argv, io);
|
1616
|
-
|
1617
|
-
|
1618
|
-
return str;
|
1754
|
+
rb_check_funcall(io, id_flush, 0, 0);
|
1755
|
+
str = rb_ensure(gets_call, io, puts_call, io);
|
1756
|
+
return str_chomp(str);
|
1619
1757
|
}
|
1620
|
-
#endif
|
1621
1758
|
|
1622
1759
|
/*
|
1623
1760
|
* IO console methods
|
@@ -1627,15 +1764,16 @@ Init_console(void)
|
|
1627
1764
|
{
|
1628
1765
|
#undef rb_intern
|
1629
1766
|
id_getc = rb_intern("getc");
|
1630
|
-
#if ENABLE_IO_GETPASS
|
1631
1767
|
id_gets = rb_intern("gets");
|
1768
|
+
id_flush = rb_intern("flush");
|
1632
1769
|
id_chomp_bang = rb_intern("chomp!");
|
1633
|
-
#endif
|
1634
1770
|
id_console = rb_intern("console");
|
1635
1771
|
id_close = rb_intern("close");
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1772
|
+
#define init_rawmode_opt_id(name) \
|
1773
|
+
rawmode_opt_ids[kwd_##name] = rb_intern(#name)
|
1774
|
+
init_rawmode_opt_id(min);
|
1775
|
+
init_rawmode_opt_id(time);
|
1776
|
+
init_rawmode_opt_id(intr);
|
1639
1777
|
#ifndef HAVE_RB_F_SEND
|
1640
1778
|
id___send__ = rb_intern("__send__");
|
1641
1779
|
#endif
|
@@ -1676,20 +1814,19 @@ InitVM_console(void)
|
|
1676
1814
|
rb_define_method(rb_cIO, "clear_screen", console_clear_screen, 0);
|
1677
1815
|
rb_define_method(rb_cIO, "pressed?", console_key_pressed_p, 1);
|
1678
1816
|
rb_define_method(rb_cIO, "check_winsize_changed", console_check_winsize_changed, 0);
|
1679
|
-
#if ENABLE_IO_GETPASS
|
1680
1817
|
rb_define_method(rb_cIO, "getpass", console_getpass, -1);
|
1681
|
-
#endif
|
1682
1818
|
rb_define_singleton_method(rb_cIO, "console", console_dev, -1);
|
1683
1819
|
{
|
1820
|
+
/* :stopdoc: */
|
1684
1821
|
VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
|
1822
|
+
/* :startdoc: */
|
1685
1823
|
rb_define_method(mReadable, "getch", io_getch, -1);
|
1686
|
-
#if ENABLE_IO_GETPASS
|
1687
1824
|
rb_define_method(mReadable, "getpass", io_getpass, -1);
|
1688
|
-
#endif
|
1689
1825
|
}
|
1690
1826
|
{
|
1691
1827
|
/* :stopdoc: */
|
1692
1828
|
cConmode = rb_define_class_under(rb_cIO, "ConsoleMode", rb_cObject);
|
1829
|
+
rb_define_const(cConmode, "VERSION", rb_str_new_cstr(IO_CONSOLE_VERSION));
|
1693
1830
|
rb_define_alloc_func(cConmode, conmode_alloc);
|
1694
1831
|
rb_undef_method(cConmode, "initialize");
|
1695
1832
|
rb_define_method(cConmode, "initialize_copy", conmode_init_copy, 1);
|
data/ext/io/console/extconf.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
# frozen_string_literal: false
|
2
2
|
require 'mkmf'
|
3
3
|
|
4
|
+
have_func("rb_io_path")
|
5
|
+
have_func("rb_io_descriptor")
|
6
|
+
have_func("rb_io_get_write_io")
|
7
|
+
have_func("rb_io_closed_p")
|
8
|
+
have_func("rb_io_open_descriptor")
|
9
|
+
|
4
10
|
ok = true if RUBY_ENGINE == "ruby" || RUBY_ENGINE == "truffleruby"
|
5
11
|
hdr = nil
|
6
12
|
case
|
@@ -29,7 +35,6 @@ when true
|
|
29
35
|
elsif have_func("rb_scheduler_timeout") # 3.0
|
30
36
|
have_func("rb_io_wait")
|
31
37
|
end
|
32
|
-
$defs << "-D""ENABLE_IO_GETPASS=1"
|
33
38
|
create_makefile("io/console") {|conf|
|
34
39
|
conf << "\n""VK_HEADER = #{vk_header}\n"
|
35
40
|
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: io-console
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nobu Nakada
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: add console capabilities to IO instances.
|
14
14
|
email: nobu@ruby-lang.org
|
@@ -17,6 +17,7 @@ extensions:
|
|
17
17
|
- ext/io/console/extconf.rb
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
|
+
- ".document"
|
20
21
|
- LICENSE.txt
|
21
22
|
- README.md
|
22
23
|
- ext/io/console/console.c
|
@@ -29,6 +30,7 @@ licenses:
|
|
29
30
|
- BSD-2-Clause
|
30
31
|
metadata:
|
31
32
|
source_code_url: https://github.com/ruby/io-console
|
33
|
+
changelog_uri: https://github.com/ruby/io-console/releases
|
32
34
|
post_install_message:
|
33
35
|
rdoc_options: []
|
34
36
|
require_paths:
|
@@ -44,7 +46,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
44
46
|
- !ruby/object:Gem::Version
|
45
47
|
version: '0'
|
46
48
|
requirements: []
|
47
|
-
rubygems_version: 3.
|
49
|
+
rubygems_version: 3.6.0.dev
|
48
50
|
signing_key:
|
49
51
|
specification_version: 4
|
50
52
|
summary: Console interface
|