linenoise源码解析

来源:互联网 发布:js 汉字长度 编辑:程序博客网 时间:2024/06/05 11:41

一、简介:

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中定义了很多函数,下面几个图方便大家理清各函数之间的关系:

图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接口。


图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<MENU_PAIR> 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);    }}


0 0
原创粉丝点击