Steven D'Aprano <steve+comp.lang.pyt...@pearwood.info> writes:

> On Mon, 21 Jul 2014 17:57:22 +0200, Lele Gaifax wrote:
>> Granted, the readline library exposes a "operate-and-get-next" function,
>> by default bound to \C-o...
>
> Have you actually got that working in Python with the readline module? 
> I've tried and tried and cannot get it to work. Any hints gratefully 
> appreciated.

This is just a first attempt to adapt the Bash code to the Python
readline.c module: I'm very surprised that the half-an-hour I spent on
it, mostly to locate related code, actually full filled the goal :-)

The patch isn't complete, in particular, it does not work on Apple's
libedit, because I have no way to try it on that system. Also, I'm not
fluent with Mercurial, so this is just a "hg diff".

Even if I know this is not the right forum and I should (and I
eventually do, assuming a positive feedback) instead open a ticket and
attach the patch there, I'd like to hear opinions on whether this should
be enabled by default, and possibly get in touch with some Apple
owner...

ciao, lele.
diff -r e5f78085499e Modules/readline.c
--- a/Modules/readline.c	Mon Aug 18 17:48:15 2014 +0300
+++ b/Modules/readline.c	Mon Aug 18 20:46:43 2014 +0200
@@ -73,6 +73,13 @@
                                    int num_matches, int max_length);
 #endif
 
+#if !defined(__APPLE__)
+static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL;
+static int hist_last_line_added;
+static int set_saved_history(void);
+static int operate_and_get_next(int count, int c);
+#endif
+
 /* Memory allocated for rl_completer_word_break_characters
    (see issue #17289 for the motivation). */
 static char *completer_word_break_characters;
@@ -1032,6 +1039,10 @@
            With libedit, this call makes readline() crash. */
         rl_variable_bind ("enable-meta-key", "off");
     }
+    
+    /* XXX: determine whether the following works on libedit */
+    rl_add_defun("operate-and-get-next", operate_and_get_next, -1);
+    rl_bind_key_if_unbound_in_map(CTRL('O'), operate_and_get_next, emacs_standard_keymap);
 #endif
 
     /* Initialize (allows .inputrc to override)
@@ -1287,3 +1298,61 @@
     setup_readline(mod_state);
     return m;
 }
+
+#ifndef __APPLE__
+
+/* XXX: determine whether the following works on libedit */
+
+/* Following code taken from bash' bashline.c */
+
+/* The equivalent of the Korn shell C-o operate-and-get-next-history-line
+   editing command. */
+static int saved_history_line_to_use = -1;
+static int last_saved_history_line = -1;
+
+#define HISTORY_FULL() (history_is_stifled() && history_length >= history_max_entries)
+
+static int
+set_saved_history()
+{
+    /* XXX - compensate for assumption that history was `shuffled' if it was
+       actually not. */
+    if (HISTORY_FULL() &&
+	hist_last_line_added == 0 &&
+	saved_history_line_to_use < history_length - 1)
+	saved_history_line_to_use++;
+
+    if (saved_history_line_to_use >= 0)	{
+	rl_get_previous_history(history_length - saved_history_line_to_use, 0);
+	last_saved_history_line = saved_history_line_to_use;
+    }
+    
+    saved_history_line_to_use = -1;
+    rl_startup_hook = old_rl_startup_hook;
+    
+    return 0;
+}
+
+static int
+operate_and_get_next (int count, int c)
+{
+    int where;
+
+    /* Accept the current line. */
+    rl_newline(1, c);
+    
+    /* Find the current line, and find the next line to use. */
+    where = where_history();
+    
+    if (HISTORY_FULL() || (where >= history_length - 1))
+	saved_history_line_to_use = where;
+    else
+	saved_history_line_to_use = where + 1;
+    
+    old_rl_startup_hook = rl_startup_hook;
+    rl_startup_hook = set_saved_history;
+    
+    return 0;
+}
+
+#endif
-- 
nickname: Lele Gaifax | Quando vivrò di quello che ho pensato ieri
real: Emanuele Gaifas | comincerò ad aver paura di chi mi copia.
l...@metapensiero.it  |                 -- Fortunato Depero, 1929.
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to