[前][次][番号順一覧][スレッド一覧]

ruby-changes:44253

From: nobu <ko1@a...>
Date: Mon, 3 Oct 2016 17:20:12 +0900 (JST)
Subject: [ruby-changes:44253] nobu:r56326 (trunk): rl_char_is_quoted_p

nobu	2016-10-03 17:20:07 +0900 (Mon, 03 Oct 2016)

  New Revision: 56326

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=56326

  Log:
    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.

  Modified files:
    trunk/ChangeLog
    trunk/ext/readline/extconf.rb
    trunk/ext/readline/readline.c
    trunk/test/readline/test_readline.rb
Index: test/readline/test_readline.rb
===================================================================
--- test/readline/test_readline.rb	(revision 56325)
+++ test/readline/test_readline.rb	(revision 56326)
@@ -464,6 +464,92 @@ class TestReadline < Test::Unit::TestCas https://github.com/ruby/ruby/blob/trunk/test/readline/test_readline.rb#L464
     end
   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
 
   def replace_stdio(stdin_path, stdout_path)
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 56325)
+++ ChangeLog	(revision 56326)
@@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Mon Oct  3 17:20:05 2016  George Brocklehurst  <ruby@g...>
+
+	* 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@r...>
 
 	* include/ruby/ruby.h (RB_INT2FIX, RB_LONG2FIX): prefix RB to
Index: ext/readline/readline.c
===================================================================
--- ext/readline/readline.c	(revision 56325)
+++ ext/readline/readline.c	(revision 56326)
@@ -59,6 +59,10 @@ static VALUE mReadline; https://github.com/ruby/ruby/blob/trunk/ext/readline/readline.c#L59
 #define COMPLETION_PROC "completion_proc"
 #define COMPLETION_CASE_FOLD "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
 static ID id_orig_prompt, id_last_prompt;
 #endif
@@ -837,6 +841,51 @@ readline_s_get_completion_proc(VALUE sel https://github.com/ruby/ruby/blob/trunk/ext/readline/readline.c#L841
     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:
  *   Readline.completion_case_fold = bool
@@ -1012,6 +1061,32 @@ readline_attempted_completion_function(c https://github.com/ruby/ruby/blob/trunk/ext/readline/readline.c#L1061
     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
 /*
  * call-seq:
@@ -1828,6 +1903,9 @@ Init_readline(void) https://github.com/ruby/ruby/blob/trunk/ext/readline/readline.c#L1903
 #if defined(HAVE_RL_SPECIAL_PREFIXES)
     id_special_prefixes = rb_intern("special_prefixes");
 #endif
+#if defined HAVE_RL_CHAR_IS_QUOTED_P
+    quoting_detection_proc = rb_intern(QUOTING_DETECTION_PROC);
+#endif
 
     mReadline = rb_define_module("Readline");
     rb_define_module_function(mReadline, "readline",
@@ -1840,6 +1918,10 @@ Init_readline(void) https://github.com/ruby/ruby/blob/trunk/ext/readline/readline.c#L1918
                                readline_s_set_completion_proc, 1);
     rb_define_singleton_method(mReadline, "completion_proc",
                                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=",
                                readline_s_set_completion_case_fold, 1);
     rb_define_singleton_method(mReadline, "completion_case_fold",
@@ -1988,6 +2070,9 @@ Init_readline(void) https://github.com/ruby/ruby/blob/trunk/ext/readline/readline.c#L2070
 #if defined(HAVE_RL_PRE_INPUT_HOOK)
     rl_pre_input_hook = readline_pre_input_hook;
 #endif
+#if defined HAVE_RL_CHAR_IS_QUOTED_P
+    rl_char_is_quoted_p = &readline_char_is_quoted;
+#endif
 #ifdef HAVE_RL_CATCH_SIGNALS
     rl_catch_signals = 0;
 #endif
Index: ext/readline/extconf.rb
===================================================================
--- ext/readline/extconf.rb	(revision 56325)
+++ ext/readline/extconf.rb	(revision 56326)
@@ -81,6 +81,7 @@ readline.have_var("rl_library_version") https://github.com/ruby/ruby/blob/trunk/ext/readline/extconf.rb#L81
 readline.have_var("rl_editing_mode")
 readline.have_var("rl_line_buffer")
 readline.have_var("rl_point")
+readline.have_var("rl_char_is_quoted_p")
 # workaround for native windows.
 /mswin|bccwin|mingw/ !~ RUBY_PLATFORM && readline.have_var("rl_event_hook")
 /mswin|bccwin|mingw/ !~ RUBY_PLATFORM && readline.have_var("rl_catch_sigwinch")

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]