ffi-ncurses 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +22 -0
- data/README.rdoc +220 -0
- data/Rakefile +50 -0
- data/examples/doc-eg1.rb +14 -0
- data/examples/doc-eg2.rb +23 -0
- data/examples/example-attributes.rb +40 -0
- data/examples/example-colour.rb +62 -0
- data/examples/example-cursor.rb +22 -0
- data/examples/example-getsetsyx.rb +55 -0
- data/examples/example-hello.rb +24 -0
- data/examples/example-jruby.rb +14 -0
- data/examples/example-keys.rb +25 -0
- data/examples/example-mouse.rb +50 -0
- data/examples/example-printw-variadic.rb +15 -0
- data/examples/example-softkeys.rb +22 -0
- data/examples/example-stdscr.rb +18 -0
- data/examples/example-windows.rb +24 -0
- data/examples/example.rb +108 -0
- data/ffi-ncurses.gemspec +37 -0
- data/lib/ffi-ncurses.rb +584 -0
- data/lib/ffi-ncurses/darwin.rb +215 -0
- data/lib/ffi-ncurses/keydefs.rb +106 -0
- data/lib/ffi-ncurses/mouse.rb +146 -0
- data/lib/ffi-ncurses/winstruct.rb +177 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +50 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +300 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- metadata +109 -0
data/History.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
== 0.3.0 / 2009-02-15
|
2
|
+
|
3
|
+
* Features
|
4
|
+
* Use FFI::NCurses rather than NCurses
|
5
|
+
* Removed dependency on rubygems
|
6
|
+
* Reorganised library layout
|
7
|
+
|
8
|
+
== 0.2.0 / 2009-02-03
|
9
|
+
|
10
|
+
* Features
|
11
|
+
* Initial gem release
|
12
|
+
* Most features of ncurses wrapped for Linux, Mac, ruby 1.8.6
|
13
|
+
and JRuby 1.1.6
|
14
|
+
|
15
|
+
* Bugs
|
16
|
+
* +newscr+ and +curscr+ cannot be implemented in JRuby until
|
17
|
+
find_sym implemented in ffi (expected in JRuby 1.1.7)
|
18
|
+
|
19
|
+
== 0.1.0 / 2009-01-19
|
20
|
+
|
21
|
+
* Features
|
22
|
+
* Initial release
|
data/README.rdoc
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
= ffi-ncurses
|
2
|
+
|
3
|
+
Author: Sean O'Halpin
|
4
|
+
|
5
|
+
A wrapper for ncurses 5.x. Tested on Mac OS X 10.4 (Tiger) and Ubuntu
|
6
|
+
8.04 with ruby 1.8.6 using ruby-ffi (>= 0.2.0) and JRuby 1.1.6.
|
7
|
+
|
8
|
+
The API is very much a transliteration of the C API rather than an
|
9
|
+
attempt to provide an idiomatic Ruby object-oriented API. The intent
|
10
|
+
is to provide a 'close to the metal' wrapper around the ncurses
|
11
|
+
library upon which you can build your own abstractions.
|
12
|
+
|
13
|
+
This is still very much a work-in-progress, so expect some rough
|
14
|
+
edges. Having said that, you can do quite a lot with it as it is. The
|
15
|
+
main things left to be done are tests, access to global variables and
|
16
|
+
various macros.
|
17
|
+
|
18
|
+
Below are some very preliminary notes on usage. See the examples
|
19
|
+
directory for real working examples.
|
20
|
+
|
21
|
+
== Usage
|
22
|
+
|
23
|
+
Load the library with:
|
24
|
+
|
25
|
+
require 'ffi-ncurses'
|
26
|
+
|
27
|
+
FFI::NCurses methods can be called as module methods:
|
28
|
+
|
29
|
+
begin
|
30
|
+
stdscr = FFI::NCurses.initscr
|
31
|
+
FFI::NCurses.clear
|
32
|
+
FFI::NCurses.addstr("Hello world!")
|
33
|
+
FFI::NCurses.refresh
|
34
|
+
FFI::NCurses.getch
|
35
|
+
ensure
|
36
|
+
FFI::NCurses.endwin
|
37
|
+
end
|
38
|
+
|
39
|
+
or as included methods:
|
40
|
+
|
41
|
+
require 'ffi-ncurses'
|
42
|
+
include FFI::NCurses
|
43
|
+
begin
|
44
|
+
stdscr = initscr
|
45
|
+
start_color
|
46
|
+
curs_set 0
|
47
|
+
raw
|
48
|
+
cbreak
|
49
|
+
noecho
|
50
|
+
clear
|
51
|
+
move 10, 10
|
52
|
+
standout
|
53
|
+
addstr("Hi!")
|
54
|
+
standend
|
55
|
+
refresh
|
56
|
+
getch
|
57
|
+
ensure
|
58
|
+
endwin
|
59
|
+
end
|
60
|
+
|
61
|
+
== Set up screen
|
62
|
+
|
63
|
+
require 'ffi-ncurses'
|
64
|
+
|
65
|
+
FFI::NCurses.initscr
|
66
|
+
begin
|
67
|
+
...
|
68
|
+
ensure
|
69
|
+
FFI::NCurses.endwin
|
70
|
+
end
|
71
|
+
|
72
|
+
== Typical initialization
|
73
|
+
|
74
|
+
stdscr = FFI::NCurses.initscr
|
75
|
+
FFI::NCurses.start_color
|
76
|
+
FFI::NCurses.curs_set 0
|
77
|
+
FFI::NCurses.raw
|
78
|
+
FFI::NCurses.cbreak
|
79
|
+
FFI::NCurses.noecho
|
80
|
+
FFI::NCurses.keypad(stdscr, true)
|
81
|
+
|
82
|
+
== Colours
|
83
|
+
|
84
|
+
start_color
|
85
|
+
init_pair(1, FFI::NCurses::COLOR_BLACK, FFI::NCurses::COLOR_RED)
|
86
|
+
attr_set FFI::NCurses::A_NORMAL, 1, nil
|
87
|
+
addch(?A)
|
88
|
+
addch(?Z | COLOR_PAIR(1))
|
89
|
+
|
90
|
+
== Cursor
|
91
|
+
|
92
|
+
=== Turn cursor off
|
93
|
+
|
94
|
+
FFI::NCurses.curs_set 0
|
95
|
+
|
96
|
+
=== Turn cursor on
|
97
|
+
|
98
|
+
FFI::NCurses.curs_set 1
|
99
|
+
|
100
|
+
== Windows
|
101
|
+
|
102
|
+
require 'ffi-ncurses'
|
103
|
+
begin
|
104
|
+
win = newwin(6, 12, 15, 15)
|
105
|
+
box(win, 0, 0)
|
106
|
+
inner_win = newwin(4, 10, 16, 16)
|
107
|
+
waddstr(inner_win, (["Hello window!"] * 5).join(' '))
|
108
|
+
wrefresh(win)
|
109
|
+
wrefresh(inner_win)
|
110
|
+
ch = wgetch(inner_win)
|
111
|
+
|
112
|
+
rescue Object => e
|
113
|
+
FFI::NCurses.endwin
|
114
|
+
puts e
|
115
|
+
ensure
|
116
|
+
FFI::NCurses.endwin
|
117
|
+
end
|
118
|
+
|
119
|
+
== Mouse handling
|
120
|
+
|
121
|
+
The ncurses mouse API is defined in a separate file. To include it use:
|
122
|
+
|
123
|
+
require 'ffi-ncurses/mouse'
|
124
|
+
|
125
|
+
You need to specify that you want keypad translation with:
|
126
|
+
|
127
|
+
keypad stdscr, FFI::NCurses::TRUE
|
128
|
+
|
129
|
+
otherwise your program will receive the raw mouse escape codes,
|
130
|
+
instead of KEY_MOUSE mouse event codes.
|
131
|
+
|
132
|
+
Specify which events you want to handle with:
|
133
|
+
|
134
|
+
mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, nil)
|
135
|
+
|
136
|
+
and set up a mouse event structure to receive the returned values:
|
137
|
+
|
138
|
+
mouse_event = FFI::NCurses::MEVENT.new
|
139
|
+
|
140
|
+
Receiving mouse events is a two-stage process: first, you are notified
|
141
|
+
that a mouse event has taken place through a special key code, then
|
142
|
+
you retrieve the event using +getmouse+. For example:
|
143
|
+
|
144
|
+
ch = getch
|
145
|
+
case ch
|
146
|
+
when FFI::NCurses::KEY_MOUSE
|
147
|
+
if getmouse(mouse_event) == FFI::NCurses::OK
|
148
|
+
|
149
|
+
The mouse event contains the button state (+bstate+) and x, y
|
150
|
+
coordinates. You can test for the button state using:
|
151
|
+
|
152
|
+
if mouse_event[:bstate] & FFI::NCurses::BUTTON1_PRESSED
|
153
|
+
|
154
|
+
or
|
155
|
+
|
156
|
+
if FFI::NCurses.BUTTON_PRESS(mouse_event[:bstate], 1)
|
157
|
+
|
158
|
+
The possible button states are: PRESS, RELEASE, CLICK, DOUBLE_CLICK
|
159
|
+
and TRIPLE_CLICK.
|
160
|
+
|
161
|
+
= Experimental stuff
|
162
|
+
|
163
|
+
== Specifying which curses library to use
|
164
|
+
|
165
|
+
You can specify which variant of curses you want to use by setting the
|
166
|
+
environment variable +RUBY_FFI_NCURSES_LIB+ to the one you want. For
|
167
|
+
example, to use PDCurses X11 curses lib, use:
|
168
|
+
|
169
|
+
RUBY_FFI_NCURSES_LIB=XCurses ruby examples/hello.rb
|
170
|
+
|
171
|
+
You can use this to specify +ncursesw+ for example. Please note that
|
172
|
+
only the bog standard ncurses lib has been in any way tested as of
|
173
|
+
yet.
|
174
|
+
|
175
|
+
= TO DO
|
176
|
+
|
177
|
+
== Complete translation of core functions to Darwin (Mac OS X)
|
178
|
+
|
179
|
+
There are some macros in darwin ncurses.h which I haven't
|
180
|
+
implemented yet. I'm working on it but if there are any you
|
181
|
+
desperately need let me know.
|
182
|
+
|
183
|
+
== +curscr+ and +newscr+ for JRuby
|
184
|
+
|
185
|
+
These global variables are not often used but are required for certain
|
186
|
+
situations (e.g. doing a wrefresh after shelling out and for the
|
187
|
+
get/setsyx macros).
|
188
|
+
|
189
|
+
This requires the implementation of +find_sym+ in JRuby (expected in
|
190
|
+
JRuby 1.1.7).
|
191
|
+
|
192
|
+
== Tests
|
193
|
+
|
194
|
+
This is tricky - I'm not sure exactly how to properly test a wrapper
|
195
|
+
for a library like ncurses. I certainly don't want to test ncurses!
|
196
|
+
Instead, I want to ensure my wrapper faithfully reproduces the
|
197
|
+
functionality of the platform's ncurses lib. To that end, I'm
|
198
|
+
experimenting with a simple DSL to generate both C and Ruby versions
|
199
|
+
of a test. With that I can generate equivalent programs and compare
|
200
|
+
the output. However, this is not really ready for prime time yet.
|
201
|
+
|
202
|
+
== Tidy up internals and examples
|
203
|
+
|
204
|
+
Things got a bit messy as I switched between the Linux and Mac
|
205
|
+
versions. The examples should be more focussed.
|
206
|
+
|
207
|
+
== Scope implementation of Menu and Form interface wrappers
|
208
|
+
|
209
|
+
I'm not particularly interested in the ncurses extension libraries for
|
210
|
+
forms and menus. I would rather spend time implementing similar
|
211
|
+
functionality on top of a portable text console library (or porting
|
212
|
+
rbcurses). However, in the interests of completeness, I suppose I
|
213
|
+
ought to at least scope it out.
|
214
|
+
|
215
|
+
= Trivia
|
216
|
+
|
217
|
+
While researching ncurses on Google, I innocently entered "curses
|
218
|
+
getsx" as a search term. NSFW and definitely not one for "I'm Feeling
|
219
|
+
Lucky".
|
220
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# Look in the tasks/setup.rb file for the various options that can be
|
2
|
+
# configured in this Rakefile. The .rake files in the tasks directory
|
3
|
+
# are where the options are used.
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bones'
|
7
|
+
Bones.setup
|
8
|
+
rescue LoadError
|
9
|
+
begin
|
10
|
+
load 'tasks/setup.rb'
|
11
|
+
rescue LoadError
|
12
|
+
raise RuntimeError, '### please install the "bones" gem ###'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
ensure_in_path 'lib'
|
17
|
+
require 'ffi-ncurses'
|
18
|
+
|
19
|
+
task :default => 'spec:run'
|
20
|
+
|
21
|
+
# see tasks/setup.rb for full list of options
|
22
|
+
|
23
|
+
PROJ.name = 'ffi-ncurses'
|
24
|
+
PROJ.authors = ["Sean O'Halpin"]
|
25
|
+
PROJ.email = 'sean.ohalpin@gmail.com'
|
26
|
+
PROJ.url = 'http://github.com/seanohalpin/ffi-ncurses'
|
27
|
+
PROJ.summary = "FFI wrapper for ncurses"
|
28
|
+
PROJ.version = "0.3.0"
|
29
|
+
PROJ.rubyforge.name = 'ffi-ncurses'
|
30
|
+
|
31
|
+
# gem
|
32
|
+
PROJ.gem.dependencies << ["ffi", ">= 0.2.0"]
|
33
|
+
|
34
|
+
# rdoc
|
35
|
+
PROJ.rdoc.exclude << "^notes"
|
36
|
+
PROJ.readme_file = 'README.rdoc'
|
37
|
+
|
38
|
+
# spec
|
39
|
+
PROJ.spec.opts << '--color'
|
40
|
+
|
41
|
+
# files
|
42
|
+
PROJ.exclude = %w(tmp$ bak$ ~$ CVS \.svn ^pkg ^doc \.git local notes)
|
43
|
+
PROJ.exclude << '^tags$' << "^bug" << "^tools"
|
44
|
+
PROJ.exclude << File.read('.gitignore').split(/\n/)
|
45
|
+
|
46
|
+
# notes
|
47
|
+
#PROJ.notes.exclude = %w(^README\.txt$ ^data/)
|
48
|
+
PROJ.notes.extensions << '.org'
|
49
|
+
|
50
|
+
# EOF
|
data/examples/doc-eg1.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Sean O'Halpin, 2009-02-15
|
4
|
+
#
|
5
|
+
require 'ffi-ncurses'
|
6
|
+
begin
|
7
|
+
stdscr = FFI::NCurses.initscr
|
8
|
+
FFI::NCurses.clear
|
9
|
+
FFI::NCurses.addstr("Hello world!")
|
10
|
+
FFI::NCurses.refresh
|
11
|
+
FFI::NCurses.getch
|
12
|
+
ensure
|
13
|
+
FFI::NCurses.endwin
|
14
|
+
end
|
data/examples/doc-eg2.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Sean O'Halpin, 2009-02-15
|
4
|
+
#
|
5
|
+
require 'ffi-ncurses'
|
6
|
+
include FFI::NCurses
|
7
|
+
begin
|
8
|
+
stdscr = initscr
|
9
|
+
start_color
|
10
|
+
curs_set 0
|
11
|
+
raw
|
12
|
+
cbreak
|
13
|
+
noecho
|
14
|
+
clear
|
15
|
+
move 10, 10
|
16
|
+
standout
|
17
|
+
addstr("Hi!")
|
18
|
+
standend
|
19
|
+
refresh
|
20
|
+
getch
|
21
|
+
ensure
|
22
|
+
endwin
|
23
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Sean O'Halpin, 2009-02-15
|
4
|
+
#
|
5
|
+
require 'ffi-ncurses'
|
6
|
+
include FFI::NCurses
|
7
|
+
initscr
|
8
|
+
begin
|
9
|
+
attributes = %w[
|
10
|
+
A_BLINK
|
11
|
+
A_BOLD
|
12
|
+
A_DIM
|
13
|
+
A_NORMAL
|
14
|
+
A_REVERSE
|
15
|
+
A_STANDOUT
|
16
|
+
A_UNDERLINE
|
17
|
+
]
|
18
|
+
alt_attributes = %w[
|
19
|
+
A_ALTCHARSET
|
20
|
+
A_HORIZONTAL
|
21
|
+
A_INVIS
|
22
|
+
A_LEFT
|
23
|
+
A_LOW
|
24
|
+
A_PROTECT
|
25
|
+
A_RIGHT
|
26
|
+
A_TOP
|
27
|
+
A_VERTICAL
|
28
|
+
]
|
29
|
+
|
30
|
+
attributes.each do |attr|
|
31
|
+
attr_const = FFI::NCurses.const_get(attr)
|
32
|
+
attr_set attr_const, 0, nil
|
33
|
+
addstr "THIS IS #{attr}\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
refresh
|
37
|
+
ch = getch
|
38
|
+
ensure
|
39
|
+
endwin
|
40
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Sean O'Halpin, 2009-02-15
|
4
|
+
#
|
5
|
+
require 'ffi-ncurses'
|
6
|
+
include FFI::NCurses
|
7
|
+
|
8
|
+
initscr
|
9
|
+
begin
|
10
|
+
# turn cursor off
|
11
|
+
curs_set 0
|
12
|
+
|
13
|
+
# initialize colour
|
14
|
+
start_color
|
15
|
+
|
16
|
+
# set up colour pairs
|
17
|
+
# Background Foreground
|
18
|
+
init_pair(0, Colour::BLACK, Colour::BLACK)
|
19
|
+
init_pair(1, Colour::RED, Colour::BLACK)
|
20
|
+
init_pair(2, Colour::GREEN, Colour::BLACK)
|
21
|
+
init_pair(3, Colour::YELLOW, Colour::BLACK)
|
22
|
+
init_pair(4, Colour::BLUE, Colour::BLACK)
|
23
|
+
init_pair(5, Colour::MAGENTA, Colour::BLACK)
|
24
|
+
init_pair(6, Colour::CYAN, Colour::BLACK)
|
25
|
+
init_pair(7, Colour::WHITE, Colour::BLACK)
|
26
|
+
|
27
|
+
init_pair(8, Colour::BLACK, Colour::BLACK)
|
28
|
+
init_pair(9, Colour::BLACK, Colour::RED)
|
29
|
+
init_pair(10, Colour::BLACK, Colour::GREEN)
|
30
|
+
init_pair(11, Colour::BLACK, Colour::YELLOW)
|
31
|
+
init_pair(12, Colour::BLACK, Colour::BLUE)
|
32
|
+
init_pair(13, Colour::BLACK, Colour::MAGENTA)
|
33
|
+
init_pair(14, Colour::BLACK, Colour::CYAN)
|
34
|
+
init_pair(15, Colour::BLACK, Colour::WHITE)
|
35
|
+
|
36
|
+
0.upto(15) do |i|
|
37
|
+
attr_set A_NORMAL, i, nil
|
38
|
+
addch(?A + i)
|
39
|
+
end
|
40
|
+
|
41
|
+
# add character and attribute together
|
42
|
+
addch(?Z | COLOR_PAIR(1)) # red
|
43
|
+
|
44
|
+
# reset attribute and colour to default
|
45
|
+
attr_set A_NORMAL, 0, nil
|
46
|
+
|
47
|
+
# start new line
|
48
|
+
addstr "\n"
|
49
|
+
|
50
|
+
# how to add a single space
|
51
|
+
addch(' '[0])
|
52
|
+
# or
|
53
|
+
addstr(" ")
|
54
|
+
|
55
|
+
addstr "Press any key"
|
56
|
+
|
57
|
+
# display and pause for key press
|
58
|
+
refresh
|
59
|
+
ch = getch
|
60
|
+
ensure
|
61
|
+
endwin
|
62
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Sean O'Halpin, 2009-02-15
|
4
|
+
#
|
5
|
+
require 'ffi-ncurses'
|
6
|
+
include FFI::NCurses
|
7
|
+
begin
|
8
|
+
initscr
|
9
|
+
addstr "Default"
|
10
|
+
getch
|
11
|
+
addstr "curs_set 0"
|
12
|
+
curs_set 0
|
13
|
+
getch
|
14
|
+
addstr "curs_set 1"
|
15
|
+
curs_set 1
|
16
|
+
getch
|
17
|
+
addstr "curs_set 2"
|
18
|
+
curs_set 2
|
19
|
+
getch
|
20
|
+
ensure
|
21
|
+
FFI::NCurses.endwin
|
22
|
+
end
|