rb-readline 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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