【解鎖】Linenoise——C命令行處理工具

Linenoise

今天解鎖一個開源的REPL工具——Linenoise。Linenoise是能夠徹底代替readline的,很是輕量級的命令行處理工具。Redis,MongoDB和Android都將Linenoise做爲命令行解析工具,那麼今天咱們就來解鎖這個開源的命令行處理工具,也許某一天在你的項目裏會派上用場。

特性

  • 支持單行和多行編輯模式,實現了經常使用的鍵綁定。
  • 支持歷史命令記錄
  • 支持命令不全
  • 支持命令提示
  • 超輕量級,大約1100行代碼(readline大約30,000行代碼)
  • 很是方便的融入你的項目李(一個.h,一個.c)

api簡介

Linenoise很是易於使用,閱讀該庫附帶的示例將使您儘快熟悉。如下是API調用及其使用方式。
char *linenoise(const char *prompt);

該接口現實命令提示符如hello> ,並返回用戶輸入緩衝區,當內存不足活文件結尾是返回NULL。
使用該接口循環接受用戶輸入命令並現實提示符git

while((line = linenoise("hello> ")) != NULL) {
    printf("You wrote: %s\n", line);
    linenoiseFree(line); /* Or just free(line) if you use libc malloc. */
}

x.gif

單行 or 多行編輯

默認狀況下linenoise使用單行編輯,若是須要輸入大量內容能夠開啓多行編輯模式。github

linenoiseSetMultiLine(1);

命令歷史

Linenoise支持歷史記錄,所以用戶沒必要一次又一次地鍵入相同的內容,而是可使用向下和向上箭頭來搜索和從新編輯已經插入的命令。——我的以爲這個功能很是有用。api

// 將一條你執行的命令添加到歷史,從而你能夠經過上下鍵找到它
int linenoiseHistoryAdd(const char *line);
// 要使用歷史記錄,您必須設置歷史記錄的長度(默認狀況下爲零,所以,若是未設置正確的長度,則將禁用歷史記錄)
int linenoiseHistorySetMaxLen(int len);
// Linenoise直接支持將歷史記錄保存到歷史記錄文件中,經過下面兩個接口能夠存取歷史文件內容
int linenoiseHistorySave(const char *filename);
int linenoiseHistoryLoad(const char *filename);

下面是一段範例代碼函數

while((line = linenoise("hello> ")) != NULL) {
        /* Do something with the string. */
        if (line[0] != '\0' && line[0] != '/') {
            printf("echo: '%s'\n", line);
            linenoiseHistoryAdd(line); /* Add to the history. */
            linenoiseHistorySave("history.txt"); /* Save the history on disk. */
        } else if (!strncmp(line,"/historylen",11)) {
            /* The "/historylen" command will change the history len. */
            int len = atoi(line+11);
            linenoiseHistorySetMaxLen(len);
        } else if (line[0] == '/') {
            printf("Unreconized command: %s\n", line);
        }
        free(line);
    }

自動補全

Linenoise支持自動補全功能,即用戶按下<TAB>鍵時會自動補全你的命令。
爲了實現這一功能,你能夠註冊並實現你的補全函數。工具

// 註冊自動補全函數completion
linenoiseSetCompletionCallback(completion);

註冊的補全必須是一個void返回值函數,須要傳入一個const char指針(該指針是用戶到目前爲止已鍵入的命令字符)和一個linenoiseCompletions對象指針,該對象指針用做是linenoiseAddCompletion將回調添加到補全中的參數。一個例子將使其更加清楚:編碼

void completion(const char *buf, linenoiseCompletions *lc) {
    if (buf[0] == 'h') {
        linenoiseAddCompletion(lc,"hello");
        linenoiseAddCompletion(lc,"hello there");
    }
}

用戶輸入'h'是會現實補全列表"hello","hello there"。
x.gifurl

命令提示

Linenoise具備稱爲提示的功能,當你使用Linenoise實現REPL時,這個功能很是有用。
當用戶鍵入時,該功能會在光標的右側顯示可能有用的提示。提示可使用與用戶鍵入的顏色不一樣的顏色顯示,也能夠加粗。
例如,當用戶開始輸入"git remote add"提示時,能夠在提示的右側顯示字符串<name> <url>
改接口與自動補全功能相似:spa

linenoiseSetHintsCallback(hints);

回調函數實現以下:命令行

char *hints(const char *buf, int *color, int *bold) {
    if (!strcasecmp(buf,"git remote add")) {
        *color = 35;
        *bold = 0;
        return " <name> <url>";
    }
    return NULL;
}

x.gif
顏色編碼:指針

red = 31
green = 32
yellow = 33
blue = 34
magenta = 35
cyan = 36
white = 37;

清屏

有時候你可能想經過輸入某條命令來清屏,好比hello> clear,那麼可使用下面的接口:

void linenoiseClearScreen(void);

總結

今天主要解鎖了Linenoise的用法,Linenoise很是簡單,且很容易嵌入到你的項目裏。但願對有REPL需求的小夥伴有些幫助。後續將繼續解鎖Linenoise的進化版Linenoise-NG(Linenoise Next Generation)。盡請期待~

Linenoise代碼託管地址

相關文章
相關標籤/搜索