readline-ffi 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +3 -0
  3. data/LICENSE +22 -0
  4. data/README.rdoc +9 -0
  5. data/Rakefile +37 -0
  6. data/ext/.gitignore +0 -0
  7. data/lib/ffi/readline.rb +71 -0
  8. data/lib/readline-ffi/version.rb +3 -0
  9. data/lib/readline.rb +300 -0
  10. data/readline-ffi.gemspec +25 -0
  11. data/spec/default.mspec +3 -0
  12. data/spec/library/readline/basic_quote_characters_spec.rb +20 -0
  13. data/spec/library/readline/basic_word_break_characters_spec.rb +20 -0
  14. data/spec/library/readline/completer_quote_characters_spec.rb +20 -0
  15. data/spec/library/readline/completer_word_break_characters_spec.rb +20 -0
  16. data/spec/library/readline/completion_append_character_spec.rb +20 -0
  17. data/spec/library/readline/completion_case_fold_spec.rb +22 -0
  18. data/spec/library/readline/completion_proc_spec.rb +26 -0
  19. data/spec/library/readline/constants_spec.rb +22 -0
  20. data/spec/library/readline/emacs_editing_mode_spec.rb +13 -0
  21. data/spec/library/readline/filename_quote_characters_spec.rb +20 -0
  22. data/spec/library/readline/history/append_spec.rb +32 -0
  23. data/spec/library/readline/history/delete_at_spec.rb +49 -0
  24. data/spec/library/readline/history/each_spec.rb +33 -0
  25. data/spec/library/readline/history/element_reference_spec.rb +44 -0
  26. data/spec/library/readline/history/element_set_spec.rb +39 -0
  27. data/spec/library/readline/history/empty_spec.rb +17 -0
  28. data/spec/library/readline/history/history_spec.rb +13 -0
  29. data/spec/library/readline/history/length_spec.rb +13 -0
  30. data/spec/library/readline/history/pop_spec.rb +34 -0
  31. data/spec/library/readline/history/push_spec.rb +30 -0
  32. data/spec/library/readline/history/shared/size.rb +14 -0
  33. data/spec/library/readline/history/shift_spec.rb +34 -0
  34. data/spec/library/readline/history/size_spec.rb +13 -0
  35. data/spec/library/readline/history/to_s_spec.rb +13 -0
  36. data/spec/library/readline/readline_spec.rb +38 -0
  37. data/spec/library/readline/vi_editing_mode_spec.rb +13 -0
  38. data/spec/spec.opts +4 -0
  39. data/spec/spec_helper.rb +53 -0
  40. data/test/test_readline.rb +69 -0
  41. metadata +106 -0
@@ -0,0 +1,2 @@
1
+ /nbproject/private/
2
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+ gemspec
3
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2009 Koichiro Ohba. All rights reserved.
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,9 @@
1
+ = Readline-ffi
2
+
3
+ GNU Readline Wrapper for Ruby-FFI(JRuby-FFI/Rubinus-FFI/Ruby-FFI).
4
+
5
+ CRuby's Readline extention intaerface compatiblity.
6
+
7
+ tested only JRuby Windows environment.
8
+
9
+ I hope supoorts environments to Mac OSX and Linux.
@@ -0,0 +1,37 @@
1
+ # -*- mode: ruby; coding: utf-8 -*-
2
+ require 'rubygems'
3
+ require 'bundler'
4
+
5
+ require 'rake'
6
+ require 'rake/clean'
7
+ require 'rake/rdoctask'
8
+ require 'fileutils'
9
+ include FileUtils
10
+
11
+ CLEAN.include ["ext/*.{log,c,so,obj,pdb,lib,def,exp,manifest,orig}", "ext/Makefile", "*.gem"]
12
+
13
+ name="readline-ffi"
14
+ version="0.0.1"
15
+
16
+ desc "Do everything, baby!"
17
+ task :default => [:package]
18
+
19
+ task :package => [:clean,:compile,:makegem]
20
+
21
+ task :ffi_generate do
22
+ require 'ffi'
23
+ require 'ffi/tools/generator'
24
+ require 'ffi/tools/struct_generator'
25
+
26
+ ffi_files = ["lib/readline.rb.ffi"]
27
+ ffi_options = "-Ilib"
28
+ ffi_files.each do |ffi_file|
29
+
30
+ end
31
+
32
+ end
33
+
34
+ desc "mspec"
35
+ task :spec do
36
+ sh "mspec -t j spec"
37
+ end
File without changes
@@ -0,0 +1,71 @@
1
+ require 'ffi'
2
+
3
+ module FFI::Readline
4
+ extend FFI::Library
5
+ CONVENTION = FFI::Platform.windows? ? :stdcall : :default
6
+
7
+ paths = %w[
8
+ /usr/local/lib/libreadline.dylib
9
+ /opt/local/lib/libreadline.dylib
10
+ /usr/lib/libreadline.dylib
11
+ /usr/lib/libreadline.so
12
+ /lib/libreadline.so
13
+ /lib/libreadline.so.5
14
+ ]
15
+ paths << File.expand_path(File.dirname(__FILE__) + "/../../ext/readline.dll")
16
+ paths.find do |path|
17
+ if File.exist?(path)
18
+ begin
19
+ ffi_lib path
20
+ true
21
+ rescue LoadError
22
+ false
23
+ end
24
+ end
25
+ end
26
+ ffi_convention(CONVENTION)
27
+
28
+ attach_function :readline, [:string], :string
29
+ attach_function :filename_completion_function, :rl_filename_completion_function, [:pointer, :int], :pointer
30
+ attach_function :username_completion_function, :rl_username_completion_function, [:string, :int], :string
31
+ callback :compentry_function, [:pointer, :int], :string
32
+ attach_function :completion_matches, :rl_completion_matches, [:string, :compentry_function], :pointer
33
+ attach_function :refresh_line, :rl_refresh_line, [:int, :int], :int
34
+
35
+ attach_variable :library_version, :rl_library_version, :pointer
36
+ attach_variable :readline_name, :rl_readline_name, :pointer
37
+ attach_variable :editing_mode, :rl_editing_mode, :int
38
+ attach_variable :insert_mode, :rl_insert_mode, :int
39
+ attach_variable :completion_entry_function, :rl_completion_entry_function, :pointer
40
+ attach_variable :completion_append_character, :rl_completion_append_character, :int
41
+ attach_variable :completer_quote_characters, :rl_completer_quote_characters, :pointer
42
+ attach_variable :filename_quote_characters, :rl_filename_quote_characters, :pointer
43
+ attach_variable :basic_quote_characters, :rl_basic_quote_characters, :pointer
44
+ attach_variable :basic_word_break_characters, :rl_basic_word_break_characters, :pointer
45
+ attach_variable :completer_word_break_characters, :rl_completer_word_break_characters, :pointer
46
+ callback :completion_function, [:string, :int, :int], :pointer
47
+ attach_variable :attempted_completion_function, :rl_attempted_completion_function, :completion_function
48
+ attach_variable :outstream, :rl_outstream, :pointer
49
+ attach_variable :instream, :rl_instream, :pointer
50
+
51
+ # History
52
+ class HistoryEntry < FFI::Struct
53
+ layout :line, :string, 0,
54
+ :timstamp, :string, 4,
55
+ :data, :pointer, 8
56
+ end
57
+
58
+ attach_function :using_history, [], :void
59
+ attach_function :add_history, [:string], :void
60
+ # attach_function :add_history_time, [:string], :void
61
+ attach_function :clear_history, [], :void
62
+ attach_function :remove_history, [:int], :pointer
63
+ attach_function :history_get, [:int], :pointer
64
+ attach_function :replace_history_entry, [:int, :string, :pointer], :pointer
65
+
66
+ attach_variable :history_base, :int
67
+ attach_variable :history_length, :int
68
+ attach_variable :history_max_entries, :int
69
+ end
70
+
71
+
@@ -0,0 +1,3 @@
1
+ module ReadlineFFI
2
+ VERSION = '0.0.2'
3
+ end
@@ -0,0 +1,300 @@
1
+ #
2
+ # Version: CPL 1.0/GPL 2.0/LGPL 2.1
3
+ #
4
+ # The contents of this file are subject to the Common Public
5
+ # License Version 1.0 (the "License"); you may not use this file
6
+ # except in compliance with the License. You may obtain a copy of
7
+ # the License at http://www.eclipse.org/legal/cpl-v10.html
8
+ #
9
+ # Software distributed under the License is distributed on an "AS
10
+ # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11
+ # implied. See the License for the specific language governing
12
+ # rights and limitations under the License.
13
+ #
14
+ # Copyright (C) 2009 Koichiro Ohba <koichiro@meadowy.org>
15
+ #
16
+ # Alternatively, the contents of this file may be used under the terms of
17
+ # either of the GNU General Public License Version 2 or later (the "GPL"),
18
+ # or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
19
+ # in which case the provisions of the GPL or the LGPL are applicable instead
20
+ # of those above. If you wish to allow use of your version of this file only
21
+ # under the terms of either the GPL or the LGPL, and not to allow others to
22
+ # use your version of this file under the terms of the CPL, indicate your
23
+ # decision by deleting the provisions above and replace them with the notice
24
+ # and other provisions required by the GPL or the LGPL. If you do not delete
25
+ # the provisions above, a recipient may use your version of this file under
26
+ # the terms of any one of the CPL, the GPL or the LGPL.
27
+
28
+ require 'ffi/readline'
29
+ require 'readeline-ffi/version'
30
+
31
+ module Readline
32
+
33
+ # filename_completion_proc_call
34
+ FILENAME_COMPLETION_PROC = Proc.new do |text|
35
+ # p = FFI::Readline.completion_matches(text) do |word, state|
36
+ # puts word
37
+ # puts word_p.read_string
38
+ # puts state
39
+ # p = FFI::Readline.filename_completion_function(word_p, state)
40
+ # nil
41
+ # p = ::FFI::MemoryPointer.new :pointer
42
+ # p.put_string("hoge")
43
+ # p
44
+ # nil
45
+ # end
46
+ # return nil if p.null?
47
+
48
+ r = Dir.glob(text + "*")
49
+ p r
50
+ r
51
+ end
52
+ # username_completion_proc_call
53
+ USERNAME_COMPLETION_PROC = Proc.new do |text|
54
+ []
55
+ end
56
+
57
+ # Readline initialize
58
+ private
59
+ FFI::Readline.readline_name = ::FFI::MemoryPointer.from_string("Ruby")
60
+ @completion_proc = nil
61
+ @completion_case_fold = nil
62
+
63
+ def self.library_version
64
+ p = FFI::Readline.library_version
65
+ p.null? ? nil : p.read_string
66
+ end
67
+
68
+ ATTEMPTED_COMPLETION_PROC = lambda do |text, start, last|
69
+ proc = @completion_proc
70
+ return nil unless proc
71
+
72
+ candidates = proc.call(text)
73
+ return nil if candidates.empty?
74
+
75
+ result_size = candidates.length + 1
76
+ result = ::FFI::MemoryPointer.new :pointer, result_size
77
+ candidates.each_with_index do |word, i|
78
+ result[i].put_pointer(0, ::FFI::MemoryPointer.from_string(word))
79
+ end
80
+ result[result_size - 1].put_pointer(0, nil)
81
+
82
+ result
83
+ end
84
+ FFI::Readline.attempted_completion_function = ATTEMPTED_COMPLETION_PROC
85
+
86
+ public
87
+ VERSION = "#{library_version} (FFI wrapper #{ReadelineFFI::VERSION})"
88
+
89
+ def readline( prompt = "", history = nil)
90
+ raise TypeError unless STDIN.kind_of? IO
91
+ raise TypeError unless STDOUT.kind_of? IO
92
+ # TODO: STDOUT,STDIN connected in rl_outstream, rl_instream
93
+ # FFI::Readline.instream
94
+ # FFI::Readline.outstream
95
+
96
+ r = FFI::Readline.readline(prompt)
97
+ if history
98
+ FFI::Readline.add_history(r)
99
+ end
100
+ r.taint
101
+ end
102
+ module_function :readline
103
+
104
+ class History
105
+ include Enumerable
106
+
107
+ private
108
+ def initialize
109
+ FFI::Readline.using_history
110
+ end
111
+
112
+ def remove_history(index)
113
+ p = FFI::Readline.remove_history(index)
114
+ return nil if p.null?
115
+ entry = FFI::Readline::HistoryEntry.new(p)
116
+ String.new(entry[:line])
117
+ end
118
+
119
+ public
120
+ def to_s; "HISTORY" end
121
+
122
+ def [](index)
123
+ index += FFI::Readline.history_length if index < 0
124
+ p = FFI::Readline.history_get(FFI::Readline.history_base + index)
125
+ raise IndexError, "invalid index" if p.null?
126
+ entry = FFI::Readline::HistoryEntry.new(p)
127
+ entry[:line].taint
128
+ end
129
+
130
+ def []=(index, str)
131
+ index += FFI::Readline.hisrory_length if index < 0
132
+ p = FFI::Readline.replace_history_entry(index, str, nil)
133
+ raise IndexError, "invalid index" if p.null?
134
+ str
135
+ end
136
+
137
+ def <<(str)
138
+ raise TypeError unless str.respond_to?(:to_str)
139
+
140
+ FFI::Readline.add_history(str.to_str)
141
+ HISTORY
142
+ end
143
+
144
+ def push(*args)
145
+ for s in args
146
+ raise TypeError unless s.respond_to?(:to_str)
147
+ FFI::Readline.add_history(s.to_str)
148
+ end
149
+ HISTORY
150
+ end
151
+
152
+ def pop
153
+ l = FFI::Readline.history_length
154
+ return nil if l <= 0
155
+ r = remove_history(l - 1)
156
+ r.taint
157
+ end
158
+
159
+ def shift
160
+ return nil unless FFI::Readline.history_length > 0
161
+ r = remove_history(0)
162
+ r.taint
163
+ end
164
+
165
+ def each(&block)
166
+ i = 0
167
+ while i < FFI::Readline.history_length
168
+ p = FFI::Readline.history_get(FFI::Readline.history_base + i)
169
+ break if p.null?
170
+ entry = FFI::Readline::HistoryEntry.new(p)
171
+ block.call(String.new(entry[:line]).taint)
172
+ i += 1
173
+ end
174
+ self
175
+ end
176
+
177
+ def length
178
+ FFI::Readline.history_length
179
+ end
180
+ alias :size :length
181
+
182
+ def empty?
183
+ FFI::Readline.history_length == 0 ? true : false
184
+ end
185
+
186
+ def delete_at(index)
187
+ l = FFI::Readline.history_length
188
+ index += l if index < 0
189
+ raise IndexError, "invalid index" if (index < 0) or (index > l - 1)
190
+ r = remove_history(index)
191
+ r.taint
192
+ end
193
+ end
194
+ HISTORY = History.new
195
+
196
+ def self.basic_word_break_characters=(str)
197
+ return nil unless str
198
+ FFI::Readline.basic_word_break_characters = ::FFI::MemoryPointer.from_string(str)
199
+ end
200
+
201
+ def self.basic_word_break_characters
202
+ p = FFI::Readline.basic_word_break_characters
203
+ p.null? ? nil : p.read_string
204
+ end
205
+
206
+ def self.completion_append_character=(str)
207
+ if str
208
+ FFI::Readline.completion_append_character = str[0]
209
+ else
210
+ FFI::Readline.completion_append_character = 0
211
+ end
212
+ end
213
+
214
+ def self.completion_append_character
215
+ ch = FFI::Readline.completion_append_character
216
+ return nil if ch == 0
217
+ ch.chr
218
+ end
219
+
220
+ def self.completer_word_break_characters=(str)
221
+ return nil unless str
222
+ FFI::Readline.completer_word_break_characters = ::FFI::MemoryPointer.from_string(str)
223
+ end
224
+
225
+ def self.completer_word_break_characters
226
+ p = FFI::Readline.completer_word_break_characters
227
+ p.null? ? nil : p.read_string
228
+ end
229
+
230
+ def self.basic_quote_characters=(str)
231
+ return nil unless str
232
+ FFI::Readline.basic_quote_characters = ::FFI::MemoryPointer.from_string(str)
233
+ HISTORY
234
+ end
235
+
236
+ def self.basic_quote_characters
237
+ p = FFI::Readline.basic_quote_characters
238
+ p.null? ? nil : p.read_string
239
+ end
240
+
241
+ def self.completer_quote_characters=(str)
242
+ return nil unless str
243
+ FFI::Readline.completer_quote_characters = ::FFI::MemoryPointer.from_string(str)
244
+ end
245
+
246
+ def self.completer_quote_characters
247
+ p = FFI::Readline.completer_quote_characters
248
+ p.null? ? nil : p.read_string
249
+ end
250
+
251
+ def self.filename_quote_characters=(str)
252
+ return nil unless str
253
+ FFI::Readline.completer_quote_characters = ::FFI::MemoryPointer.from_string(str)
254
+ end
255
+
256
+ def self.filename_quote_characters
257
+ p = FFI::Readline.filename_quote_characters
258
+ p.null? ? nil : p.read_string
259
+ end
260
+
261
+ def self.completion_proc=(proc)
262
+ raise ArgumentError, "argument must respond to `call'" unless proc.respond_to? :call
263
+ @completion_proc = proc
264
+ end
265
+
266
+ def self.completion_proc
267
+ @completion_proc
268
+ end
269
+
270
+ def self.completion_case_fold=(bool)
271
+ @completion_case_fold = bool
272
+ end
273
+
274
+ def self.completion_case_fold
275
+ @completion_case_fold
276
+ end
277
+
278
+ def self.vi_editing_mode
279
+ FFI::Readline.editing_mode = 0
280
+ nil
281
+ end
282
+
283
+ def self.emacs_editing_mode
284
+ FFI::Readline.editing_mode = 1
285
+ nil
286
+ end
287
+
288
+ def self.refresh_line()
289
+ FFI::Readline.refresh_line(0, 0)
290
+ end
291
+ end
292
+
293
+ if __FILE__ == $0
294
+ r = Readline.readline("hoge> ")
295
+ puts ">> " + r
296
+ puts FFI::Readline.editing_mode
297
+ puts Readline.emacs_editing_mode
298
+ puts Readline.completer_quote_characters
299
+ puts Readline.basic_word_break_characters
300
+ end