Search code examples
c++linuxreadlinelibreadline

Bash autocomplete an option without running the application


I have found this code as a bash autocomplete. But, it looks strange to me. What if I do not like to run the code at all. If I would like to type ./a.out then space (without entering) and then by pressing tab, I would like to see only two options apple and cherry and if I type a and press tab, then it autocomplete the option apple and similarly for c. Let's say only one of the two options are acceptable:

./a.out apple
./a.out cherry

where apple and cherry are options and not the name of the files in the directory. In the first case, I would like the program types that your option is apple and in the second case your option is cherry. In any other case, the program should print an error that the option is not valid.

All examples that I find on the internet such as what follows look like that you should run the program first, then it reacts. The while loop inside the main function collides with the normal functionality of the program. Have I misunderstood the readline library? Is the above-described application possible to implement by editing the following code?

// sudo apt-get install libreadline-dev
// g++ -std=c++11 main.cpp -lreadline

#include <iostream>

#include "readline/readline.h"
#include "readline/history.h"

using namespace std;

int main(int argc, char** argv)
{
    const char *line;
    while ((line = readline("? ")) != nullptr) {
        cout << "[" << line << "]" << endl;
        if (*line) add_history(line);
        free(line);
    }
// if(argc!=2)
// {
//  cout<<"<exe> one_parameter"<<endl;
//  return 1;
// }
// string option=argv[1];
// if(option=="apple" || option=="cherry")
//  cout<<"Your option is "<<option<<endl;
// else
// {
//  cout<<"Error: invalid option "<<option<<endl;
//  return 1;
// }

    return 0;
}

Solution

  • This has nothing to do with your executable. You need to put this in a file and source (source autocomplete_file or . autocomplete_file) it in the bash.

    _a_complete_()
    {
        local word=${COMP_WORDS[COMP_CWORD]}
        local files='apple cherry'
    
        COMPREPLY=( $( compgen -W "${files}" -- ${word} ) )
    }
    
    complete -F _a_complete_ ./a.out
    

    Here a nice documentation can be found.