diff options
author | kouji <kouji@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-05-01 13:21:55 +0000 |
---|---|---|
committer | kouji <kouji@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-05-01 13:21:55 +0000 |
commit | 7a4b214558009bcb64630ae06e552a9c0c0ffba4 (patch) | |
tree | 042db6393a5679612e8ee37d10952fb6f9f03823 | |
parent | 28b7df782088e1e18b53659b0ba0c96a1b8b1c8b (diff) | |
download | ruby-7a4b214558009bcb64630ae06e552a9c0c0ffba4.tar.gz |
* ext/readline/readline.c (Readline.pre_input_hook)
(Readline.insert_text, Readline.redisplay): new function. An
original patch was created by nagachika. [Feature #5785]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35513 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | ext/readline/extconf.rb | 3 | ||||
-rw-r--r-- | ext/readline/readline.c | 119 | ||||
-rw-r--r-- | test/readline/test_readline.rb | 80 |
4 files changed, 179 insertions, 29 deletions
@@ -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) |