io-console 0.3

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.
Files changed (4) hide show
  1. data/console.c +628 -0
  2. data/extconf.rb +20 -0
  3. data/lib/console/size.rb +20 -0
  4. metadata +48 -0
data/console.c ADDED
@@ -0,0 +1,628 @@
1
+ /* -*- c-file-style: "ruby" -*- */
2
+ /*
3
+ * console IO module
4
+ */
5
+ #include "ruby.h"
6
+ #ifdef HAVE_RUBY_IO_H
7
+ #include "ruby/io.h"
8
+ #else
9
+ #include "rubyio.h"
10
+ #endif
11
+
12
+ #ifndef HAVE_RB_IO_T
13
+ typedef OpenFile rb_io_t;
14
+ #endif
15
+
16
+ #ifdef HAVE_UNISTD_H
17
+ #include <unistd.h>
18
+ #endif
19
+ #ifdef HAVE_FCNTL_H
20
+ #include <fcntl.h>
21
+ #endif
22
+ #ifdef HAVE_SYS_IOCTL_H
23
+ #include <sys/ioctl.h>
24
+ #endif
25
+
26
+ #if defined HAVE_TERMIOS_H
27
+ # include <termios.h>
28
+ typedef struct termios conmode;
29
+
30
+ static int
31
+ setattr(int fd, conmode *t)
32
+ {
33
+ while (tcsetattr(fd, TCSAFLUSH, t)) {
34
+ if (errno != EINTR) return 0;
35
+ }
36
+ return 1;
37
+ }
38
+ # define getattr(fd, t) (tcgetattr(fd, t) == 0)
39
+ #elif defined HAVE_TERMIO_H
40
+ # include <termio.h>
41
+ typedef struct termio conmode;
42
+ # define setattr(fd, t) (ioctl(fd, TCSETAF, t) == 0)
43
+ # define getattr(fd, t) (ioctl(fd, TCGETA, t) == 0)
44
+ #elif defined HAVE_SGTTY_H
45
+ # include <sgtty.h>
46
+ typedef struct sgttyb conmode;
47
+ # ifdef HAVE_STTY
48
+ # define setattr(fd, t) (stty(fd, t) == 0)
49
+ # else
50
+ # define setattr(fd, t) (ioctl((fd), TIOCSETP, (t)) == 0)
51
+ # endif
52
+ # ifdef HAVE_GTTY
53
+ # define getattr(fd, t) (gtty(fd, t) == 0)
54
+ # else
55
+ # define getattr(fd, t) (ioctl((fd), TIOCGETP, (t)) == 0)
56
+ # endif
57
+ #elif defined _WIN32
58
+ #include <winioctl.h>
59
+ typedef DWORD conmode;
60
+
61
+ #ifdef HAVE_RB_W32_MAP_ERRNO
62
+ #define LAST_ERROR rb_w32_map_errno(GetLastError())
63
+ #else
64
+ #define LAST_ERROR EBADF
65
+ #endif
66
+ #define SET_LAST_ERROR (errno = LAST_ERROR, 0)
67
+
68
+ static int
69
+ setattr(int fd, conmode *t)
70
+ {
71
+ int x = SetConsoleMode((HANDLE)rb_w32_get_osfhandle(fd), *t);
72
+ if (!x) errno = LAST_ERROR;
73
+ return x;
74
+ }
75
+
76
+ static int
77
+ getattr(int fd, conmode *t)
78
+ {
79
+ int x = GetConsoleMode((HANDLE)rb_w32_get_osfhandle(fd), t);
80
+ if (!x) errno = LAST_ERROR;
81
+ return x;
82
+ }
83
+ #endif
84
+ #ifndef SET_LAST_ERROR
85
+ #define SET_LAST_ERROR (0)
86
+ #endif
87
+
88
+ #ifndef InitVM
89
+ #define InitVM(ext) {void InitVM_##ext(void);InitVM_##ext();}
90
+ #endif
91
+
92
+ static ID id_getc, id_console;
93
+
94
+ static void
95
+ set_rawmode(conmode *t)
96
+ {
97
+ #ifdef HAVE_CFMAKERAW
98
+ cfmakeraw(t);
99
+ #else
100
+ #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
101
+ t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
102
+ t->c_oflag &= ~OPOST;
103
+ t->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
104
+ t->c_cflag &= ~(CSIZE|PARENB);
105
+ t->c_cflag |= CS8;
106
+ #elif defined HAVE_SGTTY_H
107
+ t->sg_flags &= ~ECHO;
108
+ t->sg_flags |= RAW;
109
+ #elif defined _WIN32
110
+ *t = 0;
111
+ #endif
112
+ #endif
113
+ }
114
+
115
+ static void
116
+ set_noecho(conmode *t)
117
+ {
118
+ #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
119
+ t->c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
120
+ #elif defined HAVE_SGTTY_H
121
+ t->sg_flags &= ~ECHO;
122
+ #elif defined _WIN32
123
+ *t &= ~ENABLE_ECHO_INPUT;
124
+ #endif
125
+ }
126
+
127
+ static void
128
+ set_echo(conmode *t)
129
+ {
130
+ #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
131
+ t->c_lflag |= (ECHO | ECHOE | ECHOK | ECHONL);
132
+ #elif defined HAVE_SGTTY_H
133
+ t->sg_flags |= ECHO;
134
+ #elif defined _WIN32
135
+ *t |= ENABLE_ECHO_INPUT;
136
+ #endif
137
+ }
138
+
139
+ static int
140
+ echo_p(conmode *t)
141
+ {
142
+ #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
143
+ return (t->c_lflag & (ECHO | ECHOE | ECHOK | ECHONL)) != 0;
144
+ #elif defined HAVE_SGTTY_H
145
+ return (t->sg_flags & ECHO) != 0;
146
+ #elif defined _WIN32
147
+ return (*t & ENABLE_ECHO_INPUT) != 0;
148
+ #endif
149
+ }
150
+
151
+ static int
152
+ set_ttymode(int fd, conmode *t, void (*setter)(conmode *))
153
+ {
154
+ conmode r;
155
+ if (!getattr(fd, t)) return 0;
156
+ r = *t;
157
+ setter(&r);
158
+ return setattr(fd, &r);
159
+ }
160
+
161
+ #ifdef GetReadFile
162
+ #define GetReadFD(fptr) fileno(GetReadFile(fptr))
163
+ #else
164
+ #define GetReadFD(fptr) ((fptr)->fd)
165
+ #endif
166
+
167
+ #ifdef GetWriteFile
168
+ #define GetWriteFD(fptr) fileno(GetWriteFile(fptr))
169
+ #else
170
+ static inline int
171
+ get_write_fd(const rb_io_t *fptr)
172
+ {
173
+ VALUE wio = fptr->tied_io_for_writing;
174
+ rb_io_t *ofptr;
175
+ if (!wio) return fptr->fd;
176
+ GetOpenFile(wio, ofptr);
177
+ return ofptr->fd;
178
+ }
179
+ #define GetWriteFD(fptr) get_write_fd(fptr)
180
+ #endif
181
+
182
+ #define FD_PER_IO 2
183
+
184
+ static VALUE
185
+ ttymode(VALUE io, VALUE (*func)(VALUE), void (*setter)(conmode *))
186
+ {
187
+ rb_io_t *fptr;
188
+ int status = -1;
189
+ int error = 0;
190
+ int fd[FD_PER_IO];
191
+ conmode t[FD_PER_IO];
192
+ VALUE result = Qnil;
193
+
194
+ GetOpenFile(io, fptr);
195
+ fd[0] = GetReadFD(fptr);
196
+ if (fd[0] != -1) {
197
+ if (set_ttymode(fd[0], t+0, setter)) {
198
+ status = 0;
199
+ }
200
+ else {
201
+ error = errno;
202
+ fd[0] = -1;
203
+ }
204
+ }
205
+ fd[1] = GetWriteFD(fptr);
206
+ if (fd[1] != -1 && fd[1] != fd[0]) {
207
+ if (set_ttymode(fd[1], t+1, setter)) {
208
+ status = 0;
209
+ }
210
+ else {
211
+ error = errno;
212
+ fd[1] = -1;
213
+ }
214
+ }
215
+ if (status == 0) {
216
+ result = rb_protect(func, io, &status);
217
+ }
218
+ GetOpenFile(io, fptr);
219
+ if (fd[0] != -1 && fd[0] == GetReadFD(fptr)) {
220
+ if (!setattr(fd[0], t+0)) {
221
+ error = errno;
222
+ status = -1;
223
+ }
224
+ }
225
+ if (fd[1] != -1 && fd[1] != fd[0] && fd[1] == GetWriteFD(fptr)) {
226
+ if (!setattr(fd[1], t+1)) {
227
+ error = errno;
228
+ status = -1;
229
+ }
230
+ }
231
+ if (status) {
232
+ if (status == -1) {
233
+ errno = error;
234
+ rb_sys_fail(0);
235
+ }
236
+ rb_jump_tag(status);
237
+ }
238
+ return result;
239
+ }
240
+
241
+ /*
242
+ * call-seq:
243
+ * io.raw {|io| }
244
+ *
245
+ * Yields +self+ within raw mode.
246
+ *
247
+ * STDIN.raw(&:gets)
248
+ *
249
+ * will read and return a line with echo back and line editing.
250
+ */
251
+ static VALUE
252
+ console_raw(VALUE io)
253
+ {
254
+ return ttymode(io, rb_yield, set_rawmode);
255
+ }
256
+
257
+ /*
258
+ * call-seq:
259
+ * io.raw!
260
+ *
261
+ * Enables raw mode.
262
+ *
263
+ * If the terminal mode needs to be back, use io.raw { ... }.
264
+ */
265
+ static VALUE
266
+ console_set_raw(VALUE io)
267
+ {
268
+ conmode t;
269
+ rb_io_t *fptr;
270
+ int fd;
271
+
272
+ GetOpenFile(io, fptr);
273
+ fd = GetReadFD(fptr);
274
+ if (!getattr(fd, &t)) rb_sys_fail(0);
275
+ set_rawmode(&t);
276
+ if (!setattr(fd, &t)) rb_sys_fail(0);
277
+ return io;
278
+ }
279
+
280
+ static VALUE
281
+ getc_call(VALUE io)
282
+ {
283
+ return rb_funcall2(io, id_getc, 0, 0);
284
+ }
285
+
286
+ /*
287
+ * call-seq:
288
+ * io.getch -> char
289
+ *
290
+ * Reads and returns a character in raw mode.
291
+ */
292
+ static VALUE
293
+ console_getch(VALUE io)
294
+ {
295
+ return ttymode(io, getc_call, set_rawmode);
296
+ }
297
+
298
+ /*
299
+ * call-seq:
300
+ * io.noecho {|io| }
301
+ *
302
+ * Yields +self+ with disabling echo back.
303
+ *
304
+ * STDIN.noecho(&:gets)
305
+ *
306
+ * will read and return a line without echo back.
307
+ */
308
+ static VALUE
309
+ console_noecho(VALUE io)
310
+ {
311
+ return ttymode(io, rb_yield, set_noecho);
312
+ }
313
+
314
+ /*
315
+ * call-seq:
316
+ * io.echo = flag
317
+ *
318
+ * Enables/disables echo back.
319
+ */
320
+ static VALUE
321
+ console_set_echo(VALUE io, VALUE f)
322
+ {
323
+ conmode t;
324
+ rb_io_t *fptr;
325
+ int fd;
326
+
327
+ GetOpenFile(io, fptr);
328
+ fd = GetReadFD(fptr);
329
+ if (!getattr(fd, &t)) rb_sys_fail(0);
330
+ if (RTEST(f))
331
+ set_echo(&t);
332
+ else
333
+ set_noecho(&t);
334
+ if (!setattr(fd, &t)) rb_sys_fail(0);
335
+ return io;
336
+ }
337
+
338
+ /*
339
+ * call-seq:
340
+ * io.echo? -> true or false
341
+ *
342
+ * Returns +true+ if echo back is enabled.
343
+ */
344
+ static VALUE
345
+ console_echo_p(VALUE io)
346
+ {
347
+ conmode t;
348
+ rb_io_t *fptr;
349
+ int fd;
350
+
351
+ GetOpenFile(io, fptr);
352
+ fd = GetReadFD(fptr);
353
+ if (!getattr(fd, &t)) rb_sys_fail(0);
354
+ return echo_p(&t) ? Qtrue : Qfalse;
355
+ }
356
+
357
+ #if defined TIOCGWINSZ
358
+ typedef struct winsize rb_console_size_t;
359
+ #define getwinsize(fd, buf) (ioctl((fd), TIOCGWINSZ, (buf)) == 0)
360
+ #define setwinsize(fd, buf) (ioctl((fd), TIOCSWINSZ, (buf)) == 0)
361
+ #define winsize_row(buf) (buf)->ws_row
362
+ #define winsize_col(buf) (buf)->ws_col
363
+ #elif defined _WIN32
364
+ typedef CONSOLE_SCREEN_BUFFER_INFO rb_console_size_t;
365
+ #define getwinsize(fd, buf) ( \
366
+ GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), (buf)) || \
367
+ SET_LAST_ERROR)
368
+ #define winsize_row(buf) ((buf)->srWindow.Bottom - (buf)->srWindow.Top + 1)
369
+ #define winsize_col(buf) (buf)->dwSize.X
370
+ #endif
371
+
372
+ #if defined TIOCGWINSZ || defined _WIN32
373
+ #define USE_CONSOLE_GETSIZE 1
374
+ #endif
375
+
376
+ #ifdef USE_CONSOLE_GETSIZE
377
+ /*
378
+ * call-seq:
379
+ * io.winsize -> [rows, columns]
380
+ *
381
+ * Returns console size.
382
+ */
383
+ static VALUE
384
+ console_winsize(VALUE io)
385
+ {
386
+ rb_io_t *fptr;
387
+ int fd;
388
+ rb_console_size_t ws;
389
+
390
+ GetOpenFile(io, fptr);
391
+ fd = GetWriteFD(fptr);
392
+ if (!getwinsize(fd, &ws)) rb_sys_fail(0);
393
+ return rb_assoc_new(INT2NUM(winsize_row(&ws)), INT2NUM(winsize_col(&ws)));
394
+ }
395
+
396
+ /*
397
+ * call-seq:
398
+ * io.winsize = [rows, columns]
399
+ *
400
+ * Tries to set console size. The effect depends on the platform and
401
+ * the running environment.
402
+ */
403
+ static VALUE
404
+ console_set_winsize(VALUE io, VALUE size)
405
+ {
406
+ rb_io_t *fptr;
407
+ rb_console_size_t ws;
408
+ #if defined _WIN32
409
+ HANDLE wh;
410
+ int newrow, newcol;
411
+ #endif
412
+ VALUE row, col, xpixel, ypixel;
413
+ #if defined TIOCSWINSZ
414
+ int fd;
415
+ #endif
416
+
417
+ GetOpenFile(io, fptr);
418
+ size = rb_Array(size);
419
+ rb_scan_args((int)RARRAY_LEN(size), RARRAY_PTR(size), "22",
420
+ &row, &col, &xpixel, &ypixel);
421
+ #if defined TIOCSWINSZ
422
+ fd = GetWriteFD(fptr);
423
+ ws.ws_row = ws.ws_col = ws.ws_xpixel = ws.ws_ypixel = 0;
424
+ #define SET(m) ws.ws_##m = NIL_P(m) ? 0 : (unsigned short)NUM2UINT(m)
425
+ SET(row);
426
+ SET(col);
427
+ SET(xpixel);
428
+ SET(ypixel);
429
+ #undef SET
430
+ if (!setwinsize(fd, &ws)) rb_sys_fail(0);
431
+ #elif defined _WIN32
432
+ wh = (HANDLE)rb_w32_get_osfhandle(GetReadFD(fptr));
433
+ newrow = (SHORT)NUM2UINT(row);
434
+ newcol = (SHORT)NUM2UINT(col);
435
+ if (!getwinsize(GetReadFD(fptr), &ws)) {
436
+ rb_sys_fail("GetConsoleScreenBufferInfo");
437
+ }
438
+ if ((ws.dwSize.X < newcol && (ws.dwSize.X = newcol, 1)) ||
439
+ (ws.dwSize.Y < newrow && (ws.dwSize.Y = newrow, 1))) {
440
+ if (!(SetConsoleScreenBufferSize(wh, ws.dwSize) || SET_LAST_ERROR)) {
441
+ rb_sys_fail("SetConsoleScreenBufferInfo");
442
+ }
443
+ }
444
+ ws.srWindow.Left = 0;
445
+ ws.srWindow.Top = 0;
446
+ ws.srWindow.Right = newcol;
447
+ ws.srWindow.Bottom = newrow;
448
+ if (!(SetConsoleWindowInfo(wh, FALSE, &ws.srWindow) || SET_LAST_ERROR)) {
449
+ rb_sys_fail("SetConsoleWindowInfo");
450
+ }
451
+ #endif
452
+ return io;
453
+ }
454
+ #endif
455
+
456
+ /*
457
+ * call-seq:
458
+ * io.iflush
459
+ *
460
+ * Flushes input buffer in kernel.
461
+ */
462
+ static VALUE
463
+ console_iflush(VALUE io)
464
+ {
465
+ rb_io_t *fptr;
466
+ int fd;
467
+
468
+ GetOpenFile(io, fptr);
469
+ fd = GetReadFD(fptr);
470
+ #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
471
+ if (tcflush(fd, TCIFLUSH)) rb_sys_fail(0);
472
+ #endif
473
+ return io;
474
+ }
475
+
476
+ /*
477
+ * call-seq:
478
+ * io.oflush
479
+ *
480
+ * Flushes output buffer in kernel.
481
+ */
482
+ static VALUE
483
+ console_oflush(VALUE io)
484
+ {
485
+ rb_io_t *fptr;
486
+ int fd;
487
+
488
+ GetOpenFile(io, fptr);
489
+ fd = GetWriteFD(fptr);
490
+ #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
491
+ if (tcflush(fd, TCOFLUSH)) rb_sys_fail(0);
492
+ #endif
493
+ return io;
494
+ }
495
+
496
+ /*
497
+ * call-seq:
498
+ * io.ioflush
499
+ *
500
+ * Flushes input and output buffers in kernel.
501
+ */
502
+ static VALUE
503
+ console_ioflush(VALUE io)
504
+ {
505
+ rb_io_t *fptr;
506
+ #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
507
+ int fd1, fd2;
508
+ #endif
509
+
510
+ GetOpenFile(io, fptr);
511
+ #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H
512
+ fd1 = GetReadFD(fptr);
513
+ fd2 = GetWriteFD(fptr);
514
+ if (fd2 != -1 && fd1 != fd2) {
515
+ if (tcflush(fd1, TCIFLUSH)) rb_sys_fail(0);
516
+ if (tcflush(fd2, TCOFLUSH)) rb_sys_fail(0);
517
+ }
518
+ else {
519
+ if (tcflush(fd1, TCIOFLUSH)) rb_sys_fail(0);
520
+ }
521
+ #endif
522
+ return io;
523
+ }
524
+
525
+ /*
526
+ * call-seq:
527
+ * IO.console -> #<File:/dev/tty>
528
+ *
529
+ * Returns an File instance opened console.
530
+ */
531
+ static VALUE
532
+ console_dev(VALUE klass)
533
+ {
534
+ VALUE con = 0;
535
+ rb_io_t *fptr;
536
+
537
+ if (klass == rb_cIO) klass = rb_cFile;
538
+ if (rb_const_defined(klass, id_console)) {
539
+ con = rb_const_get(klass, id_console);
540
+ if (TYPE(con) == T_FILE) {
541
+ if ((fptr = RFILE(con)->fptr) && GetReadFD(fptr) != -1)
542
+ return con;
543
+ }
544
+ rb_mod_remove_const(klass, ID2SYM(id_console));
545
+ }
546
+ {
547
+ VALUE args[2];
548
+ #if defined HAVE_TERMIOS_H || defined HAVE_TERMIO_H || defined HAVE_SGTTY_H
549
+ # define CONSOLE_DEVICE "/dev/tty"
550
+ #elif defined _WIN32
551
+ # define CONSOLE_DEVICE "con$"
552
+ # define CONSOLE_DEVICE_FOR_READING "conin$"
553
+ # define CONSOLE_DEVICE_FOR_WRITING "conout$"
554
+ #endif
555
+ #ifndef CONSOLE_DEVICE_FOR_READING
556
+ # define CONSOLE_DEVICE_FOR_READING CONSOLE_DEVICE
557
+ #endif
558
+ #ifdef CONSOLE_DEVICE_FOR_WRITING
559
+ VALUE out;
560
+ rb_io_t *ofptr;
561
+ #endif
562
+ int fd;
563
+
564
+ #ifdef CONSOLE_DEVICE_FOR_WRITING
565
+ fd = open(CONSOLE_DEVICE_FOR_WRITING, O_WRONLY);
566
+ if (fd < 0) return Qnil;
567
+ rb_update_max_fd(fd);
568
+ args[1] = INT2FIX(O_WRONLY);
569
+ args[0] = INT2NUM(fd);
570
+ out = rb_class_new_instance(2, args, klass);
571
+ #endif
572
+ fd = open(CONSOLE_DEVICE_FOR_READING, O_RDWR);
573
+ if (fd < 0) {
574
+ #ifdef CONSOLE_DEVICE_FOR_WRITING
575
+ rb_io_close(out);
576
+ #endif
577
+ return Qnil;
578
+ }
579
+ rb_update_max_fd(fd);
580
+ args[1] = INT2FIX(O_RDWR);
581
+ args[0] = INT2NUM(fd);
582
+ con = rb_class_new_instance(2, args, klass);
583
+ GetOpenFile(con, fptr);
584
+ fptr->pathv = rb_obj_freeze(rb_str_new2(CONSOLE_DEVICE));
585
+ #ifdef CONSOLE_DEVICE_FOR_WRITING
586
+ GetOpenFile(out, ofptr);
587
+ # ifdef HAVE_RB_IO_GET_WRITE_IO
588
+ ofptr->pathv = fptr->pathv;
589
+ fptr->tied_io_for_writing = out;
590
+ # else
591
+ fptr->f2 = ofptr->f;
592
+ ofptr->f = 0;
593
+ # endif
594
+ ofptr->mode |= FMODE_SYNC;
595
+ #endif
596
+ fptr->mode |= FMODE_SYNC;
597
+ rb_const_set(klass, id_console, con);
598
+ }
599
+ return con;
600
+ }
601
+
602
+ /*
603
+ * IO console methods
604
+ */
605
+ void
606
+ Init_console(void)
607
+ {
608
+ id_getc = rb_intern("getc");
609
+ id_console = rb_intern("console");
610
+ InitVM(console);
611
+ }
612
+
613
+ void
614
+ InitVM_console(void)
615
+ {
616
+ rb_define_method(rb_cIO, "raw", console_raw, 0);
617
+ rb_define_method(rb_cIO, "raw!", console_set_raw, 0);
618
+ rb_define_method(rb_cIO, "getch", console_getch, 0);
619
+ rb_define_method(rb_cIO, "echo=", console_set_echo, 1);
620
+ rb_define_method(rb_cIO, "echo?", console_echo_p, 0);
621
+ rb_define_method(rb_cIO, "noecho", console_noecho, 0);
622
+ rb_define_method(rb_cIO, "winsize", console_winsize, 0);
623
+ rb_define_method(rb_cIO, "winsize=", console_set_winsize, 1);
624
+ rb_define_method(rb_cIO, "iflush", console_iflush, 0);
625
+ rb_define_method(rb_cIO, "oflush", console_oflush, 0);
626
+ rb_define_method(rb_cIO, "ioflush", console_ioflush, 0);
627
+ rb_define_singleton_method(rb_cIO, "console", console_dev, 0);
628
+ }
data/extconf.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'mkmf'
2
+
3
+ ok = true
4
+ hdr = nil
5
+ case
6
+ when macro_defined?("_WIN32", "")
7
+ have_func("rb_w32_map_errno", "ruby.h")
8
+ when hdr = %w"termios.h termio.h".find {|h| have_header(h)}
9
+ have_func("cfmakeraw", hdr)
10
+ when have_header(hdr = "sgtty.h")
11
+ %w"stty gtty".each {|f| have_func(f, hdr)}
12
+ else
13
+ ok = false
14
+ end
15
+ have_header("sys/ioctl.h")
16
+ have_func("rb_io_get_write_io", "ruby/io.h")
17
+ have_func("dup3", "unistd.h")
18
+ if ok
19
+ create_makefile("io/console")
20
+ end
@@ -0,0 +1,20 @@
1
+ def IO.default_console_size
2
+ [
3
+ ENV["LINES"].to_i.nonzero? || 25,
4
+ ENV["COLUMNS"].to_i.nonzero? || 80,
5
+ ]
6
+ end
7
+
8
+ begin
9
+ require 'io/console'
10
+ rescue LoadError
11
+ class IO
12
+ alias console_size default_console_size
13
+ end
14
+ else
15
+ def IO.console_size
16
+ console.winsize
17
+ rescue NoMethodError
18
+ default_console_size
19
+ end
20
+ end
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: io-console
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.3'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Nobu Nakada
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-06-24 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: add console capabilities to IO instances.
15
+ email: nobu@ruby-lang.org
16
+ executables: []
17
+ extensions:
18
+ - extconf.rb
19
+ extra_rdoc_files: []
20
+ files:
21
+ - console.c
22
+ - extconf.rb
23
+ - lib/console/size.rb
24
+ homepage: http://www.ruby-lang.org
25
+ licenses: []
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - .
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubyforge_project:
44
+ rubygems_version: 1.8.10
45
+ signing_key:
46
+ specification_version: 3
47
+ summary: Console interface
48
+ test_files: []