linenoise源码解析

一、简介:

linenoise是一个命令行编辑库(line editing library),readline的替代品,可以用于tab自动补全方法的实现。目前linenoise已经在Redis, MongoDB,Android中使用。其支持特性如下:


1) 尽可能简小,无配置,支持BSD授权。

2) 单行或多行编辑模式,实现常用的快捷键绑定。

3)支持历史键入文本查询。

4)兼容性。

5)大约只有1100行代码。

6)只使用VT100 escapes键码的子集。

注:readline是一个提供了交互式的文本编辑功能的开源跨平台程序库,它最早由Brian Fox使用C语言开发,于1989年发布。


二、文件构成:

linenoise库核心文件仅仅是linenoise.c和linenoise.h,在linenoise.h中定义了一个数据结构linenoiseCompletions,用于记录一行行完整的匹配输入。

typedef struct linenoiseCompletions {
  size_t len;
  char **cvec;
} linenoiseCompletions;

其中:

a)len表示完整的匹配输入的数目。

b)cvec相当于一个二维字符数组char[len][ ],用于记录len条匹配输入。

注意:真正的匹配输入需要在自己的注册函数中完成,也就是linenoise中的completionCallback。


三、函数调用:

linenoise.c中定义了很多函数,下面几个图方便大家理清各函数之间的关系:
linenoise源码解析_第1张图片
图3.1 函数调用图
1、其中completionCallback是定义的函数指针。
static linenoiseCompletionCallback *completionCallback = NULL;
再来看看linenoise.h文件中的函数定义:
typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);
void linenoiseSetCompletionCallback(linenoiseCompletionCallback *);
2、completionCallback就是需要用户自己去定义和实现的匹配自动补全方法。
3、函数char *linenoise(const char *prompt);是提供给用户去调用的API接口。

linenoise源码解析_第2张图片

图3.2 History函数调用

4、函数通过linenoiseHistoryLoad提供用户加载文件中的history记录,需要用户自己调用。

其实linenoiseHistoryLoad也是通过linenoiseHistoryAdd来添加history历史记录的,linenoiseHistoryAdd也可以供用户自己调用。

5、对于与linenoise edit相关度函数都是在completeEdit()函数中调用的,具体代码就不再赘述。


四、示例代码:

由于completionCallback函数需要用户自己去定义的自动补全方法,下面是一个示例代码,仅供参考。

SYS_CMD cmd[SYS_CMD_NUM] = {
    {"enable",      ENABLE},
    {"disable",     DISABLE},
    {"log",         LOG},
    {"dump",        DUMP},
    {"all",         ALL},
    {"status",      0},
    {"help",        0},
    {"exit",        0},
};
list componentList;

void tabCompletion(const char *buf, linenoiseCompletions *lc) {
    unsigned int  index =0, uLen = 0;
    const char *pLastWord = NULL;
    char *completion = NULL;

    if (buf) {
        pLastWord = buf;
        if (strlen(buf) > 0) {
            pLastWord += strlen(buf) - 1;
            while (uLen < strlen(buf) && *pLastWord != ' ') {
                pLastWord--; uLen++;
            }
            pLastWord++;
            uLen = strlen(pLastWord);
        }
        uLen = strlen(buf) - uLen;
        completion = (char *)malloc(sizeof(char) * (uLen + MAX_CMD_LEN));
        if (completion == NULL) {
            return;
        }
        memset(completion, 0, sizeof(char) * (uLen + MAX_CMD_LEN));
        strncpy(completion, buf, uLen);
        for(index = 0; index < SYS_CMD_NUM; index++) {
            if(strncmp(cmd[index].cmd, pLastWord, strlen(pLastWord)) == 0){
                strcpy(&completion[uLen],cmd[index].cmd);
                linenoiseAddCompletion(lc,completion);
            }
        }
        free(completion);
    }
}


你可能感兴趣的:(C,linenoise)