rb-readline 0.4.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.
@@ -0,0 +1,508 @@
1
+ # readline.rb -- GNU Readline module
2
+ # Copyright (C) 1997-2001 Shugo Maed
3
+ #
4
+ # Ruby translation by Park Heesob phasis@gmail.com
5
+
6
+ module Readline
7
+
8
+ require 'rbreadline'
9
+ include RbReadline
10
+
11
+ @completion_proc = nil
12
+ @completion_case_fold = false
13
+
14
+ # Begins an interactive terminal process using +prompt+ as the command
15
+ # prompt that users see when they type commands. The method returns the
16
+ # line entered whenever a carriage return is encountered.
17
+ #
18
+ # If an +add_history+ argument is provided, commands entered by users are
19
+ # stored in a history buffer that can be recalled for later use.
20
+ #
21
+ # Note that this method depends on $stdin and $stdout both being open.
22
+ # Because this is meant as an interactive console interface, they should
23
+ # generally not be redirected.
24
+ #
25
+ # Example:
26
+ #
27
+ # loop{ Readline.readline('> ') }
28
+ #
29
+ def readline(prompt, add_history=nil)
30
+ if $stdin.closed?
31
+ raise IOError, "stdin closed"
32
+ end
33
+
34
+ RbReadline.rl_instream = $stdin
35
+ RbReadline.rl_outstream = $stdout
36
+
37
+ status = 0
38
+
39
+ begin
40
+ buff = RbReadline.readline(prompt)
41
+ rescue Exception => e
42
+ buff = nil
43
+ RbReadline.rl_cleanup_after_signal()
44
+ RbReadline.rl_deprep_terminal()
45
+ raise e
46
+ end
47
+
48
+ if add_history && buff
49
+ RbReadline.add_history(buff)
50
+ end
51
+
52
+ return buff ? buff.dup : nil
53
+ end
54
+
55
+ # Sets the input stream (an IO object) for readline interaction. The
56
+ # default is <tt>$stdin</tt>.
57
+ #
58
+ def self.input=(input)
59
+ RbReadline.rl_instream = input
60
+ end
61
+
62
+ # Sets the output stream (an IO object) for readline interaction. The
63
+ # default is <tt>$stdout</tt>.
64
+ #
65
+ def self.output=(output)
66
+ RbReadline.rl_outstream = output
67
+ end
68
+
69
+ # Returns current line buffer
70
+ #
71
+ def self.line_buffer
72
+ RbReadline.rl_line_buffer
73
+ end
74
+
75
+ # Sets the auto-completion procedure (i.e. tab auto-complete).
76
+ #
77
+ # The +proc+ argument is typically a Proc object. It must respond to
78
+ # <tt>.call</tt>, take a single String argument and return an Array of
79
+ # candidates for completion.
80
+ #
81
+ # Example:
82
+ #
83
+ # list = ['search', 'next', 'clear']
84
+ # Readline.completion_proc = proc{ |s| list.grep( /^#{Regexp.escape(s)}/) }
85
+ #
86
+ def self.completion_proc=(proc)
87
+ unless defined? proc.call
88
+ raise ArgumentError,"argument must respond to `call'"
89
+ end
90
+ @completion_proc = proc
91
+ end
92
+
93
+ # Returns the current auto-completion procedure.
94
+ #
95
+ def self.completion_proc()
96
+ @completion_proc
97
+ end
98
+
99
+ # Sets whether or not the completion proc should ignore case sensitivity.
100
+ # The default is false, i.e. completion procs are case sensitive.
101
+ #
102
+ def self.completion_case_fold=(bool)
103
+ @completion_case_fold = bool
104
+ end
105
+
106
+ # Returns whether or not the completion proc is case sensitive. The
107
+ # default is false, i.e. completion procs are case sensitive.
108
+ #
109
+ def self.completion_case_fold()
110
+ @completion_case_fold
111
+ end
112
+
113
+ def self.readline_attempted_completion_function(text,start,_end)
114
+ proc = @completion_proc
115
+ return nil if proc.nil?
116
+
117
+ RbReadline.rl_attempted_completion_over = true
118
+
119
+ case_fold = @completion_case_fold
120
+ ary = proc.call(text)
121
+ if ary.class != Array
122
+ ary = Array(ary)
123
+ else
124
+ ary.compact!
125
+ end
126
+
127
+ matches = ary.length
128
+ return nil if (matches == 0)
129
+ result = Array.new(matches+2)
130
+ for i in 0 ... matches
131
+ result[i+1] = ary[i].dup
132
+ end
133
+ result[matches+1] = nil
134
+
135
+ if(matches==1)
136
+ result[0] = result[1].dup
137
+ else
138
+ i = 1
139
+ low = 100000
140
+
141
+ while (i < matches)
142
+ if (case_fold)
143
+ si = 0
144
+ while ((c1 = result[i][si,1].downcase) &&
145
+ (c2 = result[i + 1][si,1].downcase))
146
+ break if (c1 != c2)
147
+ si += 1
148
+ end
149
+ else
150
+ si = 0
151
+ while ((c1 = result[i][si,1]) &&
152
+ (c2 = result[i + 1][si,1]))
153
+ break if (c1 != c2)
154
+ si += 1
155
+ end
156
+ end
157
+ if (low > si)
158
+ low = si
159
+ end
160
+ i+=1
161
+ end
162
+ result[0] = result[1][0,low]
163
+ end
164
+
165
+ result
166
+ end
167
+
168
+ # Sets vi editing mode.
169
+ #
170
+ def self.vi_editing_mode()
171
+ RbReadline.rl_vi_editing_mode(1,0)
172
+ nil
173
+ end
174
+
175
+ # Sets emacs editing mode
176
+ #
177
+ def self.emacs_editing_mode()
178
+ RbReadline.rl_emacs_editing_mode(1,0)
179
+ nil
180
+ end
181
+
182
+ # Sets the character that is automatically appended after the
183
+ # Readline.completion_proc method is called.
184
+ #
185
+ # If +char+ is nil or empty, then a null character is used.
186
+ #
187
+ def self.completion_append_character=(char)
188
+ if char.nil?
189
+ RbReadline.rl_completion_append_character = ?\0
190
+ elsif char.length==0
191
+ RbReadline.rl_completion_append_character = ?\0
192
+ else
193
+ RbReadline.rl_completion_append_character = char[0]
194
+ end
195
+ end
196
+
197
+ # Returns the character that is automatically appended after the
198
+ # Readline.completion_proc method is called.
199
+ #
200
+ def self.completion_append_character()
201
+ if RbReadline.rl_completion_append_character == ?\0
202
+ nil
203
+ end
204
+ return RbReadline.rl_completion_append_character
205
+ end
206
+
207
+ # Sets the character string that signal a break between words for the
208
+ # completion proc.
209
+ #
210
+ def self.basic_word_break_characters=(str)
211
+ RbReadline.rl_basic_word_break_characters = str.dup
212
+ end
213
+
214
+ # Returns the character string that signal a break between words for the
215
+ # completion proc. The default is " \t\n\"\\'`@$><=|&{(".
216
+ #
217
+ def self.basic_word_break_characters()
218
+ if RbReadline.rl_basic_word_break_characters.nil?
219
+ nil
220
+ else
221
+ RbReadline.rl_basic_word_break_characters.dup
222
+ end
223
+ end
224
+
225
+ # Sets the character string that signal the start or end of a word for
226
+ # the completion proc.
227
+ #
228
+ def self.completer_word_break_characters=(str)
229
+ RbReadline.rl_completer_word_break_characters = str.dup
230
+ end
231
+
232
+ # Returns the character string that signal the start or end of a word for
233
+ # the completion proc.
234
+ #
235
+ def self.completer_word_break_characters()
236
+ if RbReadline.rl_completer_word_break_characters.nil?
237
+ nil
238
+ else
239
+ RbReadline.rl_completer_word_break_characters.dup
240
+ end
241
+ end
242
+
243
+ # Sets the list of quote characters that can cause a word break.
244
+ #
245
+ def self.basic_quote_characters=(str)
246
+ RbReadline.rl_basic_quote_characters = str.dup
247
+ end
248
+
249
+ # Returns the list of quote characters that can cause a word break.
250
+ # The default is "'\"" (single and double quote characters).
251
+ #
252
+ def self.basic_quote_characters()
253
+ if RbReadline.rl_basic_quote_characters.nil?
254
+ nil
255
+ else
256
+ RbReadline.rl_basic_quote_characters.dup
257
+ end
258
+ end
259
+
260
+ # Sets the list of characters that can be used to quote a substring of
261
+ # the line, i.e. a group of characters within quotes.
262
+ #
263
+ def self.completer_quote_characters=(str)
264
+ RbReadline.rl_completer_quote_characters = str.dup
265
+ end
266
+
267
+ # Returns the list of characters that can be used to quote a substring
268
+ # of the line, i.e. a group of characters inside quotes.
269
+ #
270
+ def self.completer_quote_characters()
271
+ if RbReadline.rl_completer_quote_characters.nil?
272
+ nil
273
+ else
274
+ RbReadline.rl_completer_quote_characters.dup
275
+ end
276
+ end
277
+
278
+ # Sets the character string of one or more characters that indicate quotes
279
+ # for the filename completion of user input.
280
+ #
281
+ def self.filename_quote_characters=(str)
282
+ RbReadline.rl_filename_quote_characters = str.dup
283
+ end
284
+
285
+ # Returns the character string used to indicate quotes for the filename
286
+ # completion of user input.
287
+ #
288
+ def self.filename_quote_characters()
289
+ if RbReadline.rl_filename_quote_characters.nil?
290
+ nil
291
+ else
292
+ RbReadline.rl_filename_quote_characters.dup
293
+ end
294
+ end
295
+
296
+ # The History class encapsulates a history of all commands entered by
297
+ # users at the prompt, providing an interface for inspection and retrieval
298
+ # of all commands.
299
+ class History
300
+ extend Enumerable
301
+
302
+ # The History class, stringified in all caps.
303
+ #--
304
+ # Why?
305
+ #
306
+ def self.to_s
307
+ "HISTORY"
308
+ end
309
+
310
+ # Returns the command that was entered at the specified +index+
311
+ # in the history buffer.
312
+ #
313
+ # Raises an IndexError if the entry is nil.
314
+ #
315
+ def self.[](index)
316
+ if index < 0
317
+ index += RbReadline.history_length
318
+ end
319
+ entry = RbReadline.history_get(RbReadline.history_base+index)
320
+ if entry.nil?
321
+ raise IndexError,"invalid index"
322
+ end
323
+ entry.line.dup
324
+ end
325
+
326
+ # Sets the command +str+ at the given index in the history buffer.
327
+ #
328
+ # You can only replace an existing entry. Attempting to create a new
329
+ # entry will result in an IndexError.
330
+ #
331
+ def self.[]=(index,str)
332
+ if index<0
333
+ index += RbReadline.history_length
334
+ end
335
+ entry = RbReadline.replace_history_entry(index,str,nil)
336
+ if entry.nil?
337
+ raise IndexError,"invalid index"
338
+ end
339
+ str
340
+ end
341
+
342
+ # Synonym for Readline.add_history.
343
+ #
344
+ def self.<<(str)
345
+ RbReadline.add_history(str)
346
+ end
347
+
348
+ # Pushes a list of +args+ onto the history buffer.
349
+ #
350
+ def self.push(*args)
351
+ args.each do |str|
352
+ RbReadline.add_history(str)
353
+ end
354
+ end
355
+
356
+ # Internal function that removes the item at +index+ from the history
357
+ # buffer, performing necessary duplication in the process.
358
+ #--
359
+ # TODO: mark private?
360
+ #
361
+ def self.rb_remove_history(index)
362
+ entry = RbReadline.remove_history(index)
363
+ if (entry)
364
+ val = entry.line.dup
365
+ entry = nil
366
+ return val
367
+ end
368
+ nil
369
+ end
370
+
371
+ # Removes and returns the last element from the history buffer.
372
+ #
373
+ def self.pop()
374
+ if RbReadline.history_length>0
375
+ rb_remove_history(RbReadline.history_length-1)
376
+ else
377
+ nil
378
+ end
379
+ end
380
+
381
+ # Removes and returns the first element from the history buffer.
382
+ #
383
+ def self.shift()
384
+ if RbReadline.history_length>0
385
+ rb_remove_history(0)
386
+ else
387
+ nil
388
+ end
389
+ end
390
+
391
+ # Iterates over each entry in the history buffer.
392
+ #
393
+ def self.each()
394
+ for i in 0 ... RbReadline.history_length
395
+ entry = RbReadline.history_get(RbReadline.history_base + i)
396
+ break if entry.nil?
397
+ yield entry.line.dup
398
+ end
399
+ self
400
+ end
401
+
402
+ # Returns the length of the history buffer.
403
+ #
404
+ def self.length()
405
+ RbReadline.history_length
406
+ end
407
+
408
+ # Synonym for Readline.length.
409
+ #
410
+ def self.size()
411
+ RbReadline.history_length
412
+ end
413
+
414
+ # Returns a bolean value indicating whether or not the history buffer
415
+ # is empty.
416
+ #
417
+ def self.empty?()
418
+ RbReadline.history_length == 0
419
+ end
420
+
421
+ # Deletes an entry from the histoyr buffer at the specified +index+.
422
+ #
423
+ def self.delete_at(index)
424
+ if index < 0
425
+ i += RbReadline.history_length
426
+ end
427
+ if index < 0 || index > RbReadline.history_length - 1
428
+ raise IndexError, "invalid index"
429
+ end
430
+ rb_remove_history(index)
431
+ end
432
+
433
+ end
434
+
435
+ HISTORY = History
436
+
437
+ # The Fcomp class provided to encapsulate typical filename completion
438
+ # procedure. You will not typically use this directly, but will instead
439
+ # use the Readline::FILENAME_COMPLETION_PROC.
440
+ #
441
+ class Fcomp
442
+ def self.call(str)
443
+ matches = RbReadline.rl_completion_matches(str,
444
+ :rl_filename_completion_function)
445
+ if (matches)
446
+ result = []
447
+ i = 0
448
+ while(matches[i])
449
+ result << matches[i].dup
450
+ matches[i] = nil
451
+ i += 1
452
+ end
453
+ matches = nil
454
+ if (result.length >= 2)
455
+ result.shift
456
+ end
457
+ else
458
+ result = nil
459
+ end
460
+ return result
461
+ end
462
+ end
463
+
464
+ FILENAME_COMPLETION_PROC = Fcomp
465
+
466
+ # The Ucomp class provided to encapsulate typical filename completion
467
+ # procedure. You will not typically use this directly, but will instead
468
+ # use the Readline::USERNAME_COMPLETION_PROC.
469
+ #
470
+ # Note that this feature currently only works on Unix systems since it
471
+ # ultimately uses the Etc module to iterate over a list of users.
472
+ #
473
+ class Ucomp
474
+ def self.call(str)
475
+ matches = RbReadline.rl_completion_matches(str,
476
+ :rl_username_completion_function)
477
+ if (matches)
478
+ result = []
479
+ i = 0
480
+ while(matches[i])
481
+ result << matches[i].dup
482
+ matches[i] = nil
483
+ i += 1
484
+ end
485
+ matches = nil
486
+ if (result.length >= 2)
487
+ result.shift
488
+ end
489
+ else
490
+ result = nil
491
+ end
492
+ return result
493
+ end
494
+ end
495
+
496
+ USERNAME_COMPLETION_PROC = Ucomp
497
+
498
+ RbReadline.rl_readline_name = "Ruby"
499
+
500
+ RbReadline.using_history()
501
+
502
+ VERSION = RbReadline.rl_library_version
503
+
504
+ module_function :readline
505
+
506
+ RbReadline.rl_attempted_completion_function = :readline_attempted_completion_function
507
+
508
+ end