diff options
Diffstat (limited to 'trunk/ext/readline/readline.c')
-rw-r--r-- | trunk/ext/readline/readline.c | 1299 |
1 files changed, 0 insertions, 1299 deletions
diff --git a/trunk/ext/readline/readline.c b/trunk/ext/readline/readline.c deleted file mode 100644 index 41914dca01..0000000000 --- a/trunk/ext/readline/readline.c +++ /dev/null @@ -1,1299 +0,0 @@ -/************************************************ - - readline.c - GNU Readline module - - $Author$ - created at: Wed Jan 20 13:59:32 JST 1999 - - Copyright (C) 1997-2008 Shugo Maeda - Copyright (C) 2008 TAKAO Kouji - - $Id$ - - Contact: - - TAKAO Kouji <kouji at takao7 dot net> (current maintainer) - -************************************************/ - -#ifdef RUBY_EXTCONF_H -#include RUBY_EXTCONF_H -#endif - -#include "ruby/config.h" -#include <errno.h> -#include <stdio.h> -#include <string.h> -#ifdef HAVE_READLINE_READLINE_H -#include <readline/readline.h> -#endif -#ifdef HAVE_READLINE_HISTORY_H -#include <readline/history.h> -#endif -#ifdef HAVE_EDITLINE_READLINE_H -#include <editline/readline.h> -#endif - -#include "ruby/ruby.h" -#include "ruby/io.h" -#include "ruby/signal.h" - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -static VALUE mReadline; - -#define EDIT_LINE_LIBRARY_VERSION "EditLine wrapper" - -#define COMPLETION_PROC "completion_proc" -#define COMPLETION_CASE_FOLD "completion_case_fold" -static ID completion_proc, completion_case_fold; - -#ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION -# define rl_filename_completion_function filename_completion_function -#endif -#ifndef HAVE_RL_USERNAME_COMPLETION_FUNCTION -# define rl_username_completion_function username_completion_function -#endif -#ifndef HAVE_RL_COMPLETION_MATCHES -# define rl_completion_matches completion_matches -#endif - -static int (*history_get_offset_func)(int); - -static char **readline_attempted_completion_function(const char *text, - int start, int end); - -#ifdef HAVE_RL_EVENT_HOOK -#define BUSY_WAIT 0 - -/* - * Document-class: Readline - * - * The Readline module provides interface for GNU Readline. - * This module defines a number of methods to facilitate completion - * and accesses input history from the Ruby interpreter. - * This module supported Edit Line(libedit) too. - * libedit is compatible with GNU Readline. - * - * GNU Readline:: http://www.gnu.org/directory/readline.html - * libedit:: http://www.thrysoee.dk/editline/ - * - * Reads one inputted line with line edit by Readline.readline method. - * At this time, the facilitatation completion and the key - * bind like Emacs can be operated like GNU Readline. - * - * require "readline" - * while buf = Readline.readline("> ", true) - * p buf - * end - * - * The content that the user input can be recorded to the history. - * The history can be accessed by Readline::HISTORY constant. - * - * require "readline" - * while buf = Readline.readline("> ", true) - * p Readline::HISTORY.to_a - * print("-> ", buf, "\n") - * end - * - * Most of methods raise SecurityError exception if $SAFE is 4. - * - * Documented by TAKAO Kouji <kouji at takao7 dot net>. - */ - -static int readline_event(void); -static int -readline_event(void) -{ -#if BUSY_WAIT - rb_thread_schedule(); -#else - fd_set rset; - - FD_ZERO(&rset); - FD_SET(fileno(rl_instream), &rset); - rb_thread_select(fileno(rl_instream) + 1, &rset, NULL, NULL, NULL); - return 0; -#endif -} -#endif - -/* - * call-seq: - * Readline.readline(prompt = "", add_hist = false) -> string or nil - * - * Shows the +prompt+ and reads the inputted line with line editing. - * The inputted line is added to the history if +add_hist+ is true. - * - * Returns nil when the inputted line is empty and user inputs EOF - * (Presses ^D on UNIX). - * - * Raises IOError exception if below conditions are satisfied. - * 1. stdin is not tty. - * 2. stdin was closed. (errno is EBADF after called isatty(2).) - * - * This method supports thread. Switchs the thread context when waits - * inputting line. - * - * Supports line edit when inputs line. Provides VI and Emacs editing mode. - * Default is Emacs editing mode. - * - * NOTE: Terminates ruby interpreter and does not return the terminal - * status after user pressed '^C' when wait inputting line. - * Give 3 examples that avoid it. - * - * * Catches the Interrupt exception by pressed ^C after returns - * terminal status: - * - * require "readline" - * - * stty_save = `stty -g`.chomp - * begin - * while buf = Readline.readline - * p buf - * end - * rescue Interrupt - * system("stty", stty_save) - * exit - * end - * end - * end - * - * * Catches the INT signal by pressed ^C after returns terminal - * status: - * - * require "readline" - * - * stty_save = `stty -g`.chomp - * trap("INT") { system "stty", stty_save; exit } - * - * while buf = Readline.readline - * p buf - * end - * - * * Ignores pressing ^C: - * - * require "readline" - * - * trap("INT", "SIG_IGN") - * - * while buf = Readline.readline - * p buf - * end - * - * Can make as follows with Readline::HISTORY constant. - * It does not record to the history if the inputted line is empty or - * the same it as last one. - * - * require "readline" - * - * while buf = Readline.readline("> ", true) - * # p Readline::HISTORY.to_a - * Readline::HISTORY.pop if /^\s*$/ =~ buf - * - * begin - * if Readline::HISTORY[Readline::HISTORY.length-2] == buf - * Readline::HISTORY.pop - * end - * rescue IndexError - * end - * - * # p Readline::HISTORY.to_a - * print "-> ", buf, "\n" - * end - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_readline(int argc, VALUE *argv, VALUE self) -{ - VALUE tmp, add_hist, result; - char *prompt = NULL; - char *buff; - int status; - - rb_secure(4); - if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) { - SafeStringValue(tmp); - prompt = RSTRING_PTR(tmp); - } - - if (!isatty(0) && errno == EBADF) rb_raise(rb_eIOError, "stdin closed"); - - buff = (char*)rb_protect((VALUE(*)_((VALUE)))readline, (VALUE)prompt, - &status); - if (status) { -#if defined HAVE_RL_CLEANUP_AFTER_SIGNAL - /* restore terminal mode and signal handler*/ - rl_cleanup_after_signal(); -#elif defined HAVE_RL_DEPREP_TERM_FUNCTION - /* restore terminal mode */ - if (rl_deprep_term_function != NULL) /* NULL in libedit. [ruby-dev:29116] */ - (*rl_deprep_term_function)(); - else -#else - rl_deprep_terminal(); -#endif - rb_jump_tag(status); - } - - if (RTEST(add_hist) && buff) { - add_history(buff); - } - if (buff) { - result = rb_tainted_str_new2(buff); - rb_enc_associate(result, rb_locale_encoding()); - } - else - result = Qnil; - if (buff) free(buff); - return result; -} - -/* - * call-seq: - * Readline.input = input - * - * Specifies a File object +input+ that is input stream for - * Readline.readline method. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_set_input(VALUE self, VALUE input) -{ - rb_io_t *ifp; - - rb_secure(4); - Check_Type(input, T_FILE); - GetOpenFile(input, ifp); - rl_instream = rb_io_stdio_file(ifp); - return input; -} - -/* - * call-seq: - * Readline.output = output - * - * Specifies a File object +output+ that is output stream for - * Readline.readline method. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_set_output(VALUE self, VALUE output) -{ - rb_io_t *ofp; - - rb_secure(4); - Check_Type(output, T_FILE); - GetOpenFile(output, ofp); - rl_outstream = rb_io_stdio_file(ofp); - return output; -} - -/* - * call-seq: - * Readline.completion_proc = proc - * - * Specifies a Proc object +proc+ to determine completion behavior. It - * should take input-string, and return an array of completion - * candidates. - * - * Raises ArgumentError exception if +proc+ does not respond to call method. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_set_completion_proc(VALUE self, VALUE proc) -{ - rb_secure(4); - if (!rb_respond_to(proc, rb_intern("call"))) - rb_raise(rb_eArgError, "argument must respond to `call'"); - return rb_ivar_set(mReadline, completion_proc, proc); -} - -/* - * call-seq: - * Readline.completion_proc -> proc - * - * Returns the completion Proc object. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_get_completion_proc(VALUE self) -{ - rb_secure(4); - return rb_attr_get(mReadline, completion_proc); -} - -/* - * call-seq: - * Readline.completion_case_fold = bool - * - * Sets whether or not to ignore case on completion. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_set_completion_case_fold(VALUE self, VALUE val) -{ - rb_secure(4); - return rb_ivar_set(mReadline, completion_case_fold, val); -} - -/* - * call-seq: - * Readline.completion_case_fold -> bool - * - * Returns true if completion ignores case. If no, returns false. - * - * NOTE: Returns the same object that is specified by - * Readline.completion_case_fold= method. - * - * require "readline" - * - * Readline.completion_case_fold = "This is a String." - * p Readline.completion_case_fold # => "This is a String." - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_get_completion_case_fold(VALUE self) -{ - rb_secure(4); - return rb_attr_get(mReadline, completion_case_fold); -} - -static char ** -readline_attempted_completion_function(const char *text, int start, int end) -{ - VALUE proc, ary, temp; - char **result; - int case_fold; - int i, matches; - - proc = rb_attr_get(mReadline, completion_proc); - if (NIL_P(proc)) - return NULL; -#ifdef HAVE_RL_ATTEMPTED_COMPLETION_OVER - rl_attempted_completion_over = 1; -#endif - case_fold = RTEST(rb_attr_get(mReadline, completion_case_fold)); - ary = rb_funcall(proc, rb_intern("call"), 1, rb_tainted_str_new2(text)); - if (TYPE(ary) != T_ARRAY) - ary = rb_Array(ary); - matches = RARRAY_LEN(ary); - if (matches == 0) - return NULL; - result = ALLOC_N(char *, matches + 2); - for (i = 0; i < matches; i++) { - temp = rb_obj_as_string(RARRAY_PTR(ary)[i]); - result[i + 1] = ALLOC_N(char, RSTRING_LEN(temp) + 1); - strcpy(result[i + 1], RSTRING_PTR(temp)); - } - result[matches + 1] = NULL; - - if (matches == 1) { - result[0] = strdup(result[1]); - } - else { - register int i = 1; - int low = 100000; - - while (i < matches) { - register int c1, c2, si; - - if (case_fold) { - for (si = 0; - (c1 = TOLOWER(result[i][si])) && - (c2 = TOLOWER(result[i + 1][si])); - si++) - if (c1 != c2) break; - } else { - for (si = 0; - (c1 = result[i][si]) && - (c2 = result[i + 1][si]); - si++) - if (c1 != c2) break; - } - - if (low > si) low = si; - i++; - } - result[0] = ALLOC_N(char, low + 1); - strncpy(result[0], result[1], low); - result[0][low] = '\0'; - } - - return result; -} - -/* - * call-seq: - * Readline.vi_editing_mode -> nil - * - * Specifies VI editing mode. See the manual of GNU Readline for - * details of VI editing mode. - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_vi_editing_mode(VALUE self) -{ -#ifdef HAVE_RL_VI_EDITING_MODE - rb_secure(4); - rl_vi_editing_mode(1,0); - return Qnil; -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_VI_EDITING_MODE */ -} - -/* - * call-seq: - * Readline.vi_editing_mode? -> bool - * - * Returns true if vi mode is active. Returns false if not. - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_vi_editing_mode_p(VALUE self) -{ -#ifdef HAVE_RL_EDITING_MODE - rb_secure(4); - return rl_editing_mode == 0 ? Qtrue : Qfalse; -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_EDITING_MODE */ -} - -/* - * call-seq: - * Readline.emacs_editing_mode -> nil - * - * Specifies Emacs editing mode. The default is this mode. See the - * manual of GNU Readline for details of Emacs editing mode. - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_emacs_editing_mode(VALUE self) -{ -#ifdef HAVE_RL_EMACS_EDITING_MODE - rb_secure(4); - rl_emacs_editing_mode(1,0); - return Qnil; -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_EMACS_EDITING_MODE */ -} - -/* - * call-seq: - * Readline.emacs_editing_mode? -> bool - * - * Returns true if emacs mode is active. Returns false if not. - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_emacs_editing_mode_p(VALUE self) -{ -#ifdef HAVE_RL_EDITING_MODE - rb_secure(4); - return rl_editing_mode == 1 ? Qtrue : Qfalse; -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_EDITING_MODE */ -} - -/* - * call-seq: - * Readline.completion_append_character = char - * - * Specifies a character to be appended on completion. - * Nothing will be appended if an empty string ("") or nil is - * specified. - * - * For example: - * require "readline" - * - * Readline.readline("> ", true) - * Readline.completion_append_character = " " - * - * Result: - * > - * Input "/var/li". - * - * > /var/li - * Press TAB key. - * - * > /var/lib - * Completes "b" and appends " ". So, you can continuously input "/usr". - * - * > /var/lib /usr - * - * NOTE: Only one character can be specified. When "string" is - * specified, sets only "s" that is the first. - * - * require "readline" - * - * Readline.completion_append_character = "string" - * p Readline.completion_append_character # => "s" - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_set_completion_append_character(VALUE self, VALUE str) -{ -#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER - rb_secure(4); - if (NIL_P(str)) { - rl_completion_append_character = '\0'; - } - else { - SafeStringValue(str); - if (RSTRING_LEN(str) == 0) { - rl_completion_append_character = '\0'; - } else { - rl_completion_append_character = RSTRING_PTR(str)[0]; - } - } - return self; -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_COMPLETION_APPEND_CHARACTER */ -} - -/* - * call-seq: - * Readline.completion_append_character -> char - * - * Returns a string containing a character to be appended on - * completion. The default is a space (" "). - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_get_completion_append_character(VALUE self) -{ -#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER - VALUE str; - - rb_secure(4); - if (rl_completion_append_character == '\0') - return Qnil; - - str = rb_str_new("", 1); - RSTRING_PTR(str)[0] = rl_completion_append_character; - return str; -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_COMPLETION_APPEND_CHARACTER */ -} - -/* - * call-seq: - * Readline.basic_word_break_characters = string - * - * Sets the basic list of characters that signal a break between words - * for the completer routine. The default is the characters which - * break words for completion in Bash: "\t\n\"\\'`@$><=;|&{(". - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_set_basic_word_break_characters(VALUE self, VALUE str) -{ -#ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS - static char *basic_word_break_characters = NULL; - - rb_secure(4); - SafeStringValue(str); - if (basic_word_break_characters == NULL) { - basic_word_break_characters = - ALLOC_N(char, RSTRING_LEN(str) + 1); - } - else { - REALLOC_N(basic_word_break_characters, char, RSTRING_LEN(str) + 1); - } - strncpy(basic_word_break_characters, - RSTRING_PTR(str), RSTRING_LEN(str)); - basic_word_break_characters[RSTRING_LEN(str)] = '\0'; - rl_basic_word_break_characters = basic_word_break_characters; - return self; -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_BASIC_WORD_BREAK_CHARACTERS */ -} - -/* - * call-seq: - * Readline.basic_word_break_characters -> string - * - * Gets the basic list of characters that signal a break between words - * for the completer routine. - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_get_basic_word_break_characters(VALUE self, VALUE str) -{ -#ifdef HAVE_RL_BASIC_WORD_BREAK_CHARACTERS - rb_secure(4); - if (rl_basic_word_break_characters == NULL) - return Qnil; - return rb_tainted_str_new2(rl_basic_word_break_characters); -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_BASIC_WORD_BREAK_CHARACTERS */ -} - -/* - * call-seq: - * Readline.completer_word_break_characters = string - * - * Sets the basic list of characters that signal a break between words - * for rl_complete_internal(). The default is the value of - * Readline.basic_word_break_characters. - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_set_completer_word_break_characters(VALUE self, VALUE str) -{ -#ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS - static char *completer_word_break_characters = NULL; - - rb_secure(4); - SafeStringValue(str); - if (completer_word_break_characters == NULL) { - completer_word_break_characters = - ALLOC_N(char, RSTRING_LEN(str) + 1); - } - else { - REALLOC_N(completer_word_break_characters, char, RSTRING_LEN(str) + 1); - } - strncpy(completer_word_break_characters, - RSTRING_PTR(str), RSTRING_LEN(str)); - completer_word_break_characters[RSTRING_LEN(str)] = '\0'; - rl_completer_word_break_characters = completer_word_break_characters; - return self; -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS */ -} - -/* - * call-seq: - * Readline.completer_word_break_characters -> string - * - * Gets the basic list of characters that signal a break between words - * for rl_complete_internal(). - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_get_completer_word_break_characters(VALUE self, VALUE str) -{ -#ifdef HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS - rb_secure(4); - if (rl_completer_word_break_characters == NULL) - return Qnil; - return rb_tainted_str_new2(rl_completer_word_break_characters); -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_COMPLETER_WORD_BREAK_CHARACTERS */ -} - -/* - * call-seq: - * Readline.basic_quote_characters = string - * - * Sets a list of quote characters which can cause a word break. - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_set_basic_quote_characters(VALUE self, VALUE str) -{ -#ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS - static char *basic_quote_characters = NULL; - - rb_secure(4); - SafeStringValue(str); - if (basic_quote_characters == NULL) { - basic_quote_characters = - ALLOC_N(char, RSTRING_LEN(str) + 1); - } - else { - REALLOC_N(basic_quote_characters, char, RSTRING_LEN(str) + 1); - } - strncpy(basic_quote_characters, - RSTRING_PTR(str), RSTRING_LEN(str)); - basic_quote_characters[RSTRING_LEN(str)] = '\0'; - rl_basic_quote_characters = basic_quote_characters; - - return self; -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_BASIC_QUOTE_CHARACTERS */ -} - -/* - * call-seq: - * Readline.basic_quote_characters -> string - * - * Gets a list of quote characters which can cause a word break. - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_get_basic_quote_characters(VALUE self, VALUE str) -{ -#ifdef HAVE_RL_BASIC_QUOTE_CHARACTERS - rb_secure(4); - if (rl_basic_quote_characters == NULL) - return Qnil; - return rb_tainted_str_new2(rl_basic_quote_characters); -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_BASIC_QUOTE_CHARACTERS */ -} - -/* - * call-seq: - * Readline.completer_quote_characters = string - * - * Sets a list of characters which can be used to quote a substring of - * the line. Completion occurs on the entire substring, and within - * the substring Readline.completer_word_break_characters are treated - * as any other character, unless they also appear within this list. - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_set_completer_quote_characters(VALUE self, VALUE str) -{ -#ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS - static char *completer_quote_characters = NULL; - - rb_secure(4); - SafeStringValue(str); - if (completer_quote_characters == NULL) { - completer_quote_characters = - ALLOC_N(char, RSTRING_LEN(str) + 1); - } - else { - REALLOC_N(completer_quote_characters, char, RSTRING_LEN(str) + 1); - } - strncpy(completer_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str)); - completer_quote_characters[RSTRING_LEN(str)] = '\0'; - rl_completer_quote_characters = completer_quote_characters; - - return self; -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_COMPLETER_QUOTE_CHARACTERS */ -} - -/* - * call-seq: - * Readline.completer_quote_characters -> string - * - * Gets a list of characters which can be used to quote a substring of - * the line. - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_get_completer_quote_characters(VALUE self, VALUE str) -{ -#ifdef HAVE_RL_COMPLETER_QUOTE_CHARACTERS - rb_secure(4); - if (rl_completer_quote_characters == NULL) - return Qnil; - return rb_tainted_str_new2(rl_completer_quote_characters); -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_COMPLETER_QUOTE_CHARACTERS */ -} - -/* - * call-seq: - * Readline.filename_quote_characters = string - * - * Sets a list of characters that cause a filename to be quoted by the completer - * when they appear in a completed filename. The default is nil. - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_set_filename_quote_characters(VALUE self, VALUE str) -{ -#ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS - static char *filename_quote_characters = NULL; - - rb_secure(4); - SafeStringValue(str); - if (filename_quote_characters == NULL) { - filename_quote_characters = - ALLOC_N(char, RSTRING_LEN(str) + 1); - } - else { - REALLOC_N(filename_quote_characters, char, RSTRING_LEN(str) + 1); - } - strncpy(filename_quote_characters, RSTRING_PTR(str), RSTRING_LEN(str)); - filename_quote_characters[RSTRING_LEN(str)] = '\0'; - rl_filename_quote_characters = filename_quote_characters; - - return self; -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_FILENAME_QUOTE_CHARACTERS */ -} - -/* - * call-seq: - * Readline.filename_quote_characters -> string - * - * Gets a list of characters that cause a filename to be quoted by the completer - * when they appear in a completed filename. - * - * Raises NotImplementedError if the using readline library does not support. - * - * Raises SecurityError exception if $SAFE is 4. - */ -static VALUE -readline_s_get_filename_quote_characters(VALUE self, VALUE str) -{ -#ifdef HAVE_RL_FILENAME_QUOTE_CHARACTERS - rb_secure(4); - if (rl_filename_quote_characters == NULL) - return Qnil; - return rb_tainted_str_new2(rl_filename_quote_characters); -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif /* HAVE_RL_FILENAME_QUOTE_CHARACTERS */ -} - -static VALUE -hist_to_s(VALUE self) -{ - return rb_str_new2("HISTORY"); -} - -static int -history_get_offset_history_base(int offset) -{ - return history_base + offset; -} - -static int -history_get_offset_0(int offset) -{ - return offset; -} - -static VALUE -hist_get(VALUE self, VALUE index) -{ - HIST_ENTRY *entry = NULL; - int i; - - rb_secure(4); - i = NUM2INT(index); - if (i < 0) { - i += history_length; - } - if (i >= 0) { - entry = history_get(history_get_offset_func(i)); - } - if (entry == NULL) { - rb_raise(rb_eIndexError, "invalid index"); - } - return rb_tainted_str_new2(entry->line); -} - -static VALUE -hist_set(VALUE self, VALUE index, VALUE str) -{ -#ifdef HAVE_REPLACE_HISTORY_ENTRY - HIST_ENTRY *entry = NULL; - int i; - - rb_secure(4); - i = NUM2INT(index); - SafeStringValue(str); - if (i < 0) { - i += history_length; - } - if (i >= 0) { - entry = replace_history_entry(i, RSTRING_PTR(str), NULL); - } - if (entry == NULL) { - rb_raise(rb_eIndexError, "invalid index"); - } - return str; -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif -} - -static VALUE -hist_push(VALUE self, VALUE str) -{ - rb_secure(4); - SafeStringValue(str); - add_history(RSTRING_PTR(str)); - return self; -} - -static VALUE -hist_push_method(int argc, VALUE *argv, VALUE self) -{ - VALUE str; - - rb_secure(4); - while (argc--) { - str = *argv++; - SafeStringValue(str); - add_history(RSTRING_PTR(str)); - } - return self; -} - -static VALUE -rb_remove_history(int index) -{ -#ifdef HAVE_REMOVE_HISTORY - HIST_ENTRY *entry; - VALUE val; - - rb_secure(4); - entry = remove_history(index); - if (entry) { - val = rb_tainted_str_new2(entry->line); - free((void *) entry->line); - free(entry); - return val; - } - return Qnil; -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif -} - -static VALUE -hist_pop(VALUE self) -{ - rb_secure(4); - if (history_length > 0) { - return rb_remove_history(history_length - 1); - } else { - return Qnil; - } -} - -static VALUE -hist_shift(VALUE self) -{ - rb_secure(4); - if (history_length > 0) { - return rb_remove_history(0); - } else { - return Qnil; - } -} - -static VALUE -hist_each(VALUE self) -{ - HIST_ENTRY *entry; - int i; - - RETURN_ENUMERATOR(self, 0, 0); - - rb_secure(4); - for (i = 0; i < history_length; i++) { - entry = history_get(history_get_offset_func(i)); - if (entry == NULL) - break; - rb_yield(rb_tainted_str_new2(entry->line)); - } - return self; -} - -static VALUE -hist_length(VALUE self) -{ - rb_secure(4); - return INT2NUM(history_length); -} - -static VALUE -hist_empty_p(VALUE self) -{ - rb_secure(4); - return history_length == 0 ? Qtrue : Qfalse; -} - -static VALUE -hist_delete_at(VALUE self, VALUE index) -{ - int i; - - rb_secure(4); - i = NUM2INT(index); - if (i < 0) - i += history_length; - if (i < 0 || i > history_length - 1) { - rb_raise(rb_eIndexError, "invalid index"); - } - return rb_remove_history(i); -} - -static VALUE -hist_clear(VALUE self) -{ -#ifdef HAVE_CLEAR_HISTORY - rb_secure(4); - clear_history(); - return self; -#else - rb_notimplement(); - return Qnil; /* not reached */ -#endif -} - -static VALUE -filename_completion_proc_call(VALUE self, VALUE str) -{ - VALUE result; - char **matches; - int i; - - matches = rl_completion_matches(StringValuePtr(str), - rl_filename_completion_function); - if (matches) { - result = rb_ary_new(); - for (i = 0; matches[i]; i++) { - rb_ary_push(result, rb_tainted_str_new2(matches[i])); - free(matches[i]); - } - free(matches); - if (RARRAY_LEN(result) >= 2) - rb_ary_shift(result); - } - else { - result = Qnil; - } - return result; -} - -static VALUE -username_completion_proc_call(VALUE self, VALUE str) -{ - VALUE result; - char **matches; - int i; - - matches = rl_completion_matches(StringValuePtr(str), - rl_username_completion_function); - if (matches) { - result = rb_ary_new(); - for (i = 0; matches[i]; i++) { - rb_ary_push(result, rb_tainted_str_new2(matches[i])); - free(matches[i]); - } - free(matches); - if (RARRAY_LEN(result) >= 2) - rb_ary_shift(result); - } - else { - result = Qnil; - } - return result; -} - -void -Init_readline() -{ - VALUE history, fcomp, ucomp, version; - - /* Allow conditional parsing of the ~/.inputrc file. */ - rl_readline_name = "Ruby"; - - using_history(); - - completion_proc = rb_intern(COMPLETION_PROC); - completion_case_fold = rb_intern(COMPLETION_CASE_FOLD); - - mReadline = rb_define_module("Readline"); - rb_define_module_function(mReadline, "readline", - readline_readline, -1); - rb_define_singleton_method(mReadline, "input=", - readline_s_set_input, 1); - rb_define_singleton_method(mReadline, "output=", - readline_s_set_output, 1); - rb_define_singleton_method(mReadline, "completion_proc=", - readline_s_set_completion_proc, 1); - rb_define_singleton_method(mReadline, "completion_proc", - readline_s_get_completion_proc, 0); - rb_define_singleton_method(mReadline, "completion_case_fold=", - readline_s_set_completion_case_fold, 1); - rb_define_singleton_method(mReadline, "completion_case_fold", - readline_s_get_completion_case_fold, 0); - rb_define_singleton_method(mReadline, "vi_editing_mode", - readline_s_vi_editing_mode, 0); - rb_define_singleton_method(mReadline, "vi_editing_mode?", - readline_s_vi_editing_mode_p, 0); - rb_define_singleton_method(mReadline, "emacs_editing_mode", - readline_s_emacs_editing_mode, 0); - rb_define_singleton_method(mReadline, "emacs_editing_mode?", - readline_s_emacs_editing_mode_p, 0); - rb_define_singleton_method(mReadline, "completion_append_character=", - readline_s_set_completion_append_character, 1); - rb_define_singleton_method(mReadline, "completion_append_character", - readline_s_get_completion_append_character, 0); - rb_define_singleton_method(mReadline, "basic_word_break_characters=", - readline_s_set_basic_word_break_characters, 1); - rb_define_singleton_method(mReadline, "basic_word_break_characters", - readline_s_get_basic_word_break_characters, 0); - rb_define_singleton_method(mReadline, "completer_word_break_characters=", - readline_s_set_completer_word_break_characters, 1); - rb_define_singleton_method(mReadline, "completer_word_break_characters", - readline_s_get_completer_word_break_characters, 0); - rb_define_singleton_method(mReadline, "basic_quote_characters=", - readline_s_set_basic_quote_characters, 1); - rb_define_singleton_method(mReadline, "basic_quote_characters", - readline_s_get_basic_quote_characters, 0); - rb_define_singleton_method(mReadline, "completer_quote_characters=", - readline_s_set_completer_quote_characters, 1); - rb_define_singleton_method(mReadline, "completer_quote_characters", - readline_s_get_completer_quote_characters, 0); - rb_define_singleton_method(mReadline, "filename_quote_characters=", - readline_s_set_filename_quote_characters, 1); - rb_define_singleton_method(mReadline, "filename_quote_characters", - readline_s_get_filename_quote_characters, 0); - - history = rb_obj_alloc(rb_cObject); - rb_extend_object(history, rb_mEnumerable); - rb_define_singleton_method(history,"to_s", hist_to_s, 0); - rb_define_singleton_method(history,"[]", hist_get, 1); - rb_define_singleton_method(history,"[]=", hist_set, 2); - rb_define_singleton_method(history,"<<", hist_push, 1); - rb_define_singleton_method(history,"push", hist_push_method, -1); - rb_define_singleton_method(history,"pop", hist_pop, 0); - rb_define_singleton_method(history,"shift", hist_shift, 0); - rb_define_singleton_method(history,"each", hist_each, 0); - rb_define_singleton_method(history,"length", hist_length, 0); - rb_define_singleton_method(history,"size", hist_length, 0); - rb_define_singleton_method(history,"empty?", hist_empty_p, 0); - rb_define_singleton_method(history,"delete_at", hist_delete_at, 1); - rb_define_singleton_method(history,"clear", hist_clear, 0); - - /* - * The history buffer. It extends Enumerable module, so it behaves - * just like an array. - * For example, gets the fifth content that the user input by - * HISTORY[4]. - */ - rb_define_const(mReadline, "HISTORY", history); - - fcomp = rb_obj_alloc(rb_cObject); - rb_define_singleton_method(fcomp, "call", - filename_completion_proc_call, 1); - /* - * The Object with the call method that is a completion for filename. - * This is sets by Readline.completion_proc= method. - */ - rb_define_const(mReadline, "FILENAME_COMPLETION_PROC", fcomp); - - ucomp = rb_obj_alloc(rb_cObject); - rb_define_singleton_method(ucomp, "call", - username_completion_proc_call, 1); - /* - * The Object with the call method that is a completion for usernames. - * This is sets by Readline.completion_proc= method. - */ - rb_define_const(mReadline, "USERNAME_COMPLETION_PROC", ucomp); - history_get_offset_func = history_get_offset_history_base; -#if defined HAVE_RL_LIBRARY_VERSION - version = rb_str_new2(rl_library_version); -#if defined HAVE_CLEAR_HISTORY - if (strncmp(rl_library_version, EDIT_LINE_LIBRARY_VERSION, - strlen(EDIT_LINE_LIBRARY_VERSION)) == 0) { - add_history("1"); - if (history_get(history_get_offset_func(0)) == NULL) { - history_get_offset_func = history_get_offset_0; - } - clear_history(); - } -#endif -#else - version = rb_str_new2("2.0 or prior version"); -#endif - /* Version string of GNU Readline or libedit. */ - rb_define_const(mReadline, "VERSION", version); - - rl_attempted_completion_function = readline_attempted_completion_function; -#ifdef HAVE_RL_EVENT_HOOK - rl_event_hook = readline_event; -#endif -#ifdef HAVE_RL_CLEAR_SIGNALS - rl_clear_signals(); -#endif -} |