一次在利用symfony的时候,创造利用命令行的时候有些关键字会自动提示。

先容

随着laravel,symfony等框架的盛行,命令行工具越来越盛行,但是很多时候命令太多,根本无法记住所有参数,或者参数太长输入太未便利。

php自动补全PHP手摸手教你撸一个会主动补全的敕令行对象1 SQL

这时是否也想拥有一个像IDE中的自动补全功能?

手摸手,一起撸一个自动补全工具

获取命令行字符串

想自动补全,必须获取命令行输入的数据,那么如何获取数据呢?

详细可以参考官方文档 PHP获取命令输入,这里我们利用一种写法

$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的后边

这样一个大略单纯的自动补全工具就出身了。
下文,我们一起来优化这个工具。

备注:Windows不支持自动补全