diff --git a/README.md b/README.md index d701f0a..f154180 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,54 @@ -# console tool +# php 命令行应用库 -a php console application library. +简洁功能全面的php命令行应用库。提供控制台参数解析, 颜色风格输出, 用户信息交互, 特殊格式信息显示 -- console application, run command/controller -- console input/output -- console color support -- console interactive +- 命令行应用, 命令行的controller,command 解析运行 +- 功能全面的命令行的选项参数解析 +- 命令行中功能强大的 input/output 管理、使用 +- 消息文本的多种颜色风格输出支持 +- 常用的特殊格式信息显示(panel,help-panel,table,title,list,progressBar) +- 常用的用户信息交互支持(select,confirm,ask) +- 命令方法注释自动解析(提取为参数 `arguments` 和 选项 `options` 等信息) +- 类似 `symfony/console` 的预定义参数定义支持(按位置赋予参数值) -[中文README](./README_zh.md) +> [EN README](./README_en.md) -## project +## 项目地址 - **github** https://github.com/inhere/php-console.git - **git@osc** https://git.oschina.net/inhere/php-console.git -**NOTICE** +**注意:** -- master branch -- is require `php >= 7` (recommended use)。 -- php5 branch -- It's a branch of PHP 5, but it hasn't been updated for some time (the basic functionality is complete). +- master 分支是要求 `php >= 7` 的(推荐使用)。 +- php5 分支是支持 php5 `php >= 5.5` 的代码分支。 -## install +## 安装 -- by composer +- 使用 composer -edit `composer.json`,at `require` add +编辑 `composer.json`,在 `require` 添加 ``` "inhere/console": "dev-master", // "inhere/console": "dev-php5", // for php5 ``` -run: `composer update` +然后执行: `composer update` -- Direct fetch +- 直接拉取 ``` git clone https://git.oschina.net/inhere/php-console.git // git@osc git clone https://github.com/inhere/php-console.git // github ``` -## usage +## 快速开始 + +如下,新建一个入口文件。 就可以开始使用了 ```php +// file: examples/app use Inhere\Console\IO\Input; use Inhere\Console\IO\Output; use Inhere\Console\Application; @@ -60,36 +67,126 @@ $app->command('demo', function (Input $in, Output $out) { $out->info('hello, this is a test command: ' . $cmd); }); +// ... ... // run $app->run(); ``` -now, you can see: +然后在命令行里执行 `php examples/app`, 立即就可以看到如下输出了: !['output-commands-info'](images/output-commands-info.png) -## input +> `Independent Commands` 中的 demo 就是我们上面添加的命令 + + +## 添加命令 + +添加命令的方式有三种 + +- 如上所示,使用闭包可以快速的添加一个简单的命令 +- 通过继承 `Inhere\Console\Command` 添加独立命令 + +```php +use Inhere\Console\Utils\AnsiCode; + +/** + * Class Test + * @package app\console\commands + */ +class TestCommand extends Command +{ + /** + * execute + * @param Inhere\Console\IO\Input $input + * @param Inhere\Console\IO\Output $output + * @return int + */ + public function execute($input, $output) + { + $output->write('hello, this in ' . __METHOD__); + } +} +``` + +注册命令,在 `$app->run()` 之前通过 `$app->command('test', TestCommand::class)` 注册独立命令。 + +- 通过继承 `Inhere\Console\Controller` 添加一组命令(命令行的控制器类) + +```php +use Inhere\Console\Controller; + +/** + * default command controller. there are some command usage examples + */ +class HomeController extends Controller +{ + const DESCRIPTION = 'default command controller. there are some command usage examples'; + + /** + * this is a command's description message + * the second line text + * @usage usage message + * @example example text one + * the second line example + */ + public function indexCommand() + { + $this->write('hello, welcome!! this is ' . __METHOD__); + } +} +``` + +注册命令,在 `$app->run()` 之前通过 `$app->controller('home', HomeController::class)` 注册命令组。 + +说明: + +命令组(eg `HomeController`) 中的命令(eg: `indexCommand`)上注释是可被解析的。 + +- 当你使用 `php examples/app home -h` 时,可以查看到 `HomeController::indexCommand` 的描述注释文本 +- 当使用 `php examples/app home/index -h` 时,可以查看到关于 `HomeController::indexCommand` 更详细的信息。包括描述注释文本、`@usage` 、`@example` + +> 小提示:注释里面同样支持带颜色的文本输出 `eg: this is a command's description message` -example(in terminal): +更多请查看 [examples](./examples) 中的示例代码 + +## 输入 + +> 输入对象是 `Inhere\Console\IO\Input` 的实例 + +在终端中执行如下命令,用于演示参数选项等信息的解析: ```bash -$ examples/app home/useArg status=2 name=john arg0 -s=test --page=23 --id=154 -e dev -v vvv -d -rf --debug --test=false +$ php examples/app home/useArg status=2 name=john arg0 -s=test --page=23 --id=154 -e dev -v vvv -d -rf --debug --test=false ``` -**NOTICE:** +**一点说明:** + +- 没有 `-` 开头的都认为是参数 (eg: `status=2` `arg0`) +- 反之,以 `-` 开头的则是选项数据 + - `--` 开头的是长选项(long-option) + - 一个 `-` 开头的是短选项(short-option) + +> 支持混合式选项的赋值 `--id=154` 和 `--id 154` 是等效的 -- These words will be as a Boolean(`true`) value: `on|yes|true` -- These words will be as a Boolean(`false`) value: `off|no|false` +**注意:** 输入如下的字符串将会认为是布尔值 -get command info: +- `on|yes|true` -- `true` +- `off|no|false` -- `false` + +### 获取命令基本信息: ```php -echo $input->getScript(); // 'examples/app' -echo $input->getCommand(); // 'home/useArg' +echo $input->getScript(); // 'examples/app' 执行的入口脚本文件 +echo $input->getCommand(); // 'home/useArg' 解析到的第一个参数将会被认为是命令名称,并且不会再存入到 参数列表中 +echo $input->getFullScript(); // 命令行输入的原样字符串 ``` -get parsed arguments: +### 获取解析后的参数信息 + +> 通常的参数如 `arg0` 只能根据 index key 来获取值。但是提供以等号(`=`)连接的方式来指定参数名(eg: `status=2`) + +打印所有的参数信息: ```php var_dump($input->getArgs()); @@ -105,10 +202,26 @@ array(3) { } ``` -get parsed options: +扩展方法: + +```php +// argument +$first = $input->getFirstArg(); // 'arg0' +$status = $input->get('status', 'default value'); // '2' +``` + +### 获取解析后的选项信息 + +- 没有值的选项,将设置默认值为 `bool(true)` +- 短选项不仅仅只是以一个 `-` 开头,而且名称 **只能是一个字符** +- 多个(默认值的)短选项可以合并到一起写。如 `-rf` 会被解析为两个短选项 `'r' => bool(true)` `'f' => bool(true)` + +打印所有的选项信息: ```php var_dump($input->getOpts()); +// var_dump($input->getLOpts()); // 只打印长选项信息 +// var_dump($input->getSOpts()); // 只打印短选项信息 ``` output: @@ -128,86 +241,278 @@ array(10) { } ``` -more method: +扩展方法: ```php -// argument -$first = $input->getFirstArg(); // 'arg0' -$status = $input->get('status', 'default'); // '2' - // option $page = $input->getOpt('page') // '23' $debug = $input->boolOpt('debug') // True $test = $input->boolOpt('test') // False + +$d = $input->boolOpt('d') // True +$d = $input->sBoolOpt('d') // True +$showHelp = $input->sameOpt(['h','help']) // 获取到一个值就返回,适合同一个含义的选项 ``` -### get user input: +### 读取用户输入 ```php echo "Your name:"; -$text = $input->read(); +$name = $input->read(); // in terminal // Your name: simon -echo $text; // 'simon' +echo $name; // 'simon' ``` -## output +也可以直接将消息文本放入参数 `$name = $input->read("Your name:");` + +## 输出 + +> 输出对象是 `Inhere\Console\IO\Output` 的实例 -basic output: +基本输出: ```php public function write(mixed $messages = '', $nl = true, $quit = false) ``` +- `$messages` mixed 要输出的消息。可以是字符串或数组。 +- `$nl` bool 输出后是否换行。 默认 `true` +- `$quit` bool|int 输出后是否退出脚本。默认 `false`, 其它值都会转换为 `int` 作为退出码(`true` 会转换为 0)。 + ```php $output->write('hello'); +$output->write(['hello', 'world']); ``` -### formatted output +## 格式化的输出 + +### 带颜色风格的输出 -#### use color style +`$output` 的 `write()` 方法支持带颜色风格的输出(当然得终端支持才行) + +```php +$output->write('hello world'); +``` + +已经内置了常用的风格: ![alt text](images/output-color-text.png "Title") -#### special format output +来自于类 `Inhere\Console\Utils\Show`。 -- `$output->title()` -- `$output->section()` -- `$output->panel()` -- `$output->table()` -- `$output->helpPanel()` +> output 实例拥有 `Inhere\Console\Utils\Show` 的所有格式化输出方法。不过都是通过对象式访问的。 -![alt text](images/output-format-msg.png "Title") +### 标题文本输出 -## more interactive +使用 `Show::title()/$output->title()` -in the class `Inhere\Console\Utils\Interact` +```php +public static function title(string $title, array $opts = []) +``` + +### 段落式文本输出 -interactive method: +使用 `Show::section()/$output->section()` + +```php +public static function section(string $title, string|array $body, array $opts = []) +``` -### `Interact::select()` (alias `Interact::chioce()`) +### 简单的进度条输出 -Select one of the options +使用 `Show::progressBar()/$output->progressBar()` ```php -select($description, $options, $default = null, $allowExit=true) -choice($description, $options, $default = null, $allowExit=true) +public static function progressBar(int $total, array $opts = []) ``` -- example 1: +示例代码: - only values, no setting option +```php + +$total = 120; +$bar = Show::progressBar($total, [ + 'msg' => 'Msg Text', + 'doneChar' => '#' +]); +echo "Progress:\n"; + +$i = 0; +while ($i <= $total) { + $bar->send($i); + usleep(50000); + $i++; +} +``` + +![show-progress](images/show-progress.png) + +### 列表数据展示输出 + +```php +public static function aList(array $data, string $title, array $opts = []) +``` + +- `$data` array 列表数据。可以是key-value 形式,也可以只有 value,还可以两种混合。 +- `$title` string 列表标题。可选的 +- `$opts` array 选项设置(**同表格、面板的选项**) + - `leftChar` 左侧边框字符。默认两个空格,也可以是其他字符(eg: `*` `.`) + - `keyStyle` 当key-value 形式时,渲染 key 的颜色风格。 默认 `info`, 设为空即是不加颜色渲染 + - `titleStyle` 标题的颜色风格。 默认 `comment` + +> `aList` 的默认选项,可以渲染一个命令的帮助信息。 + +使用 `Show::aList()/$output->aList()` + +```php +$title = 'list title'; +$data = [ + 'name' => 'value text', // key-value + 'name2' => 'value text 2', + 'more info please XXX', // only value +]; +Show::aList($data, $title); +``` + +### 多列表数据展示输出 + +```php +public static function mList(array $data, array $opts = []) +``` + +> `mList` 的默认选项,可以渲染一组命令的帮助信息。效果与 `helpPanel()` 相同,并且自定义性更高。 + + +使用 `Show::mList()/$output->mList()` 别名方法 `Show::multiList()` + +```php +$data = [ + 'list1 title' => [ + 'name' => 'value text', + 'name2' => 'value text 2', + ], + 'list2 title' => [ + 'name' => 'value text', + 'name2' => 'value text 2', + ], + // ... ... +]; + +Show::mList($data); +``` + +### 面板展示信息输出 + +```php +public static function panel(mixed $data, $title = 'Information Panel', $borderChar = '*') +``` + +展示信息面板。比如 命令行应用 开始运行时需要显示一些 版本信息,环境信息等等。 + +使用 `Show::panel()/$output->panel()` + +```php +$data = [ + 'application version' => '1.2.0', + 'system version' => '5.2.3', + 'see help' => 'please use php bin/app -h', + 'a only value message', +]; +Show::panel($data, 'panel show', '#'); +``` + +### 数据表格信息输出 + +```php +public static function table(array $data, $title = 'Data Table', array $opts = []) +``` + +使用 `Show::table()/$output->table()` + +- 可直接渲染从数据库拉取的数据(会自动提取字段名作为表头) + +```php +// like from database query's data. +$data = [ + [ col1 => value1, col2 => value2, col3 => value3, ... ], // first row + [ col1 => value4, col2 => value5, col3 => value6, ... ], // second row + ... ... +]; + +Show::table($data, 'a table'); +``` + +- 自己构造数据时,还要写字段名就有些麻烦了。so, 可以通过选项配置 `$opts` 手动配置表头字段列表 + +```php +// use custom head +$data = [ + [ value1, value2, value3, ... ], // first row + [ value4, value5, value6, ... ], // second row + // ... ... +]; + +$opts = [ + 'showBorder' => true, + 'tHead' => [col1, col2, col3, ...] +]; +Show::table($data, 'a table', $opts); +``` + +### 快速的渲染一个帮助信息面板 + +```php +public static function helpPanel(array $config, $showAfterQuit = true) +``` + +使用 `Show::helpPanel()/$output->helpPanel()` + +```php +Show::helpPanel([ + Show::HELP_DES => 'a help panel description text. (help panel show)', + Show::HELP_USAGE => 'a usage text', + Show::HELP_ARGUMENTS => [ + 'arg1' => 'arg1 description', + 'arg2' => 'arg2 description', + ], + Show::HELP_OPTIONS => [ + '--opt1' => 'a long option', + '-s' => 'a short option', + '-d' => 'Run the server on daemon.(default: false)', + '-h, --help' => 'Display this help message' + ], +], false); +``` + +### 渲染效果预览 + +![alt text](images/output-format-msg.png "Title") + +## 用户交互方法 + +需引入类 `Inhere\Console\Utils\Interact` + +### 从给出的列表中选择一项 + +```php +public static function select($description, $options, $default = null, $allowExit=true) +public static function choice($description, $options, $default = null, $allowExit=true) // alias method +``` + +使用 `Interact::select()` (alias `Interact::chioce()`) + +- 示例 1: 只有值,没有选项key ```php $select = Interact::select('Your city is ?', [ 'chengdu', 'beijing', 'shanghai' ]); - ``` -output in terminal: +渲染结果(in terminal): ``` Your city is ? @@ -219,12 +524,12 @@ You choice: 0 ``` ```php -echo $select; // '0' +echo "$select"; // '0' ``` -- example 2: +- 示例 2: -custom option, setting a default value. +有选项key, 并且设置了一个默认值. ```php $select = Interact::select('Your city is ?', [ @@ -234,7 +539,7 @@ $select = Interact::select('Your city is ?', [ ], 'a'); ``` -output in terminal: +渲染结果(in terminal): ``` Your city is? @@ -249,50 +554,95 @@ You choice[default:a] : b echo $select; // 'b' ``` -### `Interact::confirm()` +### 要求确认是否继续执行 ```php public static function confirm($question, $default = true) bool ``` -usage: - +使用 `Interact::confirm()` : ```php $result = Interact::confirm('Whether you want to continue ?'); ``` -output in terminal: +渲染结果(in terminal): ``` Whether you want to continue ? Please confirm (yes|no) [default:yes]: n ``` -result: +结果: ```php var_dump($result); // bool(false) ``` -### `Interact::question()`/`Interact::ask()` +### 询问,并返回用户的回答 ```php public static function ask($question, $default = null, \Closure $validator = null) public static function question($question, $default = null, \Closure $validator = null) ``` +使用 `Interact::question()`/`Interact::ask()` + ```php - $answer = Interact::ask('Please input your name?', null, function ($answer) { - if ( !preg_match('/\w+/', $answer) ) { +$answer = Interact::ask('Please input your name?', null, function ($answer) { + if (!preg_match('/\w+/', $answer)) { Interact::error('The name must match "/\w+/"'); - + return false; - } + } - return true; - }); + return true; +}); +``` + +### 有次数限制的询问 + +```php +public static function limitedAsk($question, $default = null, \Closure $validator = null, $times = 3) ``` + +有次数限制的询问,提出问题 + +* 若输入了值且验证成功则返回 输入的结果 +* 否则,会连续询问 `$times` 次,若仍然错误,退出 + + +```php +// no default value +$answer = Interact::limitedAsk('please input you age?', null, function($age) +{ + if ($age<1 || $age>100) { + Interact::error('Allow the input range is 1-100'); + return false; + } + + return true; +}); +``` + ## License MIT + +## 我的其他项目 + +### `inhere/redis` [github](https://github.com/inhere/php-redis) [git@osc](https://git.oschina.net/inhere/php-redis) + +简单的redis操作客户端包装库 + +### `inhere/sroute` [github](https://github.com/inhere/php-srouter) [git@osc](https://git.oschina.net/inhere/php-srouter) + + 轻量且功能丰富快速的路由库 + +### `inhere/php-validate` [github](https://github.com/inhere/php-validate) [git@osc](https://git.oschina.net/inhere/php-validate) + + 一个简洁小巧且功能完善的php验证库。仅有几个文件,无依赖。 + +### `inhere/http` [github](https://github.com/inhere/php-http) [git@osc](https://git.oschina.net/inhere/php-http) + +http 工具库(`request` 请求 `response` 响应 `curl` curl请求库,有简洁、完整和并发请求三个版本的类) diff --git a/README_en.md b/README_en.md new file mode 100644 index 0000000..47f554e --- /dev/null +++ b/README_en.md @@ -0,0 +1,298 @@ +# console tool + +a php console application library. + +- console application, run command/controller +- console input/output +- console color support +- console interactive + +[中文README](./README.md) + +## project + +- **github** https://github.com/inhere/php-console.git +- **git@osc** https://git.oschina.net/inhere/php-console.git + +**NOTICE** + +- master branch -- is require `php >= 7` (recommended use)。 +- php5 branch -- It's a branch of PHP 5, but it hasn't been updated for some time (the basic functionality is complete). + +## install + +- by composer + +edit `composer.json`,at `require` add + +``` +"inhere/console": "dev-master", +// "inhere/console": "dev-php5", // for php5 +``` + +run: `composer update` + +- Direct fetch + +``` +git clone https://git.oschina.net/inhere/php-console.git // git@osc +git clone https://github.com/inhere/php-console.git // github +``` + +## usage + +```php +use Inhere\Console\IO\Input; +use Inhere\Console\IO\Output; +use Inhere\Console\Application; + +$meta = [ + 'name' => 'My Console App', + 'version' => '1.0.2', +]; +$input = new Input; +$output = new Output; +$app = new Application($meta, $input, $output); + +// add command routes +$app->command('demo', function (Input $in, Output $out) { + $cmd = $in->getCommand(); + + $out->info('hello, this is a test command: ' . $cmd); +}); + +// run +$app->run(); +``` + +now, you can see: + +!['output-commands-info'](images/output-commands-info.png) + +## input + +example(in terminal): + +```bash +$ examples/app home/useArg status=2 name=john arg0 -s=test --page=23 --id=154 -e dev -v vvv -d -rf --debug --test=false +``` + +**NOTICE:** + +- These words will be as a Boolean(`true`) value: `on|yes|true` +- These words will be as a Boolean(`false`) value: `off|no|false` + +get command info: + +```php +echo $input->getScript(); // 'examples/app' +echo $input->getCommand(); // 'home/useArg' +``` + +get parsed arguments: + +```php +var_dump($input->getArgs()); +``` + +output: + +```php +array(3) { + 'status' => string(1) "2" + 'name' => string(4) "john" + [0] => string(4) "arg0" +} +``` + +get parsed options: + +```php +var_dump($input->getOpts()); +``` + +output: + +```php +array(10) { + 's' => string(4) "test" + 'e' => string(3) "dev" + 'v' => string(3) "vvv" + 'd' => bool(true) + 'r' => bool(true) + 'f' => bool(true) + 'page' => string(2) "23" + 'id' => string(3) "154" + 'debug' => bool(true) + 'test' => bool(false) +} +``` + +more method: + +```php +// argument +$first = $input->getFirstArg(); // 'arg0' +$status = $input->get('status', 'default'); // '2' + +// option +$page = $input->getOpt('page') // '23' +$debug = $input->boolOpt('debug') // True +$test = $input->boolOpt('test') // False +``` + +### get user input: + +```php +echo "Your name:"; + +$text = $input->read(); +// in terminal +// Your name: simon + +echo $text; // 'simon' +``` + +## output + +basic output: + +```php +public function write(mixed $messages = '', $nl = true, $quit = false) +``` + +```php +$output->write('hello'); +``` + +### formatted output + +#### use color style + +![alt text](images/output-color-text.png "Title") + +#### special format output + +- `$output->title()` +- `$output->section()` +- `$output->panel()` +- `$output->table()` +- `$output->helpPanel()` + +![alt text](images/output-format-msg.png "Title") + +## more interactive + +in the class `Inhere\Console\Utils\Interact` + +interactive method: + +### `Interact::select()` (alias `Interact::chioce()`) + +Select one of the options + +```php +select($description, $options, $default = null, $allowExit=true) +choice($description, $options, $default = null, $allowExit=true) +``` + +- example 1: + + only values, no setting option + +```php +$select = Interact::select('Your city is ?', [ + 'chengdu', 'beijing', 'shanghai' +]); + +``` + +output in terminal: + +``` +Your city is ? + 0) chengdu + 1) beijing + 2) shanghai + q) Quit // quit option. is auto add. can setting it by 4th argument. +You choice: 0 +``` + +```php +echo $select; // '0' +``` + +- example 2: + +custom option, setting a default value. + +```php +$select = Interact::select('Your city is ?', [ + 'a' => 'chengdu', + 'b' => 'beijing', + 'c' => 'shanghai' +], 'a'); +``` + +output in terminal: + +``` +Your city is? + a) chengdu + b) beijing + c) shanghai + q) Quit // quit option. is auto add. can setting it by 4th argument. +You choice[default:a] : b +``` + +```php +echo $select; // 'b' +``` + +### `Interact::confirm()` + +```php +public static function confirm($question, $default = true) bool +``` + +usage: + + +```php +$result = Interact::confirm('Whether you want to continue ?'); +``` + +output in terminal: + +``` +Whether you want to continue ? +Please confirm (yes|no) [default:yes]: n +``` + +result: + +```php +var_dump($result); // bool(false) +``` + +### `Interact::question()`/`Interact::ask()` + +```php +public static function ask($question, $default = null, \Closure $validator = null) +public static function question($question, $default = null, \Closure $validator = null) +``` + +```php + $answer = Interact::ask('Please input your name?', null, function ($answer) { + if ( !preg_match('/\w+/', $answer) ) { + Interact::error('The name must match "/\w+/"'); + + return false; + } + + return true; + }); +``` +## License + +MIT diff --git a/README_zh.md b/README_zh.md deleted file mode 100644 index cbf0820..0000000 --- a/README_zh.md +++ /dev/null @@ -1,646 +0,0 @@ -# php 命令行应用库 - -简洁的php命令行应用库。提供控制台参数解析, 颜色风格输出, 用户信息交互, 特殊格式信息显示 - -- 命令行应用, 命令行controller,command 运行 -- 命令行的选项参数解析 -- 命令行 input/output -- 颜色风格输出支持 -- 特殊格式信息显示 -- 用户信息交互支持 -- 命令方法注释自动提取为参数 `arguments` 和 选项 `options` -- 类似 symfony/console 的预定义参数定义支持 - -## 项目地址 - -- **github** https://github.com/inhere/php-console.git -- **git@osc** https://git.oschina.net/inhere/php-console.git - -**注意:** - -- master 分支是要求 `php >= 7` 的(推荐使用)。 -- php5 分支是支持 php5 `php >= 5.5` 的代码分支。 - -## 安装 - -- 使用 composer - -编辑 `composer.json`,在 `require` 添加 - -``` -"inhere/console": "dev-master", -// "inhere/console": "dev-php5", // for php5 -``` - -然后执行: `composer update` - -- 直接拉取 - -``` -git clone https://git.oschina.net/inhere/php-console.git // git@osc -git clone https://github.com/inhere/php-console.git // github -``` - -## 快速开始 - -如下,新建一个入口文件。 就可以开始使用了 - -```php -// file: examples/app -use Inhere\Console\IO\Input; -use Inhere\Console\IO\Output; -use Inhere\Console\Application; - -$meta = [ - 'name' => 'My Console App', - 'version' => '1.0.2', -]; -$input = new Input; -$output = new Output; -$app = new Application($meta, $input, $output); - -// add command routes -$app->command('demo', function (Input $in, Output $out) { - $cmd = $in->getCommand(); - - $out->info('hello, this is a test command: ' . $cmd); -}); -// ... ... - -// run -$app->run(); -``` - -然后在命令行里执行 `php examples/app`, 立即就可以看到如下输出了: - -!['output-commands-info'](images/output-commands-info.png) - -> `Independent Commands` 中的 demo 就是我们上面添加的命令 - - -## 添加命令 - -添加命令的方式有三种 - -- 如上所示,使用闭包可以快速的添加一个简单的命令 -- 通过继承 `Inhere\Console\Command` 添加独立命令 - -```php -use Inhere\Console\Utils\AnsiCode; - -/** - * Class Test - * @package app\console\commands - */ -class TestCommand extends Command -{ - /** - * execute - * @param Inhere\Console\IO\Input $input - * @param Inhere\Console\IO\Output $output - * @return int - */ - public function execute($input, $output) - { - $output->write('hello, this in ' . __METHOD__); - } -} -``` - -注册命令,在 `$app->run()` 之前通过 `$app->command('test', TestCommand::class)` 注册独立命令。 - -- 通过继承 `Inhere\Console\Controller` 添加一组命令(命令行的控制器类) - -```php -use Inhere\Console\Controller; - -/** - * default command controller. there are some command usage examples - */ -class HomeController extends Controller -{ - const DESCRIPTION = 'default command controller. there are some command usage examples'; - - /** - * this is a command's description message - * the second line text - * @usage usage message - * @example example text one - * the second line example - */ - public function indexCommand() - { - $this->write('hello, welcome!! this is ' . __METHOD__); - } -} -``` - -注册命令,在 `$app->run()` 之前通过 `$app->controller('home', HomeController::class)` 注册命令组。 - -说明: - -命令组(eg `HomeController`) 中的命令(eg: `indexCommand`)上注释是可被解析的。 - -- 当你使用 `php examples/app home -h` 时,可以查看到 `HomeController::indexCommand` 的描述注释文本 -- 当使用 `php examples/app home/index -h` 时,可以查看到关于 `HomeController::indexCommand` 更详细的信息。包括描述注释文本、`@usage` 、`@example` - -> 小提示:注释里面同样支持带颜色的文本输出 `eg: this is a command's description message` - -更多请查看 [examples](./examples) 中的示例代码 - -## 输入 - -> 输入对象是 `Inhere\Console\IO\Input` 的实例 - -在终端中执行如下命令,用于演示参数选项等信息的解析: - -```bash -$ php examples/app home/useArg status=2 name=john arg0 -s=test --page=23 --id=154 -e dev -v vvv -d -rf --debug --test=false -``` - -**一点说明:** - -- 没有 `-` 开头的都认为是参数 (eg: `status=2` `arg0`) -- 反之,以 `-` 开头的则是选项数据 - - `--` 开头的是长选项(long-option) - - 一个 `-` 开头的是短选项(short-option) - -> 支持混合式选项的赋值 `--id=154` 和 `--id 154` 是等效的 - -**注意:** 输入如下的字符串将会认为是布尔值 - -- `on|yes|true` -- `true` -- `off|no|false` -- `false` - -### 获取命令基本信息: - -```php -echo $input->getScript(); // 'examples/app' 执行的入口脚本文件 -echo $input->getCommand(); // 'home/useArg' 解析到的第一个参数将会被认为是命令名称,并且不会再存入到 参数列表中 -echo $input->getFullScript(); // 命令行输入的原样字符串 -``` - -### 获取解析后的参数信息 - -> 通常的参数如 `arg0` 只能根据 index key 来获取值。但是提供以等号(`=`)连接的方式来指定参数名(eg: `status=2`) - -打印所有的参数信息: - -```php -var_dump($input->getArgs()); -``` - -output: - -```php -array(3) { - 'status' => string(1) "2" - 'name' => string(4) "john" - [0] => string(4) "arg0" -} -``` - -扩展方法: - -```php -// argument -$first = $input->getFirstArg(); // 'arg0' -$status = $input->get('status', 'default value'); // '2' -``` - -### 获取解析后的选项信息 - -- 没有值的选项,将设置默认值为 `bool(true)` -- 短选项不仅仅只是以一个 `-` 开头,而且名称 **只能是一个字符** -- 多个(默认值的)短选项可以合并到一起写。如 `-rf` 会被解析为两个短选项 `'r' => bool(true)` `'f' => bool(true)` - -打印所有的选项信息: - -```php -var_dump($input->getOpts()); -// var_dump($input->getLOpts()); // 只打印长选项信息 -// var_dump($input->getSOpts()); // 只打印短选项信息 -``` - -output: - -```php -array(10) { - 's' => string(4) "test" - 'e' => string(3) "dev" - 'v' => string(3) "vvv" - 'd' => bool(true) - 'r' => bool(true) - 'f' => bool(true) - 'page' => string(2) "23" - 'id' => string(3) "154" - 'debug' => bool(true) - 'test' => bool(false) -} -``` - -扩展方法: - -```php -// option -$page = $input->getOpt('page') // '23' -$debug = $input->boolOpt('debug') // True -$test = $input->boolOpt('test') // False - -$d = $input->boolOpt('d') // True -$d = $input->sBoolOpt('d') // True -$showHelp = $input->sameOpt(['h','help']) // 获取到一个值就返回,适合同一个含义的选项 -``` - -### 读取用户输入 - -```php -echo "Your name:"; - -$name = $input->read(); -// in terminal -// Your name: simon - -echo $name; // 'simon' -``` - -也可以直接将消息文本放入参数 `$name = $input->read("Your name:");` - -## 输出 - -> 输出对象是 `Inhere\Console\IO\Output` 的实例 - -基本输出: - -```php -public function write(mixed $messages = '', $nl = true, $quit = false) -``` - -- `$messages` mixed 要输出的消息。可以是字符串或数组。 -- `$nl` bool 输出后是否换行。 默认 `true` -- `$quit` bool|int 输出后是否退出脚本。默认 `false`, 其它值都会转换为 `int` 作为退出码(`true` 会转换为 0)。 - -```php -$output->write('hello'); -$output->write(['hello', 'world']); -``` - -## 格式化的输出 - -### 带颜色风格的输出 - -`$output` 的 `write()` 方法支持带颜色风格的输出(当然得终端支持才行) - -```php -$output->write('hello world'); -``` - -已经内置了常用的风格: - -![alt text](images/output-color-text.png "Title") - -来自于类 `Inhere\Console\Utils\Show`。 - -> output 实例拥有 `Inhere\Console\Utils\Show` 的所有格式化输出方法。不过都是通过对象式访问的。 - -### 标题文本输出 - -使用 `Show::title()/$output->title()` - -```php -public static function title(string $title, array $opts = []) -``` - -### 段落式文本输出 - -使用 `Show::section()/$output->section()` - -```php -public static function section(string $title, string|array $body, array $opts = []) -``` - -### 简单的进度条输出 - -使用 `Show::progressBar()/$output->progressBar()` - -```php -public static function progressBar(int $total, array $opts = []) -``` - -示例代码: - -```php - -$total = 120; -$bar = Show::progressBar($total, [ - 'msg' => 'Msg Text', - 'doneChar' => '#' -]); -echo "Progress:\n"; - -$i = 0; -while ($i <= $total) { - $bar->send($i); - usleep(50000); - $i++; -} -``` - -![show-progress](images/show-progress.png) - -### 列表数据展示输出 - -```php -public static function aList(array $data, string $title, array $opts = []) -``` - -- `$data` array 列表数据。可以是key-value 形式,也可以只有 value,还可以两种混合。 -- `$title` string 列表标题。可选的 -- `$opts` array 选项设置(**同表格、面板的选项**) - - `leftChar` 左侧边框字符。默认两个空格,也可以是其他字符(eg: `*` `.`) - - `keyStyle` 当key-value 形式时,渲染 key 的颜色风格。 默认 `info`, 设为空即是不加颜色渲染 - - `titleStyle` 标题的颜色风格。 默认 `comment` - -> `aList` 的默认选项,可以渲染一个命令的帮助信息。 - -使用 `Show::aList()/$output->aList()` - -```php -$title = 'list title'; -$data = [ - 'name' => 'value text', // key-value - 'name2' => 'value text 2', - 'more info please XXX', // only value -]; -Show::aList($data, $title); -``` - -### 多列表数据展示输出 - -```php -public static function mList(array $data, array $opts = []) -``` - -> `mList` 的默认选项,可以渲染一组命令的帮助信息。效果与 `helpPanel()` 相同,并且自定义性更高。 - - -使用 `Show::mList()/$output->mList()` 别名方法 `Show::multiList()` - -```php -$data = [ - 'list1 title' => [ - 'name' => 'value text', - 'name2' => 'value text 2', - ], - 'list2 title' => [ - 'name' => 'value text', - 'name2' => 'value text 2', - ], - // ... ... -]; - -Show::mList($data); -``` - -### 面板展示信息输出 - -```php -public static function panel(mixed $data, $title = 'Information Panel', $borderChar = '*') -``` - -展示信息面板。比如 命令行应用 开始运行时需要显示一些 版本信息,环境信息等等。 - -使用 `Show::panel()/$output->panel()` - -```php -$data = [ - 'application version' => '1.2.0', - 'system version' => '5.2.3', - 'see help' => 'please use php bin/app -h', - 'a only value message', -]; -Show::panel($data, 'panel show', '#'); -``` - -### 数据表格信息输出 - -```php -public static function table(array $data, $title = 'Data Table', array $opts = []) -``` - -使用 `Show::table()/$output->table()` - -- 可直接渲染从数据库拉取的数据(会自动提取字段名作为表头) - -```php -// like from database query's data. -$data = [ - [ col1 => value1, col2 => value2, col3 => value3, ... ], // first row - [ col1 => value4, col2 => value5, col3 => value6, ... ], // second row - ... ... -]; - -Show::table($data, 'a table'); -``` - -- 自己构造数据时,还要写字段名就有些麻烦了。so, 可以通过选项配置 `$opts` 手动配置表头字段列表 - -```php -// use custom head -$data = [ - [ value1, value2, value3, ... ], // first row - [ value4, value5, value6, ... ], // second row - // ... ... -]; - -$opts = [ - 'showBorder' => true, - 'tHead' => [col1, col2, col3, ...] -]; -Show::table($data, 'a table', $opts); -``` - -### 快速的渲染一个帮助信息面板 - -```php -public static function helpPanel(array $config, $showAfterQuit = true) -``` - -使用 `Show::helpPanel()/$output->helpPanel()` - -```php -Show::helpPanel([ - Show::HELP_DES => 'a help panel description text. (help panel show)', - Show::HELP_USAGE => 'a usage text', - Show::HELP_ARGUMENTS => [ - 'arg1' => 'arg1 description', - 'arg2' => 'arg2 description', - ], - Show::HELP_OPTIONS => [ - '--opt1' => 'a long option', - '-s' => 'a short option', - '-d' => 'Run the server on daemon.(default: false)', - '-h, --help' => 'Display this help message' - ], -], false); -``` - -### 渲染效果预览 - -![alt text](images/output-format-msg.png "Title") - -## 用户交互方法 - -需引入类 `Inhere\Console\Utils\Interact` - -### 从给出的列表中选择一项 - -```php -public static function select($description, $options, $default = null, $allowExit=true) -public static function choice($description, $options, $default = null, $allowExit=true) // alias method -``` - -使用 `Interact::select()` (alias `Interact::chioce()`) - -- 示例 1: 只有值,没有选项key - -```php -$select = Interact::select('Your city is ?', [ - 'chengdu', 'beijing', 'shanghai' -]); -``` - -渲染结果(in terminal): - -``` -Your city is ? - 0) chengdu - 1) beijing - 2) shanghai - q) Quit // quit option. is auto add. can setting it by 4th argument. -You choice: 0 -``` - -```php -echo "$select"; // '0' -``` - -- 示例 2: - -有选项key, 并且设置了一个默认值. - -```php -$select = Interact::select('Your city is ?', [ - 'a' => 'chengdu', - 'b' => 'beijing', - 'c' => 'shanghai' -], 'a'); -``` - -渲染结果(in terminal): - -``` -Your city is? - a) chengdu - b) beijing - c) shanghai - q) Quit // quit option. is auto add. can setting it by 4th argument. -You choice[default:a] : b -``` - -```php -echo $select; // 'b' -``` - -### 要求确认是否继续执行 - -```php -public static function confirm($question, $default = true) bool -``` - -使用 `Interact::confirm()` : - -```php -$result = Interact::confirm('Whether you want to continue ?'); -``` - -渲染结果(in terminal): - -``` -Whether you want to continue ? -Please confirm (yes|no) [default:yes]: n -``` - -结果: - -```php -var_dump($result); // bool(false) -``` - -### 询问,并返回用户的回答 - -```php -public static function ask($question, $default = null, \Closure $validator = null) -public static function question($question, $default = null, \Closure $validator = null) -``` - -使用 `Interact::question()`/`Interact::ask()` - -```php -$answer = Interact::ask('Please input your name?', null, function ($answer) { - if (!preg_match('/\w+/', $answer)) { - Interact::error('The name must match "/\w+/"'); - - return false; - } - - return true; -}); -``` - -### 有次数限制的询问 - -```php -public static function limitedAsk($question, $default = null, \Closure $validator = null, $times = 3) -``` - -有次数限制的询问,提出问题 - -* 若输入了值且验证成功则返回 输入的结果 -* 否则,会连续询问 `$times` 次,若仍然错误,退出 - - -```php -// no default value -$answer = Interact::limitedAsk('please input you age?', null, function($age) -{ - if ($age<1 || $age>100) { - Interact::error('Allow the input range is 1-100'); - return false; - } - - return true; -}); -``` - -## License - -MIT - -## 我的其他项目 - -### `inhere/redis` [github](https://github.com/inhere/php-redis) [git@osc](https://git.oschina.net/inhere/php-redis) - -简单的redis操作客户端包装库 - -### `inhere/sroute` [github](https://github.com/inhere/php-srouter) [git@osc](https://git.oschina.net/inhere/php-srouter) - - 轻量且功能丰富快速的路由库 - -### `inhere/php-validate` [github](https://github.com/inhere/php-validate) [git@osc](https://git.oschina.net/inhere/php-validate) - - 一个简洁小巧且功能完善的php验证库。仅有几个文件,无依赖。 - -### `inhere/http` [github](https://github.com/inhere/php-http) [git@osc](https://git.oschina.net/inhere/php-http) - -http 工具库(`request` 请求 `response` 响应 `curl` curl请求库,有简洁、完整和并发请求三个版本的类) diff --git a/src/Base/AbstractApplication.php b/src/Base/AbstractApplication.php index 6fc0beb..6e84aeb 100644 --- a/src/Base/AbstractApplication.php +++ b/src/Base/AbstractApplication.php @@ -11,7 +11,7 @@ use Inhere\Console\IO\Input; use Inhere\Console\IO\Output; use Inhere\Console\Traits\InputOutputTrait; -use Inhere\Console\Traits\SimpleEventStaticTrait; +use Inhere\Console\Traits\SimpleEventTrait; /** * Class AbstractApplication @@ -20,7 +20,7 @@ abstract class AbstractApplication implements ApplicationInterface { use InputOutputTrait; - use SimpleEventStaticTrait; + use SimpleEventTrait; /** @var bool render no color */ private static $noColor = false; diff --git a/src/Traits/SimpleEventStaticTrait.php b/src/Traits/SimpleEventTrait.php similarity index 99% rename from src/Traits/SimpleEventStaticTrait.php rename to src/Traits/SimpleEventTrait.php index 662c122..0ea13f1 100644 --- a/src/Traits/SimpleEventStaticTrait.php +++ b/src/Traits/SimpleEventTrait.php @@ -12,7 +12,7 @@ * Class SimpleEventStaticTrait * @package Inhere\Console\Traits */ -trait SimpleEventStaticTrait +trait SimpleEventTrait { /** * set the supported events, if you need.