OSDN Git Service

ruby-1.9.1-rc1
[splhack/AndroidRuby.git] / lib / ruby-1.9.1-rc1 / ext / readline / readline.c
1 /************************************************
2
3   readline.c - GNU Readline module
4
5   $Author: yugui $
6   created at: Wed Jan 20 13:59:32 JST 1999
7
8   Copyright (C) 1997-2008  Shugo Maeda
9   Copyright (C) 2008       TAKAO Kouji
10
11   $Id: readline.c 20709 2008-12-13 01:59:19Z yugui $
12
13   Contact:
14    - TAKAO Kouji <kouji at takao7 dot net> (current maintainer)
15
16 ************************************************/
17
18 #ifdef RUBY_EXTCONF_H
19 #include RUBY_EXTCONF_H
20 #endif
21
22 #include "ruby/config.h"
23 #include <errno.h>
24 #include <stdio.h>
25 #include <string.h>
26 #ifdef HAVE_READLINE_READLINE_H
27 #include <readline/readline.h>
28 #endif
29 #ifdef HAVE_READLINE_HISTORY_H
30 #include <readline/history.h>
31 #endif
32 #ifdef HAVE_EDITLINE_READLINE_H
33 #include <editline/readline.h>
34 #endif
35
36 #include "ruby/ruby.h"
37 #include "ruby/io.h"
38
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
43 static VALUE mReadline;
44
45 #define EDIT_LINE_LIBRARY_VERSION "EditLine wrapper"
46
47 #define COMPLETION_PROC "completion_proc"
48 #define COMPLETION_CASE_FOLD "completion_case_fold"
49 static ID completion_proc, completion_case_fold;
50
51 #ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION
52 # define rl_filename_completion_function filename_completion_function
53 #endif
54 #ifndef HAVE_RL_USERNAME_COMPLETION_FUNCTION
55 # define rl_username_completion_function username_completion_function
56 #endif
57 #ifndef HAVE_RL_COMPLETION_MATCHES
58 # define rl_completion_matches completion_matches
59 #endif
60
61 static int (*history_get_offset_func)(int);
62
63 static char **readline_attempted_completion_function(const char *text,
64                                                      int start, int end);
65
66 #define OutputStringValue(str) do {\
67     SafeStringValue(str);\
68     str = rb_str_conv_enc(str, rb_enc_get(str), rb_locale_encoding());\
69 } while (0)\
70
71 #ifdef HAVE_RL_EVENT_HOOK
72 #define BUSY_WAIT 0
73
74 /*
75  * Document-class: Readline
76  *
77  * The Readline module provides interface for GNU Readline.
78  * This module defines a number of methods to facilitate completion
79  * and accesses input history from the Ruby interpreter.
80  * This module supported Edit Line(libedit) too.
81  * libedit is compatible with GNU Readline.
82  *
83  * GNU Readline:: http://www.gnu.org/directory/readline.html
84  * libedit::      http://www.thrysoee.dk/editline/
85  *
86  * Reads one inputted line with line edit by Readline.readline method. 
87  * At this time, the facilitatation completion and the key
88  * bind like Emacs can be operated like GNU Readline.
89  *
90  *   require "readline"
91  *   while buf = Readline.readline("> ", true)
92  *     p buf
93  *   end
94  *
95  * The content that the user input can be recorded to the history.
96  * The history can be accessed by Readline::HISTORY constant.
97  *
98  *   require "readline"
99  *   while buf = Readline.readline("> ", true)
100  *     p Readline::HISTORY.to_a
101  *     print("-> ", buf, "\n")
102  *   end
103  *
104  * Most of methods raise SecurityError exception if $SAFE is 4.
105  *
106  * Documented by TAKAO Kouji <kouji at takao7 dot net>.
107  */
108
109 static int readline_event(void);
110 static int
111 readline_event(void)
112 {
113 #if BUSY_WAIT
114     rb_thread_schedule();
115 #else
116     fd_set rset;
117
118     FD_ZERO(&rset);
119     FD_SET(fileno(rl_instream), &rset);
120     rb_thread_select(fileno(rl_instream) + 1, &rset, NULL, NULL, NULL);
121     return 0;
122 #endif
123 }
124 #endif
125
126 /*
127  * call-seq:
128  *   Readline.readline(prompt = "", add_hist = false) -> string or nil
129  *
130  * Shows the +prompt+ and reads the inputted line with line editing.
131  * The inputted line is added to the history if +add_hist+ is true.
132  *
133  * Returns nil when the inputted line is empty and user inputs EOF
134  * (Presses ^D on UNIX).
135  *
136  * Raises IOError exception if below conditions are satisfied.
137  * 1. stdin is not tty.
138  * 2. stdin was closed. (errno is EBADF after called isatty(2).)
139  *
140  * This method supports thread. Switchs the thread context when waits
141  * inputting line.
142  *
143  * Supports line edit when inputs line. Provides VI and Emacs editing mode.
144  * Default is Emacs editing mode.
145  *
146  * NOTE: Terminates ruby interpreter and does not return the terminal
147  * status after user pressed '^C' when wait inputting line.
148  * Give 3 examples that avoid it.
149  *
150  * * Catches the Interrupt exception by pressed ^C after returns
151  *   terminal status:
152  * 
153  *     require "readline"
154  *     
155  *     stty_save = `stty -g`.chomp
156  *     begin
157  *       while buf = Readline.readline
158  *           p buf
159  *           end
160  *         rescue Interrupt
161  *           system("stty", stty_save)
162  *           exit
163  *         end
164  *       end
165  *     end
166  * 
167  * * Catches the INT signal by pressed ^C after returns terminal
168  *   status:
169  * 
170  *     require "readline"
171  *     
172  *     stty_save = `stty -g`.chomp
173  *     trap("INT") { system "stty", stty_save; exit }
174  *   
175  *     while buf = Readline.readline
176  *       p buf
177  *     end
178  *
179  * * Ignores pressing ^C:
180  * 
181  *     require "readline"
182  *     
183  *     trap("INT", "SIG_IGN")
184  *     
185  *     while buf = Readline.readline
186  *       p buf
187  *     end
188  *
189  * Can make as follows with Readline::HISTORY constant.
190  * It does not record to the history if the inputted line is empty or
191  * the same it as last one.
192  *
193  *   require "readline"
194  *     
195  *   while buf = Readline.readline("> ", true)
196  *     # p Readline::HISTORY.to_a
197  *     Readline::HISTORY.pop if /^\s*$/ =~ buf
198  *  
199  *     begin
200  *       if Readline::HISTORY[Readline::HISTORY.length-2] == buf
201  *         Readline::HISTORY.pop 
202  *       end
203  *     rescue IndexError
204  *     end
205  *  
206  *     # p Readline::HISTORY.to_a
207  *     print "-> ", buf, "\n"
208  *   end
209  *
210  * Raises SecurityError exception if $SAFE is 4.
211  */
212 static VALUE
213 readline_readline(int argc, VALUE *argv, VALUE self)
214 {
215     VALUE tmp, add_hist, result;
216     char *prompt = NULL;
217     char *buff;
218     int status;
219
220     rb_secure(4);
221     if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) {
222         OutputStringValue(tmp);
223         prompt = RSTRING_PTR(tmp);
224     }
225
226     if (!isatty(0) && errno == EBADF) rb_raise(rb_eIOError, "closed stdin");
227
228     buff = (char*)rb_protect((VALUE(*)_((VALUE)))readline, (VALUE)prompt,
229                               &status);
230     if (status) {
231 #if defined HAVE_RL_CLEANUP_AFTER_SIGNAL
232         /* restore terminal mode and signal handler*/
233         rl_cleanup_after_signal();
234 #elif defined HAVE_RL_DEPREP_TERM_FUNCTION
235         /* restore terminal mode */
236         if (rl_deprep_term_function != NULL) /* NULL in libedit. [ruby-dev:29116] */
237             (*rl_deprep_term_function)();
238         else
239 #else
240         rl_deprep_terminal();
241 #endif
242         rb_jump_tag(status);
243     }
244
245     if (RTEST(add_hist) && buff) {
246         add_history(buff);
247     }
248     if (buff) {
249         result = rb_locale_str_new_cstr(buff);
250     }
251     else
252         result = Qnil;
253     if (buff) free(buff);
254     return result;
255 }
256
257 /*
258  * call-seq:
259  *   Readline.input = input
260  *
261  * Specifies a File object +input+ that is input stream for
262  * Readline.readline method.
263  *
264  * Raises SecurityError exception if $SAFE is 4.
265  */
266 static VALUE
267 readline_s_set_input(VALUE self, VALUE input)
268 {
269     rb_io_t *ifp;
270
271     rb_secure(4);
272     Check_Type(input, T_FILE);
273     GetOpenFile(input, ifp);
274     rl_instream = rb_io_stdio_file(ifp);
275     return input;
276 }
277
278 /*
279  * call-seq:
280  *   Readline.output = output
281  *
282  * Specifies a File object +output+ that is output stream for
283  * Readline.readline method.
284  *
285  * Raises SecurityError exception if $SAFE is 4.
286  */
287 static VALUE
288 readline_s_set_output(VALUE self, VALUE output)
289 {
290     rb_io_t *ofp;
291
292     rb_secure(4);
293     Check_Type(output, T_FILE);
294     GetOpenFile(output, ofp);
295     rl_outstream = rb_io_stdio_file(ofp);
296     return output;
297 }
298
299 /*
300  * call-seq:
301  *   Readline.completion_proc = proc
302  *
303  * Specifies a Proc object +proc+ to determine completion behavior. It
304  * should take input-string, and return an array of completion
305  * candidates.
306  *
307  * Raises ArgumentError exception if +proc+ does not respond to call method.
308  *
309  * Raises SecurityError exception if $SAFE is 4.
310  */
311 static VALUE
312 readline_s_set_completion_proc(VALUE self, VALUE proc)
313 {
314     rb_secure(4);
315     if (!rb_respond_to(proc, rb_intern("call")))
316         rb_raise(rb_eArgError, "argument must respond to `call'");
317     return rb_ivar_set(mReadline, completion_proc, proc);
318 }
319
320 /*
321  * call-seq:
322  *   Readline.completion_proc -> proc
323  *
324  * Returns the completion Proc object.
325  *
326  * Raises SecurityError exception if $SAFE is 4.
327  */
328 static VALUE
329 readline_s_get_completion_proc(VALUE self)
330 {
331     rb_secure(4);
332     return rb_attr_get(mReadline, completion_proc);
333 }
334
335 /*
336  * call-seq:
337  *   Readline.completion_case_fold = bool
338  *
339  * Sets whether or not to ignore case on completion.
340  *
341  * Raises SecurityError exception if $SAFE is 4.
342  */
343 static VALUE
344 readline_s_set_completion_case_fold(VALUE self, VALUE val)
345 {
346     rb_secure(4);
347     return rb_ivar_set(mReadline, completion_case_fold, val);
348 }
349
350 /*
351  * call-seq:
352  *   Readline.completion_case_fold -> bool
353  *
354  * Returns true if completion ignores case. If no, returns false.
355  *
356  * NOTE: Returns the same object that is specified by
357  * Readline.completion_case_fold= method.
358  *
359  *   require "readline"
360  *   
361  *   Readline.completion_case_fold = "This is a String."
362  *   p Readline.completion_case_fold # => "This is a String."
363  *
364  * Raises SecurityError exception if $SAFE is 4.
365  */
366 static VALUE
367 readline_s_get_completion_case_fold(VALUE self)
368 {
369     rb_secure(4);
370     return rb_attr_get(mReadline, completion_case_fold);
371 }
372
373 static char **
374 readline_attempted_completion_function(const char *text, int start, int end)
375 {
376     VALUE proc, ary, temp;
377     char **result;
378     int case_fold;
379     int i, matches;
380
381     proc = rb_attr_get(mReadline, completion_proc);
382     if (NIL_P(proc))
383         return NULL;
384 #ifdef HAVE_RL_ATTEMPTED_COMPLETION_OVER
385     rl_attempted_completion_over = 1;
386 #endif
387     case_fold = RTEST(rb_attr_get(mReadline, completion_case_fold));
388     ary = rb_funcall(proc, rb_intern("call"), 1, rb_locale_str_new_cstr(text));
389     if (TYPE(ary) != T_ARRAY)
390         ary = rb_Array(ary);
391     matches = RARRAY_LEN(ary);
392     if (matches == 0)
393         return NULL;
394     result = ALLOC_N(char *, matches + 2);
395     for (i = 0; i < matches; i++) {
396         temp = rb_obj_as_string(RARRAY_PTR(ary)[i]);
397         result[i + 1] = ALLOC_N(char, RSTRING_LEN(temp) + 1);
398         strcpy(result[i + 1], RSTRING_PTR(temp));
399     }
400     result[matches + 1] = NULL;
401
402     if (matches == 1) {
403         result[0] = strdup(result[1]);
404     }
405     else {
406         register int i = 1;
407         int low = 100000;
408
409         while (i < matches) {
410             register int c1, c2, si;
411
412             if (case_fold) {
413                 for (si = 0;
414                      (c1 = TOLOWER(result[i][si])) &&
415                          (c2 = TOLOWER(result[i + 1][si]));
416                      si++)
417                     if (c1 != c2) break;
418             } else {
419                 for (si = 0;
420                      (c1 = result[i][si]) &&
421                          (c2 = result[i + 1][si]);
422                      si++)
423                     if (c1 != c2) break;
424             }
425
426             if (low > si) low = si;
427             i++;
428         }
429         result[0] = ALLOC_N(char, low + 1);
430         strncpy(result[0], result[1], low);
431         result[0][low] = '\0';
432     }
433
434     return result;
435 }
436
437 /*
438  * call-seq:
439  *   Readline.vi_editing_mode -> nil
440  *
441  * Specifies VI editing mode. See the manual of GNU Readline for
442  * details of VI editing mode.
443  *
444  * Raises NotImplementedError if the using readline library does not support.
445  *
446  * Raises SecurityError exception if $SAFE is 4.
447  */
448 static VALUE
449 readline_s_vi_editing_mode(VALUE self)
450 {
451 #ifdef HAVE_RL_VI_EDITING_MODE
452     rb_secure(4);
453     rl_vi_editing_mode(1,0);
454     return Qnil;
455 #else
456     rb_notimplement();
457     return Qnil; /* not reached */
458 #endif /* HAVE_RL_VI_EDITING_MODE */
459 }
460
461 /*
462  * call-seq:
463  *   Readline.vi_editing_mode? -> bool
464  *
465  * Returns true if vi mode is active. Returns false if not.
466  *
467  * Raises NotImplementedError if the using readline library does not support.
468  *
469  * Raises SecurityError exception if $SAFE is 4.
470  */
471 static VALUE
472 readline_s_vi_editing_mode_p(VALUE self)
473 {
474 #ifdef HAVE_RL_EDITING_MODE
475     rb_secure(4);
476     return rl_editing_mode == 0 ? Qtrue : Qfalse;
477 #else
478     rb_notimplement();
479     return Qnil; /* not reached */
480 #endif /* HAVE_RL_EDITING_MODE */
481 }
482
483 /*
484  * call-seq:
485  *   Readline.emacs_editing_mode -> nil
486  *
487  * Specifies Emacs editing mode. The default is this mode. See the
488  * manual of GNU Readline for details of Emacs editing mode.
489  *
490  * Raises NotImplementedError if the using readline library does not support.
491  *
492  * Raises SecurityError exception if $SAFE is 4.
493  */
494 static VALUE
495 readline_s_emacs_editing_mode(VALUE self)
496 {
497 #ifdef HAVE_RL_EMACS_EDITING_MODE
498     rb_secure(4);
499     rl_emacs_editing_mode(1,0);
500     return Qnil;
501 #else
502     rb_notimplement();
503     return Qnil; /* not reached */
504 #endif /* HAVE_RL_EMACS_EDITING_MODE */
505 }
506
507 /*
508  * call-seq:
509  *   Readline.emacs_editing_mode? -> bool
510  *
511  * Returns true if emacs mode is active. Returns false if not.
512  *
513  * Raises NotImplementedError if the using readline library does not support.
514  *
515  * Raises SecurityError exception if $SAFE is 4.
516  */
517 static VALUE
518 readline_s_emacs_editing_mode_p(VALUE self)
519 {
520 #ifdef  HAVE_RL_EDITING_MODE
521     rb_secure(4);
522     return rl_editing_mode == 1 ? Qtrue : Qfalse;
523 #else
524     rb_notimplement();
525     return Qnil; /* not reached */
526 #endif /* HAVE_RL_EDITING_MODE */
527 }
528
529 /*
530  * call-seq:
531  *   Readline.completion_append_character = char
532  *
533  * Specifies a character to be appended on completion.
534  * Nothing will be appended if an empty string ("") or nil is
535  * specified.
536  *
537  * For example:
538  *   require "readline"
539  *   
540  *   Readline.readline("> ", true)
541  *   Readline.completion_append_character = " "
542  *
543  * Result:
544  *   >
545  *   Input "/var/li".
546  *   
547  *   > /var/li
548  *   Press TAB key.
549  *   
550  *   > /var/lib
551  *   Completes "b" and appends " ". So, you can continuously input "/usr".
552  *   
553  *   > /var/lib /usr
554  *
555  * NOTE: Only one character can be specified. When "string" is
556  * specified, sets only "s" that is the first.
557  *
558  *   require "readline"
559  *
560  *   Readline.completion_append_character = "string"
561  *   p Readline.completion_append_character # => "s"
562  *
563  * Raises NotImplementedError if the using readline library does not support.
564  *
565  * Raises SecurityError exception if $SAFE is 4.
566  */
567 static VALUE
568 readline_s_set_completion_append_character(VALUE self, VALUE str)
569 {
570 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
571     rb_secure(4);
572     if (NIL_P(str)) {
573         rl_completion_append_character = '\0';
574     }
575     else {
576         OutputStringValue(str);
577         if (RSTRING_LEN(str) == 0) {
578             rl_completion_append_character = '\0';
579         } else {
580             rl_completion_append_character = RSTRING_PTR(str)[0];
581         }
582     }
583     return self;
584 #else
585     rb_notimplement();
586     return Qnil; /* not reached */
587 #endif /* HAVE_RL_COMPLETION_APPEND_CHARACTER */
588 }
589
590 /*
591  * call-seq:
592  *   Readline.completion_append_character -> char
593  *
594  * Returns a string containing a character to be appended on
595  * completion. The default is a space (" ").
596  *
597  * Raises NotImplementedError if the using readline library does not support.
598  *
599  * Raises SecurityError exception if $SAFE is 4.
600  */
601 static VALUE
602 readline_s_get_completion_append_character(VALUE self)
603 {
604 #ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
605     char buf[1];
606
607     rb_secure(4);
608     if (rl_completion_append_character == '\0')
609         return Qnil;
610
611     buf[0] = (char) rl_completion_append_character;
612     return rb_locale_str_new(buf, 1);
613 #else
614     rb_notimplement();
615     return Qnil; /* not reached */
616 #endif /* HAVE_RL_COMPLETION_APPEND_CHARACTER */
617 }
618
619 /*
620  * call-seq:
621  *   Readline.basic_word_break_characters = string
622  *
623  * Sets the basic list of characters that signal a break between words
624  * for the completer routine. The default is the characters which
625  * break words for completion in Bash: "\t\n\"\\'`@$><=;|&{(".
626  *
627  * Raises NotImplementedError if the using readline library does not support.
628  *
629  * Raises SecurityError exception if $SAFE is 4.
630  */
631 static VALUE
632 readline_s_set_basic_word_break_characters(VALUE self, VALUE str)
633 {
634 #ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS
635     static char *basic_word_break_characters = NULL;
636
637     rb_secure(4);
638     OutputStringValue(str);
639     if (basic_word_break_characters == NULL) {
640         basic_word_break_characters =
641             ALLOC_N(char, RSTRING_LEN(str) + 1);
642     }
643     else {
644         REALLOC_N(basic_word_break_characters, char, RSTRING_LEN(str) + 1);
645     }
646     strncpy(basic_word_break_characters,
647             RSTRING_PTR(str), RSTRING_LEN(str));
648     basic_word_break_characters[RSTRING_LEN(str)] = '\0';
649     rl_basic_word_break_characters = basic_word_break_characters;
650     return self;
651 #else
652     rb_notimplement();
653     return Qnil; /* not reached */
654 #endif /* HAVE_RL_BASIC_WORD_BREAK_CHARACTERS */
655 }
656
657 /*
658  * call-seq:
659  *   Readline.basic_word_break_characters -> string
660  *
661  * Gets the basic list of characters that signal a break between words
662  * for the completer routine.
663  * 
664  * Raises NotImplementedError if the using readline library does not support.
665  *
666  * Raises SecurityError exception if $SAFE is 4.
667  */
668 static VALUE
669 readline_s_get_basic_word_break_characters(VALUE self, VALUE str)
670 {
671 #ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS
672     rb_secure(4);
673     if (rl_basic_word_break_characters == NULL)
674         return Qnil;
675     return rb_locale_str_new_cstr(rl_basic_word_break_characters);
676 #else
677     rb_notimplement();
678     return Qnil; /* not reached */
679 #endif /* HAVE_RL_BASIC_WORD_BREAK_CHARACTERS */
680 }
681
682 /*
683  * call-seq:
684  *   Readline.completer_word_break_characters = string
685  *
686  * Sets the basic list of characters that signal a break between words
687  * for rl_complete_internal(). The default is the value of
688  * Readline.basic_word_break_characters.
689  *
690  * Raises NotImplementedError if the using readline library does not support.
691  *
692  * Raises SecurityError exception if $SAFE is 4.
693  */
694 static VALUE
695 readline_s_set_completer_word_break_characters(VALUE self, VALUE str)
696 {
697 #ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS
698     static char *completer_word_break_characters = NULL;
699
700     rb_secure(4);
701     OutputStringValue(str);
702     if (completer_word_break_characters == NULL) {
703         completer_word_break_characters =
704             ALLOC_N(char, RSTRING_LEN(str) + 1);
705     }
706     else {
707         REALLOC_N(completer_word_break_characters, char, RSTRING_LEN(str) + 1);
708     }
709     strncpy(completer_word_break_characters,
710             RSTRING_PTR(str), RSTRING_LEN(str));
711     completer_word_break_characters[RSTRING_LEN(str)] = '\0';
712     rl_completer_word_break_characters = completer_word_break_characters;
713     return self;
714 #else
715     rb_notimplement();
716     return Qnil; /* not reached */
717 #endif /* HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS */
718 }
719
720 /*
721  * call-seq:
722  *   Readline.completer_word_break_characters -> string
723  *
724  * Gets the basic list of characters that signal a break between words
725  * for rl_complete_internal().
726  * 
727  * Raises NotImplementedError if the using readline library does not support.
728  *
729  * Raises SecurityError exception if $SAFE is 4.
730  */
731 static VALUE
732 readline_s_get_completer_word_break_characters(VALUE self, VALUE str)
733 {
734 #ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS
735     rb_secure(4);
736     if (rl_completer_word_break_characters == NULL)
737         return Qnil;
738     return rb_locale_str_new_cstr(rl_completer_word_break_characters);
739 #else
740     rb_notimplement();
741     return Qnil; /* not reached */
742 #endif /* HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS */
743 }
744
745 /*
746  * call-seq:
747  *   Readline.basic_quote_characters = string
748  *
749  * Sets a list of quote characters which can cause a word break.
750  *
751  * Raises NotImplementedError if the using readline library does not support.
752  *
753  * Raises SecurityError exception if $SAFE is 4.
754  */
755 static VALUE
756 readline_s_set_basic_quote_characters(VALUE self, VALUE str)
757 {
758 #ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS
759     static char *basic_quote_characters = NULL;
760
761     rb_secure(4);
762     OutputStringValue(str);
763     if (basic_quote_characters == NULL) {
764         basic_quote_characters =
765             ALLOC_N(char, RSTRING_LEN(str) + 1);
766     }
767     else {
768         REALLOC_N(basic_quote_characters, char, RSTRING_LEN(str) + 1);
769     }
770     strncpy(basic_quote_characters,
771             RSTRING_PTR(str), RSTRING_LEN(str));
772     basic_quote_characters[RSTRING_LEN(str)] = '\0';
773     rl_basic_quote_characters = basic_quote_characters;
774
775     return self;
776 #else
777     rb_notimplement();
778     return Qnil; /* not reached */
779 #endif /* HAVE_RL_BASIC_QUOTE_CHARACTERS */
780 }
781
782 /*
783  * call-seq:
784  *   Readline.basic_quote_characters -> string
785  *
786  * Gets a list of quote characters which can cause a word break.
787  *
788  * Raises NotImplementedError if the using readline library does not support.
789  *
790  * Raises SecurityError exception if $SAFE is 4.
791  */
792 static VALUE
793 readline_s_get_basic_quote_characters(VALUE self, VALUE str)
794 {
795 #ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS
796     rb_secure(4);
797     if (rl_basic_quote_characters == NULL)
798         return Qnil;
799     return rb_locale_str_new_cstr(rl_basic_quote_characters);
800 #else
801     rb_notimplement();
802     return Qnil; /* not reached */
803 #endif /* HAVE_RL_BASIC_QUOTE_CHARACTERS */
804 }
805
806 /*
807  * call-seq:
808  *   Readline.completer_quote_characters = string
809  *
810  * Sets a list of characters which can be used to quote a substring of
811  * the line. Completion occurs on the entire substring, and within
812  * the substring Readline.completer_word_break_characters are treated
813  * as any other character, unless they also appear within this list.
814  *
815  * Raises NotImplementedError if the using readline library does not support.
816  *
817  * Raises SecurityError exception if $SAFE is 4.
818  */
819 static VALUE
820 readline_s_set_completer_quote_characters(VALUE self, VALUE str)
821 {
822 #ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS
823     static char *completer_quote_characters = NULL;
824
825     rb_secure(4);
826     OutputStringValue(str);
827     if (completer_quote_characters == NULL) {
828         completer_quote_characters =
829             ALLOC_N(char, RSTRING_LEN(str) + 1);
830     }
831     else {
832         REALLOC_N(completer_quote_characters, char, RSTRING_LEN(str) + 1);
833     }
834     strncpy(completer_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str));
835     completer_quote_characters[RSTRING_LEN(str)] = '\0';
836     rl_completer_quote_characters = completer_quote_characters;
837
838     return self;
839 #else
840     rb_notimplement();
841     return Qnil; /* not reached */
842 #endif /* HAVE_RL_COMPLETER_QUOTE_CHARACTERS */
843 }
844
845 /*
846  * call-seq:
847  *   Readline.completer_quote_characters -> string
848  *
849  * Gets a list of characters which can be used to quote a substring of
850  * the line.
851  *
852  * Raises NotImplementedError if the using readline library does not support.
853  *
854  * Raises SecurityError exception if $SAFE is 4.
855  */
856 static VALUE
857 readline_s_get_completer_quote_characters(VALUE self, VALUE str)
858 {
859 #ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS
860     rb_secure(4);
861     if (rl_completer_quote_characters == NULL)
862         return Qnil;
863     return rb_locale_str_new_cstr(rl_completer_quote_characters);
864 #else
865     rb_notimplement();
866     return Qnil; /* not reached */
867 #endif /* HAVE_RL_COMPLETER_QUOTE_CHARACTERS */
868 }
869
870 /*
871  * call-seq:
872  *   Readline.filename_quote_characters = string
873  *
874  * Sets a list of characters that cause a filename to be quoted by the completer
875  * when they appear in a completed filename. The default is nil.
876  *
877  * Raises NotImplementedError if the using readline library does not support.
878  *
879  * Raises SecurityError exception if $SAFE is 4.
880  */
881 static VALUE
882 readline_s_set_filename_quote_characters(VALUE self, VALUE str)
883 {
884 #ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
885     static char *filename_quote_characters = NULL;
886
887     rb_secure(4);
888     OutputStringValue(str);
889     if (filename_quote_characters == NULL) {
890         filename_quote_characters =
891             ALLOC_N(char, RSTRING_LEN(str) + 1);
892     }
893     else {
894         REALLOC_N(filename_quote_characters, char, RSTRING_LEN(str) + 1);
895     }
896     strncpy(filename_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str));
897     filename_quote_characters[RSTRING_LEN(str)] = '\0';
898     rl_filename_quote_characters = filename_quote_characters;
899
900     return self;
901 #else
902     rb_notimplement();
903     return Qnil; /* not reached */
904 #endif /* HAVE_RL_FILENAME_QUOTE_CHARACTERS */
905 }
906
907 /*
908  * call-seq:
909  *   Readline.filename_quote_characters -> string
910  *
911  * Gets a list of characters that cause a filename to be quoted by the completer
912  * when they appear in a completed filename.
913  *
914  * Raises NotImplementedError if the using readline library does not support.
915  *
916  * Raises SecurityError exception if $SAFE is 4.
917  */
918 static VALUE
919 readline_s_get_filename_quote_characters(VALUE self, VALUE str)
920 {
921 #ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS
922     rb_secure(4);
923     if (rl_filename_quote_characters == NULL)
924         return Qnil;
925     return rb_locale_str_new_cstr(rl_filename_quote_characters);
926 #else
927     rb_notimplement();
928     return Qnil; /* not reached */
929 #endif /* HAVE_RL_FILENAME_QUOTE_CHARACTERS */
930 }
931
932 static VALUE
933 hist_to_s(VALUE self)
934 {
935     return rb_str_new_cstr("HISTORY");
936 }
937
938 static int
939 history_get_offset_history_base(int offset)
940 {
941     return history_base + offset;
942 }
943
944 static int
945 history_get_offset_0(int offset)
946 {
947     return offset;
948 }
949
950 static VALUE
951 hist_get(VALUE self, VALUE index)
952 {
953     HIST_ENTRY *entry = NULL;
954     int i;
955
956     rb_secure(4);
957     i = NUM2INT(index);
958     if (i < 0) {
959         i += history_length;
960     }
961     if (i >= 0) {
962         entry = history_get(history_get_offset_func(i));
963     }
964     if (entry == NULL) {
965         rb_raise(rb_eIndexError, "invalid index");
966     }
967     return rb_locale_str_new_cstr(entry->line);
968 }
969
970 static VALUE
971 hist_set(VALUE self, VALUE index, VALUE str)
972 {
973 #ifdef HAVE_REPLACE_HISTORY_ENTRY
974     HIST_ENTRY *entry = NULL;
975     int i;
976
977     rb_secure(4);
978     i = NUM2INT(index);
979     OutputStringValue(str);
980     if (i < 0) {
981         i += history_length;
982     }
983     if (i >= 0) {
984         entry = replace_history_entry(i, RSTRING_PTR(str), NULL);
985     }
986     if (entry == NULL) {
987         rb_raise(rb_eIndexError, "invalid index");
988     }
989     return str;
990 #else
991     rb_notimplement();
992     return Qnil; /* not reached */
993 #endif
994 }
995
996 static VALUE
997 hist_push(VALUE self, VALUE str)
998 {
999     rb_secure(4);
1000     OutputStringValue(str);
1001     add_history(RSTRING_PTR(str));
1002     return self;
1003 }
1004
1005 static VALUE
1006 hist_push_method(int argc, VALUE *argv, VALUE self)
1007 {
1008     VALUE str;
1009     
1010     rb_secure(4);
1011     while (argc--) {
1012         str = *argv++;
1013         OutputStringValue(str);
1014         add_history(RSTRING_PTR(str));
1015     }
1016     return self;
1017 }
1018
1019 static VALUE
1020 rb_remove_history(int index)
1021 {
1022 #ifdef HAVE_REMOVE_HISTORY
1023     HIST_ENTRY *entry;
1024     VALUE val;
1025
1026     rb_secure(4);
1027     entry = remove_history(index);
1028     if (entry) {
1029         val = rb_locale_str_new_cstr(entry->line);
1030         free((void *) entry->line);
1031         free(entry);
1032         return val;
1033     }
1034     return Qnil;
1035 #else
1036     rb_notimplement();
1037     return Qnil; /* not reached */
1038 #endif
1039 }
1040
1041 static VALUE
1042 hist_pop(VALUE self)
1043 {
1044     rb_secure(4);
1045     if (history_length > 0) {
1046         return rb_remove_history(history_length - 1);
1047     } else {
1048         return Qnil;
1049     }
1050 }
1051
1052 static VALUE
1053 hist_shift(VALUE self)
1054 {
1055     rb_secure(4);
1056     if (history_length > 0) {
1057         return rb_remove_history(0);
1058     } else {
1059         return Qnil;
1060     }
1061 }
1062
1063 static VALUE
1064 hist_each(VALUE self)
1065 {
1066     HIST_ENTRY *entry;
1067     int i;
1068
1069     RETURN_ENUMERATOR(self, 0, 0);
1070
1071     rb_secure(4);
1072     for (i = 0; i < history_length; i++) {
1073         entry = history_get(history_get_offset_func(i));
1074         if (entry == NULL)
1075             break;
1076         rb_yield(rb_locale_str_new_cstr(entry->line));
1077     }
1078     return self;
1079 }
1080
1081 static VALUE
1082 hist_length(VALUE self)
1083 {
1084     rb_secure(4);
1085     return INT2NUM(history_length);
1086 }
1087
1088 static VALUE
1089 hist_empty_p(VALUE self)
1090 {
1091     rb_secure(4);
1092     return history_length == 0 ? Qtrue : Qfalse;
1093 }
1094
1095 static VALUE
1096 hist_delete_at(VALUE self, VALUE index)
1097 {
1098     int i;
1099
1100     rb_secure(4);
1101     i = NUM2INT(index);
1102     if (i < 0)
1103         i += history_length;
1104     if (i < 0 || i > history_length - 1) {
1105         rb_raise(rb_eIndexError, "invalid index");
1106     }
1107     return rb_remove_history(i);
1108 }
1109
1110 static VALUE
1111 hist_clear(VALUE self)
1112 {
1113 #ifdef HAVE_CLEAR_HISTORY
1114     rb_secure(4);
1115     clear_history();
1116     return self;
1117 #else
1118     rb_notimplement();
1119     return Qnil; /* not reached */
1120 #endif
1121 }
1122
1123 static VALUE
1124 filename_completion_proc_call(VALUE self, VALUE str)
1125 {
1126     VALUE result;
1127     char **matches;
1128     int i;
1129
1130     matches = rl_completion_matches(StringValuePtr(str),
1131                                     rl_filename_completion_function);
1132     if (matches) {
1133         result = rb_ary_new();
1134         for (i = 0; matches[i]; i++) {
1135             rb_ary_push(result, rb_locale_str_new_cstr(matches[i]));
1136             free(matches[i]);
1137         }
1138         free(matches);
1139         if (RARRAY_LEN(result) >= 2)
1140             rb_ary_shift(result);
1141     }
1142     else {
1143         result = Qnil;
1144     }
1145     return result;
1146 }
1147
1148 static VALUE
1149 username_completion_proc_call(VALUE self, VALUE str)
1150 {
1151     VALUE result;
1152     char **matches;
1153     int i;
1154
1155     matches = rl_completion_matches(StringValuePtr(str),
1156                                     rl_username_completion_function);
1157     if (matches) {
1158         result = rb_ary_new();
1159         for (i = 0; matches[i]; i++) {
1160             rb_ary_push(result, rb_locale_str_new_cstr(matches[i]));
1161             free(matches[i]);
1162         }
1163         free(matches);
1164         if (RARRAY_LEN(result) >= 2)
1165             rb_ary_shift(result);
1166     }
1167     else {
1168         result = Qnil;
1169     }
1170     return result;
1171 }
1172
1173 void
1174 Init_readline()
1175 {
1176     VALUE history, fcomp, ucomp, version;
1177
1178     /* Allow conditional parsing of the ~/.inputrc file. */
1179     rl_readline_name = "Ruby";
1180
1181     using_history();
1182
1183     completion_proc = rb_intern(COMPLETION_PROC);
1184     completion_case_fold = rb_intern(COMPLETION_CASE_FOLD);
1185
1186     mReadline = rb_define_module("Readline");
1187     rb_define_module_function(mReadline, "readline",
1188                               readline_readline, -1);
1189     rb_define_singleton_method(mReadline, "input=",
1190                                readline_s_set_input, 1);
1191     rb_define_singleton_method(mReadline, "output=",
1192                                readline_s_set_output, 1);
1193     rb_define_singleton_method(mReadline, "completion_proc=",
1194                                readline_s_set_completion_proc, 1);
1195     rb_define_singleton_method(mReadline, "completion_proc",
1196                                readline_s_get_completion_proc, 0);
1197     rb_define_singleton_method(mReadline, "completion_case_fold=",
1198                                readline_s_set_completion_case_fold, 1);
1199     rb_define_singleton_method(mReadline, "completion_case_fold",
1200                                readline_s_get_completion_case_fold, 0);
1201     rb_define_singleton_method(mReadline, "vi_editing_mode",
1202                                readline_s_vi_editing_mode, 0);
1203     rb_define_singleton_method(mReadline, "vi_editing_mode?",
1204                                readline_s_vi_editing_mode_p, 0);
1205     rb_define_singleton_method(mReadline, "emacs_editing_mode",
1206                                readline_s_emacs_editing_mode, 0);
1207     rb_define_singleton_method(mReadline, "emacs_editing_mode?",
1208                                readline_s_emacs_editing_mode_p, 0);
1209     rb_define_singleton_method(mReadline, "completion_append_character=",
1210                                readline_s_set_completion_append_character, 1);
1211     rb_define_singleton_method(mReadline, "completion_append_character",
1212                                readline_s_get_completion_append_character, 0);
1213     rb_define_singleton_method(mReadline, "basic_word_break_characters=",
1214                                readline_s_set_basic_word_break_characters, 1);
1215     rb_define_singleton_method(mReadline, "basic_word_break_characters",
1216                                readline_s_get_basic_word_break_characters, 0);
1217     rb_define_singleton_method(mReadline, "completer_word_break_characters=",
1218                                readline_s_set_completer_word_break_characters, 1);
1219     rb_define_singleton_method(mReadline, "completer_word_break_characters",
1220                                readline_s_get_completer_word_break_characters, 0);
1221     rb_define_singleton_method(mReadline, "basic_quote_characters=",
1222                                readline_s_set_basic_quote_characters, 1);
1223     rb_define_singleton_method(mReadline, "basic_quote_characters",
1224                                readline_s_get_basic_quote_characters, 0);
1225     rb_define_singleton_method(mReadline, "completer_quote_characters=",
1226                                readline_s_set_completer_quote_characters, 1);
1227     rb_define_singleton_method(mReadline, "completer_quote_characters",
1228                                readline_s_get_completer_quote_characters, 0);
1229     rb_define_singleton_method(mReadline, "filename_quote_characters=",
1230                                readline_s_set_filename_quote_characters, 1);
1231     rb_define_singleton_method(mReadline, "filename_quote_characters",
1232                                readline_s_get_filename_quote_characters, 0);
1233
1234     history = rb_obj_alloc(rb_cObject);
1235     rb_extend_object(history, rb_mEnumerable);
1236     rb_define_singleton_method(history,"to_s", hist_to_s, 0);
1237     rb_define_singleton_method(history,"[]", hist_get, 1);
1238     rb_define_singleton_method(history,"[]=", hist_set, 2);
1239     rb_define_singleton_method(history,"<<", hist_push, 1);
1240     rb_define_singleton_method(history,"push", hist_push_method, -1);
1241     rb_define_singleton_method(history,"pop", hist_pop, 0);
1242     rb_define_singleton_method(history,"shift", hist_shift, 0);
1243     rb_define_singleton_method(history,"each", hist_each, 0);
1244     rb_define_singleton_method(history,"length", hist_length, 0);
1245     rb_define_singleton_method(history,"size", hist_length, 0);
1246     rb_define_singleton_method(history,"empty?", hist_empty_p, 0);
1247     rb_define_singleton_method(history,"delete_at", hist_delete_at, 1);
1248     rb_define_singleton_method(history,"clear", hist_clear, 0);
1249
1250     /*
1251      * The history buffer. It extends Enumerable module, so it behaves
1252      * just like an array.
1253      * For example, gets the fifth content that the user input by
1254      * HISTORY[4].
1255      */
1256     rb_define_const(mReadline, "HISTORY", history);
1257
1258     fcomp = rb_obj_alloc(rb_cObject);
1259     rb_define_singleton_method(fcomp, "call",
1260                                filename_completion_proc_call, 1);
1261     /*
1262      * The Object with the call method that is a completion for filename.
1263      * This is sets by Readline.completion_proc= method.
1264      */
1265     rb_define_const(mReadline, "FILENAME_COMPLETION_PROC", fcomp);
1266
1267     ucomp = rb_obj_alloc(rb_cObject);
1268     rb_define_singleton_method(ucomp, "call",
1269                                username_completion_proc_call, 1);
1270     /*
1271      * The Object with the call method that is a completion for usernames.
1272      * This is sets by Readline.completion_proc= method.
1273      */
1274     rb_define_const(mReadline, "USERNAME_COMPLETION_PROC", ucomp);
1275     history_get_offset_func = history_get_offset_history_base;
1276 #if defined HAVE_RL_LIBRARY_VERSION
1277     version = rb_str_new_cstr(rl_library_version);
1278 #if defined HAVE_CLEAR_HISTORY || defined HAVE_REMOVE_HISTORY
1279     if (strncmp(rl_library_version, EDIT_LINE_LIBRARY_VERSION, 
1280                 strlen(EDIT_LINE_LIBRARY_VERSION)) == 0) {
1281         add_history("1");
1282         if (history_get(history_get_offset_func(0)) == NULL) {
1283             history_get_offset_func = history_get_offset_0;
1284         }
1285 #if !defined HAVE_CLEAR_HISTORY
1286         clear_history();
1287 #else
1288         {
1289             HIST_ENTRY *entry = remove_history(0);
1290             free(entry->line);
1291             free(entry);
1292         }
1293 #endif
1294     }
1295 #endif
1296 #else
1297     version = rb_str_new_cstr("2.0 or prior version");
1298 #endif
1299     /* Version string of GNU Readline or libedit. */
1300     rb_define_const(mReadline, "VERSION", version);
1301
1302     rl_attempted_completion_function = readline_attempted_completion_function;
1303 #ifdef HAVE_RL_EVENT_HOOK
1304     rl_event_hook = readline_event;
1305 #endif
1306 #ifdef HAVE_RL_CLEAR_SIGNALS
1307     rl_clear_signals();
1308 #endif
1309 }