summaryrefslogtreecommitdiff
path: root/ext/readline/readline.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/readline/readline.c')
-rw-r--r--ext/readline/readline.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index 14b66ea6c1..130ea9ce59 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -59,6 +59,10 @@ static VALUE mReadline;
#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 self)
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(const char *text, int start, int end)
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)
#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)
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)
#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