Question

I have been trying to get tab completion working.. I am very confused and don't know what to do. Could you please take a look at my code and tell me how I could possibly fix it.

By the way I used rl_attempted_completion_function since I got it from an online tutorial but it is an C++ function. What function can I use to replace it without making changes.

Thanks

   static char** completion( const char * text , int start,  int end){
            char **matches;
            matches = (char **)NULL;

            if (start == 0)
                    matches = rl_completion_matches ((char*)text, &generator);

            return (matches);
    }

    char* generator(const char* text, int state) {
            int index, len;
            char *comm;
            if (!state) {
                    index = 0;
                    len = (int)strlen (text);
            }

            while ( (*comm = newEnv[index])) {
                    index++;
                    if (strncmp (comm, text, len) == 0)
                            return ((comm));
            }
            return NULL;
    }

    int main (int argc,  char * argv[]) {

            using_history();
            rl_readline_name = basename(argv[0]);

            rl_attempted_completion_function = completion;

            while ( readline(">> ")!= NULL )  
                    rl_bind_key('\t',rl_complete);

            return 0;
    }
Was it helpful?

Solution

I notice this:

char *comm;
...
while ( (*comm = newEnv[index])) {

I don't know what the return type of newEnv is, but you probably want to put it in comm, not *comm, because you didn't point comm at anything.

OTHER TIPS

Your code is very similar to an example in the readline manual. The bug I see is that you have not declared index and len in the generator function to be static.

As mentioned in the top answer from Tom Zych, you should change *comm = newEnv[index] to comm = newEnv[index]

But I also see a couple other problems with this as-is

For one, these two variables should be static:

int index, len;

Like so: static int index, len;

Otherwise, you are always returning the first match (And I think you might end up with an infinite loop if there is a match). Making these static makes it so that subsequent calls for a non zero state look for matches starting from the last match. You will get a state of 0 for the first completion suggestion search of each tab completion request, if I'm understanding correctly (Which will reset the static index to 0)

Only looking for the length of the input when you get a state of 0 is an optimization (Since you will get the same input, you can sort of "cache" it), but the static index is not: It is required

Next, you should change

return ((comm));

To

return strdup(comm);

And finally, change completion to:

char **completion(const char *text, int start, int end)
{
    return rl_completion_matches(text, generator);
}

The 0 start check is not needed

Also, make sure your newEnv array has a NULL value at the end, like so:

char* envVar[] = {"a", "b", NULL};

As an aside, make sure you're forward declaring or defining generator before you use it within completion

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top