summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--ext/readline/extconf.rb3
-rw-r--r--ext/readline/readline.c119
-rw-r--r--test/readline/test_readline.rb80
4 files changed, 179 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog
index 95462e0b88..ad3009bd87 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Tue May 1 22:18:45 2012 Kouji Takao <kouji.takao@gmail.com>
+
+ * ext/readline/readline.c (Readline.pre_input_hook)
+ (Readline.insert_text, Readline.redisplay): new function. An
+ original patch was created by nagachika. [Feature #5785]
+
Tue May 1 15:46:48 2012 Koichi Sasada <ko1@atdot.net>
* common.mk: "$(Q)-..." doesn't work on nmake.
diff --git a/ext/readline/extconf.rb b/ext/readline/extconf.rb
index b8e9e0fab4..3a854d6609 100644
--- a/ext/readline/extconf.rb
+++ b/ext/readline/extconf.rb
@@ -83,6 +83,7 @@ have_readline_var("rl_point")
/mswin|bccwin|mingw/ !~ RUBY_PLATFORM && have_readline_var("rl_event_hook")
/mswin|bccwin|mingw/ !~ RUBY_PLATFORM && have_readline_var("rl_catch_sigwinch")
/mswin|bccwin|mingw/ !~ RUBY_PLATFORM && have_readline_var("rl_catch_signals")
+have_readline_var("rl_pre_input_hook")
have_readline_func("rl_cleanup_after_signal")
have_readline_func("rl_free_line_state")
have_readline_func("rl_clear_signals")
@@ -93,6 +94,8 @@ have_readline_func("rl_emacs_editing_mode")
have_readline_func("replace_history_entry")
have_readline_func("remove_history")
have_readline_func("clear_history")
+have_readline_func("rl_redisplay")
+have_readline_func("rl_insert_text")
have_readline_macro("RL_PROMPT_START_IGNORE")
have_readline_macro("RL_PROMPT_END_IGNORE")
create_makefile("readline")
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index e550782c5d..64922c6c0f 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -61,6 +61,9 @@ static ID completion_proc, completion_case_fold;
#if USE_INSERT_IGNORE_ESCAPE
static ID id_orig_prompt, id_last_prompt;
#endif
+#if defined(HAVE_RL_PRE_INPUT_HOOK)
+static ID id_pre_input_hook;
+#endif
#ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION
# define rl_filename_completion_function filename_completion_function
@@ -468,6 +471,108 @@ readline_s_set_output(VALUE self, VALUE output)
return output;
}
+#if defined(HAVE_RL_PRE_INPUT_HOOK)
+/*
+ * call-seq:
+ * Readline.pre_input_hook = proc
+ *
+ * Specifies a Proc object +proc+ to call after the first prompt has
+ * been printed and just before readline starts reading input
+ * characters.
+ *
+ * See GNU Readline's rl_pre_input_hook variable.
+ *
+ * Raises ArgumentError if +proc+ does not respond to the call method.
+ *
+ * Raises SecurityError if $SAFE is 4.
+ */
+static VALUE
+readline_s_set_pre_input_hook(VALUE self, VALUE proc)
+{
+ rb_secure(4);
+ if (!NIL_P(proc) && !rb_respond_to(proc, rb_intern("call")))
+ rb_raise(rb_eArgError, "argument must respond to `call'");
+ return rb_ivar_set(mReadline, id_pre_input_hook, proc);
+}
+
+/*
+ * call-seq:
+ * Readline.pre_input_hook -> proc
+ *
+ * Returns a Proc object +proc+ to call after the first prompt has
+ * been printed and just before readline starts reading input
+ * characters. The default is nil.
+ *
+ * Raises SecurityError if $SAFE is 4.
+ */
+static VALUE
+readline_s_get_pre_input_hook(VALUE self)
+{
+ rb_secure(4);
+ return rb_attr_get(mReadline, id_pre_input_hook);
+}
+
+static int
+readline_pre_input_hook(void)
+{
+ VALUE proc;
+
+ proc = rb_attr_get(mReadline, id_pre_input_hook);
+ if (!NIL_P(proc))
+ rb_funcall(proc, rb_intern("call"), 0);
+ return 0;
+}
+#else
+#define readline_s_set_pre_input_hook rb_f_notimplement
+#define readline_s_get_pre_input_hook rb_f_notimplement
+#endif
+
+#if defined(HAVE_RL_INSERT_TEXT)
+/*
+ * call-seq:
+ * Readline.insert_text(string) -> self
+ *
+ * Insert text into the line at the current cursor position.
+ *
+ * See GNU Readline's rl_insert_text function.
+ *
+ * Raises SecurityError if $SAFE is 4.
+ */
+static VALUE
+readline_s_insert_text(VALUE self, VALUE str)
+{
+ rb_secure(4);
+ OutputStringValue(str);
+ rl_insert_text(RSTRING_PTR(str));
+ return self;
+}
+#else
+#define readline_s_insert_text rb_f_notimplement
+#endif
+
+#if defined(HAVE_RL_REDISPLAY)
+/*
+ * call-seq:
+ * Readline.redisplay -> self
+ *
+ * Change what's displayed on the screen to reflect the current
+ * contents.
+ *
+ * See GNU Readline's rl_redisplay function.
+ *
+ * Raises SecurityError if $SAFE is 4.
+ */
+static VALUE
+readline_s_redisplay(VALUE self)
+{
+ rb_secure(4);
+ rl_redisplay();
+ return self;
+}
+#else
+#define readline_s_redisplay rb_f_notimplement
+#endif
+
/*
* call-seq:
* Readline.completion_proc = proc
@@ -1537,6 +1642,9 @@ Init_readline()
completion_proc = rb_intern(COMPLETION_PROC);
completion_case_fold = rb_intern(COMPLETION_CASE_FOLD);
+#if defined(HAVE_RL_PRE_INPUT_HOOK)
+ id_pre_input_hook = rb_intern("pre_input_hook");
+#endif
mReadline = rb_define_module("Readline");
rb_define_module_function(mReadline, "readline",
@@ -1595,6 +1703,14 @@ Init_readline()
readline_s_get_filename_quote_characters, 0);
rb_define_singleton_method(mReadline, "refresh_line",
readline_s_refresh_line, 0);
+ rb_define_singleton_method(mReadline, "pre_input_hook=",
+ readline_s_set_pre_input_hook, 1);
+ rb_define_singleton_method(mReadline, "pre_input_hook",
+ readline_s_get_pre_input_hook, 0);
+ rb_define_singleton_method(mReadline, "insert_text",
+ readline_s_insert_text, 1);
+ rb_define_singleton_method(mReadline, "redisplay",
+ readline_s_redisplay, 0);
#if USE_INSERT_IGNORE_ESCAPE
CONST_ID(id_orig_prompt, "orig_prompt");
@@ -1678,6 +1794,9 @@ Init_readline()
rb_define_const(mReadline, "VERSION", version);
rl_attempted_completion_function = readline_attempted_completion_function;
+#if defined(HAVE_RL_PRE_INPUT_HOOK)
+ rl_pre_input_hook = (Function *)readline_pre_input_hook;
+#endif
#ifdef HAVE_RL_CATCH_SIGNALS
rl_catch_signals = 0;
#endif
diff --git a/test/readline/test_readline.rb b/test/readline/test_readline.rb
index 9ac67ca991..98922a2120 100644
--- a/test/readline/test_readline.rb
+++ b/test/readline/test_readline.rb
@@ -1,34 +1,5 @@
begin
require "readline"
-=begin
- class << Readline
- [
- "line_buffer",
- "point",
- "set_screen_size",
- "get_screen_size",
- "vi_editing_mode",
- "emacs_editing_mode",
- "completion_append_character=",
- "completion_append_character",
- "basic_word_break_characters=",
- "basic_word_break_characters",
- "completer_word_break_characters=",
- "completer_word_break_characters",
- "basic_quote_characters=",
- "basic_quote_characters",
- "completer_quote_characters=",
- "completer_quote_characters",
- "filename_quote_characters=",
- "filename_quote_characters",
- "refresh_line",
- ].each do |method_name|
- define_method(method_name.to_sym) do |*args|
- raise NotImplementedError
- end
- end
- end
-=end
rescue LoadError
else
require "test/unit"
@@ -77,6 +48,10 @@ class TestReadline < Test::Unit::TestCase
["point"],
["set_screen_size", 1, 1],
["get_screen_size"],
+ ["pre_input_hook=", proc {}],
+ ["pre_input_hook"],
+ ["insert_text", ""],
+ ["redisplay"],
]
method_args.each do |method_name, *args|
assert_raise(SecurityError, NotImplementedError,
@@ -372,6 +347,53 @@ class TestReadline < Test::Unit::TestCase
end
end
+ def test_pre_input_hook
+ begin
+ pr = proc {}
+ assert_equal(Readline.pre_input_hook = pr, pr)
+ assert_equal(Readline.pre_input_hook, pr)
+ assert_nil(Readline.pre_input_hook = nil)
+ rescue NotImplementedError
+ end
+ end
+
+ def test_insert_text
+ begin
+ str = "test_insert_text"
+ assert_equal(Readline.insert_text(str), Readline)
+ assert_equal(Readline.line_buffer, str)
+ assert_equal(Readline.line_buffer.encoding,
+ get_default_internal_encoding)
+ rescue NotImplementedError
+ end
+ end if !/EditLine/n.match(Readline::VERSION)
+
+ def test_modify_text_in_pre_input_hook
+ begin
+ stdin = Tempfile.new("readline_redisplay_stdin")
+ stdout = Tempfile.new("readline_redisplay_stdout")
+ stdin.write("world\n")
+ stdin.close
+ Readline.pre_input_hook = proc do
+ assert_equal("", Readline.line_buffer)
+ Readline.insert_text("hello ")
+ Readline.redisplay
+ end
+ replace_stdio(stdin.path, stdout.path) do
+ line = Readline.readline("> ")
+ assert_equal("hello world", line)
+ end
+ assert_equal("> hello world\n", stdout.read)
+ stdout.close
+ rescue NotImplementedError
+ ensure
+ begin
+ Readline.pre_input_hook = nil
+ rescue NotImplementedError
+ end
+ end
+ end if !/EditLine/n.match(Readline::VERSION)
+
private
def replace_stdio(stdin_path, stdout_path)