认识linenoise

5 篇文章 0 订阅

在学习redis的client源码的过程中,遇到了linenoise这个函数,知道它是一个处理命令的工具,但它具体能做什么工作,怎样作这些工作还是不清楚。通过查看相关资料,对linenoise的功能及部分使用方法有了初步的认识,下面就让我介绍一下:

1,linenoise是个处理指令的交互窗口

在redis中,linenoise用在client中,就像是一个交互窗口,在这个窗口中,可以输入指令,可以显示返回结果。除非Ctrl+C退出,一般程序会一直停留在这个窗口上。实现这一点,其实并不难,通过while调用函数就可以实现。看一下代码就清楚了,下面是linenoise的API接口。

char *linenoise(const char *prompt);

函数的输入值为提示符(更像linux的虚拟终端了,哈哈),函数的返回值为输入的字符串。

redis-cli通过如下方式调用linenoise,

while((line = linenoise(context ? config.prompt : "not connected> ")) != NULL) {

可以看出promt为config.promt配置的一个字符串,或者"not connected> "。

而只要输入不为空,就可以保证输入的line可以被while内的代码处理。下图为redis-cli连接server后的界面,更直观。

2,linenoise可以实现长字符串自动换行

在没有换行处理的情况下,不按回车键,字母就会一直往后填,就像text文本一样,很不容易阅读。而linenoise解决了这个问题,当字符个数超过终端串口的长度时,会自动换行,可以通过如下代码设置。

linenoiseSetMultiLine(1)

3,支持历史回溯功能

啥意思呢,就是更像linux虚拟终端了,它可以记录之前输入的命令,并可以通过UP、DOWN上下查找。也可以将之前的命令存储到文件之中。具体实现有以下四个函数。

    int linenoiseHistoryAdd(const char *line);
    int linenoiseHistorySetMaxLen(int len);
    int linenoiseHistorySave(const char *filename);
    int linenoiseHistoryLoad(const char *filename);

4,命令行自动补全功能

可以通过Tab键补全命令行,根据几个字母补全,补全的字母为何是需要自己定义的。主要函数包括两个:

/* Register a callback function to be called for tab-completion. */
void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) {
    completionCallback = fn;
}

void completion(const char *buf, linenoiseCompletions *lc)

其中,第一个函数为接口函数,将函数指针completionCallback指向completion。

第二个函数为实现函数,在redis中没有定义completion,直接定义了completionCallback。如下:

/* Linenoise completion callback. */
static void completionCallback(const char *buf, linenoiseCompletions *lc) {
    size_t startpos = 0; 
    int mask;
    int i;
    size_t matchlen;
    sds tmp; 
    
    //判断mask类型,是CLI_HELP_COMMAND,CLI_HELP_GROUP
    if (strncasecmp(buf,"help ",5) == 0) { 
        startpos = 5; 
        while (isspace(buf[startpos])) startpos++;
        mask = CLI_HELP_COMMAND | CLI_HELP_GROUP;
    } else {
        mask = CLI_HELP_COMMAND;
    }    

    //根据已输入的字符串及其长度判断,遍历helpEntries,查看其中是否有与输入字符串匹配的值
    for (i = 0; i < helpEntriesLen; i++) {
        if (!(helpEntries[i].type & mask)) continue;

        matchlen = strlen(buf+startpos);
        if (strncasecmp(buf+startpos,helpEntries[i].full,matchlen) == 0) { 
            tmp = sdsnewlen(buf,startpos);
            tmp = sdscat(tmp,helpEntries[i].full);
            linenoiseAddCompletion(lc,tmp);
            sdsfree(tmp);
        }
    }    
}

该函数可以根据已输入的字符串,查找helpEntries数组中与其匹配的字符串,找到后,填入到linenoiseAddCompletion(lc,tmp)中,进行补全。

5,语法提示功能

也是使用回调函数,在helpEntries中查找匹配的字符串,方法与命令补全类似。函数声明如下:

linenoiseSetHintsCallback(hints);
char *hints(const char *buf, int *color, int *bold);

前者为接口,后者为实现。

总结:

关于linenoise的功能及其使用方法具体就这5个,而这些功能如何实现还待进一步探究。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值