前言
一次在使用symfony的时候,发现使用命令行的时候有些关键字会自动提示。
介绍
随着laravel,symfony等框架的流行,命令行工具越来越流行,但是很多时候命令太多,根本无法记住所有参数,或者参数太长输入太不方便。
这时是否也想拥有一个像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不支持自动补全
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。