C 中的制表符补全(readline 库)

发布于 2024-12-01 22:01:24 字数 1239 浏览 1 评论 0原文

我一直在尝试让制表符完成工作。我很困惑,不知道该怎么办。您能看一下我的代码并告诉我如何修复它吗?

顺便说一句,我使用了 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;
    }

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

旧竹 2024-12-08 22:01:24

我注意到这一点:

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

我不知道 newEnv 的返回类型是什么,但您可能想将其放在 comm 中,而不是 *comm >,因为你没有将comm指向任何东西。

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.

提笔落墨 2024-12-08 22:01:24

您的代码与 readline 手册中的示例非常相似。我看到的错误是您没有在生成器函数中将 index 和 len 声明为静态

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.

彻夜缠绵 2024-12-08 22:01:24

正如 Tom Zych 的最佳答案中提到的,您应该将 *comm = newEnv[index] 更改为 comm = newEnv[index]

但我还看到了其他一些问题首先

,这两个变量应该是静态的:

int index, len;

就像这样:
静态 int 索引,len;

否则,您总是返回第一个匹配项(我认为如果有匹配项,您可能会陷入无限循环)。使这些静态化使得后续对非零状态的调用可以从最后一个匹配开始查找匹配。如果我理解正确的话,对于每个选项卡完成请求的第一个完成建议搜索,您将获得 0 状态(这会将静态索引重置为 0)

仅在状态为 0 时查找输入的长度是一种优化(因为您将获得相同的输入,所以您可以对其进行排序“缓存”),但静态索引不是:它是必需的

接下来,您应该更改

return ((comm));

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

顺便说一句,请确保在 completion 中使用它之前先声明或定义 generator

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文