mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
rl_char_is_quoted_p
* ext/readline/readline.c (readline_s_set_quoting_detection_proc): support rl_char_is_quoted_p. [Feature #12659] * ext/readline/readline.c (readline_s_get_quoting_detection_proc): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56326 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
d3c6292401
commit
402f042689
4 changed files with 180 additions and 0 deletions
|
@ -1,3 +1,11 @@
|
||||||
|
Mon Oct 3 17:20:05 2016 George Brocklehurst <ruby@georgebrock.com>
|
||||||
|
|
||||||
|
* ext/readline/readline.c (readline_s_set_quoting_detection_proc):
|
||||||
|
support rl_char_is_quoted_p. [Feature #12659]
|
||||||
|
|
||||||
|
* ext/readline/readline.c (readline_s_get_quoting_detection_proc):
|
||||||
|
ditto.
|
||||||
|
|
||||||
Sun Oct 2 08:22:28 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
Sun Oct 2 08:22:28 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* include/ruby/ruby.h (RB_INT2FIX, RB_LONG2FIX): prefix RB to
|
* include/ruby/ruby.h (RB_INT2FIX, RB_LONG2FIX): prefix RB to
|
||||||
|
|
|
@ -81,6 +81,7 @@ readline.have_var("rl_library_version")
|
||||||
readline.have_var("rl_editing_mode")
|
readline.have_var("rl_editing_mode")
|
||||||
readline.have_var("rl_line_buffer")
|
readline.have_var("rl_line_buffer")
|
||||||
readline.have_var("rl_point")
|
readline.have_var("rl_point")
|
||||||
|
readline.have_var("rl_char_is_quoted_p")
|
||||||
# workaround for native windows.
|
# workaround for native windows.
|
||||||
/mswin|bccwin|mingw/ !~ RUBY_PLATFORM && readline.have_var("rl_event_hook")
|
/mswin|bccwin|mingw/ !~ RUBY_PLATFORM && readline.have_var("rl_event_hook")
|
||||||
/mswin|bccwin|mingw/ !~ RUBY_PLATFORM && readline.have_var("rl_catch_sigwinch")
|
/mswin|bccwin|mingw/ !~ RUBY_PLATFORM && readline.have_var("rl_catch_sigwinch")
|
||||||
|
|
|
@ -59,6 +59,10 @@ static VALUE mReadline;
|
||||||
#define COMPLETION_PROC "completion_proc"
|
#define COMPLETION_PROC "completion_proc"
|
||||||
#define COMPLETION_CASE_FOLD "completion_case_fold"
|
#define COMPLETION_CASE_FOLD "completion_case_fold"
|
||||||
static ID id_call, completion_proc, completion_case_fold;
|
static ID id_call, completion_proc, completion_case_fold;
|
||||||
|
#if defined HAVE_RL_CHAR_IS_QUOTED_P
|
||||||
|
#define QUOTING_DETECTION_PROC "quoting_detection_proc"
|
||||||
|
static ID quoting_detection_proc;
|
||||||
|
#endif
|
||||||
#if USE_INSERT_IGNORE_ESCAPE
|
#if USE_INSERT_IGNORE_ESCAPE
|
||||||
static ID id_orig_prompt, id_last_prompt;
|
static ID id_orig_prompt, id_last_prompt;
|
||||||
#endif
|
#endif
|
||||||
|
@ -837,6 +841,51 @@ readline_s_get_completion_proc(VALUE self)
|
||||||
return rb_attr_get(mReadline, completion_proc);
|
return rb_attr_get(mReadline, completion_proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_RL_CHAR_IS_QUOTED_P
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* Readline.quoting_detection_proc = proc
|
||||||
|
*
|
||||||
|
* Specifies a Proc object +proc+ to determine if a character in the user's
|
||||||
|
* input is escaped. It should take the user's input and the index of the
|
||||||
|
* character in question as input, and return a boolean (true if the specified
|
||||||
|
* character is escaped).
|
||||||
|
*
|
||||||
|
* Readline will only call this proc with characters specified in
|
||||||
|
* +completer_quote_characters+, to discover if they indicate the end of a
|
||||||
|
* quoted argument, or characters specified in
|
||||||
|
* +completer_word_break_characters+, to discover if they indicate a break
|
||||||
|
* between arguments.
|
||||||
|
*
|
||||||
|
* If +completer_quote_characters+ is not set, or if the user input doesn't
|
||||||
|
* contain one of the +completer_quote_characters+ or a +\+ character,
|
||||||
|
* Readline will not attempt to use this proc at all.
|
||||||
|
*
|
||||||
|
* Raises ArgumentError if +proc+ does not respond to the call method.
|
||||||
|
*/
|
||||||
|
static VALUE
|
||||||
|
readline_s_set_quoting_detection_proc(VALUE self, VALUE proc)
|
||||||
|
{
|
||||||
|
mustbe_callable(proc);
|
||||||
|
return rb_ivar_set(mReadline, quoting_detection_proc, proc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* Readline.quoting_detection_proc -> proc
|
||||||
|
*
|
||||||
|
* Returns the quoting detection Proc object.
|
||||||
|
*/
|
||||||
|
static VALUE
|
||||||
|
readline_s_get_quoting_detection_proc(VALUE self)
|
||||||
|
{
|
||||||
|
return rb_attr_get(mReadline, quoting_detection_proc);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define readline_s_set_quoting_detection_proc rb_f_notimplement
|
||||||
|
#define readline_s_get_quoting_detection_proc rb_f_notimplement
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* Readline.completion_case_fold = bool
|
* Readline.completion_case_fold = bool
|
||||||
|
@ -1012,6 +1061,32 @@ readline_attempted_completion_function(const char *text, int start, int end)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_RL_CHAR_IS_QUOTED_P
|
||||||
|
static int
|
||||||
|
readline_char_is_quoted(char *text, int byte_index)
|
||||||
|
{
|
||||||
|
VALUE proc, result, str;
|
||||||
|
long char_index;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
proc = rb_attr_get(mReadline, quoting_detection_proc);
|
||||||
|
if (NIL_P(proc)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen(text);
|
||||||
|
if (byte_index < 0 || len < (size_t)byte_index) {
|
||||||
|
rb_raise(rb_eIndexError, "invalid byte index (%d in %"PRIdSIZE")",
|
||||||
|
byte_index, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
str = rb_locale_str_new_cstr(text);
|
||||||
|
char_index = rb_str_sublen(str, byte_index);
|
||||||
|
result = rb_funcall(proc, id_call, 2, str, LONG2FIX(char_index));
|
||||||
|
return RTEST(result);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_RL_SET_SCREEN_SIZE
|
#ifdef HAVE_RL_SET_SCREEN_SIZE
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
|
@ -1828,6 +1903,9 @@ Init_readline(void)
|
||||||
#if defined(HAVE_RL_SPECIAL_PREFIXES)
|
#if defined(HAVE_RL_SPECIAL_PREFIXES)
|
||||||
id_special_prefixes = rb_intern("special_prefixes");
|
id_special_prefixes = rb_intern("special_prefixes");
|
||||||
#endif
|
#endif
|
||||||
|
#if defined HAVE_RL_CHAR_IS_QUOTED_P
|
||||||
|
quoting_detection_proc = rb_intern(QUOTING_DETECTION_PROC);
|
||||||
|
#endif
|
||||||
|
|
||||||
mReadline = rb_define_module("Readline");
|
mReadline = rb_define_module("Readline");
|
||||||
rb_define_module_function(mReadline, "readline",
|
rb_define_module_function(mReadline, "readline",
|
||||||
|
@ -1840,6 +1918,10 @@ Init_readline(void)
|
||||||
readline_s_set_completion_proc, 1);
|
readline_s_set_completion_proc, 1);
|
||||||
rb_define_singleton_method(mReadline, "completion_proc",
|
rb_define_singleton_method(mReadline, "completion_proc",
|
||||||
readline_s_get_completion_proc, 0);
|
readline_s_get_completion_proc, 0);
|
||||||
|
rb_define_singleton_method(mReadline, "quoting_detection_proc=",
|
||||||
|
readline_s_set_quoting_detection_proc, 1);
|
||||||
|
rb_define_singleton_method(mReadline, "quoting_detection_proc",
|
||||||
|
readline_s_get_quoting_detection_proc, 0);
|
||||||
rb_define_singleton_method(mReadline, "completion_case_fold=",
|
rb_define_singleton_method(mReadline, "completion_case_fold=",
|
||||||
readline_s_set_completion_case_fold, 1);
|
readline_s_set_completion_case_fold, 1);
|
||||||
rb_define_singleton_method(mReadline, "completion_case_fold",
|
rb_define_singleton_method(mReadline, "completion_case_fold",
|
||||||
|
@ -1988,6 +2070,9 @@ Init_readline(void)
|
||||||
#if defined(HAVE_RL_PRE_INPUT_HOOK)
|
#if defined(HAVE_RL_PRE_INPUT_HOOK)
|
||||||
rl_pre_input_hook = readline_pre_input_hook;
|
rl_pre_input_hook = readline_pre_input_hook;
|
||||||
#endif
|
#endif
|
||||||
|
#if defined HAVE_RL_CHAR_IS_QUOTED_P
|
||||||
|
rl_char_is_quoted_p = &readline_char_is_quoted;
|
||||||
|
#endif
|
||||||
#ifdef HAVE_RL_CATCH_SIGNALS
|
#ifdef HAVE_RL_CATCH_SIGNALS
|
||||||
rl_catch_signals = 0;
|
rl_catch_signals = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -464,6 +464,92 @@ class TestReadline < Test::Unit::TestCase
|
||||||
end
|
end
|
||||||
end if Readline.respond_to?(:refresh_line)
|
end if Readline.respond_to?(:refresh_line)
|
||||||
|
|
||||||
|
def test_setting_quoting_detection_proc
|
||||||
|
return unless Readline.respond_to?(:quoting_detection_proc=)
|
||||||
|
|
||||||
|
expected = proc { |text, index| false }
|
||||||
|
Readline.quoting_detection_proc = expected
|
||||||
|
assert_equal(expected, Readline.quoting_detection_proc)
|
||||||
|
|
||||||
|
assert_raise(ArgumentError) do
|
||||||
|
Readline.quoting_detection_proc = "This does not have call method."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_using_quoting_detection_proc
|
||||||
|
saved_completer_quote_characters = Readline.completer_quote_characters
|
||||||
|
saved_completer_word_break_characters = Readline.completer_word_break_characters
|
||||||
|
return unless Readline.respond_to?(:quoting_detection_proc=)
|
||||||
|
|
||||||
|
passed_text = nil
|
||||||
|
line = nil
|
||||||
|
|
||||||
|
with_temp_stdio do |stdin, stdout|
|
||||||
|
replace_stdio(stdin.path, stdout.path) do
|
||||||
|
Readline.completion_proc = -> (text) do
|
||||||
|
passed_text = text
|
||||||
|
['completion']
|
||||||
|
end
|
||||||
|
Readline.completer_quote_characters = '\'"'
|
||||||
|
Readline.completer_word_break_characters = ' '
|
||||||
|
Readline.quoting_detection_proc = -> (text, index) do
|
||||||
|
index > 0 && text[index-1] == '\\'
|
||||||
|
end
|
||||||
|
|
||||||
|
stdin.write("first second\\ third\t")
|
||||||
|
stdin.flush
|
||||||
|
line = Readline.readline('> ', false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal('second\\ third', passed_text)
|
||||||
|
assert_equal('first completion', line)
|
||||||
|
ensure
|
||||||
|
Readline.completer_quote_characters = saved_completer_quote_characters
|
||||||
|
Readline.completer_word_break_characters = saved_completer_word_break_characters
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_using_quoting_detection_proc_with_multibyte_input
|
||||||
|
saved_completer_quote_characters = Readline.completer_quote_characters
|
||||||
|
saved_completer_word_break_characters = Readline.completer_word_break_characters
|
||||||
|
return unless Readline.respond_to?(:quoting_detection_proc=)
|
||||||
|
unless Encoding.find("locale") == Encoding::UTF_8
|
||||||
|
return if assert_under_utf8
|
||||||
|
skip 'this test needs UTF-8 locale'
|
||||||
|
end
|
||||||
|
|
||||||
|
passed_text = nil
|
||||||
|
escaped_char_indexes = []
|
||||||
|
line = nil
|
||||||
|
|
||||||
|
with_temp_stdio do |stdin, stdout|
|
||||||
|
replace_stdio(stdin.path, stdout.path) do
|
||||||
|
Readline.completion_proc = -> (text) do
|
||||||
|
passed_text = text
|
||||||
|
['completion']
|
||||||
|
end
|
||||||
|
Readline.completer_quote_characters = '\'"'
|
||||||
|
Readline.completer_word_break_characters = ' '
|
||||||
|
Readline.quoting_detection_proc = -> (text, index) do
|
||||||
|
escaped = index > 0 && text[index-1] == '\\'
|
||||||
|
escaped_char_indexes << index if escaped
|
||||||
|
escaped
|
||||||
|
end
|
||||||
|
|
||||||
|
stdin.write("\u3042\u3093 second\\ third\t")
|
||||||
|
stdin.flush
|
||||||
|
line = Readline.readline('> ', false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal([10], escaped_char_indexes)
|
||||||
|
assert_equal('second\\ third', passed_text)
|
||||||
|
assert_equal("\u3042\u3093 completion", line)
|
||||||
|
ensure
|
||||||
|
Readline.completer_quote_characters = saved_completer_quote_characters
|
||||||
|
Readline.completer_word_break_characters = saved_completer_word_break_characters
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def replace_stdio(stdin_path, stdout_path)
|
def replace_stdio(stdin_path, stdout_path)
|
||||||
|
|
Loading…
Add table
Reference in a new issue