ruby-terminfo 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
+