Redis是一個優秀的開源項目,網上下載下來的也都是源程序版本,查看起來也很方便,因此本着學習的精神,嘗試閱讀其源碼,但願能有所獲。html
通常來講,項目的需求是衡量項目是否完善的標準,對於商業項目來講,需求是客戶提供的,而對於自由項目來講,這個需求就是本身研究開發的了,需求開發的好壞,與軟件質量、開發週期都有關係,因此,在看代碼以前,須要捋一捋Redis客戶端的開發需求。 Redis是一個內存數據庫,跟許多其餘的數據庫同樣,客戶端的重要性並非那麼高,使用Redis的主要是各類應用程序或網站,通常都會寫程序或者調用各類庫來鏈接Redis的服務端,因此服務端的重要性更高。做爲一個數據庫,其主要的服務端必須具備效率高、可用性高、不易出錯等等屬性,而對於一個客戶端來講,簡潔、友好、簡單,讓初次接觸Redis的用戶也不以爲頭大,讓各類服務端提供的功能可以在客戶端上顯現出來,就能夠了。因此,Redis的客戶端需求十分簡單,主要就是實現各類指令的實現,以及和服務端的交互,而後,最好能有一個友好一些的交互界面就能夠了。 ###Linenoise實現 爲實現客戶端交互更爲友好,Redis採用的是Linenoise,一個優秀的命令行提示的c語言庫。 Linenoise是Redis的做者開發的另外一個開源項目,實現的功能就是輸入幾個字符後,在Console中可以顯示對應的提示語,以下圖,做爲一個變成小白來講,這確實是一個很好玩的功能,因此就學習一下。 redis
如圖所示,在輸入指令「set」後,界面上就顯示出一行顏色較淡的提示性文字,這實際上是經過控制輸出的字符的顏色來實現的,好比printf("\033[33mhello world\033[m")打印出來的就是黃色的「hello world」,具體顏色和顯示效果,參見printf打印帶顏色的字體和背景的方法。 但正常狀況下,像printf這樣的函數打印的只能是一次性的,沒法實現對已打印或輸出的字符進行編輯,爲了實現這個功能,Linenoise採用了更改輸入端模式的辦法,具體改變以下:數據庫
這樣修改之後,就能夠任意更改已輸出或輸入的字符串了,只是須要注意,顯示的全部字符都要本身排列好,否則就顯示出一團糟了。我用做者的方法實踐了一下,發現效果仍是不錯的,測試代碼:函數
void getOutLine(char *obuf, char *ibuf, char *hints, char *prompt) { int ilen = strlen(ibuf); if(ilen<2 || hints == NULL || strncmp(ibuf, hints, ilen) !=0 ) { sprintf(obuf,"\r%s%s\x1b[0K\r\x1b[%dC",prompt, ibuf,(int)(strlen(prompt)+ilen)); } else{ sprintf(obuf,"\r%s%s\x1b[33m%s\x1b[m\x1b[0K\r\x1b[%dC",prompt, ibuf,hints+ilen, (int)(strlen(prompt)+ilen)); } } int main() { char ibuf[32], obuf[128], hints[32], prompt[32]; char *p = ibuf; char c; memset(ibuf, 0, 32); sprintf(prompt, "redis> "); sprintf(hints, "this a test"); enableRawMode(STDIN_FILENO); while(1) { getOutLine(obuf, ibuf, hints, prompt); write(STDOUT_FILENO, obuf, strlen(obuf)); read(STDIN_FILENO, &c, 1); if(c == 13){ getOutLine(obuf, ibuf, NULL, prompt); write(STDOUT_FILENO, obuf, strlen(obuf)); break; } else if(c == 127){ p--; *p = '\0'; getOutLine(obuf, ibuf, hints, prompt); write(STDOUT_FILENO, obuf, strlen(obuf)); } else { *p = c; p ++; } } disableRawMode(STDIN_FILENO); printf("\n"); return 0; }
以上就是主要的實現代碼,至於enableRawMode()和disableRawMode()兩個函數則是直接從linenoise.c文件裏面拷過來的,這裏就不貼出來了。須要說明的是,以前說到printf打印出顏色的時候,用的顏色開頭標誌是「\033」,而linenoise.c裏面一概用的是「\x1b」,其實二者是同樣的一個是八進制的27一個是十六進制的27。 ###小結 雖然寫這一篇筆記大概花了我兩小時的時間,寫出一個達到本身預期目標的測試程序大概是一天時間,但期間爲了讀懂整個Linenoise代碼,花了我近一個星期,主要是本身水平還不夠吧,一看到陌生的有些奇怪的代碼,頭都大了,之後仍是要多練練。 期間,在寫到「c==13」這個地方的時候,我用的是「c=='\n'」,表示換行,結果怎麼測試都不行,後來查了源碼才明白,我敲的「Enter」鍵輸入的是「\r」,也就是「13」,並非「\n」,哎,習慣換行直接敲「Enter」了,都忘了它的本意就是「光標回到起點」,也就是「\r」。而變量obuf原先給它配的size也跟你們同樣是32,結果輸入一兩個字符之後就冒出稀奇古怪的顯示了,一怒之下直接改爲obuf[128],這下總算顯示正確了。學習