【问题标题】:Tab Completion in C (readline library)C 中的制表符补全(readline 库)
【发布时间】:2011-08-30 00:57:40
【问题描述】:

我一直在尝试让标签完成工作。我很困惑,不知道该怎么做。能否请您看一下我的代码并告诉我如何修复它。

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

【问题讨论】:

  • 让选项卡完成在什么情况下工作?一个外壳、一个编辑器,还是别的什么?
  • 您是否为此使用了一些库?请告诉它是哪一个,否则任何人都很难帮助你。
  • rl_attempted_completion_function”明确表示 Readline,例如GNU readline 库。
  • atm 按下制表符时出现分段错误

标签: c tabs readline libreadline


【解决方案1】:

我注意到了这一点:

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

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

【讨论】:

  • 是的,我修复了它并删除了分段错误,但由于某种原因它仍然没有返回 newEnv[]
  • 看起来您的 strncmp 测试可能无法正常工作,因此它最终落入 return NULL。尝试在每次测试之前打印出comm 的值。确保generator 也得到了您期望的参数。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    但我也看到了其他几个问题

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

    int index, len;
    

    像这样: 静态 int 索引,长度;

    否则,您总是返回第一个匹配项(而且我认为如果有匹配项,您可能会以无限循环结束)。使这些静态化使得后续对非零状态的调用从最后一个匹配开始查找匹配。如果我理解正确,您将在每个选项卡完成请求的第一次完成建议搜索中获得 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-16
      相关资源
      最近更新 更多