curses 1.0.2 → 1.1.0
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.
- checksums.yaml +4 -4
- data/README.md +42 -4
- data/ext/curses/curses.c +306 -20
- data/ext/curses/extconf.rb +4 -3
- data/lib/2.2/curses.so +0 -0
- data/lib/2.3/curses.so +0 -0
- data/lib/2.4/curses.so +0 -0
- data/lib/curses.rb +22 -1
- data/sample/hello.rb +13 -14
- data/sample/mouse.rb +16 -16
- data/sample/rain.rb +46 -50
- data/sample/view.rb +23 -38
- data/sample/view2.rb +37 -48
- metadata +30 -75
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/History.md +0 -18
- data/Manifest.txt +0 -16
- data/Rakefile +0 -41
- data/curses.gemspec +0 -13
- metadata.gz.sig +0 -1
data/ext/curses/extconf.rb
CHANGED
@@ -30,9 +30,9 @@ have_library("tinfo", "tgetent") or have_library("termcap", "tgetent")
|
|
30
30
|
|
31
31
|
header_library = nil
|
32
32
|
[
|
33
|
+
["ncursesw/curses.h", ["ncursesw"]],
|
33
34
|
["ncurses.h", ["ncursesw", "ncurses"]],
|
34
35
|
["ncurses/curses.h", ["ncurses"]],
|
35
|
-
["ncursesw/curses.h", ["ncursesw"]],
|
36
36
|
["curses_colr/curses.h", ["cur_colr"]],
|
37
37
|
["curses.h", ["curses", "pdcurses"]],
|
38
38
|
# ["xcurses.h", ["XCurses"]], # XCurses (PDCurses for X11)
|
@@ -59,9 +59,10 @@ if header_library
|
|
59
59
|
getbkgd getnstr init isendwin keyname keypad resizeterm
|
60
60
|
scrl set setscrreg ungetch
|
61
61
|
wattroff wattron wattrset wbkgd wbkgdset wdeleteln wgetnstr
|
62
|
-
wresize wscrl wsetscrreg
|
62
|
+
wresize wscrl wsetscrreg werase redrawwin
|
63
63
|
def_prog_mode reset_prog_mode timeout wtimeout nodelay
|
64
|
-
init_color wcolor_set use_default_colors newpad
|
64
|
+
init_color wcolor_set use_default_colors newpad
|
65
|
+
unget_wch get_wch wget_wch)
|
65
66
|
have_func(f) || (have_macro(f, curses) && $defs.push(format("-DHAVE_%s", f.upcase)))
|
66
67
|
end
|
67
68
|
flag = "-D_XOPEN_SOURCE_EXTENDED"
|
data/lib/2.2/curses.so
ADDED
Binary file
|
data/lib/2.3/curses.so
ADDED
Binary file
|
data/lib/2.4/curses.so
ADDED
Binary file
|
data/lib/curses.rb
CHANGED
@@ -1 +1,22 @@
|
|
1
|
-
|
1
|
+
pdcurses_path = File.expand_path("../vendor/#{RUBY_PLATFORM}/PDCurses", __dir__)
|
2
|
+
pdcurses_bundled = File.directory?(pdcurses_path)
|
3
|
+
if pdcurses_bundled
|
4
|
+
path = ENV["PATH"]
|
5
|
+
dir = File::ALT_SEPARATOR ?
|
6
|
+
pdcurses_path.tr("/", File::ALT_SEPARATOR) : dir
|
7
|
+
dirs = path.split(File::PATH_SEPARATOR)
|
8
|
+
if !dirs.include?(dir)
|
9
|
+
ENV["PATH"] = [dir, *dirs].join(File::PATH_SEPARATOR)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
begin
|
14
|
+
major, minor, _ = RUBY_VERSION.split(/\./)
|
15
|
+
require "#{major}.#{minor}/curses.so"
|
16
|
+
rescue LoadError
|
17
|
+
require "curses.so"
|
18
|
+
end
|
19
|
+
|
20
|
+
if pdcurses_bundled
|
21
|
+
Curses.keyboard_encoding = Encoding::UTF_8
|
22
|
+
end
|
data/sample/hello.rb
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "curses"
|
4
|
-
include Curses
|
5
4
|
|
6
5
|
def show_message(message)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
height = 5
|
7
|
+
width = message.length + 6
|
8
|
+
top = (Curses.lines - height) / 2
|
9
|
+
left = (Curses.cols - width) / 2
|
10
|
+
win = Curses::Window.new(height, width, top, left)
|
11
|
+
win.box("|", "-")
|
11
12
|
win.setpos(2, 3)
|
12
13
|
win.addstr(message)
|
13
14
|
win.refresh
|
@@ -15,16 +16,14 @@ def show_message(message)
|
|
15
16
|
win.close
|
16
17
|
end
|
17
18
|
|
18
|
-
init_screen
|
19
|
+
Curses.init_screen
|
19
20
|
begin
|
20
|
-
crmode
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
getch
|
21
|
+
Curses.crmode
|
22
|
+
Curses.setpos((Curses.lines - 1) / 2, (Curses.cols - 11) / 2)
|
23
|
+
Curses.addstr("Hit any key")
|
24
|
+
Curses.refresh
|
25
|
+
Curses.getch
|
26
26
|
show_message("Hello, World!")
|
27
|
-
refresh
|
28
27
|
ensure
|
29
|
-
close_screen
|
28
|
+
Curses.close_screen
|
30
29
|
end
|
data/sample/mouse.rb
CHANGED
@@ -5,13 +5,13 @@ include Curses
|
|
5
5
|
|
6
6
|
def show_message(*msgs)
|
7
7
|
message = msgs.join
|
8
|
-
width = message.length + 6
|
9
|
-
|
10
|
-
|
8
|
+
height, width = 5, message.length + 6
|
9
|
+
top, left = (lines - height) / 2, (cols - width) / 2
|
10
|
+
win = Window.new(height, width, top, left)
|
11
11
|
win.keypad = true
|
12
|
-
win.attron(color_pair(COLOR_RED))
|
13
|
-
win.box(
|
14
|
-
|
12
|
+
win.attron(color_pair(COLOR_RED)) do
|
13
|
+
win.box("|", "-", "+")
|
14
|
+
end
|
15
15
|
win.setpos(2, 3)
|
16
16
|
win.addstr(message)
|
17
17
|
win.refresh
|
@@ -21,28 +21,28 @@ end
|
|
21
21
|
|
22
22
|
init_screen
|
23
23
|
start_color
|
24
|
-
init_pair(COLOR_BLUE,COLOR_BLUE,COLOR_WHITE)
|
25
|
-
init_pair(COLOR_RED,COLOR_RED,COLOR_WHITE)
|
24
|
+
init_pair(COLOR_BLUE, COLOR_BLUE, COLOR_WHITE)
|
25
|
+
init_pair(COLOR_RED, COLOR_RED, COLOR_WHITE)
|
26
26
|
crmode
|
27
27
|
noecho
|
28
28
|
stdscr.keypad(true)
|
29
29
|
|
30
30
|
begin
|
31
31
|
mousemask(BUTTON1_CLICKED|BUTTON2_CLICKED|BUTTON3_CLICKED|BUTTON4_CLICKED)
|
32
|
-
setpos((lines -
|
33
|
-
attron(color_pair(COLOR_BLUE)|A_BOLD)
|
32
|
+
setpos((lines - 1) / 2, (cols - 5) / 2)
|
33
|
+
attron(color_pair(COLOR_BLUE)|A_BOLD) do
|
34
34
|
addstr("click")
|
35
|
-
|
35
|
+
end
|
36
36
|
refresh
|
37
|
-
|
37
|
+
loop do
|
38
38
|
c = getch
|
39
39
|
case c
|
40
40
|
when KEY_MOUSE
|
41
41
|
m = getmouse
|
42
|
-
if
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
if m
|
43
|
+
show_message("getch = #{c.inspect}, ",
|
44
|
+
"mouse event = #{'0x%x' % m.bstate}, ",
|
45
|
+
"axis = (#{m.x},#{m.y},#{m.z})")
|
46
46
|
end
|
47
47
|
break
|
48
48
|
end
|
data/sample/rain.rb
CHANGED
@@ -1,76 +1,72 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# rain for a curses test
|
3
2
|
|
4
3
|
require "curses"
|
5
|
-
include Curses
|
6
4
|
|
7
|
-
def onsig(
|
8
|
-
close_screen
|
9
|
-
exit
|
5
|
+
def onsig(signal)
|
6
|
+
Curses.close_screen
|
7
|
+
exit signal
|
10
8
|
end
|
11
9
|
|
12
|
-
def
|
13
|
-
|
10
|
+
def place_string(y, x, string)
|
11
|
+
Curses.setpos(y, x)
|
12
|
+
Curses.addstr(string)
|
14
13
|
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
def cycle_index(index)
|
16
|
+
(index + 1) % 5
|
17
|
+
end
|
18
|
+
|
19
|
+
%w[HUP INT QUIT TERM].each do |sig|
|
20
|
+
unless trap(sig, "IGNORE") == "IGNORE" # previous handler
|
21
|
+
trap(sig) {|s| onsig(s) }
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
|
-
init_screen
|
24
|
-
nl
|
25
|
-
noecho
|
25
|
+
Curses.init_screen
|
26
|
+
Curses.nl
|
27
|
+
Curses.noecho
|
28
|
+
Curses.curs_set 0
|
26
29
|
srand
|
27
30
|
|
28
|
-
xpos = {}
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
xpos[i] = (c * ranf).to_i + 2
|
34
|
-
ypos[i] = (r * ranf).to_i + 2
|
31
|
+
xpos, ypos = {}, {}
|
32
|
+
x_range = 2..(Curses.cols - 3)
|
33
|
+
y_range = 2..(Curses.lines - 3)
|
34
|
+
(0..4).each do |i|
|
35
|
+
xpos[i], ypos[i] = rand(x_range), rand(y_range)
|
35
36
|
end
|
36
37
|
|
37
38
|
i = 0
|
38
|
-
|
39
|
-
x = (
|
40
|
-
y = (r * ranf).to_i + 2
|
39
|
+
loop do
|
40
|
+
x, y = rand(x_range), rand(y_range)
|
41
41
|
|
42
|
+
place_string(y, x, ".")
|
42
43
|
|
43
|
-
|
44
|
+
place_string(ypos[i], xpos[i], "o")
|
44
45
|
|
45
|
-
|
46
|
+
i = cycle_index(i)
|
47
|
+
place_string(ypos[i], xpos[i], "O")
|
46
48
|
|
47
|
-
i =
|
48
|
-
|
49
|
+
i = cycle_index(i)
|
50
|
+
place_string(ypos[i] - 1, xpos[i], "-")
|
51
|
+
place_string(ypos[i], xpos[i] - 1, "|.|")
|
52
|
+
place_string(ypos[i] + 1, xpos[i], "-")
|
49
53
|
|
50
|
-
i =
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
+
i = cycle_index(i)
|
55
|
+
place_string(ypos[i] - 2, xpos[i], "-")
|
56
|
+
place_string(ypos[i] - 1, xpos[i] - 1, "/ \\")
|
57
|
+
place_string(ypos[i], xpos[i] - 2, "| O |")
|
58
|
+
place_string(ypos[i] + 1, xpos[i] - 1, "\\ /")
|
59
|
+
place_string(ypos[i] + 2, xpos[i], "-")
|
54
60
|
|
55
|
-
i =
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
+
i = cycle_index(i)
|
62
|
+
place_string(ypos[i] - 2, xpos[i], " ")
|
63
|
+
place_string(ypos[i] - 1, xpos[i] - 1, " ")
|
64
|
+
place_string(ypos[i], xpos[i] - 2, " ")
|
65
|
+
place_string(ypos[i] + 1, xpos[i] - 1, " ")
|
66
|
+
place_string(ypos[i] + 2, xpos[i], " ")
|
61
67
|
|
62
|
-
i
|
63
|
-
setpos(ypos[i] - 2, xpos[i]); addstr(" ")
|
64
|
-
setpos(ypos[i] - 1, xpos[i] - 1); addstr(" ")
|
65
|
-
setpos(ypos[i], xpos[i] - 2); addstr(" ")
|
66
|
-
setpos(ypos[i] + 1, xpos[i] - 1); addstr(" ")
|
67
|
-
setpos(ypos[i] + 2, xpos[i]); addstr(" ")
|
68
|
+
xpos[i], ypos[i] = x, y
|
68
69
|
|
69
|
-
|
70
|
-
xpos[i] = x
|
71
|
-
ypos[i] = y
|
72
|
-
refresh
|
70
|
+
Curses.refresh
|
73
71
|
sleep(0.5)
|
74
72
|
end
|
75
|
-
|
76
|
-
# end of main
|
data/sample/view.rb
CHANGED
@@ -3,54 +3,41 @@
|
|
3
3
|
require "curses"
|
4
4
|
include Curses
|
5
5
|
|
6
|
-
|
7
|
-
#
|
8
|
-
#
|
9
|
-
|
10
|
-
if ARGV.size != 1 then
|
11
|
-
printf("usage: view file\n");
|
6
|
+
unless ARGV.size == 1
|
7
|
+
puts "usage: #{$0} file"
|
12
8
|
exit
|
13
9
|
end
|
10
|
+
|
14
11
|
begin
|
15
|
-
|
12
|
+
data_lines = File.readlines(ARGV[0])
|
16
13
|
rescue
|
17
|
-
raise "cannot open file: #{ARGV[
|
14
|
+
raise "cannot open file: #{ARGV[0]}"
|
18
15
|
end
|
19
16
|
|
20
|
-
# signal(SIGINT, finish)
|
21
|
-
|
22
17
|
init_screen
|
23
|
-
#keypad(stdscr,
|
18
|
+
#keypad(stdscr, true)
|
24
19
|
nonl
|
25
20
|
cbreak
|
26
21
|
noecho
|
27
|
-
#scrollok(stdscr,
|
28
|
-
|
29
|
-
# slurp the file
|
30
|
-
data_lines = []
|
31
|
-
fp.each_line { |l|
|
32
|
-
data_lines.push(l)
|
33
|
-
}
|
34
|
-
fp.close
|
35
|
-
|
22
|
+
#scrollok(stdscr, true)
|
36
23
|
|
37
24
|
lptr = 0
|
38
|
-
|
39
|
-
|
40
|
-
while i < lines
|
25
|
+
loop do
|
26
|
+
lines.times do |i|
|
41
27
|
setpos(i, 0)
|
42
28
|
#clrtoeol
|
43
|
-
addstr(data_lines[lptr + i] ||
|
44
|
-
i += 1
|
29
|
+
addstr(data_lines[lptr + i] || "")
|
45
30
|
end
|
46
31
|
refresh
|
47
32
|
|
48
|
-
explicit =
|
33
|
+
explicit = false
|
49
34
|
n = 0
|
50
|
-
|
35
|
+
c = nil
|
36
|
+
loop do
|
51
37
|
c = getch
|
52
38
|
if c =~ /[0-9]/
|
53
39
|
n = 10 * n + c.to_i
|
40
|
+
explicit = true
|
54
41
|
else
|
55
42
|
break
|
56
43
|
end
|
@@ -61,31 +48,29 @@ while TRUE
|
|
61
48
|
case c
|
62
49
|
when "n" #when KEY_DOWN
|
63
50
|
i = 0
|
64
|
-
|
65
|
-
if lptr + lines < data_lines.size
|
66
|
-
|
51
|
+
n.times do
|
52
|
+
if lptr + lines < data_lines.size
|
53
|
+
lptr += 1
|
67
54
|
else
|
68
|
-
|
55
|
+
break
|
69
56
|
end
|
70
57
|
i += 1
|
71
58
|
end
|
72
59
|
#wscrl(i)
|
73
|
-
|
74
60
|
when "p" #when KEY_UP
|
75
61
|
i = 0
|
76
|
-
|
77
|
-
if lptr > 0
|
78
|
-
|
62
|
+
n.times do
|
63
|
+
if lptr > 0
|
64
|
+
lptr -= 1
|
79
65
|
else
|
80
|
-
|
66
|
+
break
|
81
67
|
end
|
82
68
|
i += 1
|
83
69
|
end
|
84
70
|
#wscrl(-i)
|
85
|
-
|
86
71
|
when "q"
|
87
72
|
break
|
88
73
|
end
|
89
|
-
|
90
74
|
end
|
75
|
+
|
91
76
|
close_screen
|
data/sample/view2.rb
CHANGED
@@ -3,10 +3,10 @@
|
|
3
3
|
require "curses"
|
4
4
|
|
5
5
|
|
6
|
-
# A curses based file viewer
|
6
|
+
# A curses based file viewer.
|
7
7
|
class FileViewer
|
8
8
|
|
9
|
-
# Create a new
|
9
|
+
# Create a new FileViewer and view the file.
|
10
10
|
def initialize(filename)
|
11
11
|
@data_lines = []
|
12
12
|
@screen = nil
|
@@ -16,10 +16,8 @@ class FileViewer
|
|
16
16
|
interact
|
17
17
|
end
|
18
18
|
|
19
|
-
# Perform the curses setup
|
19
|
+
# Perform the curses setup.
|
20
20
|
def init_curses
|
21
|
-
# signal(SIGINT, finish)
|
22
|
-
|
23
21
|
Curses.init_screen
|
24
22
|
Curses.nonl
|
25
23
|
Curses.cbreak
|
@@ -28,37 +26,32 @@ class FileViewer
|
|
28
26
|
@screen = Curses.stdscr
|
29
27
|
|
30
28
|
@screen.scrollok(true)
|
31
|
-
|
29
|
+
#@screen.keypad(true)
|
32
30
|
end
|
33
31
|
|
34
|
-
# Load the file into memory
|
35
|
-
# the first part on the curses display.
|
32
|
+
# Load the file into memory and
|
33
|
+
# put the first part on the curses display.
|
36
34
|
def load_file(filename)
|
37
|
-
|
38
|
-
# slurp the file
|
39
|
-
fp.each_line { |l|
|
40
|
-
@data_lines.push(l.chop)
|
41
|
-
}
|
42
|
-
end
|
35
|
+
@data_lines = File.readlines(filename).map(&:chomp)
|
43
36
|
@top = 0
|
44
|
-
@data_lines[0..@screen.maxy-1].each_with_index
|
37
|
+
@data_lines[0..@screen.maxy-1].each_with_index do |line, idx|
|
45
38
|
@screen.setpos(idx, 0)
|
46
39
|
@screen.addstr(line)
|
47
|
-
|
48
|
-
@screen.setpos(0,0)
|
40
|
+
end
|
41
|
+
@screen.setpos(0, 0)
|
49
42
|
@screen.refresh
|
50
43
|
rescue
|
51
44
|
raise "cannot open file '#{filename}' for reading"
|
52
45
|
end
|
53
46
|
|
54
47
|
|
55
|
-
# Scroll the display up by one line
|
48
|
+
# Scroll the display up by one line.
|
56
49
|
def scroll_up
|
57
|
-
if
|
50
|
+
if @top > 0
|
58
51
|
@screen.scrl(-1)
|
59
52
|
@top -= 1
|
60
53
|
str = @data_lines[@top]
|
61
|
-
if
|
54
|
+
if str
|
62
55
|
@screen.setpos(0, 0)
|
63
56
|
@screen.addstr(str)
|
64
57
|
end
|
@@ -68,13 +61,13 @@ class FileViewer
|
|
68
61
|
end
|
69
62
|
end
|
70
63
|
|
71
|
-
# Scroll the display down by one line
|
64
|
+
# Scroll the display down by one line.
|
72
65
|
def scroll_down
|
73
|
-
if
|
66
|
+
if @top + @screen.maxy < @data_lines.length
|
74
67
|
@screen.scrl(1)
|
75
68
|
@top += 1
|
76
69
|
str = @data_lines[@top + @screen.maxy - 1]
|
77
|
-
if
|
70
|
+
if str
|
78
71
|
@screen.setpos(@screen.maxy - 1, 0)
|
79
72
|
@screen.addstr(str)
|
80
73
|
end
|
@@ -85,53 +78,49 @@ class FileViewer
|
|
85
78
|
end
|
86
79
|
|
87
80
|
# Allow the user to interact with the display.
|
88
|
-
# This uses
|
81
|
+
# This uses Emacs-like keybindings, and also
|
89
82
|
# vi-like keybindings as well, except that left
|
90
83
|
# and right move to the beginning and end of the
|
91
84
|
# file, respectively.
|
92
85
|
def interact
|
93
|
-
|
86
|
+
loop do
|
94
87
|
result = true
|
95
88
|
c = Curses.getch
|
96
89
|
case c
|
97
|
-
when Curses::KEY_DOWN, Curses::KEY_CTRL_N,
|
90
|
+
when Curses::KEY_DOWN, Curses::KEY_CTRL_N, "j"
|
98
91
|
result = scroll_down
|
99
|
-
when Curses::KEY_UP, Curses::KEY_CTRL_P,
|
92
|
+
when Curses::KEY_UP, Curses::KEY_CTRL_P, "k"
|
100
93
|
result = scroll_up
|
101
|
-
when Curses::KEY_NPAGE,
|
102
|
-
|
103
|
-
if
|
104
|
-
|
105
|
-
result = false
|
106
|
-
end
|
94
|
+
when Curses::KEY_NPAGE, " "
|
95
|
+
(@screen.maxy - 1).times do |i|
|
96
|
+
if !scroll_down && i == 0
|
97
|
+
result = false
|
107
98
|
break
|
108
99
|
end
|
109
100
|
end
|
110
101
|
when Curses::KEY_PPAGE
|
111
|
-
|
112
|
-
if
|
113
|
-
|
114
|
-
result = false
|
115
|
-
end
|
102
|
+
(@screen.maxy - 1).times do |i|
|
103
|
+
if !scroll_up && i == 0
|
104
|
+
result = false
|
116
105
|
break
|
117
106
|
end
|
118
107
|
end
|
119
|
-
when Curses::KEY_LEFT, Curses::KEY_CTRL_T,
|
120
|
-
while
|
108
|
+
when Curses::KEY_LEFT, Curses::KEY_CTRL_T, "h"
|
109
|
+
while scroll_up
|
121
110
|
end
|
122
|
-
when Curses::KEY_RIGHT, Curses::KEY_CTRL_B,
|
123
|
-
while
|
111
|
+
when Curses::KEY_RIGHT, Curses::KEY_CTRL_B, "l"
|
112
|
+
while scroll_down
|
124
113
|
end
|
125
|
-
when
|
114
|
+
when "q"
|
126
115
|
break
|
127
116
|
else
|
128
|
-
@screen.setpos(0,0)
|
117
|
+
@screen.setpos(0, 0)
|
129
118
|
@screen.addstr("[unknown key `#{Curses.keyname(c)}'=#{c}] ")
|
130
119
|
end
|
131
|
-
if
|
120
|
+
if !result
|
132
121
|
Curses.beep
|
133
122
|
end
|
134
|
-
@screen.setpos(0,0)
|
123
|
+
@screen.setpos(0, 0)
|
135
124
|
end
|
136
125
|
Curses.close_screen
|
137
126
|
end
|
@@ -140,8 +129,8 @@ end
|
|
140
129
|
|
141
130
|
# If we are being run as a main program...
|
142
131
|
if __FILE__ == $0
|
143
|
-
|
144
|
-
|
132
|
+
unless ARGV.size == 1
|
133
|
+
puts "usage: #{$0} file"
|
145
134
|
exit
|
146
135
|
end
|
147
136
|
|