customizing the readline module

Huaiyu Zhu huaiyu at gauss.almadan.ibm.com
Mon Aug 19 20:44:58 CEST 2002


holger krekel <pyth at devel.trillke.net> wrote:
>Huaiyu Zhu wrote:
>> Is it possible to customize readline so that the prompt at each stage can be
>> modified depending on what have been chosen?
>
>don't understand.  you want to modify the *prompt*?  The one that is
>usually set by the environment variable PS1? 

Sorry for the misleading term.  I meant the 'prompted words for completion',
not PS1.  For example, in Python, if you hit 'd' and press TAB, you are
given a choice of def, del, delattr, and so on.  By prompt I mean this set
of words.  

In the shell, if you hit TAB at the start of command line, you are prompted
with a set of command names, but if you hist TAB at the second word, you are
prompted with a set of file names.  I want to vary this set of prompted
choices at each stage.  That is, I want this set to be a function of the
partial command line before the current cursor position.

>
>> Example:
>>     Give a data structure
>>     
>>         {a:{b:1, c:1, d:1}, e:{f:1, g:{h:1,i:1}}}
>>     
>>     The first tab should prompt choices (a, e).  The second tab should prompt
>>     (b, c, d) if a is chosen, or (f, g) if b is chosen.
>> 
>> My failed attempts appear to boil down to the following situation.  As far
>> as I can figure out, the readline module uses a completor c by calling c(x,
>> n) repeatedly, where x is the partial word and n is the n-th time it is
>> called.  This does not appear to provide an adequate means to disambiguate
>> between [e] and [e,g] if e and g happen to be the same word.
>
>Again i am lost.  Note that the multiple calls to the completer function
>are only a protocol to pass a list of strings. 

Let me see if I can make this example more concrete.  For this example,
let's assume that a='a', b='b', etc.  The acceptable answers from the
interaction (the "legal command lines") would be one of the following

a b 
a c
a d
e f
e g h
e g i

The intended behavior would be this: When user types 'e' and hit tab, the
given choices should be (f, g).  If the user typed 'e g', the given choices
should be (h, i).  That is, the set of choices would depend on what the user
has typed so far on that line.

I can do this with the current readline module, as long as the last word 'g'
uniquely identify the history 'e g', with the assumption that backspace is
not used to change a partial answer.

This breaks down when e and g are the same word.  There is not sufficient
information in deciding between the choices (f, g), which follows 'e', and
(h, i), which follows 'e e'.

>> Given the above structure, it is easy a write a function 
>>     [] -> (a,b)
>>     [a] -> (b,c,d)
>>     [e] -> (f,g)
>>     [e,g] -> (h,i)
>> 
>> Is there a way for readline to accept mapping from a history to a list of
>> choices?  The completer object could cache the history, of course, as long
>> as readline can somehow indicate that it has advanced one word.
>
>Please try to come up with real-life examples and please, don't bring
>in so much terminology.  What do you mean with history?  And what
>is a mapping from 'a history to a list of choices'?

I hope the above explanation is clear enough by now.  By 'history', I'm
refering to the partial command line from the beginning of the line up to
the current cursor point.  (I realize there is another unintended collision
of terminology with shell history.)  

An example (which is my typical usage) is this.  I'm doing several numerical
experiments with a few parameters.  Sometime, such as during debugging, I'd
like to set the parameters by hand, but other times I want them to be
obtained from config files, in which case I'd like to set the config file
names.  So a command line might be any of the following

run -p <a> <b> <c> <d>
run -c <config-file-name>
run -c <config-file-name> -r <result-dir-name>

or some other combinations.  Obviously, the choices given after 'run -c'
should be different from 'run -r'.  The choices for each of <a>, <b>,
... should also be different.  Some of them would be numbers, in that case
it would be useful if the prompted choice could be the variable name or its
allowed range.  I'd like to know if this is doable without using curses
module.

Just to preempt another possible confusion, let me emphasize that I'm not
dealing with the Unix shell command lines.  It is about using the readline
module in an interactive shell written in Python.  So why don't I just use a
dialog style interaction?  The answer is that in most cases the ability to
use shell history is very handy.


Huaiyu





More information about the Python-list mailing list