Skip to content
This repository was archived by the owner on Jan 23, 2019. It is now read-only.

Commit 861817d

Browse files
committed
add console help show function
1 parent 454feaf commit 861817d

File tree

4 files changed

+293
-51
lines changed

4 files changed

+293
-51
lines changed

src/console/ConsoleHelper.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,57 @@ public static function isInteractive($fileDescriptor)
3737
{
3838
return function_exists('posix_isatty') && @posix_isatty($fileDescriptor);
3939
}
40+
41+
/**
42+
* get key Max Width
43+
*
44+
* @param array $data
45+
* [
46+
* 'key1' => 'value1',
47+
* 'key2-test' => 'value2',
48+
* ]
49+
* @return int
50+
*/
51+
public static function keyMaxWidth(array $data, $expactInt = true)
52+
{
53+
$keyMaxWidth = 0;
54+
55+
foreach ($data as $key => $value) {
56+
// key is not a integer
57+
if ( !$expactInt || !is_numeric($key) ) {
58+
$width = mb_strlen($key, 'UTF-8');
59+
$keyMaxWidth = $width > $keyMaxWidth ? $width : $keyMaxWidth;
60+
}
61+
}
62+
63+
return $keyMaxWidth;
64+
}
65+
66+
/**
67+
* spliceArray
68+
* @param array $data
69+
* e.g [
70+
* 'system' => 'Linux',
71+
* 'version' => '4.4.5',
72+
* ]
73+
* @param int $keyMaxWidth
74+
* @param string $sepChar e.g ' | ' => OUT: key | value
75+
* @param string $leftChar e.g ' * '
76+
* @return string
77+
*/
78+
public static function spliceKeyValue($data, $keyMaxWidth, $sepChar = ' ', $leftChar='')
79+
{
80+
$text = '';
81+
foreach ($panelData as $key => $value) {
82+
$text .= $leftChar;
83+
84+
if ($keyMaxWidth) {
85+
$text .= str_pad($key, $keyMaxWidth, ' ') . $sepChar;
86+
}
87+
88+
$text .= "$value\n";
89+
}
90+
91+
return $text;
92+
}
4093
}

src/console/Interact.php

Lines changed: 174 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -24,71 +24,97 @@ class Interact
2424
const NL_TAB = "\n ";// new line + tab
2525

2626
/////////////////////////////////////////////////////////////////
27-
/// Interactive
27+
/// Interactive method (select/confirm/question/loopAsk)
2828
/////////////////////////////////////////////////////////////////
2929

3030
/**
3131
* 多选一
32-
* @param string $question 说明
33-
* @param mixed $option 选项数据
34-
* @param bool $allowExit 有退出选项 默认 true
32+
* @param string $description 说明
33+
* @param mixed $options 选项数据
34+
* e.g
35+
* [
36+
* // option => value
37+
* '1' => 'chengdu',
38+
* '2' => 'beijing'
39+
* ]
40+
* @param mixed $default 默认选项
41+
* @param bool $allowExit 有退出选项 默认 true
3542
* @return string
3643
*/
37-
public static function choice($question, $option, $allowExit=true)
44+
public static function select($description, $options, $default = null, $allowExit=true)
3845
{
39-
self::write(" <comment>$question</comment>");
46+
self::choice($description, $options, $default, $allowExit);
47+
}
48+
public static function choice($description, $options, $default = null, $allowExit=true)
49+
{
50+
if ( !$description = trim($description) ) {
51+
self::error('Please provide a description text!', 1);
52+
}
53+
54+
self::write(" <comment>$description</comment>");
4055

41-
$option = is_array($option) ? $option : explode(',', $option);
42-
// no set key
43-
$isNumeric = isset($option[0]);
4456
$keys = [];
4557
$optStr = '';
58+
$options = is_array($options) ? $options : explode(',', $options);
4659

47-
foreach ($option as $key => $value) {
48-
$keys[] = $isNumeric ? ++$key : $key;
60+
// If defaut option is error
61+
if ( null === $default && !isset($options[$default]) ) {
62+
self::error("The default option [{$default}] don't exists.", true);
63+
}
4964

50-
$optStr .= "\n $key) $value";
65+
foreach ($options as $key => $value) {
66+
$keys[] = $key;
67+
$optStr .= "\n <info>$key</info>) $value";
5168
}
5269

5370
if ($allowExit) {
5471
$keys[] = 'q';
5572
$optStr .= "\n q) quit";
5673
}
5774

58-
self::write($optStr . "\n You choice : ");
59-
60-
$r = self::readRow();
75+
$r = self::read($optStr . "\n You choice : ");
6176

77+
// error, allow try again
6278
if ( !in_array($r, $keys) ) {
63-
self::write("Warning! option <comment>$r<comment>) don't exists! please entry again! :");
79+
$r = self::read("Warning! Option <info>$r</info>) don't exists! Please entry again! : ");
80+
}
6481

65-
$r = self::readRow();
82+
// exit
83+
if ( $r === 'q' ) {
84+
self::write("\n Quit,ByeBye.", true, true);
6685
}
6786

68-
if ($r === 'q' || !in_array($r, $keys) ) {
69-
exit("\n\n Quit,ByeBye.\n");
87+
// error
88+
if ( !in_array($r, $keys) ) {
89+
if ( null === $default ) {
90+
self::write("\n Select error. Quit,ByeBye.", true, true);
91+
}
92+
93+
$r = $default;
7094
}
7195

7296
return $r;
7397
}
7498

7599
/**
76-
* 确认, 发出信息要求确认;返回 true | false
77-
* @param string $question 发出的信息
78-
* @param bool $yes
100+
* 确认, 发出信息要求确认
101+
* @param string $question 发出的信息
102+
* @param bool $default Default value
79103
* @return bool
80104
*/
81-
public static function confirm($question, $yes = true)
105+
public static function confirm($question, $default = true)
82106
{
83-
$question = ucfirst(trim($question));
84-
$defaultText = $yes ? 'yes' : 'no';
107+
if ( !$question = trim($question) ) {
108+
self::error('Please provide a question text!', 1);
109+
}
85110

86-
$message = "<comment>$question</comment>\n Please confirm (yes|no) [default:<info>$defaultText</info>]: ";
87-
self::write($message, false);
111+
$question = ucfirst($question);
112+
$defaultText = (bool)$default ? 'yes' : 'no';
88113

89-
$answer = self::readRow();
114+
$message = " <comment>$question ?</comment>\n Please confirm (yes|no) [default:<info>$defaultText</info>]: ";
115+
$answer = self::read($message);
90116

91-
return $answer ? !strncasecmp($answer, 'y', 1) : (bool)$yes;
117+
return $answer ? !strncasecmp($answer, 'y', 1) : (bool)$default;
92118
}
93119

94120
/**
@@ -231,7 +257,7 @@ public static function loopAsk($question, $default = null, \Closure $validator =
231257
}
232258

233259
/////////////////////////////////////////////////////////////////
234-
/// Output Message
260+
/// Output Format Message(title/section/helpPanel/panel/table)
235261
/////////////////////////////////////////////////////////////////
236262

237263
/**
@@ -260,31 +286,140 @@ public static function section($msg, $width = 50, $char = '-')
260286
}
261287

262288
/**
263-
* 多行信息展示
289+
* Show console help message
290+
* @param string $usage The usage message text. e.g 'command [options] [arguments]'
291+
* @param array $commands The command list
292+
* e.g
293+
* [
294+
* // command => description
295+
* 'start' => 'Start the app server',
296+
* ... ...
297+
* ]
298+
* @param array $options The option list
299+
* e.g
300+
* [
301+
* // option => description
302+
* '-d' => 'Run the server on daemonize.(default: <comment>false</comment>)',
303+
* '-h, --help' => 'Display this help message'
304+
* ... ...
305+
* ]
306+
* @param array $examples The command usage example. e.g 'php server.php {start|reload|restart|stop} [-d]'
307+
* @param string $description The description text. e.g 'Composer version 1.3.2'
308+
*/
309+
public static function consoleHelp($usage, $commands = [], $options = [], $examples = [], $description = '')
310+
{
311+
self::helpPanel($usage, $commands, $options, $examples, $description);
312+
}
313+
public static function helpPanel($usage, $commands = [], $options = [], $examples = [], $description = '')
314+
{
315+
// usage
316+
self::write("<comment>Usage</comment>:\n {$usage}\n");
317+
318+
// options list
319+
if ( $options ) {
320+
// translate array to string
321+
if ( is_array($options)) {
322+
$optionMaxWidth = ConsoleHelper::keyMaxWidth($options);
323+
$options = ConsoleHelper::spliceKeyValue($options, $optionMaxWidth);
324+
}
325+
326+
if ( is_string($options) ) {
327+
self::write("<comment>Options</comment>:\n {$options}\n");
328+
}
329+
}
330+
331+
// command list
332+
if ( $commands ) {
333+
// translate array to string
334+
if ( is_array($commands)) {
335+
$commandMaxWidth = ConsoleHelper::keyMaxWidth($commands);
336+
$commands = ConsoleHelper::spliceKeyValue($commands, $commandMaxWidth);
337+
}
338+
339+
if ( is_string($commands) ) {
340+
self::write("<comment>Commands</comment>:\n {$commands}\n");
341+
}
342+
}
343+
344+
// examples list
345+
if ( $examples ) {
346+
$examples = is_array($examples) ? implode(PHP_EOL, $examples) : $examples;
347+
self::write("<comment>Examples</comment>:\n {$examples}\n");
348+
}
349+
}
350+
351+
/**
352+
* Show information data panel
264353
* @param mixed $data
265354
* @param string $title
266355
* @return void
267356
*/
268-
public static function panel(array $data, $title='Info panel')
357+
public static function panel($data, $title='Info panel', $char = '*')
269358
{
270359
$data = is_array($data) ? array_filter($data) : [trim($data)];
271-
$title = ucwords(trim($title));
360+
$title = trim($title);
361+
362+
$panelData = []; // [ 'label' => 'value' ]
363+
$labelMaxWidth = 0; // if label exists, label max width
364+
$valueMaxWidth = 0; // value max width
272365

273366
self::write("\n " . sprintf(self::STAR_LINE,"<bold>$title</bold>"), false);
274367

275368
foreach ($data as $label => $value) {
276-
$line = ' * ';
369+
// label exists
370+
if ( !is_numeric($label) ) {
371+
$width = mb_strlen($label, 'UTF-8');
372+
$labelMaxWidth = $width > $labelMaxWidth ? $width : $labelMaxWidth;
373+
}
374+
375+
// translate array to string
376+
if ( is_array($value) ) {
377+
$temp = '';
277378

278-
if (!is_numeric($label)) {
279-
$line .= "$label: ";
379+
foreach ($value as $key => $val) {
380+
$val = (string)$val;
381+
$temp .= (!is_numeric($key) ? "$key: " : '') . "<info>$value</info>, ";
382+
}
383+
384+
$value = rtrim($temp, ' ,');
280385
}
281386

282-
self::write("$line <info>$value</info>");
387+
// get value width
388+
if ( is_string($value) || is_numeric($value) ) {
389+
$value = trim($value);
390+
$width = mb_strlen(strip_tags($value), 'UTF-8'); // must clear style tag
391+
$valueMaxWidth = $width > $valueMaxWidth ? $width : $valueMaxWidth;
392+
} else {
393+
throw new \Exception('Panel data value only allow [array|string|number]');
394+
}
395+
396+
$panelData[$label] = $value;
397+
}
398+
399+
$panelWidth = $labelMaxWidth + $valueMaxWidth;
400+
401+
// output title
402+
if ($title) {
403+
$title = ucwords($title);
404+
$titleLength = mb_strlen($title, 'UTF-8');
405+
$indentSpace = str_pad(' ', ceil($panelWidth/2) - ceil($titleLength/2) + 2*2, ' ');
406+
self::write(" {$indentSpace}<bold>{$title}</bold>");
283407
}
284408

285-
$star = $title ? substr(self::STAR_LINE, 0, strlen($title)): '';
409+
// output panel top border
410+
$border = str_pad($char, $panelWidth + (2*3), $char);
411+
self::write(' ' . $border);
412+
413+
// output panel body
414+
$panelStr = ConsoleHelper::spliceKeyValue($panelData, $labelMaxWidth, ' | ', " $char ");
415+
416+
// already exists "\n"
417+
self::write($panelStr, false);
418+
419+
// output panel bottom border
420+
self::write(" $border\n");
286421

287-
self::write(' ' . sprintf(self::STAR_LINE, $star ));
422+
unset($data, $panelData);
288423
}
289424

290425
/**

src/console/Output.php

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,39 +37,41 @@ class Output
3737
/// Output Message
3838
/////////////////////////////////////////////////////////////////
3939

40-
4140
/**
42-
* @param $msg
41+
* @see Interact::title()
4342
*/
4443
public function title($msg, $width = null)
4544
{
4645
Interact::title($msg, $width);
4746
}
4847

4948
/**
50-
* @param $msg
49+
* @see Interact::section()
5150
*/
5251
public function section($msg, $width = null)
5352
{
5453
Interact::section($msg, $width);
5554
}
5655

5756
/**
58-
* 多行信息展示
59-
* @param mixed $data
60-
* @param string $title
61-
* @return void
57+
* helpPanel
58+
* @see Interact::helpPanel()
59+
*/
60+
public function helpPanel($usage, $commands = [], $options = [], $examples = [], $description = '')
61+
{
62+
Interact::helpPanel($msg, $width);
63+
}
64+
65+
/**
66+
* @see Interact::panel()
6267
*/
6368
public function panel(array $data, $title='Info panel')
6469
{
6570
Interact::panel($data, $title);
6671
}
6772

6873
/**
69-
* 表格数据信息展示
70-
* @param array $data
71-
* @param string $title
72-
* @return void
74+
* @see Interact::table()
7375
*/
7476
public function table(array $data, $title='Info List', $showBorder = true)
7577
{

0 commit comments

Comments
 (0)