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 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
@@ -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
@@ -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