[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Bug-readline] partial word completion
From: |
David Fang |
Subject: |
Re: [Bug-readline] partial word completion |
Date: |
Mon, 23 Feb 2009 20:05:01 -0500 (EST) |
Hi Chet,
Your suggestion worked, thanks for your help! I just provided my
own display hook that transformed the string pointers by munching up to
the common prefix of the hierarchical name, and passed that to the
standard display-matches function. I had to append a call to
rl_forced_update_display() to restore the line buffer. (code pasted below)
The standard readline mechanism for multiple completions is an array of
matches, where matches[0] contains the common prefix, and matches[1..n]
contain the possible completions, including the common prefix. This
allows readline to sort, eliminate duplicates, and so on.
Ahh, I didn't about matches[0] being special before.
That explains a few things... :)
I would like this to behave similarly to directory completion:
% cd foo/bar/x<TAB>
% cd foo/bar/xx
You need to handle the display of possible completions yourself.
The way to do that is to `register' a function to display matches by
assigning its address to rl_completion_display_matches_hook. That
function receives the list of matches in the form described above, the
number of matches in the list, and the length in characters of the
longest entry.
Your code can manipulate the list of matches to remove the common
prefix, if you'd like, but make sure that you keep any new common prefix
in matches[0]. Readline provides a convenience function to display
the contents of the array, rl_display_match_list(), which you can call
with your modified array and the same two additional arguments your
function received, modified appropriately.
For anyone interested, my display hook function looks like this:
// candidate matches can look like (hierarchical prefix always match):
// for set:
// x. x.foo x.bar x.baz
//
// desired behavior:
// prompt> x.<TAB>
// foo bar baz
// prompt> x.
// prompt> x.b<TAB>
// prompt> x.ba<TAB>
// bar baz
void
my_display_matches_hook(char** matches, int len, int max) {
if (len) {
// find the last '.', if any
char* tail = strrchr(matches[0], '.');
if (tail) {
const int dist = tail -matches[0] +1; // past '.'
std::vector<char*> mod_matches;
mod_matches.reserve(len+1);
mod_matches.push_back(matches[0]);
int i=1;
for ( ; i<=len; ++i) {
// remove common prefix
assert(matches[i]);
const size_t ml = strlen(matches[i]);
assert(ml > size_t(dist));
mod_matches.push_back(matches[i] +dist);
}
assert(max > dist);
rl_display_match_list(&mod_matches[0], len, max -dist);
} else {
// use default printer
rl_display_match_list(matches, len, max);
}
rl_forced_update_display(); // refresh prompt, line-buffer
}
}
Fang
David Fang
http://www.csl.cornell.edu/~fang/
http://www.achronix.com/