Hi,
On 2008/08/11, at 13:42, Takao K. wrote:
but if the user would type
“blabalblabla foo” # there should be no result
I want to add some methods that satisfy the Marc H.'s demands.
The patch contributed to the RubyForge is taken.
[#3212] Readline does not provide enough context to the completion_proc
http://rubyforge.org/tracker/index.php?func=detail&aid=3212&group_id=426&atid=1698
First of all, I will take it into ruby 1.9. Afterwards, backport to 1.8.
I will add the follows methods.
- line_buffer: Returns the full line that is being edited.
(same as rl_line_buffer)
- point: Returns the index of the current cursor position
in Readline.line_buffer. (same as rl_point)
The match_start is computed by subtracting the length of input-string
from Readline.point.
The match_end and Readline.line_buffer are same.
Attached the patch for ruby 1.9 (r18525).
Thanks, TAKAO Kouji.
Index: ext/readline/readline.c
— ext/readline/readline.c (revision 18525)
+++ ext/readline/readline.c (working copy)
@@ -367,6 +367,56 @@
return rb_attr_get(mReadline, completion_case_fold);
}
+/*
-
-
- Readline.line_buffer → string
-
-
- Returns the full line that is being edited. This is useful from
-
- within the complete_proc for determining the context of the
-
-
-
- The length of +Readline.line_buffer+ and GNU Readline’s rl_end are
-
- */
+static VALUE
+readline_s_get_line_buffer(VALUE self)
+{
+#ifdef HAVE_RL_LINE_BUFFER
- rb_secure(4);
- if (rl_line_buffer == NULL)
- return Qnil;
- return rb_tainted_str_new2(rl_line_buffer);
+#else
- rb_notimplement();
- return Qnil; /* not reached /
+#endif / HAVE_RL_LINE_BUFFER */
+}
-
+/*
-
-
-
-
- Returns the index of the current cursor position in
-
-
-
- The index in +Readline.line_buffer+ which matches the start of
-
- input-string passed to completion_proc is computed by subtracting
-
- the length of input-string from +Readline.point+.
-
-
- start = (the length of input-string) - Readline.point
- */
+static VALUE
+readline_s_get_point(VALUE self)
+{
+#ifdef HAVE_RL_POINT
- rb_secure(4);
- return INT2NUM(rl_point);
+#else
- rb_notimplement();
- return Qnil; /* not reached /
+#endif / HAVE_RL_POINT */
+}
-
static char **
readline_attempted_completion_function(const char *text, int start, int
end)
{
@@ -1196,6 +1246,10 @@
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, “line_buffer”,
-
readline_s_get_line_buffer, 0);
- rb_define_singleton_method(mReadline, “point”,
-
readline_s_get_point, 0);
rb_define_singleton_method(mReadline, “vi_editing_mode”,
readline_s_vi_editing_mode, 0);
rb_define_singleton_method(mReadline, “vi_editing_mode?”,
Index: ext/readline/extconf.rb
===================================================================
— ext/readline/extconf.rb (revision 18525)
+++ ext/readline/extconf.rb (working copy)
@@ -59,6 +59,8 @@
have_readline_var(“rl_attempted_completion_over”)
have_readline_var(“rl_library_version”)
have_readline_var(“rl_editing_mode”)
+have_readline_var(“rl_line_buffer”)
+have_readline_var(“rl_point”)
workaround for native windows.
/mswin|bccwin|mingw/ !~ RUBY_PLATFORM &&
have_readline_var(“rl_event_hook”)
have_readline_func(“rl_cleanup_after_signal”)
Index: test/readline/test_readline.rb
— test/readline/test_readline.rb (revision 18525)
+++ test/readline/test_readline.rb (working copy)
@@ -3,6 +3,8 @@
=begin
class << Readline
[
-
"line_buffer",
-
"point",
"vi_editing_mode",
"emacs_editing_mode",
"completion_append_character=",
@@ -61,6 +63,8 @@
[“completer_quote_characters”],
[“filename_quote_characters=”, “\”],
[“filename_quote_characters”],
-
["line_buffer"],
-
["point"],
]
method_args.each do |method_name, *args|
assert_raises(SecurityError, NotImplementedError,
@@ -74,41 +78,83 @@
end
end
- def test_readline
- stdin = Tempfile.new(“test_readline_stdin”)
- stdout = Tempfile.new(“test_readline_stdout”)
- begin
-
stdin.write("hello\n")
-
stdin.close
-
stdout.close
-
line = replace_stdio(stdin.path, stdout.path) {
-
Readline.readline("> ", true)
-
}
-
assert_equal("hello", line)
-
assert_equal(true, line.tainted?)
-
stdout.open
-
assert_equal("> ", stdout.read(2))
-
assert_equal(1, Readline::HISTORY.length)
-
assert_equal("hello", Readline::HISTORY[0])
-
assert_raises(SecurityError) do
-
Thread.start {
-
$SAFE = 1
-
replace_stdio(stdin.path, stdout.path) do
-
Readline.readline("> ".taint)
-
end
-
}.join
- if !/EditLine/n.match(Readline::VERSION)
- def test_readline
-
stdin = Tempfile.new("test_readline_stdin")
-
stdout = Tempfile.new("test_readline_stdout")
-
begin
-
stdin.write("hello\n")
-
stdin.close
-
stdout.close
-
line = replace_stdio(stdin.path, stdout.path) {
-
Readline.readline("> ", true)
-
}
-
assert_equal("hello", line)
-
assert_equal(true, line.tainted?)
-
stdout.open
-
assert_equal("> ", stdout.read(2))
-
assert_equal(1, Readline::HISTORY.length)
-
assert_equal("hello", Readline::HISTORY[0])
-
assert_raises(SecurityError) do
-
Thread.start {
-
$SAFE = 1
-
replace_stdio(stdin.path, stdout.path) do
-
Readline.readline("> ".taint)
-
end
-
}.join
-
end
-
assert_raises(SecurityError) do
-
Thread.start {
-
$SAFE = 4
-
replace_stdio(stdin.path, stdout.path) {
Readline.readline("> ") }
-
}.join
-
end
-
ensure
-
stdin.close(true)
-
stdout.close(true)
end
") }
- ensure
-
stdin.close(true)
-
stdout.close(true)
-
-
stdin = Tempfile.new("test_readline_stdin")
-
stdout = Tempfile.new("test_readline_stdout")
-
begin
-
actual_text = nil
-
actual_line_buffer = nil
-
actual_point = nil
-
Readline.completion_proc = proc { |text|
-
actual_text = text
-
actual_point = Readline.point
-
actual_buffer_line = Readline.line_buffer
-
stdin.write(" finish\n")
-
stdin.close
-
stdout.close
-
return ["complete"]
-
}
-
stdin.write("first second\t")
-
stdin.flush
-
line = replace_stdio(stdin.path, stdout.path) {
-
Readline.readline("> ", false)
-
}
-
assert_equal("first second", actual_line_buffer)
-
assert_equal(12, actual_point)
-
assert_equal("first complete finish", Readline.line_buffer)
-
assert_equal(21, Readline.point)
-
ensure
-
stdin.close(true)
-
stdout.close(true)
-
end
end
- end if !/EditLine/n.match(Readline::VERSION)