一次在使用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