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

ruby-changes:18474

From: kouji <ko1@a...>
Date: Sun, 9 Jan 2011 14:54:46 +0900 (JST)
Subject: [ruby-changes:18474] Ruby:r30496 (trunk): * ext/readline/readline.c: apply a patch from Nobuyoshi Nakada.

kouji	2011-01-09 14:54:33 +0900 (Sun, 09 Jan 2011)

  New Revision: 30496

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=30496

  Log:
    * ext/readline/readline.c: apply a patch from Nobuyoshi Nakada.
      fixed #3616 [ruby-core:31484] IRB + readline incorrectly counts
      non-printing characters in prompt

  Modified files:
    trunk/ChangeLog
    trunk/ext/readline/readline.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 30495)
+++ ChangeLog	(revision 30496)
@@ -1,3 +1,9 @@
+Sun Jan  9 14:47:50 2011  TAKAO Kouji  <kouji@t...>
+
+	* ext/readline/readline.c: apply a patch from Nobuyoshi Nakada.
+	  fixed #3616 [ruby-core:31484] IRB + readline incorrectly counts
+	  non-printing characters in prompt
+
 Sat Jan  8 21:47:26 2011  Tanaka Akira  <akr@f...>
 
 	* enum.c (enum_sort_by): use rb_ary_resize.
Index: ext/readline/readline.c
===================================================================
--- ext/readline/readline.c	(revision 30495)
+++ ext/readline/readline.c	(revision 30496)
@@ -43,10 +43,20 @@
 static VALUE mReadline;
 
 #define EDIT_LINE_LIBRARY_VERSION "EditLine wrapper"
+#ifndef USE_INSERT_IGNORE_ESCAPE
+# ifndef HAVE_EDITLINE_READLINE_H
+#  define USE_INSERT_IGNORE_ESCAPE 1
+# else
+#  define USE_INSERT_IGNORE_ESCAPE 0
+# endif
+#endif
 
 #define COMPLETION_PROC "completion_proc"
 #define COMPLETION_CASE_FOLD "completion_case_fold"
 static ID completion_proc, completion_case_fold;
+#if USE_INSERT_IGNORE_ESCAPE
+static ID id_orig_prompt, id_last_prompt;
+#endif
 
 #ifndef HAVE_RL_FILENAME_COMPLETION_FUNCTION
 # define rl_filename_completion_function filename_completion_function
@@ -145,7 +155,82 @@
 }
 #endif
 
+#if USE_INSERT_IGNORE_ESCAPE
 static VALUE
+insert_ignore_escape(VALUE self, VALUE prompt)
+{
+    VALUE last_prompt, orig_prompt = rb_attr_get(self, id_orig_prompt);
+    int ignoring = 0;
+    const char *s0, *s, *e;
+    long len;
+    static const char ignore_code[2] = {RL_PROMPT_START_IGNORE, RL_PROMPT_END_IGNORE};
+
+    prompt = rb_str_new_shared(prompt);
+    last_prompt = rb_attr_get(self, id_last_prompt);
+    if (orig_prompt == prompt) return last_prompt;
+    len = RSTRING_LEN(prompt);
+    if (NIL_P(last_prompt)) {
+	last_prompt = rb_str_tmp_new(len);
+    }
+
+    s = s0 = RSTRING_PTR(prompt);
+    e = s0 + len;
+    rb_str_set_len(last_prompt, 0);
+    while (s < e && *s) {
+	switch (*s) {
+	  case RL_PROMPT_START_IGNORE:
+	    ignoring = -1;
+	    rb_str_cat(last_prompt, s0, ++s - s0);
+	    s0 = s;
+	    break;
+	  case RL_PROMPT_END_IGNORE:
+	    ignoring = 0;
+	    rb_str_cat(last_prompt, s0, ++s - s0);
+	    s0 = s;
+	    break;
+	  case '\033':
+	    if (++s < e && *s == '[') {
+		rb_str_cat(last_prompt, s0, s - s0 - 1);
+		s0 = s - 1;
+		while (++s < e && *s) {
+		    if (ISALPHA(*s)) {
+			if (!ignoring) {
+			    ignoring = 1;
+			    rb_str_cat(last_prompt, ignore_code+0, 1);
+			}
+			rb_str_cat(last_prompt, s0, ++s - s0);
+			s0 = s;
+			break;
+		    }
+		    else if (!('0' <= *s && *s <= '9' || *s == ';')) {
+			break;
+		    }
+		}
+	    }
+	    break;
+	  default:
+	    if (ignoring > 0) {
+		ignoring = 0;
+		rb_str_cat(last_prompt, ignore_code+1, 1);
+	    }
+	    s++;
+	    break;
+	}
+    }
+    if (ignoring > 0) {
+	ignoring = 0;
+	rb_str_cat(last_prompt, ignore_code+1, 1);
+    }
+    rb_str_cat(last_prompt, s0, s - s0);
+
+    rb_ivar_set(self, id_orig_prompt, prompt);
+    rb_ivar_set(self, id_last_prompt, last_prompt);
+
+    return last_prompt;
+}
+#endif
+
+static VALUE
 readline_get(VALUE prompt)
 {
     return (VALUE)readline((char *)prompt);
@@ -248,6 +333,10 @@
     rb_secure(4);
     if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) {
 	OutputStringValue(tmp);
+#if USE_INSERT_IGNORE_ESCAPE
+	tmp = insert_ignore_escape(self, tmp);
+	rb_str_locktmp(tmp);
+#endif
 	prompt = RSTRING_PTR(tmp);
     }
 
@@ -257,6 +346,11 @@
     rl_prep_terminal(1);
 #endif
     buff = (char*)rb_protect(readline_get, (VALUE)prompt, &status);
+#if USE_INSERT_IGNORE_ESCAPE
+    if (prompt) {
+	rb_str_unlocktmp(tmp);
+    }
+#endif
     if (status) {
 #if defined HAVE_RL_CLEANUP_AFTER_SIGNAL
         /* restore terminal mode and signal handler*/
@@ -1383,6 +1477,11 @@
     rb_define_singleton_method(mReadline, "refresh_line",
 			       readline_s_refresh_line, 0);
 
+#if USE_INSERT_IGNORE_ESCAPE
+    CONST_ID(id_orig_prompt, "orig_prompt");
+    CONST_ID(id_last_prompt, "last_prompt");
+#endif
+
     history = rb_obj_alloc(rb_cObject);
     rb_extend_object(history, rb_mEnumerable);
     rb_define_singleton_method(history,"to_s", hist_to_s, 0);

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

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