一次在使用symfony的時候,發現使用命令行的時候有些關鍵字會自動提示。php
隨着laravel,symfony等框架的流行,命令行工具愈來愈流行,可是不少時候命令太多,根本沒法記住全部參數,或者參數太長輸入太不方便。
這時是否也想擁有一個像IDE中的自動補全功能?laravel
想自動補全,必須獲取命令行輸入的數據,那麼如何獲取數據呢?
具體能夠參考官方文檔 PHP獲取命令輸入,這裏咱們使用一種寫法shell
$c = fread(\STDIN, 1);
這樣咱們就能夠獲取每次輸入的按鍵。框架
進行了上面的操做之後,咱們已經能夠獲取到輸入的內容,可是發現一個問題,咱們必須按下回車之後才能夠獲取到輸入的內容,即便咱們設置了fread最大讀取的長度,那麼到底是什麼問題的?
原來Linux終端中,默認是必須按下回車的。那麼咱們必須關閉這個功能。爲了防止咱們使用其餘軟件出現問題,咱們不須要該功能後須要將其關閉。工具
//執行以下命令後,就能夠一個字符一個字符的獲取了 $sttyMode = shell_exec('stty -g'); shell_exec('stty -icanon -echo'); //恢復原來的狀態 shell_exec(sprintf('stty %s', $sttyMode));
這時,咱們在進行測試測試
$sttyMode = shell_exec('stty -g'); shell_exec('stty -icanon -echo'); $c = fread(\STDIN, 1); var_dump($c); shell_exec(sprintf('stty %s', $sttyMode));
<?php $sttyMode = shell_exec('stty -g'); shell_exec('stty -icanon -echo'); $autoComplete = [ "Auto", "Complete" ]; $inputStream = STDIN; while (!feof($inputStream)) { $c = fread($inputStream, 1); //是否是空 if (false === $c || empty($c)) { throw new Exception('Aborted.'); } elseif ("\177" === $c) { // 刪除按鍵 //printf(177); } elseif ("\033" === $c) { // printf(033); // $c .= fread($inputStream, 2); // printf($c); } elseif (\ord($c) < 32) { // if ("\t" === $c || "\n" === $c) { // if ("\n" === $c) { // break; // } // } continue; } else { if ("\x80" <= $c) { $c .= fread($inputStream, ["\xC0" => 1, "\xD0" => 1, "\xE0" => 2, "\xF0" => 3][$c & "\xF0"]); } printf("\r\033[k"); foreach($autoComplete as $one){ if (strpos($one,$c)===0){ printf($one); } } } } shell_exec(sprintf('stty %s', $sttyMode));
下面咱們在優化一下,當輸入A之後,讓光標在A的後邊優化
這樣一個簡易的自動補全工具就誕生了。下文,咱們一塊兒來優化這個工具。spa
備註:Windows不支持自動補全.net