programster / command
一个用于创建CLI命令的库。
0.2.6
2022-09-01 14:03 UTC
Requires
- php: >=8.1.0
README
一个用于简化PHP中CLI命令创建的包,支持BASH自动补全。
执行参数
在编写你的execute
函数时,请注意选项和开关的键始终是长名称,且不带任何连字符。例如,当用户输入--shell
或-s
时,应使用shell
而不是s
。
选项值验证
我们不验证传递给选项的任何值,因此你需要自己进行验证。
示例
以下是一个示例,其中我编写了一个命令,该命令封装了docker-exec,允许我通过Tab键补全容器名称,然后通过ID输入它们,默认使用BASH shell,但允许用户通过提供--shell
或-s
选项来指定他们想使用sh
。
class DockerEnter extends \Programster\Command\Command { /** * This is your entrypoint for the program when it is being told to execute, and not being * asked by BASH for tab-completion hints. * @param array $options - an associative array of option-name/value pairs provided by the user. * E.g. a user passing --encoding=hevc would turn into ["encoding" => "hevc"] * @param array $switches - an associative array of switch-name/value pairs provided by the user. * E.g. a user passing --recursive would turn into ["recursive" => true] * @param array $args - a collection of arguments passed by the user. * @return void */ public function execute(array $options, array $switches, array $args): void { if (count($args) !== 1) { throw new Exception("You must pass the ID or name of the container you wish to enter."); } $nameOrId = $args[0]; $info = shell_exec("docker ps --format '{{ json .}}'"); $lines = array_filter(explode(PHP_EOL, $info)); $handled = false; $shell = array_key_exists("shell", $options) ? "/bin/{$options['shell']}" : "/bin/bash"; foreach ($lines as $line) { $containerArray = json_decode($line, true); if ($containerArray['ID'] === $nameOrId) { passthru("docker exec -it {$containerArray['ID']} {$shell}"); $handled = true; break; } elseif ($containerArray['Names'] === $nameOrId) { passthru("docker exec -it {$containerArray['ID']} {$shell}"); $handled = true; break; } } if (!$handled) { die("There is no container with that ID or name."); } } /** * Get a list of possible arguments for tab completion. In this case, we want to return a list * of all the running container names. * @return array|null - all the hints, or an empty array/null if there are none. */ public function getPossibleArgs(): ?array { $hints = []; $info = shell_exec("docker ps --format '{{ json .}}'"); $lines = array_filter(explode(PHP_EOL, $info)); foreach ($lines as $line) { $containerArray = json_decode($line, true); $hints[] = $containerArray['ID']; $hints[] = $containerArray['Names']; } return $hints; } /** * Returns the list of possible options (e.g. --something=value). In this case we allow the * user to optionally set the shell to "sh" instead of the default of "bash" * @return CommandOptionCollection|null */ public function getOptions(): ?CommandOptionCollection { return new CommandOptionCollection( new BasicCommandOption("shell", "s", ["bash", "sh"]) ); } /** * Set the switches (E.G. --something-on). In this case we have none. * @return CommandSwitchCollection|null */ public function getSwitches(): ?CommandSwitchCollection { return null; } /** * Get a collection of any possible subcommands. In future we may wrap this DockerEnter * command within a parent "DockerHelper" command, in which case this would return the * DockerEnter class inside a collection. * @return CommandCollection|null */ public function getSubCommands(): ?CommandCollection { return null; } /** * Get the name of this command, should it ever become a subcommand of another * command in future. * @return string */ public function getName(): string { return "enter"; } } // Need to call the command $command = new DockerHelper(); $command->run();
安装命令
一旦你使用此框架构建了一个命令,你将想知道如何“安装”它,以便你可以在任何地方执行它,并且BASH自动补全功能正常工作。
放置到你的$PATH中
将命令或其符号链接放置在你的$PATH中的/usr/bin/{command name}。确保设置了可执行标志。
创建BASH自动补全文件
遗憾的是,仍然需要为你的程序创建一个自动补全文件,以便告诉BASH询问你的程序以获取Tab提示。你可以通过使用“hidden”--generate-autocomplete-file
开关,如下所示,使用你的程序轻松地创建此文件
my-command --generate-autocomplete-file | sudo tee /etc/bash_completion.d/dothis-completion.bash > /dev/null
或者,你可以手动创建自己的自动补全脚本。以下是一个针对你创建的自定义命令my-command
的示例。
#!/usr/bin/env bash __my_command_completions() { REGEXP="*[[:space:]]" if [[ ${COMP_LINE} == ${REGEXP} ]]; then ENDS_IN_SPACE=1 else ENDS_IN_SPACE=0 fi readarray -t COMPREPLY <<< $(my-command --autocomplete-help ${ENDS_IN_SPACE} ${COMP_LINE}) } complete -o nospace -F __my_command_completions dothis
现在打开一个新的BASH shell,你应该能看到它正在工作!
路线图
- 防止建议已传递的选项/开关。