ruby-terminfo 0.1.1

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 (7) hide show
  1. data/ChangeLog +3 -0
  2. data/README +80 -0
  3. data/Rakefile +143 -0
  4. data/extconf.rb +53 -0
  5. data/lib/terminfo.rb +140 -0
  6. data/terminfo.c +336 -0
  7. metadata +72 -0
@@ -0,0 +1,3 @@
1
+ 2007-04-10 Tanaka Akira <akr@fsij.org>
2
+
3
+ * version 0.1 released.
data/README ADDED
@@ -0,0 +1,80 @@
1
+ = ruby-terminfo - terminfo binding for Ruby
2
+
3
+ == Author
4
+
5
+ Tanaka Akira <akr@fsij.org>
6
+
7
+ == Home Page
8
+
9
+ http://www.a-k-r.org/ruby-terminfo/
10
+
11
+ == Feature
12
+
13
+ * easy to use method, control, for combination of tigetstr/tparm/tputs.
14
+ * low-level terminfo binding (setupterm, tigetflag, tigetnum, tigetstr, tparm, tputs)
15
+ * TIOCGWINSZ/TIOCSWINSZ ioctl for screen size
16
+
17
+ == Usage
18
+
19
+ === easy to use methods
20
+
21
+ require 'terminfo'
22
+ TermInfo.control("cuf", 7) # cursor forward 7 columns
23
+ p TermInfo.screen_size # use TIOCGWINSZ, LINES/COLUMNS env. or terminfo lines#/cols#
24
+
25
+ === low level methods
26
+
27
+ require 'terminfo'
28
+ t = TermInfo.new(ENV["TERM"], STDOUT)
29
+ print t.tputs(t.tparm(t.tigetstr("cuf"), 7), 1) # cursor forward 7 columns
30
+ p TermInfo.tiocgwinsz(STDOUT) # use TIOCGWINSZ
31
+
32
+ == Requirements
33
+
34
+ * ruby : http://www.ruby-lang.org/
35
+
36
+ == Download
37
+
38
+ * latest release: http://www.a-k-r.org/ruby-terminfo/ruby-terminfo-0.1.tar.gz
39
+
40
+ * development version in Subversion repository:
41
+
42
+ % svn co svn://svn@svn.a-k-r.org/akr/ruby-terminfo/trunk ruby-terminfo
43
+
44
+ == Install
45
+
46
+ % ruby extconf.rb
47
+ % make
48
+ % make install
49
+
50
+ == Reference Manual
51
+
52
+ See rdoc/classes/TermInfo.html or
53
+ http://www.a-k-r.org/ruby-terminfo/rdoc/classes/TermInfo.html
54
+
55
+ == License
56
+
57
+ The modified BSD licence
58
+
59
+ Redistribution and use in source and binary forms, with or without
60
+ modification, are permitted provided that the following conditions are met:
61
+
62
+ 1. Redistributions of source code must retain the above copyright notice, this
63
+ list of conditions and the following disclaimer.
64
+ 2. Redistributions in binary form must reproduce the above copyright notice,
65
+ this list of conditions and the following disclaimer in the documentation
66
+ and/or other materials provided with the distribution.
67
+ 3. The name of the author may not be used to endorse or promote products
68
+ derived from this software without specific prior written permission.
69
+
70
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
71
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
72
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
73
+ EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
74
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
75
+ OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
76
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
77
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
78
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
79
+ OF SUCH DAMAGE.
80
+
@@ -0,0 +1,143 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
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
+
64
+ s.files = %w(README ChangeLog Rakefile) +
65
+ Dir.glob("{bin,doc,test,lib,templates,generator,extras,website,script}/**/*") +
66
+ Dir.glob("*.{c,rb}") +
67
+ Dir.glob("examples/**/*.rb") +
68
+ Dir.glob("tools/*.rb") +
69
+ Dir.glob("rails/*.rb")
70
+
71
+ s.extensions = ["extconf.rb"]
72
+ end
73
+
74
+ Rake::GemPackageTask.new(spec) do |p|
75
+ p.need_tar = true
76
+ p.gem_spec = spec
77
+ end
78
+
79
+ task :install do
80
+ name = "#{NAME}-#{VERS}.gem"
81
+ sh %{rake package}
82
+ sh %{sudo gem install pkg/#{name}}
83
+ end
84
+
85
+ task :uninstall => [:clean] do
86
+ sh %{sudo gem uninstall #{NAME}}
87
+ end
88
+
89
+
90
+ Rake::RDocTask.new do |rdoc|
91
+ rdoc.rdoc_dir = 'html'
92
+ rdoc.options += RDOC_OPTS
93
+ rdoc.template = "resh"
94
+ #rdoc.template = "#{ENV['template']}.rb" if ENV['template']
95
+ if ENV['DOC_FILES']
96
+ rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
97
+ else
98
+ rdoc.rdoc_files.include('README', 'ChangeLog')
99
+ rdoc.rdoc_files.include('lib/**/*.rb')
100
+ rdoc.rdoc_files.include('**/*.c')
101
+ end
102
+ end
103
+
104
+ desc "Publish to RubyForge"
105
+ task :rubyforge => [:rdoc, :package] do
106
+ require 'rubyforge'
107
+ Rake::RubyForgePublisher.new(RUBYFORGE_PROJECT, 'takiuchi').upload
108
+ end
109
+
110
+ desc 'Package and upload the release to rubyforge.'
111
+ task :release => [:clean, :package] do |t|
112
+ v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z"
113
+ abort "Versions don't match #{v} vs #{VERS}" unless v == VERS
114
+ pkg = "pkg/#{NAME}-#{VERS}"
115
+
116
+ require 'rubyforge'
117
+ rf = RubyForge.new.configure
118
+ puts "Logging in"
119
+ rf.login
120
+
121
+ c = rf.userconfig
122
+ # c["release_notes"] = description if description
123
+ # c["release_changes"] = changes if changes
124
+ c["preformatted"] = true
125
+
126
+ files = [
127
+ "#{pkg}.tgz",
128
+ "#{pkg}.gem"
129
+ ].compact
130
+
131
+ puts "Releasing #{NAME} v. #{VERS}"
132
+ rf.add_release RUBYFORGE_PROJECT, NAME, VERS, *files
133
+ end
134
+
135
+ desc 'Show information about the gem.'
136
+ task :debug_gem do
137
+ puts spec.to_ruby
138
+ end
139
+
140
+ desc 'Update gem spec'
141
+ task :gemspec do
142
+ open("#{NAME}.gemspec", 'w').write spec.to_ruby
143
+ end
@@ -0,0 +1,53 @@
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
+ # GNU/Linux -lncurses
34
+ # FreeBSD -lncurses
35
+ # HP-UX -lcurses
36
+
37
+ have_library("ncurses", "setupterm") or
38
+ have_library("curses", "setupterm")
39
+
40
+ have_type("rb_io_t", ["ruby.h", "rubyio.h"])
41
+ have_struct_member("rb_io_t", "fd", ["ruby.h", "rubyio.h"])
42
+ have_struct_member("OpenFile", "fd", ["ruby.h", "rubyio.h"])
43
+
44
+ create_header
45
+ create_makefile('terminfo')
46
+
47
+ open("Makefile", "a") {|mfile|
48
+ mfile.puts <<'End'
49
+ rdoc:
50
+ rdoc --op rdoc terminfo.c lib/terminfo.rb
51
+ End
52
+ }
53
+
@@ -0,0 +1,140 @@
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 = open("/dev/tty", "r+")
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
@@ -0,0 +1,336 @@
1
+ /* terminfo.c - 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
+
32
+ #include "ruby.h"
33
+ #include "rubyio.h"
34
+ #include "extconf.h"
35
+
36
+ #include <curses.h>
37
+ #include <term.h>
38
+ #include <termios.h>
39
+ #include <sys/ioctl.h>
40
+
41
+ static VALUE cTermInfo;
42
+ static VALUE eTermInfoError;
43
+
44
+ #ifndef HAVE_TYPE_RB_IO_T
45
+ typedef OpenFile rb_io_t;
46
+ #endif
47
+
48
+ static void
49
+ rt_free(void *ptr)
50
+ {
51
+ if(ptr != NULL)
52
+ del_curterm(ptr);
53
+ }
54
+
55
+ static VALUE
56
+ rt_alloc(VALUE klass)
57
+ {
58
+ return Data_Wrap_Struct(klass, NULL, rt_free, 0);
59
+ }
60
+
61
+ static TERMINAL *
62
+ check_rt(VALUE self)
63
+ {
64
+ Check_Type(self, T_DATA);
65
+ if (RDATA(self)->dfree != rt_free) {
66
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected TermInfo)",
67
+ rb_class2name(CLASS_OF(self)));
68
+ }
69
+ return DATA_PTR(self);
70
+ }
71
+
72
+ static void
73
+ setup(VALUE self)
74
+ {
75
+ TERMINAL *old;
76
+ TERMINAL *term = check_rt(self);
77
+ if (term == NULL) { rb_raise(eTermInfoError, "terminfo object not initialized"); }
78
+ if (cur_term == term)
79
+ return;
80
+ old = set_curterm(term);
81
+ }
82
+
83
+ /*
84
+ * TermInfo#setupterm(term, fd) => int
85
+ *
86
+ * TermInfo#setupterm initializes TermInfo object.
87
+ *
88
+ * term is a string of nil.
89
+ * If nil is given, the environment variable $TERM is used.
90
+ *
91
+ * fd is a file descriptor for target terminal.
92
+ */
93
+ static VALUE
94
+ rt_setupterm(VALUE self, VALUE v_term, VALUE v_fd)
95
+ {
96
+ char *term;
97
+ int fd;
98
+ int err;
99
+ int ret;
100
+ if (check_rt(self) != NULL) { rb_raise(eTermInfoError, "terminfo object already initialized"); }
101
+
102
+ if (v_term == Qnil)
103
+ term = NULL;
104
+ else
105
+ term = StringValueCStr(v_term);
106
+ fd = NUM2INT(v_fd);
107
+
108
+ ret = setupterm(term, fd, &err);
109
+ if (ret == ERR) {
110
+ if (err == 1) rb_raise(eTermInfoError, "hardcopy terminal");
111
+ else if (err == 0) rb_raise(eTermInfoError, "terminal could not be found");
112
+ else if (err == -1) rb_raise(eTermInfoError, "terminfo database could not be found");
113
+ else rb_raise(eTermInfoError, "unexpected setupterm error");
114
+ }
115
+
116
+ DATA_PTR(self) = cur_term;
117
+
118
+ return INT2NUM(err);
119
+ }
120
+
121
+ /*
122
+ * TermInfo#tigetflag(capname) => int
123
+ *
124
+ * TermInfo#tigetflag returns a boolean capability specified by capname.
125
+ */
126
+ static VALUE
127
+ rt_tigetflag(VALUE self, VALUE v_capname)
128
+ {
129
+ int ret;
130
+ setup(self);
131
+ ret = tigetflag(StringValueCStr(v_capname));
132
+ if (ret == -1) { rb_raise(eTermInfoError, "not a boolean capability"); }
133
+ return RTEST(ret) ? Qtrue : Qfalse;
134
+ }
135
+
136
+ /*
137
+ * TermInfo#tigetnum(capname) => int
138
+ *
139
+ * TermInfo#tigetnum returns a numeric capability specified by capname.
140
+ */
141
+ static VALUE
142
+ rt_tigetnum(VALUE self, VALUE v_capname)
143
+ {
144
+ int ret;
145
+ setup(self);
146
+ ret = tigetnum(StringValueCStr(v_capname));
147
+ if (ret == -2) { rb_raise(eTermInfoError, "not a numeric capability"); }
148
+ if (ret == -1) { rb_raise(eTermInfoError, "canceled or absent numeric capability"); }
149
+ return INT2NUM(ret);
150
+ }
151
+
152
+ /*
153
+ * TermInfo#tigetstr(capname) => str
154
+ *
155
+ * TermInfo#tigetstr returns a string capability specified by capname.
156
+ *
157
+ * The return value should be printed after tputs is applied.
158
+ * Also tparm should be applied if it has parameters.
159
+ *
160
+ * io.print ti.tputs(ti.tparm(ti.tigetstr("cuf"), 2))
161
+ *
162
+ * Note that "cuf" means "cursor forward".
163
+ */
164
+ static VALUE
165
+ rt_tigetstr(VALUE self, VALUE v_capname)
166
+ {
167
+ char *ret;
168
+ setup(self);
169
+ ret = tigetstr(StringValueCStr(v_capname));
170
+ if (ret == (char*)-1) {
171
+ rb_raise(eTermInfoError, "not a string capability");
172
+ }
173
+ if (ret == 0) {
174
+ rb_raise(eTermInfoError, "canceled or absent string capability");
175
+ }
176
+ return rb_str_new2(ret);
177
+ }
178
+
179
+ /*
180
+ * TermInfo#tparm(str, ...) => str
181
+ *
182
+ * TermInfo#tparm expands parameters in str returned by tigetstr.
183
+ */
184
+ static VALUE
185
+ rt_tparm(int argc, VALUE *argv, VALUE self)
186
+ {
187
+ char *capname, *ret;
188
+ setup(self);
189
+ VALUE v_capname, v1, v2, v3, v4, v5, v6, v7, v8, v9;
190
+ long p1, p2, p3, p4, p5, p6, p7, p8, p9;
191
+ setup(self);
192
+
193
+ if (rb_scan_args(argc, argv, "19", &v_capname, &v1, &v2, &v3, &v4, &v5, &v6, &v7, &v8, &v9) == 0) {
194
+ rb_raise(rb_eArgError, "capname required");
195
+ }
196
+
197
+ capname = StringValueCStr(v_capname);
198
+ #define conv(p, v) do { if (v == Qnil) p = 0; else p = NUM2LONG(v); } while(0)
199
+ conv(p1, v1);
200
+ conv(p2, v2);
201
+ conv(p3, v3);
202
+ conv(p4, v4);
203
+ conv(p5, v5);
204
+ conv(p6, v6);
205
+ conv(p7, v7);
206
+ conv(p8, v8);
207
+ conv(p9, v9);
208
+
209
+ ret = tparm(capname, p1, p2, p3, p4, p5, p6, p7, p8, p9);
210
+
211
+ if (ret == NULL) { rb_raise(eTermInfoError, "tparm failed"); }
212
+
213
+ return rb_str_new2(ret);
214
+ }
215
+
216
+ static VALUE putfunc_output; /* xxx: not thread safe */
217
+
218
+ static int
219
+ putfunc(int arg)
220
+ {
221
+ char ch = arg;
222
+ rb_str_cat(putfunc_output, &ch, 1);
223
+ return arg;
224
+ }
225
+
226
+ /*
227
+ * TermInfo#tputs(str, affcnt) => str
228
+ *
229
+ * TermInfo#tputs expands padding informaiton using padding characters.
230
+ * affcnt is a number of lines affected by the str.
231
+ */
232
+ static VALUE
233
+ rt_tputs(VALUE self, VALUE v_str, VALUE v_affcnt)
234
+ {
235
+ int ret;
236
+ char *str;
237
+ int affcnt;
238
+ VALUE output;
239
+
240
+ setup(self);
241
+ str = StringValueCStr(v_str);
242
+ affcnt = NUM2INT(v_affcnt);
243
+
244
+ putfunc_output = output = rb_str_new2("");
245
+ ret = tputs(str, affcnt, putfunc);
246
+ putfunc_output = Qnil;
247
+
248
+ if (ret == ERR) { rb_raise(eTermInfoError, "tputs failed"); }
249
+
250
+ return output;
251
+ }
252
+
253
+ #if defined(HAVE_ST_FD)
254
+ # define FILENO(fptr) (fptr->fd)
255
+ #elif defined(HAVE_RB_IO_T_FD)
256
+ # define FILENO(fptr) fileno(fptr->fd)
257
+ #else
258
+ # define FILENO(fptr) fileno(fptr->f)
259
+ #endif
260
+
261
+ /*
262
+ * TermInfo.tiocgwinsz(io) => [row, col]
263
+ *
264
+ * TermInfo.tiocgwinsz returns the screen size of the terminal refered by io,
265
+ * using TIOCGWINSZ ioctl.
266
+ */
267
+ static VALUE
268
+ rt_tiocgwinsz(VALUE self, VALUE io)
269
+ {
270
+ #ifdef TIOCGWINSZ
271
+ rb_io_t *fptr;
272
+ struct winsize sz;
273
+ int ret;
274
+
275
+ GetOpenFile(io, fptr);
276
+
277
+ ret = ioctl(FILENO(fptr), TIOCGWINSZ, &sz);
278
+ if (ret == -1) rb_raise(rb_eIOError, "TIOCGWINSZ failed");
279
+
280
+ return rb_ary_new3(2, INT2NUM(sz.ws_row), INT2NUM(sz.ws_col));
281
+ #else
282
+ rb_notimplement();
283
+ #endif
284
+ }
285
+
286
+ /*
287
+ * TermInfo.tiocswinsz(io, row, col)
288
+ *
289
+ * TermInfo.tiocgwinsz update the screen size information of the terminal refered by io,
290
+ * using TIOCSWINSZ ioctl.
291
+ *
292
+ * It returns nil.
293
+ */
294
+ static VALUE
295
+ rt_tiocswinsz(VALUE self, VALUE io, VALUE row, VALUE col)
296
+ {
297
+ #ifdef TIOCSWINSZ
298
+ rb_io_t *fptr;
299
+ struct winsize sz;
300
+ int ret;
301
+
302
+ GetOpenFile(io, fptr);
303
+
304
+ sz.ws_row = NUM2INT(row);
305
+ sz.ws_col = NUM2INT(col);
306
+
307
+ ret = ioctl(FILENO(fptr), TIOCSWINSZ, &sz);
308
+ if (ret == -1) rb_raise(rb_eIOError, "TIOCSWINSZ failed");
309
+
310
+ return Qnil;
311
+ #else
312
+ rb_notimplement();
313
+ #endif
314
+ }
315
+
316
+ void
317
+ Init_terminfo()
318
+ {
319
+ putfunc_output = Qnil;
320
+ rb_global_variable(&putfunc_output);
321
+
322
+ cTermInfo = rb_define_class("TermInfo", rb_cData);
323
+ eTermInfoError = rb_define_class_under(cTermInfo, "TermInfoError", rb_eRuntimeError);
324
+
325
+ rb_define_alloc_func(cTermInfo, rt_alloc);
326
+
327
+ rb_define_method(cTermInfo, "setupterm", rt_setupterm, 2);
328
+ rb_define_method(cTermInfo, "tigetflag", rt_tigetflag, 1);
329
+ rb_define_method(cTermInfo, "tigetnum", rt_tigetnum, 1);
330
+ rb_define_method(cTermInfo, "tigetstr", rt_tigetstr, 1);
331
+ rb_define_method(cTermInfo, "tparm", rt_tparm, -1);
332
+ rb_define_method(cTermInfo, "tputs", rt_tputs, 2);
333
+
334
+ rb_define_module_function(cTermInfo, "tiocgwinsz", rt_tiocgwinsz, 1);
335
+ rb_define_module_function(cTermInfo, "tiocswinsz", rt_tiocswinsz, 3);
336
+ }
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-terminfo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Tanaka Akira
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-13 00:00:00 +13:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: terminfo binding for Ruby
17
+ email: akr@fsij.org
18
+ executables: []
19
+
20
+ extensions:
21
+ - extconf.rb
22
+ extra_rdoc_files:
23
+ - README
24
+ - ChangeLog
25
+ files:
26
+ - README
27
+ - ChangeLog
28
+ - Rakefile
29
+ - lib/terminfo.rb
30
+ - terminfo.c
31
+ - extconf.rb
32
+ has_rdoc: true
33
+ homepage: http://ruby-terminfo.rubyforge.org
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --title
39
+ - ruby-terminfo documentation
40
+ - --charset
41
+ - utf-8
42
+ - --opname
43
+ - index.html
44
+ - --line-numbers
45
+ - --main
46
+ - README
47
+ - --inline-source
48
+ - --exclude
49
+ - ^(examples|extras)/
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ requirements: []
65
+
66
+ rubyforge_project: ruby-terminfo
67
+ rubygems_version: 1.3.5
68
+ signing_key:
69
+ specification_version: 2
70
+ summary: terminfo binding for Ruby
71
+ test_files: []
72
+