[Patches] [ python-Patches-494066 ] Access to readline history elements

noreply@sourceforge.net noreply@sourceforge.net
Sat, 23 Mar 2002 17:12:13 -0800


Patches item #494066, was opened at 2001-12-17 04:04
You can respond by visiting: 
http://sourceforge.net/tracker/?func=detail&atid=305470&aid=494066&group_id=5470

Category: Library (Lib)
Group: Python 2.3
>Status: Closed
>Resolution: Accepted
Priority: 5
Submitted By: Chuck Blake (cblake)
Assigned to: Nobody/Anonymous (nobody)
Summary: Access to readline history elements

Initial Comment:
The current readlinemodule.c has a relatively minimal
wrapper around the functionality of the GNU readline
and history libraries.  That may be fine, and since
some try to use libeditline instead it may be the best.

However the current module does not enable any access
from within Python to the libreadline maintained list
of input lines.  The ideal thing would be to actually
export that dynamically maintained C list as a Python 
object.  In lieu of that more complex change, my patch
simply adds very simple history_get() and history_len()
methods.  This is the least one needs to access the
list.  I'm pretty sure the library functions go waaaay
back, probably to the merger of the history and
readline libraries.

This patch also adds one final little ingredient which
is rl_redisplay() in the wrapper for rl_insert_text().
Without this the user cannot see the inserted text
until they type another character, which seems pretty
undesirable.

Together these two updates allow the regular Unix
readline-enabled shell to perform "auto indentation".
I.e., inserting into the edit buffer the leading 
whitespace from the preceding non-result producing
line.  Since it can be editted, one can just backspace
a couple times to reverse the autoindent.

This makes the basic readline-enabled read-eval-print 
loop substantially more pleasant.  I can provide an
example PYTHONSTARTUP file that shows how to use it.
Only a tiny 8 line or so pre_input_hook is needed and
a slightly smart sys.ps1 or sys.ps2 object that
communicates via a variable to our hook function 
whether or not the parser is expecting more input.

----------------------------------------------------------------------

>Comment By: Neil Schemenauer (nascheme)
Date: 2002-03-24 01:12

Message:
Logged In: YES 
user_id=35752

Checked in as readline 2.45.

I renamed the functions to get_history_item and 
get_current_history_length.  The last one's a bit 
unwieldly but hopefully clear.
get_history_length really should have been called
get_max_history_length.  Too late for that unfortunately.

I also added a redisplay function instead of adding the
redisplay call to insert_text.

----------------------------------------------------------------------

Comment By: Chuck Blake (cblake)
Date: 2001-12-17 20:41

Message:
Logged In: YES 
user_id=403855

Sounds quite reasonable.  Having a nice readline completer
and history matching interface is pretty cool when you're
using the shell over a network where remote X windows would
be painful.  It's been a very useful interface for a while,
and likely will be for the forseeable future.

When I get a chance I'll work on seeing what parts of 
readline have been around for a very long time (e.g. since
readline 2.0 or so) and try to wrap the basically available 
features more intelligently with Python objects, e.g. a
tuple or list for command input history.

Hopefully not too much will need to be conditionalized on 
readline versions.  A lot of added functionality could be
written trivially in Python if there is access to the 
library structures and exporting of hook/event type functions.

----------------------------------------------------------------------

Comment By: Guido van Rossum (gvanrossum)
Date: 2001-12-17 20:13

Message:
Logged In: YES 
user_id=6380

OK, in the sake of stability, let's not do any of this in
2.2 then. Sounds like there are plenty of things we *could*
do. I'm not against expanding the readline module -- but I
don't have a use for it in mind myself. For fancy editing I
much prefer IDLE's command line editor, since it lets you
edit an entire multi-line command as a single unit, than on
a per-line basis as readline does...

----------------------------------------------------------------------

Comment By: Chuck Blake (cblake)
Date: 2001-12-17 20:00

Message:
Logged In: YES 
user_id=403855

I have something this in my ~/.py/rc.py (STARTUP file).
The just_did_a_result var is also maintained by sys.ps1.

    def auto_indent():
        global just_did_a_result
        if just_did_a_result:
            just_did_a_result = 0
            return
        last = readline.history_get(readline.history_len())
        spc = len(last) - len(last.lstrip())
        if spc > 0:
            readline.insert_text(last[ : spc])
    readline.set_pre_input_hook(auto_indent)

I don't know if you have a system where set_pre_input_hook
is available.  Unless you have access to the history or at
least the very last input line from within Python, then it
doesn't seem very useful.  That is because there is no way
for your input_hook to know when/what it should stuff text
into your command buffer.

The redisplay() is innocuous when it happens to be
unnecessary, so it shouldn't be very objecionable.
It's an interactive prompt so hyper-optimization isn't
very important or noticeable.  Even on a slow terminal
it is only a few characters in one command prompt being
re-drawn.

If it is really an issue, though, then an alternative to
adding my redisplay() fix would be to export another
function from readline to Python, namely rl_redisplay().
Anyone's Python code could then just call it as necessary.

Longer term, it seems like an awful lot more libhistory and
libreadline functionality could profitably be included in 
the readline module.  That's surely a 2.3 or later change,
but the exporting of rl_redisplay() might be a closer step
in that direction.

----------------------------------------------------------------------

Comment By: Guido van Rossum (gvanrossum)
Date: 2001-12-17 19:40

Message:
Logged In: YES 
user_id=6380

Hm, I was going to see if the insert_text fix was a simple
enough fix to apply to 2.2, but I don't have an example of
where this is needed. If I call it from the startup hook the
text I insert is already being displayed.

----------------------------------------------------------------------

You can respond by visiting: 
http://sourceforge.net/tracker/?func=detail&atid=305470&aid=494066&group_id=5470