ruby-terminfo-r3 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +44 -0
- data/README +92 -0
- data/extconf.rb +80 -0
- data/lib/terminfo.rb +140 -0
- data/make_gem +24 -0
- data/terminfo.c +427 -0
- metadata +73 -0
data/ChangeLog
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
2009-03-06 Tanaka Akira <akr@fsij.org>
|
2
|
+
|
3
|
+
* version 0.2 released.
|
4
|
+
|
5
|
+
2008-12-30 Tanaka Akira <akr@fsij.org>
|
6
|
+
|
7
|
+
* terminfo.c (rt_wcswidth): check the return value of wcwidth.
|
8
|
+
|
9
|
+
2008-12-30 Tanaka Akira <akr@fsij.org>
|
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 <akr@fsij.org>
|
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 <akr@fsij.org>
|
26
|
+
|
27
|
+
* sample/resize: new sample program.
|
28
|
+
|
29
|
+
2007-04-29 Tanaka Akira <akr@fsij.org>
|
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 <akr@fsij.org>
|
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 <akr@fsij.org>
|
43
|
+
|
44
|
+
* version 0.1 released.
|
data/README
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
= ruby-terminfo-r3 - terminfo binding for Ruby-3
|
2
|
+
|
3
|
+
ruby-terminfo-r3 is a terminfo binding for Ruby-3. It is a repackaged version
|
4
|
+
of the Ruby-2 package ruby-terminfo.
|
5
|
+
|
6
|
+
Use './make_gem' to build the GEM.
|
7
|
+
|
8
|
+
The home page for this package is https://github.com/clrgit/ruby-terminfo-r3,
|
9
|
+
the original README follows below:
|
10
|
+
|
11
|
+
= ruby-terminfo - terminfo binding for Ruby
|
12
|
+
|
13
|
+
ruby-terminfo is a terminfo binding for Ruby
|
14
|
+
|
15
|
+
== Author
|
16
|
+
|
17
|
+
Tanaka Akira <akr@fsij.org>
|
18
|
+
|
19
|
+
== Home Page
|
20
|
+
|
21
|
+
http://www.a-k-r.org/ruby-terminfo/
|
22
|
+
|
23
|
+
== Feature
|
24
|
+
|
25
|
+
* easy to use method, control, for combination of tigetstr/tparm/tputs
|
26
|
+
* low-level terminfo binding (setupterm, tigetflag, tigetnum, tigetstr, tparm, tputs)
|
27
|
+
* TIOCGWINSZ/TIOCSWINSZ ioctl for screen size
|
28
|
+
* ctermid to avoid hardcoding /dev/tty
|
29
|
+
* wcswidth to measure a string width in number of columns
|
30
|
+
|
31
|
+
== Usage
|
32
|
+
|
33
|
+
=== easy to use methods
|
34
|
+
|
35
|
+
require 'terminfo'
|
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
|
+
=== low level methods
|
40
|
+
|
41
|
+
require 'terminfo'
|
42
|
+
t = TermInfo.new(ENV["TERM"], File.open(TermInfo.ctermid, "r+"))
|
43
|
+
print t.tputs(t.tparm(t.tigetstr("cuf"), 7), 1) # cursor forward 7 columns
|
44
|
+
p TermInfo.tiocgwinsz(STDOUT) # use TIOCGWINSZ
|
45
|
+
|
46
|
+
== Requirements
|
47
|
+
|
48
|
+
* ruby : http://www.ruby-lang.org/
|
49
|
+
|
50
|
+
== Download
|
51
|
+
|
52
|
+
* latest release: http://www.a-k-r.org/ruby-terminfo/ruby-terminfo-0.2.tar.gz
|
53
|
+
|
54
|
+
* development version: http://github.com/akr/ruby-terminfo
|
55
|
+
|
56
|
+
== Install
|
57
|
+
|
58
|
+
% ruby extconf.rb
|
59
|
+
% make
|
60
|
+
% make install
|
61
|
+
|
62
|
+
== Reference Manual
|
63
|
+
|
64
|
+
See rdoc/TermInfo.html or
|
65
|
+
http://www.a-k-r.org/ruby-terminfo/rdoc/TermInfo.html
|
66
|
+
|
67
|
+
== License
|
68
|
+
|
69
|
+
|
70
|
+
Redistribution and use in source and binary forms, with or without
|
71
|
+
modification, are permitted provided that the following conditions are met:
|
72
|
+
|
73
|
+
(1) Redistributions of source code must retain the above copyright notice, this
|
74
|
+
list of conditions and the following disclaimer.
|
75
|
+
(2) Redistributions in binary form must reproduce the above copyright notice,
|
76
|
+
this list of conditions and the following disclaimer in the documentation
|
77
|
+
and/or other materials provided with the distribution.
|
78
|
+
(3) The name of the author may not be used to endorse or promote products
|
79
|
+
derived from this software without specific prior written permission.
|
80
|
+
|
81
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
82
|
+
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
83
|
+
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
84
|
+
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
85
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
86
|
+
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
87
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
88
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
89
|
+
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
90
|
+
OF SUCH DAMAGE.
|
91
|
+
|
92
|
+
(The modified BSD licence)
|
data/extconf.rb
ADDED
@@ -0,0 +1,80 @@
|
|
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
|
data/lib/terminfo.rb
ADDED
@@ -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 = 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
|
data/make_gem
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/bash
|
2
|
+
|
3
|
+
set -eo pipefail
|
4
|
+
|
5
|
+
# Create the GEM package. The gem command is not used to create the package
|
6
|
+
# because it doesn't contain a Gemspec file. Instead it is create using tar and
|
7
|
+
# gzip
|
8
|
+
|
9
|
+
NAME="ruby-terminfo-r3"
|
10
|
+
VERSION="0.1.1"
|
11
|
+
PCK=$NAME-$VERSION
|
12
|
+
FILES="README ChangeLog lib/terminfo.rb terminfo.c extconf.rb make_gem"
|
13
|
+
|
14
|
+
tar cf - $FILES | gzip --best --stdout >data.tar.gz
|
15
|
+
gzip --best --stdout metadata >metadata.gz
|
16
|
+
tar cf $PCK.gem data.tar.gz metadata.gz
|
17
|
+
rm data.tar.gz metadata.gz
|
18
|
+
|
19
|
+
|
20
|
+
#tar zcf - $FILES | gzip --best --stdout >data.tar.gz
|
21
|
+
#gzip --best --stdout metadata >metadata.gz
|
22
|
+
#tar cf $PCK.gem data.tar.gz metadata.gz
|
23
|
+
#rm data.tar.gz metadata.gz
|
24
|
+
|
data/terminfo.c
ADDED
@@ -0,0 +1,427 @@
|
|
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 <ncurses.h>
|
42
|
+
#elif defined(HAVE_CURSES_H)
|
43
|
+
#include <curses.h>
|
44
|
+
#endif
|
45
|
+
|
46
|
+
#ifdef HAVE_TERM_H
|
47
|
+
#include <term.h>
|
48
|
+
#endif
|
49
|
+
|
50
|
+
#include <termios.h>
|
51
|
+
#include <sys/ioctl.h>
|
52
|
+
#include <unistd.h>
|
53
|
+
|
54
|
+
#ifdef HAVE_WCHAR_H
|
55
|
+
#include <wchar.h>
|
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 *old;
|
110
|
+
TERMINAL *term = check_rt(self);
|
111
|
+
if (term == NULL) { rb_raise(eTermInfoError, "terminfo object not initialized"); }
|
112
|
+
if (cur_term == term)
|
113
|
+
return;
|
114
|
+
old = set_curterm(term);
|
115
|
+
}
|
116
|
+
|
117
|
+
/*
|
118
|
+
* TermInfo#setupterm(term, fd) => int
|
119
|
+
*
|
120
|
+
* TermInfo#setupterm initializes TermInfo object.
|
121
|
+
*
|
122
|
+
* term is a string of nil.
|
123
|
+
* If nil is given, the environment variable $TERM is used.
|
124
|
+
*
|
125
|
+
* fd is a file descriptor for target terminal.
|
126
|
+
*/
|
127
|
+
static VALUE
|
128
|
+
rt_setupterm(VALUE self, VALUE v_term, VALUE v_fd)
|
129
|
+
{
|
130
|
+
char *term;
|
131
|
+
int fd;
|
132
|
+
int err;
|
133
|
+
int ret;
|
134
|
+
if (check_rt(self) != NULL) { rb_raise(eTermInfoError, "terminfo object already initialized"); }
|
135
|
+
|
136
|
+
if (v_term == Qnil)
|
137
|
+
term = NULL;
|
138
|
+
else
|
139
|
+
term = StringValueCStr(v_term);
|
140
|
+
fd = NUM2INT(v_fd);
|
141
|
+
|
142
|
+
ret = setupterm(term, fd, &err);
|
143
|
+
if (ret == ERR) {
|
144
|
+
if (err == 1) rb_raise(eTermInfoError, "hardcopy terminal");
|
145
|
+
else if (err == 0) rb_raise(eTermInfoError, "terminal could not be found");
|
146
|
+
else if (err == -1) rb_raise(eTermInfoError, "terminfo database could not be found");
|
147
|
+
else rb_raise(eTermInfoError, "unexpected setupterm error");
|
148
|
+
}
|
149
|
+
|
150
|
+
DATA_PTR(self) = cur_term;
|
151
|
+
|
152
|
+
return INT2NUM(err);
|
153
|
+
}
|
154
|
+
|
155
|
+
/*
|
156
|
+
* TermInfo#tigetflag(capname) => int
|
157
|
+
*
|
158
|
+
* TermInfo#tigetflag returns a boolean capability specified by capname.
|
159
|
+
*/
|
160
|
+
static VALUE
|
161
|
+
rt_tigetflag(VALUE self, VALUE v_capname)
|
162
|
+
{
|
163
|
+
int ret;
|
164
|
+
setup(self);
|
165
|
+
ret = tigetflag(StringValueCStr(v_capname));
|
166
|
+
if (ret == -1) { rb_raise(eTermInfoError, "not a boolean capability"); }
|
167
|
+
return RTEST(ret) ? Qtrue : Qfalse;
|
168
|
+
}
|
169
|
+
|
170
|
+
/*
|
171
|
+
* TermInfo#tigetnum(capname) => int
|
172
|
+
*
|
173
|
+
* TermInfo#tigetnum returns a numeric capability specified by capname.
|
174
|
+
*/
|
175
|
+
static VALUE
|
176
|
+
rt_tigetnum(VALUE self, VALUE v_capname)
|
177
|
+
{
|
178
|
+
int ret;
|
179
|
+
setup(self);
|
180
|
+
ret = tigetnum(StringValueCStr(v_capname));
|
181
|
+
if (ret == -2) { rb_raise(eTermInfoError, "not a numeric capability"); }
|
182
|
+
if (ret == -1) { rb_raise(eTermInfoError, "canceled or absent numeric capability"); }
|
183
|
+
return INT2NUM(ret);
|
184
|
+
}
|
185
|
+
|
186
|
+
/*
|
187
|
+
* TermInfo#tigetstr(capname) => str
|
188
|
+
*
|
189
|
+
* TermInfo#tigetstr returns a string capability specified by capname.
|
190
|
+
*
|
191
|
+
* The return value should be printed after tputs is applied.
|
192
|
+
* Also tparm should be applied if it has parameters.
|
193
|
+
*
|
194
|
+
* io.print ti.tputs(ti.tparm(ti.tigetstr("cuf"), 2))
|
195
|
+
*
|
196
|
+
* Note that "cuf" means "cursor forward".
|
197
|
+
*/
|
198
|
+
static VALUE
|
199
|
+
rt_tigetstr(VALUE self, VALUE v_capname)
|
200
|
+
{
|
201
|
+
char *ret;
|
202
|
+
setup(self);
|
203
|
+
ret = tigetstr(StringValueCStr(v_capname));
|
204
|
+
if (ret == (char*)-1) {
|
205
|
+
rb_raise(eTermInfoError, "not a string capability");
|
206
|
+
}
|
207
|
+
if (ret == 0) {
|
208
|
+
rb_raise(eTermInfoError, "canceled or absent string capability");
|
209
|
+
}
|
210
|
+
return rb_str_new2(ret);
|
211
|
+
}
|
212
|
+
|
213
|
+
/*
|
214
|
+
* TermInfo#tparm(str, ...) => str
|
215
|
+
*
|
216
|
+
* TermInfo#tparm expands parameters in str returned by tigetstr.
|
217
|
+
*/
|
218
|
+
static VALUE
|
219
|
+
rt_tparm(int argc, VALUE *argv, VALUE self)
|
220
|
+
{
|
221
|
+
char *capname, *ret;
|
222
|
+
setup(self);
|
223
|
+
VALUE v_capname, v1, v2, v3, v4, v5, v6, v7, v8, v9;
|
224
|
+
long p1, p2, p3, p4, p5, p6, p7, p8, p9;
|
225
|
+
setup(self);
|
226
|
+
|
227
|
+
if (rb_scan_args(argc, argv, "19", &v_capname, &v1, &v2, &v3, &v4, &v5, &v6, &v7, &v8, &v9) == 0) {
|
228
|
+
rb_raise(rb_eArgError, "capname required");
|
229
|
+
}
|
230
|
+
|
231
|
+
capname = StringValueCStr(v_capname);
|
232
|
+
#define conv(p, v) do { if (v == Qnil) p = 0; else p = NUM2LONG(v); } while(0)
|
233
|
+
conv(p1, v1);
|
234
|
+
conv(p2, v2);
|
235
|
+
conv(p3, v3);
|
236
|
+
conv(p4, v4);
|
237
|
+
conv(p5, v5);
|
238
|
+
conv(p6, v6);
|
239
|
+
conv(p7, v7);
|
240
|
+
conv(p8, v8);
|
241
|
+
conv(p9, v9);
|
242
|
+
|
243
|
+
ret = tparm(capname, p1, p2, p3, p4, p5, p6, p7, p8, p9);
|
244
|
+
|
245
|
+
if (ret == NULL) { rb_raise(eTermInfoError, "tparm failed"); }
|
246
|
+
|
247
|
+
return rb_str_new2(ret);
|
248
|
+
}
|
249
|
+
|
250
|
+
static VALUE putfunc_output; /* xxx: not thread safe */
|
251
|
+
|
252
|
+
static int
|
253
|
+
putfunc(int arg)
|
254
|
+
{
|
255
|
+
char ch = arg;
|
256
|
+
rb_str_cat(putfunc_output, &ch, 1);
|
257
|
+
return arg;
|
258
|
+
}
|
259
|
+
|
260
|
+
/*
|
261
|
+
* TermInfo#tputs(str, affcnt) => str
|
262
|
+
*
|
263
|
+
* TermInfo#tputs expands padding informaiton using padding characters.
|
264
|
+
* affcnt is a number of lines affected by the str.
|
265
|
+
*/
|
266
|
+
static VALUE
|
267
|
+
rt_tputs(VALUE self, VALUE v_str, VALUE v_affcnt)
|
268
|
+
{
|
269
|
+
int ret;
|
270
|
+
char *str;
|
271
|
+
int affcnt;
|
272
|
+
VALUE output;
|
273
|
+
|
274
|
+
setup(self);
|
275
|
+
str = StringValueCStr(v_str);
|
276
|
+
affcnt = NUM2INT(v_affcnt);
|
277
|
+
|
278
|
+
putfunc_output = output = rb_str_new2("");
|
279
|
+
ret = tputs(str, affcnt, putfunc);
|
280
|
+
putfunc_output = Qnil;
|
281
|
+
|
282
|
+
if (ret == ERR) { rb_raise(eTermInfoError, "tputs failed"); }
|
283
|
+
|
284
|
+
return output;
|
285
|
+
}
|
286
|
+
|
287
|
+
/*
|
288
|
+
* TermInfo.tiocgwinsz(io) => [row, col]
|
289
|
+
*
|
290
|
+
* TermInfo.tiocgwinsz returns the screen size of the terminal refered by io,
|
291
|
+
* using TIOCGWINSZ ioctl.
|
292
|
+
*/
|
293
|
+
static VALUE
|
294
|
+
rt_tiocgwinsz(VALUE self, VALUE io)
|
295
|
+
{
|
296
|
+
#ifdef TIOCGWINSZ
|
297
|
+
rb_io_t *fptr;
|
298
|
+
struct winsize sz;
|
299
|
+
int ret;
|
300
|
+
|
301
|
+
GetOpenFile(io, fptr);
|
302
|
+
|
303
|
+
ret = ioctl(FILENO(fptr), TIOCGWINSZ, &sz);
|
304
|
+
if (ret == -1) rb_raise(rb_eIOError, "TIOCGWINSZ failed");
|
305
|
+
|
306
|
+
return rb_ary_new3(2, INT2NUM(sz.ws_row), INT2NUM(sz.ws_col));
|
307
|
+
#else
|
308
|
+
rb_notimplement();
|
309
|
+
#endif
|
310
|
+
}
|
311
|
+
|
312
|
+
/*
|
313
|
+
* TermInfo.tiocswinsz(io, row, col)
|
314
|
+
*
|
315
|
+
* TermInfo.tiocgwinsz update the screen size information of the terminal refered by io,
|
316
|
+
* using TIOCSWINSZ ioctl.
|
317
|
+
*
|
318
|
+
* It returns nil.
|
319
|
+
*/
|
320
|
+
static VALUE
|
321
|
+
rt_tiocswinsz(VALUE self, VALUE io, VALUE row, VALUE col)
|
322
|
+
{
|
323
|
+
#ifdef TIOCSWINSZ
|
324
|
+
rb_io_t *fptr;
|
325
|
+
struct winsize sz;
|
326
|
+
int ret;
|
327
|
+
|
328
|
+
GetOpenFile(io, fptr);
|
329
|
+
|
330
|
+
sz.ws_row = NUM2INT(row);
|
331
|
+
sz.ws_col = NUM2INT(col);
|
332
|
+
|
333
|
+
ret = ioctl(FILENO(fptr), TIOCSWINSZ, &sz);
|
334
|
+
if (ret == -1) rb_raise(rb_eIOError, "TIOCSWINSZ failed");
|
335
|
+
|
336
|
+
return Qnil;
|
337
|
+
#else
|
338
|
+
rb_notimplement();
|
339
|
+
#endif
|
340
|
+
}
|
341
|
+
|
342
|
+
/*
|
343
|
+
* TermInfo.ctermid
|
344
|
+
*
|
345
|
+
* TermInfo.ctermid returns a pathname for the current controling terminal,
|
346
|
+
* such as "/dev/tty".
|
347
|
+
*/
|
348
|
+
static VALUE
|
349
|
+
rt_ctermid(VALUE self)
|
350
|
+
{
|
351
|
+
#ifdef HAVE_CTERMID
|
352
|
+
char buf[L_ctermid];
|
353
|
+
return rb_str_new2(ctermid(buf));
|
354
|
+
#else
|
355
|
+
return rb_str_new2("/dev/tty");
|
356
|
+
#endif
|
357
|
+
}
|
358
|
+
|
359
|
+
/*
|
360
|
+
* TermInfo.wcswidth(str)
|
361
|
+
*
|
362
|
+
* TermInfo.wcswidth returns a the number of columns of str,
|
363
|
+
* according to current locale.
|
364
|
+
*/
|
365
|
+
static VALUE
|
366
|
+
rt_wcswidth(VALUE self, VALUE str)
|
367
|
+
{
|
368
|
+
char *s;
|
369
|
+
size_t l, r;
|
370
|
+
mbstate_t mbs;
|
371
|
+
wchar_t wc;
|
372
|
+
long cols;
|
373
|
+
int width;
|
374
|
+
|
375
|
+
#ifdef HAVE_RUBY_ENCODING_H
|
376
|
+
/* The encoding of str is assumed to be the locale encoding on Ruby 1.8. */
|
377
|
+
str = rb_str_encode(str, rb_enc_from_encoding(rb_locale_encoding()), 0, Qnil);
|
378
|
+
#endif
|
379
|
+
|
380
|
+
memset(&mbs,0,sizeof(mbstate_t));
|
381
|
+
|
382
|
+
s = StringValueCStr(str);
|
383
|
+
l = RSTRING_LEN(str);
|
384
|
+
|
385
|
+
cols = 0;
|
386
|
+
while (0 < l) {
|
387
|
+
r = mbrtowc(&wc, s, l, &mbs);
|
388
|
+
if (r == 0)
|
389
|
+
rb_raise(rb_eArgError, "NUL found");
|
390
|
+
|
391
|
+
width = wcwidth(wc);
|
392
|
+
if (width == -1)
|
393
|
+
rb_raise(rb_eArgError, "non-printable charactor found");
|
394
|
+
cols += width;
|
395
|
+
|
396
|
+
l -= r;
|
397
|
+
s += r;
|
398
|
+
}
|
399
|
+
|
400
|
+
return LONG2NUM(cols);
|
401
|
+
}
|
402
|
+
|
403
|
+
void
|
404
|
+
Init_terminfo()
|
405
|
+
{
|
406
|
+
putfunc_output = Qnil;
|
407
|
+
rb_global_variable(&putfunc_output);
|
408
|
+
|
409
|
+
cTermInfo = rb_define_class("TermInfo", rb_cData);
|
410
|
+
eTermInfoError = rb_define_class_under(cTermInfo, "TermInfoError", rb_eRuntimeError);
|
411
|
+
|
412
|
+
rb_define_alloc_func(cTermInfo, rt_alloc);
|
413
|
+
|
414
|
+
rb_define_method(cTermInfo, "setupterm", rt_setupterm, 2);
|
415
|
+
rb_define_method(cTermInfo, "tigetflag", rt_tigetflag, 1);
|
416
|
+
rb_define_method(cTermInfo, "tigetnum", rt_tigetnum, 1);
|
417
|
+
rb_define_method(cTermInfo, "tigetstr", rt_tigetstr, 1);
|
418
|
+
rb_define_method(cTermInfo, "tparm", rt_tparm, -1);
|
419
|
+
rb_define_method(cTermInfo, "tputs", rt_tputs, 2);
|
420
|
+
|
421
|
+
rb_define_module_function(cTermInfo, "tiocgwinsz", rt_tiocgwinsz, 1);
|
422
|
+
rb_define_module_function(cTermInfo, "tiocswinsz", rt_tiocswinsz, 3);
|
423
|
+
|
424
|
+
rb_define_module_function(cTermInfo, "ctermid", rt_ctermid, 0);
|
425
|
+
|
426
|
+
rb_define_module_function(cTermInfo, "wcswidth", rt_wcswidth, 1);
|
427
|
+
}
|
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ruby-terminfo-r3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tanaka Akira
|
8
|
+
- Claus Rasmussen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2022-07-20 00:00:00 +02:00
|
14
|
+
default_executable:
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description: terminfo binding for Ruby-3. Derives from the ruby-terminfo package
|
18
|
+
email: akr@fsij.org
|
19
|
+
executables: []
|
20
|
+
|
21
|
+
extensions:
|
22
|
+
- extconf.rb
|
23
|
+
extra_rdoc_files:
|
24
|
+
- README
|
25
|
+
- ChangeLog
|
26
|
+
files:
|
27
|
+
- README
|
28
|
+
- ChangeLog
|
29
|
+
- lib/terminfo.rb
|
30
|
+
- terminfo.c
|
31
|
+
- extconf.rb
|
32
|
+
- make_gem
|
33
|
+
has_rdoc: true
|
34
|
+
homepage: http://ruby-terminfo.rubyforge.org
|
35
|
+
licenses: []
|
36
|
+
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options:
|
39
|
+
- --title
|
40
|
+
- ruby-terminfo documentation
|
41
|
+
- --charset
|
42
|
+
- utf-8
|
43
|
+
- --opname
|
44
|
+
- index.html
|
45
|
+
- --line-numbers
|
46
|
+
- --main
|
47
|
+
- README
|
48
|
+
- --inline-source
|
49
|
+
- --exclude
|
50
|
+
- ^(examples|extras)/
|
51
|
+
require_paths:
|
52
|
+
- lib
|
53
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
version:
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: "0"
|
64
|
+
version:
|
65
|
+
requirements: []
|
66
|
+
|
67
|
+
rubyforge_project: ruby-terminfo
|
68
|
+
rubygems_version: 1.3.5
|
69
|
+
signing_key:
|
70
|
+
specification_version: 2
|
71
|
+
summary: terminfo binding for Ruby-3
|
72
|
+
test_files: []
|
73
|
+
|