Завершение табуляции в C (библиотека readline)

Я пытался заставить работать завершение табуляции. Я очень смущен и не знаю, что делать. Не могли бы вы взглянуть на мой код и сказать мне, как я могу его исправить.

Кстати, я использовал rl_attempted_completion_function, так как я получил его из онлайн-учебника, но это функция C++. Какую функцию я могу использовать, чтобы заменить его, не внося изменений.

Спасибо

   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;
    }

person MattD    schedule 30.08.2011    source источник
comment
В каком контексте работает завершение табуляции? Оболочка, редактор, что-то еще?   -  person Tom Zych    schedule 30.08.2011
comment
Вы используете какую-то библиотеку для этого? Пожалуйста, скажите, что это такое, иначе никому будет трудно вам помочь.   -  person hmakholm left over Monica    schedule 30.08.2011
comment
rl_attempted_completion_function явно означает Readline, например. Библиотека чтения GNU.   -  person osgx    schedule 30.08.2011
comment
atm выдает ошибку сегментации при нажатии на вкладку   -  person MattD    schedule 30.08.2011


Ответы (3)


Я замечаю это:

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

Я не знаю, какой тип возвращает newEnv, но вы, вероятно, захотите поместить его в comm, а не *comm, потому что вы ни на что не указали comm.

person Tom Zych    schedule 30.08.2011
comment
да, я исправил это, и он удалил ошибку сегментации, но по какой-то причине он все еще не возвращает newEnv[] - person MattD; 30.08.2011
comment
Похоже, ваш тест strncmp работает неправильно, поэтому он проваливается до return NULL. Попробуйте распечатать значение comm перед каждым тестом. Убедитесь, что generator также получает аргументы, которые вы ожидаете. - person Tom Zych; 30.08.2011

Ваш код очень похож на пример в руководстве readline. Ошибка, которую я вижу, заключается в том, что вы не объявили index и len в функции генератора как static.

person MattW    schedule 19.06.2015

Как упоминалось в верхнем ответе Тома Зыка, вы должны изменить *comm = newEnv[index] на comm = newEnv[index]

Но я также вижу пару других проблем с этим как есть

Во-первых, эти две переменные должны быть статическими:

int index, len;

Вот так: статический индекс int, len;

В противном случае вы всегда возвращаете первое совпадение (и я думаю, что вы можете получить бесконечный цикл, если есть совпадение). Если сделать их статическими, последующие вызовы ненулевого состояния будут искать совпадения, начиная с последнего совпадения. Если я правильно понимаю, вы получите состояние 0 для первого предложения о завершении каждого запроса на завершение вкладки (что сбросит статический индекс до 0)

Только поиск длины ввода, когда вы получаете состояние 0, является оптимизацией (поскольку вы получите тот же ввод, вы можете его кэшировать), но статический индекс не является: он требуется

Далее следует изменить

return ((comm));

To

return strdup(comm);

И, наконец, измените завершение на:

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

Проверка запуска 0 не требуется

Кроме того, убедитесь, что ваш массив newEnv имеет значение NULL в конце, например:

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

Кроме того, убедитесь, что вы заранее объявляете или определяете generator, прежде чем использовать его в completion.

person Nicolás Abram    schedule 18.09.2020