├── Gemfile ├── .gitignore ├── test └── test_winsize.rb ├── rdoc ├── classes │ ├── TermInfo.src │ │ ├── M000013.html │ │ ├── M000011.html │ │ ├── M000019.html │ │ ├── M000006.html │ │ ├── M000021.html │ │ ├── M000007.html │ │ ├── M000008.html │ │ ├── M000010.html │ │ ├── M000009.html │ │ ├── M000016.html │ │ ├── M000004.html │ │ ├── M000024.html │ │ ├── M000003.html │ │ ├── M000005.html │ │ ├── M000002.html │ │ ├── M000025.html │ │ ├── M000015.html │ │ ├── M000029.html │ │ ├── M000028.html │ │ ├── M000030.html │ │ ├── M000012.html │ │ ├── M000026.html │ │ ├── M000001.html │ │ ├── M000027.html │ │ ├── M000023.html │ │ ├── M000014.html │ │ ├── M000017.html │ │ └── M000018.html │ ├── TermInfo │ │ └── TermInfoError.html │ └── TermInfo.html ├── index.html ├── fr_class_index.html ├── fr_file_index.html ├── files │ ├── terminfo_c.html │ ├── extconf_rb.html │ └── lib │ │ └── terminfo_rb.html ├── fr_method_index.html └── rdoc-style.css ├── ChangeLog ├── ruby-terminfo.gemspec ├── sample ├── resize └── fill ├── extconf.rb ├── README.md ├── Rakefile ├── lib └── terminfo.rb └── terminfo.c /Gemfile: -------------------------------------------------------------------------------- 1 | source 'http://rubygems.org' 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | pkg 2 | *.log 3 | Makefile 4 | extconf.h 5 | *.bundle 6 | *.o 7 | -------------------------------------------------------------------------------- /test/test_winsize.rb: -------------------------------------------------------------------------------- 1 | require 'test/unit' 2 | require 'pty' 3 | require 'terminfo' 4 | 5 | class TestTermInfoWinsize < Test::Unit::TestCase 6 | def test_winsize 7 | PTY.open {|m, s| 8 | TermInfo.tiocswinsz(s, 80, 25) 9 | assert_equal([80,25], TermInfo.tiocgwinsz(s)) 10 | TermInfo.tiocswinsz(s, 200, 300) 11 | assert_equal([200,300], TermInfo.tiocgwinsz(s)) 12 | } 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000013.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | inspect (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 61
14 |   def inspect
15 |     "\#<#{self.class}:#{@term}>"
16 |   end
17 | 18 | -------------------------------------------------------------------------------- /rdoc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 13 | RDoc Documentation 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /rdoc/fr_class_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 12 | 13 | 14 | Classes 15 | 16 | 17 | 18 | 19 | 20 |
21 |

Classes

22 |
23 | TermInfo
24 | TermInfo::TermInfoError
25 |
26 |
27 | 28 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000011.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | io (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 52
14 |   def TermInfo.io() default_object.io() end
15 | 16 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000019.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | screen_lines (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 130
14 |   def screen_lines
15 |     self.screen_size[0]
16 |   end
17 | 18 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000006.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | screen_size (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 47
14 |   def TermInfo.screen_size() default_object.screen_size() end
15 | 16 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000021.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | screen_columns (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 136
14 |   def screen_columns
15 |     self.screen_size[1]
16 |   end
17 | 18 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000007.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | screen_lines (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 48
14 |   def TermInfo.screen_lines() default_object.screen_lines() end
15 | 16 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000008.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | screen_height (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 49
14 |   def TermInfo.screen_height() default_object.screen_height() end
15 | 16 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000010.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | screen_width (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 51
14 |   def TermInfo.screen_width() default_object.screen_width() end
15 | 16 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000009.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | screen_columns (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 50
14 |   def TermInfo.screen_columns() default_object.screen_columns() end
15 | 16 | -------------------------------------------------------------------------------- /rdoc/fr_file_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 12 | 13 | 14 | Files 15 | 16 | 17 | 18 | 19 | 20 |
21 |

Files

22 |
23 | extconf.rb
24 | lib/terminfo.rb
25 | terminfo.c
26 |
27 |
28 | 29 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000016.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | write (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 91
14 |   def write(str)
15 |     @io.write(str)
16 |   end
17 | 18 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000004.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | write (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 45
14 |   def TermInfo.write(str) default_object.write(str) end
15 | 16 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000024.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | tigetflag (TermInfo) 9 | 10 | 11 | 12 | 13 |
/*
14 |  * TermInfo#tigetflag(capname) => int
15 |  *
16 |  * TermInfo#tigetflag returns a boolean capability specified by capname.
17 |  */
18 | static VALUE
19 | rt_tigetflag(VALUE self, VALUE v_capname)
20 | {
21 |   int ret;
22 |   setup(self);
23 |   ret = tigetflag(StringValueCStr(v_capname));
24 |   if (ret == -1) { rb_raise(eTermInfoError, "not a boolean capability"); }
25 |   return RTEST(ret) ? Qtrue : Qfalse;
26 | }
27 | 28 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000003.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | control (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 44
14 |   def TermInfo.control(*args) default_object.control(*args) end
15 | 16 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000005.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | flush (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 46
14 |   def TermInfo.flush(&block) default_object.flush(&block) end
15 | 16 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000002.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | control_string (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 43
14 |   def TermInfo.control_string(*args) default_object.control_string(*args) end
15 | 16 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000025.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | tigetnum (TermInfo) 9 | 10 | 11 | 12 | 13 |
/*
14 |  * TermInfo#tigetnum(capname) => int
15 |  *
16 |  * TermInfo#tigetnum returns a numeric capability specified by capname.
17 |  */
18 | static VALUE
19 | rt_tigetnum(VALUE self, VALUE v_capname)
20 | {
21 |   int ret;
22 |   setup(self);
23 |   ret = tigetnum(StringValueCStr(v_capname));
24 |   if (ret == -2) { rb_raise(eTermInfoError, "not a numeric capability"); }
25 |   if (ret == -1) { rb_raise(eTermInfoError, "canceled or absent numeric capability"); }
26 |   return INT2NUM(ret);
27 | }
28 | 29 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000015.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | control (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 86
14 |   def control(*args)
15 |     @io.write(self.control_string(*args))
16 |     nil
17 |   end
18 | 19 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000029.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | tiocgwinsz (TermInfo) 9 | 10 | 11 | 12 | 13 |
/*
14 |  * TermInfo.tiocgwinsz(io) => [row, col]
15 |  *
16 |  * TermInfo.tiocgwinsz returns the screen size of the terminal refered by io,
17 |  * using TIOCGWINSZ ioctl.
18 |  */
19 | static VALUE
20 | rt_tiocgwinsz(VALUE self, VALUE io)
21 | {
22 | #ifdef TIOCGWINSZ
23 |   rb_io_t *fptr;
24 |   struct winsize sz;
25 |   int ret;
26 | 
27 |   GetOpenFile(io, fptr);
28 | 
29 |   ret = ioctl(FILENO(fptr), TIOCGWINSZ, &sz);
30 |   if (ret == -1) rb_raise(rb_eIOError, "TIOCGWINSZ failed");
31 | 
32 |   return rb_ary_new3(2, INT2NUM(sz.ws_row), INT2NUM(sz.ws_col));
33 | #else
34 |   rb_notimplement();
35 | #endif
36 | }
37 | 38 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000028.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | tputs (TermInfo) 9 | 10 | 11 | 12 | 13 |
/*
14 |  * TermInfo#tputs(str, affcnt) => str
15 |  *
16 |  * TermInfo#tputs expands padding informaiton using padding characters.
17 |  * affcnt is a number of lines affected by the str.
18 |  */
19 | static VALUE
20 | rt_tputs(VALUE self, VALUE v_str, VALUE v_affcnt)
21 | {
22 |   int ret;
23 |   char *str;
24 |   int affcnt;
25 |   VALUE output;
26 | 
27 |   setup(self);
28 |   str = StringValueCStr(v_str);
29 |   affcnt = NUM2INT(v_affcnt);
30 | 
31 |   putfunc_output = output = rb_str_new2("");
32 |   ret = tputs(str, affcnt, putfunc);
33 |   putfunc_output = Qnil;
34 | 
35 |   if (ret == ERR) { rb_raise(eTermInfoError, "tputs failed"); }
36 | 
37 |   return output;
38 | }
39 | 40 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000030.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | tiocswinsz (TermInfo) 9 | 10 | 11 | 12 | 13 |
/*
14 |  * TermInfo.tiocswinsz(io, row, col)
15 |  *
16 |  * TermInfo.tiocgwinsz update the screen size information of the terminal refered by io,
17 |  * using TIOCSWINSZ ioctl.
18 |  *
19 |  * It returns nil.
20 |  */
21 | static VALUE
22 | rt_tiocswinsz(VALUE self, VALUE io, VALUE row, VALUE col)
23 | {
24 | #ifdef TIOCSWINSZ
25 |   rb_io_t *fptr;
26 |   struct winsize sz;
27 |   int ret;
28 | 
29 |   GetOpenFile(io, fptr);
30 | 
31 |   sz.ws_row = NUM2INT(row);
32 |   sz.ws_col = NUM2INT(col);
33 | 
34 |   ret = ioctl(FILENO(fptr), TIOCSWINSZ, &sz);
35 |   if (ret == -1) rb_raise(rb_eIOError, "TIOCSWINSZ failed");
36 | 
37 |   return Qnil;
38 | #else
39 |   rb_notimplement();
40 | #endif
41 | }
42 | 43 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000012.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | new (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 54
14 |   def initialize(term=ENV['TERM'], io=STDERR)
15 |     setupterm(term, io.fileno)
16 |     @term = term
17 |     @io = io
18 |   end
19 | 20 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2009-03-06 Tanaka Akira 2 | 3 | * version 0.2 released. 4 | 5 | 2008-12-30 Tanaka Akira 6 | 7 | * terminfo.c (rt_wcswidth): check the return value of wcwidth. 8 | 9 | 2008-12-30 Tanaka Akira 10 | 11 | * terminfo.c: prefer ruby/io.h over rubyio.h. 12 | include wchar.h. 13 | (FILENO): condition refined. 14 | (rt_wcswidth): new method TermInfo.wcswidth. 15 | 16 | * extconf.rb: check ruby/io.h and ruby/encoding.h. 17 | 18 | 2007-05-30 Tanaka Akira 19 | 20 | * terminfo.c (TermInfo.ctermid): defined. 21 | 22 | * lib/terminfo.rb, sample/resize: use TermInfo.ctermid instead of 23 | "/dev/tty". 24 | 25 | 2007-05-29 Tanaka Akira 26 | 27 | * sample/resize: new sample program. 28 | 29 | 2007-04-29 Tanaka Akira 30 | 31 | * lib/terminfo.rb (TermInfo.default_object): Use File::NOCTTY for 32 | opening /dev/tty to avoid acquire a controlling terminal. 33 | 34 | 2007-04-19 Tanaka Akira 35 | 36 | * extconf.rb, terminfo.c: try ncurses.h when ncurses is used. 37 | NetBSD has curses.h which is incompatible with ncurses. 38 | 39 | * terminfo.c: define del_curterm empty on FreeBSD and OpenBSD to 40 | avoid warning and core dump. 41 | 42 | 2007-04-10 Tanaka Akira 43 | 44 | * version 0.1 released. 45 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000026.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | tigetstr (TermInfo) 9 | 10 | 11 | 12 | 13 |
/*
14 |  * TermInfo#tigetstr(capname) => str
15 |  *
16 |  * TermInfo#tigetstr returns a string capability specified by capname.
17 |  *
18 |  * The return value should be printed after tputs is applied.
19 |  * Also tparm should be applied if it has parameters.
20 |  *
21 |  *   io.print ti.tputs(ti.tparm(ti.tigetstr("cuf"), 2))
22 |  *
23 |  * Note that "cuf" means "cursor forward".
24 |  */
25 | static VALUE
26 | rt_tigetstr(VALUE self, VALUE v_capname)
27 | {
28 |   char *ret;
29 |   setup(self);
30 |   ret = tigetstr(StringValueCStr(v_capname));
31 |   if (ret == (char*)-1) {
32 |     rb_raise(eTermInfoError, "not a string capability");
33 |   }
34 |   if (ret == 0) {
35 |     rb_raise(eTermInfoError, "canceled or absent string capability");
36 |   }
37 |   return rb_str_new2(ret);
38 | }
39 | 40 | -------------------------------------------------------------------------------- /ruby-terminfo.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | # stub: ruby-terminfo 0.1.1 ruby lib 3 | # stub: extconf.rb 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "ruby-terminfo".freeze 7 | s.version = "0.1.1" 8 | 9 | s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= 10 | s.require_paths = ["lib".freeze] 11 | s.authors = ["Tanaka Akira".freeze] 12 | s.date = "2022-12-24" 13 | s.description = "terminfo binding for Ruby".freeze 14 | s.email = "akr@fsij.org".freeze 15 | s.extensions = ["extconf.rb".freeze] 16 | s.extra_rdoc_files = ["README".freeze, "ChangeLog".freeze] 17 | s.files = ["ChangeLog".freeze, "README".freeze, "Rakefile".freeze, "extconf.rb".freeze, "lib/terminfo.rb".freeze, "terminfo.c".freeze, "test/test_winsize.rb".freeze] 18 | s.homepage = "http://ruby-terminfo.rubyforge.org".freeze 19 | s.rdoc_options = ["--title".freeze, "ruby-terminfo documentation".freeze, "--charset".freeze, "utf-8".freeze, "--opname".freeze, "index.html".freeze, "--line-numbers".freeze, "--main".freeze, "README".freeze, "--inline-source".freeze, "--exclude".freeze, "^(examples|extras)/".freeze] 20 | s.rubygems_version = "3.3.7".freeze 21 | s.summary = "terminfo binding for Ruby".freeze 22 | 23 | if s.respond_to? :specification_version then 24 | s.specification_version = 4 25 | end 26 | 27 | if s.respond_to? :add_runtime_dependency then 28 | s.add_development_dependency(%q.freeze, ["~> 13.0"]) 29 | else 30 | s.add_dependency(%q.freeze, ["~> 13.0"]) 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /sample/resize: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # xterm's "resize" command clone. 4 | # 5 | # It assumes VT100 compatible terminal. 6 | 7 | require 'terminfo' 8 | require 'termios' 9 | 10 | def stty(io) 11 | termios = Termios.getattr(io) 12 | old = Marshal.load(Marshal.dump(termios)) 13 | begin 14 | yield termios 15 | ensure 16 | Termios.setattr(io, Termios::TCSADRAIN, old) 17 | end 18 | end 19 | 20 | def noecho_raw(io) 21 | stty(io) {|termios| 22 | termios.iflag &= ~(Termios::ISTRIP|Termios::PARMRK|Termios::INLCR|Termios::ICRNL|Termios::IGNCR|Termios::IXON|Termios::IXOFF) 23 | termios.oflag &= ~(Termios::OPOST|Termios::ONLCR|Termios::OCRNL|Termios::ONOCR|Termios::ONLRET) 24 | termios.lflag &= ~(Termios::ISIG|Termios::ICANON|Termios::ECHO|Termios::IEXTEN) 25 | termios.cc[Termios::VMIN] = 1 26 | termios.cc[Termios::VTIME] = 0 27 | Termios.setattr(io, Termios::TCSADRAIN, termios) 28 | yield 29 | } 30 | end 31 | 32 | tty = File.open(TermInfo.ctermid, "r+") 33 | tty.sync = true 34 | 35 | str = nil 36 | noecho_raw(tty) { 37 | tty.print( 38 | "\e7" + # DECSC -- Save Cursor (DEC Private) 39 | "\e[999;999H" + # CUP -- Cursor Position 40 | "\e[6n") # DSR -- Device Status Report 41 | str = tty.readpartial(16) 42 | tty.print "\e8" # DECRC -- Restore Cursor (DEC Private) 43 | } 44 | 45 | exit false if /\e\[(\d+);(\d+)R/ !~ str 46 | 47 | rows = $1.to_i 48 | cols = $2.to_i 49 | 50 | TermInfo.tiocswinsz(tty, rows, cols) 51 | 52 | print <<"End" 53 | COLUMNS=#{cols}; 54 | LINES=#{rows}; 55 | export COLUMNS LINES; 56 | End 57 | 58 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000001.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | default_object (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 34
14 |   def TermInfo.default_object
15 |     unless defined? @default_terminfo
16 |       io = open("/dev/tty", "r+")
17 |       io.sync = true
18 |       @default_terminfo = TermInfo.new(ENV['TERM'], io)
19 |     end
20 |     @default_terminfo
21 |   end
22 | 23 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000027.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | tparm (TermInfo) 9 | 10 | 11 | 12 | 13 |
/*
14 |  * TermInfo#tparm(str, ...) => str
15 |  *
16 |  * TermInfo#tparm expands parameters in str returned by tigetstr.
17 |  */
18 | static VALUE
19 | rt_tparm(int argc, VALUE *argv, VALUE self)
20 | {
21 |   char *capname, *ret;
22 |   setup(self);
23 |   VALUE v_capname, v1, v2, v3, v4, v5, v6, v7, v8, v9;
24 |   long p1, p2, p3, p4, p5, p6, p7, p8, p9;
25 |   setup(self);
26 | 
27 |   if (rb_scan_args(argc, argv, "19", &v_capname, &v1, &v2, &v3, &v4, &v5, &v6, &v7, &v8, &v9) == 0) {
28 |     rb_raise(rb_eArgError, "capname required");
29 |   }
30 | 
31 |   capname = StringValueCStr(v_capname);
32 | #define conv(p, v) do { if (v == Qnil) p = 0; else p = NUM2LONG(v); } while(0)
33 |   conv(p1, v1);
34 |   conv(p2, v2);
35 |   conv(p3, v3);
36 |   conv(p4, v4);
37 |   conv(p5, v5);
38 |   conv(p6, v6);
39 |   conv(p7, v7);
40 |   conv(p8, v8);
41 |   conv(p9, v9);
42 | 
43 |   ret = tparm(capname, p1, p2, p3, p4, p5, p6, p7, p8, p9);
44 | 
45 |   if (ret == NULL) { rb_raise(eTermInfoError, "tparm failed"); }
46 | 
47 |   return rb_str_new2(ret);
48 | }
49 | 50 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000023.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | setupterm (TermInfo) 9 | 10 | 11 | 12 | 13 |
/*
14 |  * TermInfo#setupterm(term, fd) => int
15 |  *
16 |  * TermInfo#setupterm initializes TermInfo object.
17 |  *
18 |  * term is a string of nil.
19 |  * If nil is given, the environment variable $TERM is used.
20 |  *
21 |  * fd is a file descriptor for target terminal.
22 |  */
23 | static VALUE
24 | rt_setupterm(VALUE self, VALUE v_term, VALUE v_fd)
25 | {
26 |   char *term;
27 |   int fd;
28 |   int err;
29 |   int ret;
30 |   if (check_rt(self) != NULL) { rb_raise(eTermInfoError, "terminfo object already initialized"); }
31 | 
32 |   if (v_term == Qnil)
33 |     term = NULL;
34 |   else
35 |     term = StringValueCStr(v_term);
36 |   fd = NUM2INT(v_fd);
37 | 
38 |   ret = setupterm(term, fd, &err);
39 |   if (ret == ERR) {
40 |     if (err == 1) rb_raise(eTermInfoError, "hardcopy terminal");
41 |     else if (err == 0) rb_raise(eTermInfoError, "terminal could not be found");
42 |     else if (err == -1) rb_raise(eTermInfoError, "terminfo database could not be found");
43 |     else rb_raise(eTermInfoError, "unexpected setupterm error");
44 |   }
45 | 
46 |   DATA_PTR(self) = cur_term;
47 | 
48 |   return INT2NUM(err);
49 | }
50 | 51 | -------------------------------------------------------------------------------- /sample/fill: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'terminfo' 4 | require 'termios' 5 | 6 | def stty(io) 7 | termios = Termios.getattr(io) 8 | old = Marshal.load(Marshal.dump(termios)) 9 | begin 10 | yield termios 11 | ensure 12 | Termios.setattr(io, Termios::TCSADRAIN, old) 13 | end 14 | end 15 | 16 | 17 | def noecho_raw(io) 18 | stty(io) {|termios| 19 | termios.iflag &= ~(Termios::ISTRIP|Termios::PARMRK|Termios::INLCR|Termios::ICRNL|Termios::IGNCR|Termios::IXON|Termios::IXOFF) 20 | termios.oflag &= ~(Termios::OPOST|Termios::ONLCR|Termios::OCRNL|Termios::ONOCR|Termios::ONLRET) 21 | termios.lflag &= ~(Termios::ISIG|Termios::ICANON|Termios::ECHO|Termios::IEXTEN) 22 | termios.cc[Termios::VMIN] = 1 23 | termios.cc[Termios::VTIME] = 0 24 | Termios.setattr(io, Termios::TCSADRAIN, termios) 25 | yield 26 | } 27 | end 28 | 29 | tty = STDERR 30 | ti = TermInfo.new 31 | 32 | chars = %w[! " # $ % & ' = - ^ ~ @ * . , ?] 33 | ch = chars[rand(chars.length)] 34 | 35 | def left_to_right(ch) 36 | lines, cols = TermInfo.screen_size 37 | 0.upto(cols-1) {|x| 38 | 0.upto(lines-1) {|y| 39 | TermInfo.control("cup", y, x) 40 | TermInfo.write ch 41 | } 42 | } 43 | end 44 | 45 | def topleft_to_bottomright(ch) 46 | lines, cols = TermInfo.screen_size 47 | 0.upto(lines+cols-1) {|i| 48 | 0.upto(lines-1) {|y| 49 | x = i-y 50 | next if x < 0 || cols <= x 51 | TermInfo.control("cup", y, x) 52 | TermInfo.write ch 53 | } 54 | } 55 | end 56 | 57 | def spiral(ch) 58 | lines, cols = TermInfo.screen_size 59 | cx = cols/2.0 60 | cy = lines/2.0 61 | r = 0.0 62 | t = 0.0 63 | rmax = Math.sqrt(lines**2 + cols**2)/2+1 64 | oldx = oldy = nil 65 | loop { 66 | r += 0.001 67 | t += 0.01 68 | break if rmax < r 69 | x = cx + Math.sin(t) * r 70 | y = cy + Math.cos(t) * r 71 | x = x.round.to_i 72 | y = y.round.to_i 73 | next if oldx == x && oldy == y 74 | next if x < 0 || cols <= x 75 | next if y < 0 || lines <= y 76 | TermInfo.control("cup", y, x) 77 | TermInfo.write ch 78 | oldx = x 79 | oldy = y 80 | } 81 | end 82 | 83 | methods = [ 84 | :left_to_right, 85 | :topleft_to_bottomright, 86 | :spiral, 87 | ] 88 | 89 | noecho_raw(tty) { 90 | lines, cols = TermInfo.screen_size 91 | meth = methods[rand(methods.length)] 92 | send(meth, ch) 93 | TermInfo.control("cup", 999, 0) 94 | } 95 | -------------------------------------------------------------------------------- /rdoc/files/terminfo_c.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | File: terminfo.c 9 | 10 | 11 | 12 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 |

terminfo.c

51 | 52 | 53 | 54 | 56 | 57 | 58 | 59 | 60 | 61 |
Path:terminfo.c 55 |
Last Update:2007-04-10 02:02:25 +0900
62 |
63 | 64 | 65 |
66 | 67 | 68 | 69 |
70 | 71 | 72 | 73 |
74 | 75 | 76 |
77 | 78 | 79 | 80 | 81 |
82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 |
94 | 95 | 96 |
97 |

[Validate]

98 |
99 | 100 | 101 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000014.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | control_string (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 74
14 |   def control_string(*args)
15 |     afflines = 1
16 |     raise ArgumentError, "capname requried" if args.empty?
17 |     afflines = args.shift.to_i if args.first.respond_to?(:to_int)
18 |     raise ArgumentError, "capname not given" if !args.first.respond_to?(:to_str)
19 |     capname = args.shift.to_str 
20 |     self.tputs(self.tparm(self.tigetstr(capname), *args), afflines)
21 |   end
22 | 23 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000017.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | flush (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 95
14 |   def flush
15 |     oldlevel = nil
16 |     if block_given?
17 |       oldlevel = Thread.current[:TermInfo_Flush_level]
18 |       oldsync = @io.sync
19 |       begin
20 |         Thread.current[:TermInfo_Flush_level] = (oldlevel || 0) + 1
21 |         @io.sync = false
22 |         yield
23 |       ensure
24 |         Thread.current[:TermInfo_Flush_level] = oldlevel
25 |         @io.sync = oldsync
26 |       end
27 |     end
28 |     @io.flush if oldlevel == nil
29 |     nil
30 |   end
31 | 32 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.src/M000018.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | screen_size (TermInfo) 9 | 10 | 11 | 12 | 13 |
# File lib/terminfo.rb, line 114
14 |   def screen_size
15 |     begin
16 |       size = TermInfo.tiocgwinsz(@io)
17 |     rescue NotImplementedError
18 |       size = [0,0]
19 |     end
20 |     if size[0] == 0
21 |       size[0] = ENV.include?('LINES') ? ENV['LINES'].to_i : self.tigetnum("lines")
22 |     end
23 |     if size[1] == 0
24 |       size[1] = ENV.include?('COLUMNS') ? ENV['COLUMNS'].to_i : self.tigetnum("cols")
25 |     end
26 |     size
27 |   end
28 | 29 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo/TermInfoError.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | Class: TermInfo::TermInfoError 9 | 10 | 11 | 12 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 70 | 71 |
ClassTermInfo::TermInfoError
In: 58 | 59 | terminfo.c 60 | 61 |
62 |
Parent: 68 | RuntimeError 69 |
72 |
73 | 74 | 75 |
76 | 77 | 78 | 79 |
80 | 81 | 82 | 83 |
84 | 85 | 86 |
87 | 88 | 89 | 90 | 91 |
92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 |
104 | 105 | 106 |
107 |

[Validate]

108 |
109 | 110 | 111 | -------------------------------------------------------------------------------- /rdoc/fr_method_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 12 | 13 | 14 | Methods 15 | 16 | 17 | 18 | 19 | 20 | 55 | 56 | -------------------------------------------------------------------------------- /extconf.rb: -------------------------------------------------------------------------------- 1 | # extconf.rb - a part of a Ruby binding for terminfo library. 2 | # 3 | # Copyright (C) 2007 Tanaka Akira. All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions 7 | # are met: 8 | # 9 | # 1. Redistributions of source code must retain the above copyright 10 | # notice, this list of conditions and the following disclaimer. 11 | # 2. Redistributions in binary form must reproduce the above 12 | # copyright notice, this list of conditions and the following 13 | # disclaimer in the documentation and/or other materials provided 14 | # with the distribution. 15 | # 3. The name of the author may not be used to endorse or promote 16 | # products derived from this software without specific prior 17 | # written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 23 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 25 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 | # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | require 'mkmf' 32 | 33 | # Debian GNU/Linux 4.0 (etch) curses.h, term.h, -lncurses (ncurses.h is linked to curses.h) 34 | # FreeBSD 6.2 curses.h, term.h, -lncurses (ncurses.h is linked to curses.h) 35 | # OpenBSD 4.0 curses.h, term.h, -lncurses (curses.h includes ncurses.h by default) 36 | # HP-UX 11i v3 term.h, -lcurses 37 | # SunOS 5.10 curses.h, term.h, -lcurses 38 | 39 | # NetBSD 3.1 with ncurses ncurses.h, -lncurses (curses.h is incompatible for ncurses) 40 | 41 | have_header("curses.h") 42 | have_header("term.h") 43 | 44 | have_func("ctermid", "stdio.h") 45 | 46 | has_setupterm = true 47 | if have_library("ncurses", "setupterm") 48 | have_header("ncurses.h") 49 | elsif have_library("curses", "setupterm") 50 | else 51 | has_setupterm = false 52 | end 53 | 54 | have_header("wchar.h") 55 | 56 | rubyio_h = nil 57 | rubyio_h = "ruby/io.h" if have_header("ruby/io.h") 58 | rubyio_h = "rubyio.h" unless rubyio_h 59 | 60 | if have_type("rb_io_t", ["ruby.h", rubyio_h]) 61 | have_struct_member("rb_io_t", "fd", ["ruby.h", rubyio_h]) 62 | else 63 | have_struct_member("OpenFile", "fd", ["ruby.h", rubyio_h]) 64 | end 65 | 66 | have_header("ruby/encoding.h") 67 | 68 | if has_setupterm 69 | create_header 70 | create_makefile('terminfo') 71 | 72 | open("Makefile", "a") {|mfile| 73 | mfile.puts <<'End' 74 | rdoc: 75 | rdoc --op rdoc terminfo.c lib/terminfo.rb 76 | End 77 | } 78 | else 79 | puts "terminfo library not found" 80 | end 81 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ruby-terminfo - terminfo bindings for Ruby 2 | 3 | ruby-terminfo provides terminfo bindings for Ruby 4 | 5 | [![Gem Version](https://badge.fury.io/rb/ruby-terminfo.svg)](https://badge.fury.io/rb/ruby-terminfo) 6 | 7 | ## Author 8 | 9 | Tanaka Akira 10 | 11 | ## Home Page 12 | 13 | http://www.a-k-r.org/ruby-terminfo/ 14 | 15 | ## Features 16 | 17 | * Easy to use methods 18 | * `control` (combination of `tigetstr`/`tparm`/`tputs`) 19 | * Low-level terminfo bindings 20 | * `setupterm` 21 | * `tigetflag` 22 | * `tigetnum` 23 | * `tigetstr` 24 | * `tparm` 25 | * `tputs` 26 | * TIOCGWINSZ/TIOCSWINSZ ioctl for screen size 27 | * `ctermid` to avoid hardcoding /dev/tty 28 | * `wcswidth` to measure a string width in number of columns 29 | 30 | ## Usage 31 | 32 | ### Easy to use methods 33 | ```ruby 34 | require 'terminfo' 35 | 36 | TermInfo.control("cuf", 7) # cursor forward 7 columns 37 | p TermInfo.screen_size # use TIOCGWINSZ, LINES/COLUMNS env. or terminfo lines#/cols# 38 | ``` 39 | 40 | ### Low level methods 41 | ```ruby 42 | require 'terminfo' 43 | 44 | t = TermInfo.new(ENV["TERM"], File.open(TermInfo.ctermid, "r+")) 45 | print t.tputs(t.tparm(t.tigetstr("cuf"), 7), 1) # cursor forward 7 columns 46 | p TermInfo.tiocgwinsz(STDOUT) # use TIOCGWINSZ 47 | ``` 48 | 49 | ## Requirements 50 | 51 | * Ruby : http://www.ruby-lang.org/ 52 | 53 | ## Download 54 | 55 | * Latest release: http://www.a-k-r.org/ruby-terminfo/ruby-terminfo-0.2.tar.gz 56 | 57 | * Development version: http://github.com/akr/ruby-terminfo 58 | 59 | ## Install 60 | 61 | ```shell 62 | ruby extconf.rb 63 | make 64 | make install 65 | ``` 66 | 67 | ## Reference Manual 68 | 69 | See rdoc/TermInfo.html or 70 | http://www.a-k-r.org/ruby-terminfo/rdoc/TermInfo.html 71 | 72 | ## License 73 | 74 | 75 | Redistribution and use in source and binary forms, with or without 76 | modification, are permitted provided that the following conditions are met: 77 | 78 | (1) Redistributions of source code must retain the above copyright notice, this 79 | list of conditions and the following disclaimer. 80 | (2) Redistributions in binary form must reproduce the above copyright notice, 81 | this list of conditions and the following disclaimer in the documentation 82 | and/or other materials provided with the distribution. 83 | (3) The name of the author may not be used to endorse or promote products 84 | derived from this software without specific prior written permission. 85 | 86 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 87 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 88 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 89 | EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 90 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 91 | OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 92 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 93 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 94 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 95 | OF SUCH DAMAGE. 96 | 97 | (The modified BSD licence) 98 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'rake' 3 | require 'rake/clean' 4 | require 'rake/testtask' 5 | require 'rake/packagetask' 6 | require 'rubygems/package_task' 7 | require 'rdoc/task' 8 | #require 'rake/contrib/rubyforgepublisher' 9 | #require 'rake/contrib/sshpublisher' 10 | require 'fileutils' 11 | include FileUtils 12 | 13 | NAME = "ruby-terminfo" 14 | AUTHOR = "Tanaka Akira" 15 | EMAIL = "akr@fsij.org" 16 | DESCRIPTION = "terminfo binding for Ruby" 17 | RUBYFORGE_PROJECT = "ruby-terminfo" 18 | HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org" 19 | BIN_FILES = %w( ) 20 | 21 | VERS = "0.1.1" 22 | REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil 23 | CLEAN.include ['**/.*.sw?', '*.gem', '.config'] 24 | RDOC_OPTS = [ 25 | '--title', "#{NAME} documentation", 26 | "--charset", "utf-8", 27 | "--opname", "index.html", 28 | "--line-numbers", 29 | "--main", "README", 30 | "--inline-source", 31 | ] 32 | 33 | task :default => [:test] 34 | task :package => [:clean] 35 | 36 | Rake::TestTask.new("test") do |t| 37 | t.libs << "test" 38 | t.pattern = "test/**/*_test.rb" 39 | t.verbose = true 40 | end 41 | 42 | spec = Gem::Specification.new do |s| 43 | s.name = NAME 44 | s.version = VERS 45 | s.platform = Gem::Platform::RUBY 46 | #s.has_rdoc = true 47 | s.extra_rdoc_files = ["README", "ChangeLog"] 48 | s.rdoc_options += RDOC_OPTS + ['--exclude', '^(examples|extras)/'] 49 | s.summary = DESCRIPTION 50 | s.description = DESCRIPTION 51 | s.author = AUTHOR 52 | s.email = EMAIL 53 | s.homepage = HOMEPATH 54 | s.executables = BIN_FILES 55 | s.rubyforge_project = RUBYFORGE_PROJECT 56 | s.bindir = "bin" 57 | s.require_path = "lib" 58 | #s.autorequire = "" 59 | s.test_files = Dir["test/*_test.rb"] 60 | 61 | #s.add_dependency('activesupport', '>=1.3.1') 62 | #s.required_ruby_version = '>= 1.8.2' 63 | s.add_development_dependency('rake', '~> 13.0') 64 | 65 | s.files = %w(README ChangeLog Rakefile) + 66 | Dir.glob("{bin,doc,test,lib,templates,generator,extras,website,script}/**/*") + 67 | Dir.glob("*.{c,rb}") + 68 | Dir.glob("examples/**/*.rb") + 69 | Dir.glob("tools/*.rb") + 70 | Dir.glob("rails/*.rb") 71 | 72 | s.extensions = ["extconf.rb"] 73 | end 74 | 75 | Rake::PackageTask.new(spec.name, VERS) do |pkg| 76 | pkg.need_tar = true 77 | end 78 | 79 | 80 | task :install do 81 | name = "#{NAME}-#{VERS}.gem" 82 | sh %{rake package} 83 | sh %{sudo gem install pkg/#{name}} 84 | end 85 | 86 | task :uninstall => [:clean] do 87 | sh %{sudo gem uninstall #{NAME}} 88 | end 89 | 90 | 91 | Rake::RDocTask.new do |rdoc| 92 | rdoc.rdoc_dir = 'html' 93 | rdoc.options += RDOC_OPTS 94 | rdoc.template = "resh" 95 | #rdoc.template = "#{ENV['template']}.rb" if ENV['template'] 96 | if ENV['DOC_FILES'] 97 | rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/)) 98 | else 99 | rdoc.rdoc_files.include('README', 'ChangeLog') 100 | rdoc.rdoc_files.include('lib/**/*.rb') 101 | rdoc.rdoc_files.include('**/*.c') 102 | end 103 | end 104 | 105 | desc "Publish to RubyForge" 106 | task :rubyforge => [:rdoc, :package] do 107 | require 'rubyforge' 108 | Rake::RubyForgePublisher.new(RUBYFORGE_PROJECT, 'takiuchi').upload 109 | end 110 | 111 | desc 'Package and upload the release to rubyforge.' 112 | task :release => [:clean, :package] do |t| 113 | v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z" 114 | abort "Versions don't match #{v} vs #{VERS}" unless v == VERS 115 | pkg = "pkg/#{NAME}-#{VERS}" 116 | 117 | require 'rubyforge' 118 | rf = RubyForge.new.configure 119 | puts "Logging in" 120 | rf.login 121 | 122 | c = rf.userconfig 123 | # c["release_notes"] = description if description 124 | # c["release_changes"] = changes if changes 125 | c["preformatted"] = true 126 | 127 | files = [ 128 | "#{pkg}.tgz", 129 | "#{pkg}.gem" 130 | ].compact 131 | 132 | puts "Releasing #{NAME} v. #{VERS}" 133 | rf.add_release RUBYFORGE_PROJECT, NAME, VERS, *files 134 | end 135 | 136 | desc 'Show information about the gem.' 137 | task :debug_gem do 138 | puts spec.to_ruby 139 | end 140 | 141 | desc 'Update gem spec' 142 | task :gemspec do 143 | open("#{NAME}.gemspec", 'w').write spec.to_ruby 144 | end 145 | -------------------------------------------------------------------------------- /rdoc/files/extconf_rb.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | File: extconf.rb 9 | 10 | 11 | 12 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 |

extconf.rb

51 | 52 | 53 | 54 | 56 | 57 | 58 | 59 | 60 | 61 |
Path:extconf.rb 55 |
Last Update:2007-04-10 18:07:11 +0900
62 |
63 | 64 | 65 |
66 | 67 | 68 | 69 |
70 | 71 |
72 |

73 | extconf.rb - a part of a Ruby binding for terminfo library. 74 |

75 |

76 | Copyright (C) 2007 Tanaka Akira. All rights reserved. 77 |

78 |

79 | Redistribution and use in source and binary forms, with or without 80 | modification, are permitted provided that the following conditions are met: 81 |

82 |
 83 |  1. Redistributions of source code must retain the above copyright
 84 |     notice, this list of conditions and the following disclaimer.
 85 |  2. Redistributions in binary form must reproduce the above
 86 |     copyright notice, this list of conditions and the following
 87 |     disclaimer in the documentation and/or other materials provided
 88 |     with the distribution.
 89 |  3. The name of the author may not be used to endorse or promote
 90 |     products derived from this software without specific prior
 91 |     written permission.
 92 | 
93 |

94 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS’’ AND ANY 95 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 96 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 97 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 98 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 99 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 100 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 101 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 102 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 103 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 104 | DAMAGE. 105 |

106 | 107 |
108 | 109 |
110 |

Required files

111 | 112 |
113 | mkmf   114 |
115 |
116 | 117 |
118 | 119 | 120 |
121 | 122 | 123 | 124 | 125 |
126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 |
138 | 139 | 140 |
141 |

[Validate]

142 |
143 | 144 | 145 | -------------------------------------------------------------------------------- /rdoc/files/lib/terminfo_rb.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | File: terminfo.rb 9 | 10 | 11 | 12 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 |

terminfo.rb

51 | 52 | 53 | 54 | 56 | 57 | 58 | 59 | 60 | 61 |
Path:lib/terminfo.rb 55 |
Last Update:2007-04-10 15:03:55 +0900
62 |
63 | 64 | 65 |
66 | 67 | 68 | 69 |
70 | 71 |
72 |

73 | terminfo.rb - a part of a Ruby binding for terminfo library. 74 |

75 |

76 | Copyright (C) 2007 Tanaka Akira. All rights reserved. 77 |

78 |

79 | Redistribution and use in source and binary forms, with or without 80 | modification, are permitted provided that the following conditions are met: 81 |

82 |
 83 |  1. Redistributions of source code must retain the above copyright
 84 |     notice, this list of conditions and the following disclaimer.
 85 |  2. Redistributions in binary form must reproduce the above
 86 |     copyright notice, this list of conditions and the following
 87 |     disclaimer in the documentation and/or other materials provided
 88 |     with the distribution.
 89 |  3. The name of the author may not be used to endorse or promote
 90 |     products derived from this software without specific prior
 91 |     written permission.
 92 | 
93 |

94 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS’’ AND ANY 95 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 96 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 97 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 98 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 99 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 100 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 101 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 102 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 103 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 104 | DAMAGE. 105 |

106 | 107 |
108 | 109 |
110 |

Required files

111 | 112 |
113 | terminfo.so   114 |
115 |
116 | 117 |
118 | 119 | 120 |
121 | 122 | 123 | 124 | 125 |
126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 |
138 | 139 | 140 |
141 |

[Validate]

142 |
143 | 144 | 145 | -------------------------------------------------------------------------------- /lib/terminfo.rb: -------------------------------------------------------------------------------- 1 | # terminfo.rb - a part of a Ruby binding for terminfo library. 2 | # 3 | # Copyright (C) 2007 Tanaka Akira. All rights reserved. 4 | # 5 | # Redistribution and use in source and binary forms, with or without 6 | # modification, are permitted provided that the following conditions 7 | # are met: 8 | # 9 | # 1. Redistributions of source code must retain the above copyright 10 | # notice, this list of conditions and the following disclaimer. 11 | # 2. Redistributions in binary form must reproduce the above 12 | # copyright notice, this list of conditions and the following 13 | # disclaimer in the documentation and/or other materials provided 14 | # with the distribution. 15 | # 3. The name of the author may not be used to endorse or promote 16 | # products derived from this software without specific prior 17 | # written permission. 18 | # 19 | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 23 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 25 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 | # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | require 'terminfo.so' 32 | 33 | class TermInfo 34 | def TermInfo.default_object 35 | unless defined? @default_terminfo 36 | io = File.open(TermInfo.ctermid, File::RDWR|File::NOCTTY) 37 | io.sync = true 38 | @default_terminfo = TermInfo.new(ENV['TERM'], io) 39 | end 40 | @default_terminfo 41 | end 42 | 43 | def TermInfo.control_string(*args) default_object.control_string(*args) end 44 | def TermInfo.control(*args) default_object.control(*args) end 45 | def TermInfo.write(str) default_object.write(str) end 46 | def TermInfo.flush(&block) default_object.flush(&block) end 47 | def TermInfo.screen_size() default_object.screen_size() end 48 | def TermInfo.screen_lines() default_object.screen_lines() end 49 | def TermInfo.screen_height() default_object.screen_height() end 50 | def TermInfo.screen_columns() default_object.screen_columns() end 51 | def TermInfo.screen_width() default_object.screen_width() end 52 | def TermInfo.io() default_object.io() end 53 | 54 | def initialize(term=ENV['TERM'], io=STDERR) 55 | setupterm(term, io.fileno) 56 | @term = term 57 | @io = io 58 | end 59 | attr_reader :io 60 | 61 | def inspect 62 | "\#<#{self.class}:#{@term}>" 63 | end 64 | 65 | # TermInfo#control_string return a string to control terminal. 66 | # 67 | # TermInfo#control_string([afflines,] capname, p1, p2, ...) 68 | # 69 | # capname is a terminfo string capability such as "cuu", "el". 70 | # 71 | # p1, p2, ... are parameters for the capability. 72 | # 73 | # afflines is a number of lines affected. (used for determining padding length) 74 | def control_string(*args) 75 | afflines = 1 76 | raise ArgumentError, "capname requried" if args.empty? 77 | afflines = args.shift.to_i if args.first.respond_to?(:to_int) 78 | raise ArgumentError, "capname not given" if !args.first.respond_to?(:to_str) 79 | capname = args.shift.to_str 80 | self.tputs(self.tparm(self.tigetstr(capname), *args), afflines) 81 | end 82 | 83 | # TermInfo#control controls a terminal. 84 | # 85 | # It prints the result of control_string to io specified at initialization. 86 | def control(*args) 87 | @io.write(self.control_string(*args)) 88 | nil 89 | end 90 | 91 | def write(str) 92 | @io.write(str) 93 | end 94 | 95 | def flush 96 | oldlevel = nil 97 | if block_given? 98 | oldlevel = Thread.current[:TermInfo_Flush_level] 99 | oldsync = @io.sync 100 | begin 101 | Thread.current[:TermInfo_Flush_level] = (oldlevel || 0) + 1 102 | @io.sync = false 103 | yield 104 | ensure 105 | Thread.current[:TermInfo_Flush_level] = oldlevel 106 | @io.sync = oldsync 107 | end 108 | end 109 | @io.flush if oldlevel == nil 110 | nil 111 | end 112 | 113 | # returns terminal screen size in a two element array: [lines, columns]. 114 | def screen_size 115 | begin 116 | size = TermInfo.tiocgwinsz(@io) 117 | rescue NotImplementedError 118 | size = [0,0] 119 | end 120 | if size[0] == 0 121 | size[0] = ENV.include?('LINES') ? ENV['LINES'].to_i : self.tigetnum("lines") 122 | end 123 | if size[1] == 0 124 | size[1] = ENV.include?('COLUMNS') ? ENV['COLUMNS'].to_i : self.tigetnum("cols") 125 | end 126 | size 127 | end 128 | 129 | # returns terminal screen height. 130 | def screen_lines 131 | self.screen_size[0] 132 | end 133 | alias screen_height screen_lines 134 | 135 | # returns terminal screen width. 136 | def screen_columns 137 | self.screen_size[1] 138 | end 139 | alias screen_width screen_columns 140 | end 141 | -------------------------------------------------------------------------------- /rdoc/rdoc-style.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | font-family: Verdana,Arial,Helvetica,sans-serif; 4 | font-size: 90%; 5 | margin: 0; 6 | margin-left: 40px; 7 | padding: 0; 8 | background: white; 9 | } 10 | 11 | h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; } 12 | h1 { font-size: 150%; } 13 | h2,h3,h4 { margin-top: 1em; } 14 | 15 | a { background: #eef; color: #039; text-decoration: none; } 16 | a:hover { background: #039; color: #eef; } 17 | 18 | /* Override the base stylesheet's Anchor inside a table cell */ 19 | td > a { 20 | background: transparent; 21 | color: #039; 22 | text-decoration: none; 23 | } 24 | 25 | /* and inside a section title */ 26 | .section-title > a { 27 | background: transparent; 28 | color: #eee; 29 | text-decoration: none; 30 | } 31 | 32 | /* === Structural elements =================================== */ 33 | 34 | div#index { 35 | margin: 0; 36 | margin-left: -40px; 37 | padding: 0; 38 | font-size: 90%; 39 | } 40 | 41 | 42 | div#index a { 43 | margin-left: 0.7em; 44 | } 45 | 46 | div#index .section-bar { 47 | margin-left: 0px; 48 | padding-left: 0.7em; 49 | background: #ccc; 50 | font-size: small; 51 | } 52 | 53 | 54 | div#classHeader, div#fileHeader { 55 | width: auto; 56 | color: white; 57 | padding: 0.5em 1.5em 0.5em 1.5em; 58 | margin: 0; 59 | margin-left: -40px; 60 | border-bottom: 3px solid #006; 61 | } 62 | 63 | div#classHeader a, div#fileHeader a { 64 | background: inherit; 65 | color: white; 66 | } 67 | 68 | div#classHeader td, div#fileHeader td { 69 | background: inherit; 70 | color: white; 71 | } 72 | 73 | 74 | div#fileHeader { 75 | background: #057; 76 | } 77 | 78 | div#classHeader { 79 | background: #048; 80 | } 81 | 82 | 83 | .class-name-in-header { 84 | font-size: 180%; 85 | font-weight: bold; 86 | } 87 | 88 | 89 | div#bodyContent { 90 | padding: 0 1.5em 0 1.5em; 91 | } 92 | 93 | div#description { 94 | padding: 0.5em 1.5em; 95 | background: #efefef; 96 | border: 1px dotted #999; 97 | } 98 | 99 | div#description h1,h2,h3,h4,h5,h6 { 100 | color: #125;; 101 | background: transparent; 102 | } 103 | 104 | div#validator-badges { 105 | text-align: center; 106 | } 107 | div#validator-badges img { border: 0; } 108 | 109 | div#copyright { 110 | color: #333; 111 | background: #efefef; 112 | font: 0.75em sans-serif; 113 | margin-top: 5em; 114 | margin-bottom: 0; 115 | padding: 0.5em 2em; 116 | } 117 | 118 | 119 | /* === Classes =================================== */ 120 | 121 | table.header-table { 122 | color: white; 123 | font-size: small; 124 | } 125 | 126 | .type-note { 127 | font-size: small; 128 | color: #DEDEDE; 129 | } 130 | 131 | .xxsection-bar { 132 | background: #eee; 133 | color: #333; 134 | padding: 3px; 135 | } 136 | 137 | .section-bar { 138 | color: #333; 139 | border-bottom: 1px solid #999; 140 | margin-left: -20px; 141 | } 142 | 143 | 144 | .section-title { 145 | background: #79a; 146 | color: #eee; 147 | padding: 3px; 148 | margin-top: 2em; 149 | margin-left: -30px; 150 | border: 1px solid #999; 151 | } 152 | 153 | .top-aligned-row { vertical-align: top } 154 | .bottom-aligned-row { vertical-align: bottom } 155 | 156 | /* --- Context section classes ----------------------- */ 157 | 158 | .context-row { } 159 | .context-item-name { font-family: monospace; font-weight: bold; color: black; } 160 | .context-item-value { font-size: small; color: #448; } 161 | .context-item-desc { color: #333; padding-left: 2em; } 162 | 163 | /* --- Method classes -------------------------- */ 164 | .method-detail { 165 | background: #efefef; 166 | padding: 0; 167 | margin-top: 0.5em; 168 | margin-bottom: 1em; 169 | border: 1px dotted #ccc; 170 | } 171 | .method-heading { 172 | color: black; 173 | background: #ccc; 174 | border-bottom: 1px solid #666; 175 | padding: 0.2em 0.5em 0 0.5em; 176 | } 177 | .method-signature { color: black; background: inherit; } 178 | .method-name { font-weight: bold; } 179 | .method-args { font-style: italic; } 180 | .method-description { padding: 0 0.5em 0 0.5em; } 181 | 182 | /* --- Source code sections -------------------- */ 183 | 184 | a.source-toggle { font-size: 90%; } 185 | div.method-source-code { 186 | background: #262626; 187 | color: #ffdead; 188 | margin: 1em; 189 | padding: 0.5em; 190 | border: 1px dashed #999; 191 | overflow: hidden; 192 | } 193 | 194 | div.method-source-code pre { color: #ffdead; overflow: hidden; } 195 | 196 | /* --- Ruby keyword styles --------------------- */ 197 | 198 | .standalone-code { background: #221111; color: #ffdead; overflow: hidden; } 199 | 200 | .ruby-constant { color: #7fffd4; background: transparent; } 201 | .ruby-keyword { color: #00ffff; background: transparent; } 202 | .ruby-ivar { color: #eedd82; background: transparent; } 203 | .ruby-operator { color: #00ffee; background: transparent; } 204 | .ruby-identifier { color: #ffdead; background: transparent; } 205 | .ruby-node { color: #ffa07a; background: transparent; } 206 | .ruby-comment { color: #b22222; font-weight: bold; background: transparent; } 207 | .ruby-regexp { color: #ffa07a; background: transparent; } 208 | .ruby-value { color: #7fffd4; background: transparent; } -------------------------------------------------------------------------------- /terminfo.c: -------------------------------------------------------------------------------- 1 | /* terminfo.c - Ruby binding for terminfo library. 2 | 3 | Copyright (C) 2007, 2008 Tanaka Akira. All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions 7 | are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 2. Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 3. The name of the author may not be used to endorse or promote 16 | products derived from this software without specific prior 17 | written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 25 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include "ruby.h" 33 | #ifdef HAVE_RUBY_IO_H 34 | # include "ruby/io.h" 35 | #else 36 | # include "rubyio.h" 37 | #endif 38 | #include "extconf.h" 39 | 40 | #if defined(HAVE_NCURSES_H) 41 | #include 42 | #elif defined(HAVE_CURSES_H) 43 | #include 44 | #endif 45 | 46 | #ifdef HAVE_TERM_H 47 | #include 48 | #endif 49 | 50 | #include 51 | #include 52 | #include 53 | 54 | #ifdef HAVE_WCHAR_H 55 | #include 56 | #endif 57 | 58 | static VALUE cTermInfo; 59 | static VALUE eTermInfoError; 60 | 61 | #ifndef HAVE_TYPE_RB_IO_T 62 | typedef OpenFile rb_io_t; 63 | #endif 64 | 65 | #if defined(HAVE_RB_IO_T_FD) || defined(HAVE_ST_FD) 66 | # define FILENO(fptr) (fptr->fd) 67 | #else 68 | # define FILENO(fptr) fileno(fptr->f) 69 | #endif 70 | 71 | #if (defined(__FreeBSD__) && __FreeBSD_cc_version <= 602001) || \ 72 | defined(__OpenBSD__) 73 | /* 74 | * warning on FreeBSD 75 | http://www.FreeBSD.org/cgi/query-pr.cgi?pr=108117&cat= 76 | * core dump on OpenBSD 77 | http://cvs.openbsd.org/cgi-bin/query-pr-wrapper?full=yes&textonly=yes&numbers=5447 78 | */ 79 | #define del_curterm(oterm) do {} while(0) 80 | #endif 81 | 82 | static void 83 | rt_free(void *ptr) 84 | { 85 | if(ptr != NULL) 86 | del_curterm(ptr); 87 | } 88 | 89 | static VALUE 90 | rt_alloc(VALUE klass) 91 | { 92 | return Data_Wrap_Struct(klass, NULL, rt_free, 0); 93 | } 94 | 95 | static TERMINAL * 96 | check_rt(VALUE self) 97 | { 98 | Check_Type(self, T_DATA); 99 | if (RDATA(self)->dfree != rt_free) { 100 | rb_raise(rb_eTypeError, "wrong argument type %s (expected TermInfo)", 101 | rb_class2name(CLASS_OF(self))); 102 | } 103 | return DATA_PTR(self); 104 | } 105 | 106 | static void 107 | setup(VALUE self) 108 | { 109 | TERMINAL *term = check_rt(self); 110 | if (term == NULL) { rb_raise(eTermInfoError, "terminfo object not initialized"); } 111 | if (cur_term == term) 112 | return; 113 | } 114 | 115 | /* 116 | * TermInfo#setupterm(term, fd) => int 117 | * 118 | * TermInfo#setupterm initializes TermInfo object. 119 | * 120 | * term is a string of nil. 121 | * If nil is given, the environment variable $TERM is used. 122 | * 123 | * fd is a file descriptor for target terminal. 124 | */ 125 | static VALUE 126 | rt_setupterm(VALUE self, VALUE v_term, VALUE v_fd) 127 | { 128 | char *term; 129 | int fd; 130 | int err; 131 | int ret; 132 | if (check_rt(self) != NULL) { rb_raise(eTermInfoError, "terminfo object already initialized"); } 133 | 134 | if (v_term == Qnil) 135 | term = NULL; 136 | else 137 | term = StringValueCStr(v_term); 138 | fd = NUM2INT(v_fd); 139 | 140 | ret = setupterm(term, fd, &err); 141 | if (ret == ERR) { 142 | if (err == 1) rb_raise(eTermInfoError, "hardcopy terminal"); 143 | else if (err == 0) rb_raise(eTermInfoError, "terminal could not be found"); 144 | else if (err == -1) rb_raise(eTermInfoError, "terminfo database could not be found"); 145 | else rb_raise(eTermInfoError, "unexpected setupterm error"); 146 | } 147 | 148 | DATA_PTR(self) = cur_term; 149 | 150 | return INT2NUM(err); 151 | } 152 | 153 | /* 154 | * TermInfo#tigetflag(capname) => int 155 | * 156 | * TermInfo#tigetflag returns a boolean capability specified by capname. 157 | */ 158 | static VALUE 159 | rt_tigetflag(VALUE self, VALUE v_capname) 160 | { 161 | int ret; 162 | setup(self); 163 | ret = tigetflag(StringValueCStr(v_capname)); 164 | if (ret == -1) { rb_raise(eTermInfoError, "not a boolean capability"); } 165 | return RTEST(ret) ? Qtrue : Qfalse; 166 | } 167 | 168 | /* 169 | * TermInfo#tigetnum(capname) => int 170 | * 171 | * TermInfo#tigetnum returns a numeric capability specified by capname. 172 | */ 173 | static VALUE 174 | rt_tigetnum(VALUE self, VALUE v_capname) 175 | { 176 | int ret; 177 | setup(self); 178 | ret = tigetnum(StringValueCStr(v_capname)); 179 | if (ret == -2) { rb_raise(eTermInfoError, "not a numeric capability"); } 180 | if (ret == -1) { rb_raise(eTermInfoError, "canceled or absent numeric capability"); } 181 | return INT2NUM(ret); 182 | } 183 | 184 | /* 185 | * TermInfo#tigetstr(capname) => str 186 | * 187 | * TermInfo#tigetstr returns a string capability specified by capname. 188 | * 189 | * The return value should be printed after tputs is applied. 190 | * Also tparm should be applied if it has parameters. 191 | * 192 | * io.print ti.tputs(ti.tparm(ti.tigetstr("cuf"), 2)) 193 | * 194 | * Note that "cuf" means "cursor forward". 195 | */ 196 | static VALUE 197 | rt_tigetstr(VALUE self, VALUE v_capname) 198 | { 199 | char *ret; 200 | setup(self); 201 | ret = tigetstr(StringValueCStr(v_capname)); 202 | if (ret == (char*)-1) { 203 | rb_raise(eTermInfoError, "not a string capability"); 204 | } 205 | if (ret == 0) { 206 | rb_raise(eTermInfoError, "canceled or absent string capability"); 207 | } 208 | return rb_str_new2(ret); 209 | } 210 | 211 | /* 212 | * TermInfo#tparm(str, ...) => str 213 | * 214 | * TermInfo#tparm expands parameters in str returned by tigetstr. 215 | */ 216 | static VALUE 217 | rt_tparm(int argc, VALUE *argv, VALUE self) 218 | { 219 | char *capname, *ret; 220 | setup(self); 221 | VALUE v_capname, v1, v2, v3, v4, v5, v6, v7, v8, v9; 222 | long p1, p2, p3, p4, p5, p6, p7, p8, p9; 223 | setup(self); 224 | 225 | if (rb_scan_args(argc, argv, "19", &v_capname, &v1, &v2, &v3, &v4, &v5, &v6, &v7, &v8, &v9) == 0) { 226 | rb_raise(rb_eArgError, "capname required"); 227 | } 228 | 229 | capname = StringValueCStr(v_capname); 230 | #define conv(p, v) do { if (v == Qnil) p = 0; else p = NUM2LONG(v); } while(0) 231 | conv(p1, v1); 232 | conv(p2, v2); 233 | conv(p3, v3); 234 | conv(p4, v4); 235 | conv(p5, v5); 236 | conv(p6, v6); 237 | conv(p7, v7); 238 | conv(p8, v8); 239 | conv(p9, v9); 240 | 241 | ret = tparm(capname, p1, p2, p3, p4, p5, p6, p7, p8, p9); 242 | 243 | if (ret == NULL) { rb_raise(eTermInfoError, "tparm failed"); } 244 | 245 | return rb_str_new2(ret); 246 | } 247 | 248 | static VALUE putfunc_output; /* xxx: not thread safe */ 249 | 250 | static int 251 | putfunc(int arg) 252 | { 253 | char ch = arg; 254 | rb_str_cat(putfunc_output, &ch, 1); 255 | return arg; 256 | } 257 | 258 | /* 259 | * TermInfo#tputs(str, affcnt) => str 260 | * 261 | * TermInfo#tputs expands padding informaiton using padding characters. 262 | * affcnt is a number of lines affected by the str. 263 | */ 264 | static VALUE 265 | rt_tputs(VALUE self, VALUE v_str, VALUE v_affcnt) 266 | { 267 | int ret; 268 | char *str; 269 | int affcnt; 270 | VALUE output; 271 | 272 | setup(self); 273 | str = StringValueCStr(v_str); 274 | affcnt = NUM2INT(v_affcnt); 275 | 276 | putfunc_output = output = rb_str_new2(""); 277 | ret = tputs(str, affcnt, putfunc); 278 | putfunc_output = Qnil; 279 | 280 | if (ret == ERR) { rb_raise(eTermInfoError, "tputs failed"); } 281 | 282 | return output; 283 | } 284 | 285 | /* 286 | * TermInfo.tiocgwinsz(io) => [row, col] 287 | * 288 | * TermInfo.tiocgwinsz returns the screen size of the terminal refered by io, 289 | * using TIOCGWINSZ ioctl. 290 | */ 291 | static VALUE 292 | rt_tiocgwinsz(VALUE self, VALUE io) 293 | { 294 | #ifdef TIOCGWINSZ 295 | struct winsize sz; 296 | int ret; 297 | 298 | ret = ioctl(rb_io_descriptor(io), TIOCGWINSZ, &sz); 299 | if (ret == -1) rb_raise(rb_eIOError, "TIOCGWINSZ failed"); 300 | 301 | return rb_ary_new3(2, INT2NUM(sz.ws_row), INT2NUM(sz.ws_col)); 302 | #else 303 | rb_notimplement(); 304 | #endif 305 | } 306 | 307 | /* 308 | * TermInfo.tiocswinsz(io, row, col) 309 | * 310 | * TermInfo.tiocgwinsz update the screen size information of the terminal refered by io, 311 | * using TIOCSWINSZ ioctl. 312 | * 313 | * It returns nil. 314 | */ 315 | static VALUE 316 | rt_tiocswinsz(VALUE self, VALUE io, VALUE row, VALUE col) 317 | { 318 | #ifdef TIOCSWINSZ 319 | struct winsize sz; 320 | int ret; 321 | 322 | sz.ws_row = NUM2INT(row); 323 | sz.ws_col = NUM2INT(col); 324 | 325 | ret = ioctl(rb_io_descriptor(io), TIOCSWINSZ, &sz); 326 | if (ret == -1) rb_raise(rb_eIOError, "TIOCSWINSZ failed"); 327 | 328 | return Qnil; 329 | #else 330 | rb_notimplement(); 331 | #endif 332 | } 333 | 334 | /* 335 | * TermInfo.ctermid 336 | * 337 | * TermInfo.ctermid returns a pathname for the current controling terminal, 338 | * such as "/dev/tty". 339 | */ 340 | static VALUE 341 | rt_ctermid(VALUE self) 342 | { 343 | #ifdef HAVE_CTERMID 344 | char buf[L_ctermid]; 345 | return rb_str_new2(ctermid(buf)); 346 | #else 347 | return rb_str_new2("/dev/tty"); 348 | #endif 349 | } 350 | 351 | /* 352 | * TermInfo.wcswidth(str) 353 | * 354 | * TermInfo.wcswidth returns a the number of columns of str, 355 | * according to current locale. 356 | */ 357 | static VALUE 358 | rt_wcswidth(VALUE self, VALUE str) 359 | { 360 | char *s; 361 | size_t l, r; 362 | mbstate_t mbs; 363 | wchar_t wc; 364 | long cols; 365 | int width; 366 | 367 | #ifdef HAVE_RUBY_ENCODING_H 368 | /* The encoding of str is assumed to be the locale encoding on Ruby 1.8. */ 369 | str = rb_str_encode(str, rb_enc_from_encoding(rb_locale_encoding()), 0, Qnil); 370 | #endif 371 | 372 | memset(&mbs,0,sizeof(mbstate_t)); 373 | 374 | s = StringValueCStr(str); 375 | l = RSTRING_LEN(str); 376 | 377 | cols = 0; 378 | while (0 < l) { 379 | r = mbrtowc(&wc, s, l, &mbs); 380 | if (r == 0) 381 | rb_raise(rb_eArgError, "NUL found"); 382 | 383 | width = wcwidth(wc); 384 | if (width == -1) 385 | rb_raise(rb_eArgError, "non-printable charactor found"); 386 | cols += width; 387 | 388 | l -= r; 389 | s += r; 390 | } 391 | 392 | return LONG2NUM(cols); 393 | } 394 | 395 | void 396 | Init_terminfo(void) 397 | { 398 | putfunc_output = Qnil; 399 | rb_global_variable(&putfunc_output); 400 | 401 | cTermInfo = rb_define_class("TermInfo", rb_cObject); 402 | eTermInfoError = rb_define_class_under(cTermInfo, "TermInfoError", rb_eRuntimeError); 403 | 404 | rb_define_alloc_func(cTermInfo, rt_alloc); 405 | 406 | rb_define_method(cTermInfo, "setupterm", rt_setupterm, 2); 407 | rb_define_method(cTermInfo, "tigetflag", rt_tigetflag, 1); 408 | rb_define_method(cTermInfo, "tigetnum", rt_tigetnum, 1); 409 | rb_define_method(cTermInfo, "tigetstr", rt_tigetstr, 1); 410 | rb_define_method(cTermInfo, "tparm", rt_tparm, -1); 411 | rb_define_method(cTermInfo, "tputs", rt_tputs, 2); 412 | 413 | rb_define_module_function(cTermInfo, "tiocgwinsz", rt_tiocgwinsz, 1); 414 | rb_define_module_function(cTermInfo, "tiocswinsz", rt_tiocswinsz, 3); 415 | 416 | rb_define_module_function(cTermInfo, "ctermid", rt_ctermid, 0); 417 | 418 | rb_define_module_function(cTermInfo, "wcswidth", rt_wcswidth, 1); 419 | } 420 | -------------------------------------------------------------------------------- /rdoc/classes/TermInfo.html: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | Class: TermInfo 9 | 10 | 11 | 12 | 43 | 44 | 45 | 46 | 47 | 48 | 49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 67 | 68 | 69 | 70 | 71 | 74 | 75 |
ClassTermInfo
In: 58 | 59 | lib/terminfo.rb 60 | 61 |
62 | 63 | terminfo.c 64 | 65 |
66 |
Parent: 72 | Object 73 |
76 |
77 | 78 | 79 |
80 | 81 | 82 | 83 |
84 | 85 | 86 | 87 |
88 | 89 |
90 |

Methods

91 | 92 |
93 | control   94 | control   95 | control_string   96 | control_string   97 | default_object   98 | flush   99 | flush   100 | inspect   101 | io   102 | new   103 | screen_columns   104 | screen_columns   105 | screen_height   106 | screen_height   107 | screen_lines   108 | screen_lines   109 | screen_size   110 | screen_size   111 | screen_width   112 | screen_width   113 | setupterm   114 | tigetflag   115 | tigetnum   116 | tigetstr   117 | tiocgwinsz   118 | tiocswinsz   119 | tparm   120 | tputs   121 | write   122 | write   123 |
124 |
125 | 126 |
127 | 128 | 129 | 130 | 131 |
132 | 133 |
134 |

Classes and Modules

135 | 136 | Class TermInfo::TermInfoError
137 | 138 |
139 | 140 | 141 | 142 | 143 |
144 |

Attributes

145 | 146 |
147 | 148 | 149 | 150 | 151 | 152 | 153 |
io [R] 
154 |
155 |
156 | 157 | 158 | 159 | 160 |
161 |

Public Class methods

162 | 163 |
164 | 165 | 166 | 172 | 173 |
174 |
175 |
176 | 177 |
178 | 179 | 180 | 186 | 187 |
188 |
189 |
190 | 191 |
192 | 193 | 194 | 200 | 201 |
202 |
203 |
204 | 205 |
206 | 207 | 208 | 214 | 215 |
216 |
217 |
218 | 219 |
220 | 221 | 222 |
223 | 225 | io() 226 | 227 |
228 | 229 |
230 |
231 |
232 | 233 |
234 | 235 | 236 | 242 | 243 |
244 |
245 |
246 | 247 |
248 | 249 | 250 | 256 | 257 |
258 |
259 |
260 | 261 |
262 | 263 | 264 | 270 | 271 |
272 |
273 |
274 | 275 |
276 | 277 | 278 | 284 | 285 |
286 |
287 |
288 | 289 |
290 | 291 | 292 | 298 | 299 |
300 |
301 |
302 | 303 |
304 | 305 | 306 | 312 | 313 |
314 |
315 |
316 | 317 |
318 | 319 | 320 | 326 | 327 |
328 |

329 | TermInfo.tiocgwinsz(io) => [row, 330 | col] 331 |

332 |

333 | TermInfo.tiocgwinsz returns the screen 334 | size of the terminal refered by io, 335 | using TIOCGWINSZ ioctl. 336 |

337 |
338 |
339 | 340 |
341 | 342 | 343 | 349 | 350 |
351 |

352 | TermInfo.tiocswinsz(io, row, col) 354 |

355 |

356 | TermInfo.tiocgwinsz update the screen 357 | size information of the terminal refered by io, using TIOCSWINSZ ioctl. 359 |

360 |

361 | It returns nil. 362 |

363 |
364 |
365 | 366 |
367 | 368 | 369 | 375 | 376 |
377 |
378 |
379 | 380 |

Public Instance methods

381 | 382 |
383 | 384 | 385 | 391 | 392 |
393 |

394 | TermInfo#control controls a terminal. 395 |

396 |

397 | It prints the result of control_string 398 | to io specified at initialization. 399 |

400 |
401 |
402 | 403 |
404 | 405 | 406 | 412 | 413 |
414 |

415 | TermInfo#control_string return a string 416 | to control terminal. 417 |

418 |
419 |   TermInfo#control_string([afflines,] capname, p1, p2, ...)
420 | 
421 |

422 | capname is a terminfo string capability such as "cuu", 423 | "el". 424 |

425 |

426 | p1, p2, … are parameters for the capability. 427 |

428 |

429 | afflines is a number of lines affected. (used for determining padding 430 | length) 431 |

432 |
433 |
434 | 435 |
436 | 437 | 438 | 444 | 445 |
446 |
447 |
448 | 449 |
450 | 451 | 452 | 458 | 459 |
460 |
461 |
462 | 463 |
464 | 465 | 466 | 472 | 473 |
474 |

475 | returns terminal screen width. 476 |

477 |
478 |
479 | 480 |
481 | 482 | 483 |
484 | screen_height() 485 |
486 | 487 |
488 |

489 | Alias for screen_lines 490 |

491 |
492 |
493 | 494 |
495 | 496 | 497 | 503 | 504 |
505 |

506 | returns terminal screen height. 507 |

508 |
509 |
510 | 511 |
512 | 513 | 514 | 520 | 521 |
522 |

523 | returns terminal screen size in a two element array: [lines, columns]. 524 |

525 |
526 |
527 | 528 |
529 | 530 | 531 |
532 | screen_width() 533 |
534 | 535 |
536 |

537 | Alias for screen_columns 538 |

539 |
540 |
541 | 542 |
543 | 544 | 545 | 551 | 552 |
553 |

554 | TermInfo#setupterm(term, fd) => int 555 |

556 |

557 | TermInfo#setupterm initializes TermInfo object. 559 |

560 |

561 | term is a string of nil. If nil is given, the environment variable $TERM is 562 | used. 563 |

564 |

565 | fd is a file descriptor for target terminal. 566 |

567 |
568 |
569 | 570 |
571 | 572 | 573 | 579 | 580 |
581 |

582 | TermInfo#tigetflag(capname) => int 583 |

584 |

585 | TermInfo#tigetflag returns a boolean 586 | capability specified by capname. 587 |

588 |
589 |
590 | 591 |
592 | 593 | 594 | 600 | 601 |
602 |

603 | TermInfo#tigetnum(capname) => int 604 |

605 |

606 | TermInfo#tigetnum returns a numeric 607 | capability specified by capname. 608 |

609 |
610 |
611 | 612 |
613 | 614 | 615 | 621 | 622 |
623 |

624 | TermInfo#tigetstr(capname) => str 625 |

626 |

627 | TermInfo#tigetstr returns a string 628 | capability specified by capname. 629 |

630 |

631 | The return value should be printed after tputs is applied. Also tparm should be applied if it has 634 | parameters. 635 |

636 |
637 |   io.print ti.tputs(ti.tparm(ti.tigetstr("cuf"), 2))
638 | 
639 |

640 | Note that "cuf" means "cursor forward". 641 |

642 |
643 |
644 | 645 |
646 | 647 | 648 | 654 | 655 |
656 |

657 | TermInfo#tparm(str, …) => str 658 |

659 |

660 | TermInfo#tparm expands parameters in 661 | str returned by tigetstr. 662 |

663 |
664 |
665 | 666 |
667 | 668 | 669 | 675 | 676 |
677 |

678 | TermInfo#tputs(str, affcnt) => str 679 |

680 |

681 | TermInfo#tputs expands padding 682 | informaiton using padding characters. affcnt is a number of lines affected 683 | by the str. 684 |

685 |
686 |
687 | 688 |
689 | 690 | 691 | 697 | 698 |
699 |
700 |
701 | 702 | 703 |
704 | 705 | 706 |
707 | 708 | 709 |
710 |

[Validate]

711 |
712 | 713 | 714 | --------------------------------------------------------------------------------