Commit 89ea3fef by Carsten Brandt

Next iteration on console commands

issue #33 - implemted getScreenSize for linux systems - tiny adjustments and better naming for console color methods - color switch in base Controller changed to magic property - colorized Help command
parent aadcb59c
......@@ -36,12 +36,35 @@ class Controller extends \yii\base\Controller
public $interactive = true;
/**
* @var bool whether to enable ANSI style in output.
* @var boolean whether to enable ANSI style in output.
* Defaults to null meaning auto-detect.
*/
private $_colors;
/**
* Whether to enable ANSI style in output.
*
* Setting this will affect [[ansiFormat()]], [[stdout()]] and [[stderr()]].
* If not set it will be auto detected using [[yii\helpers\Console::streamSupportsAnsiColors()]] with STDOUT
* for [[ansiFormat()]] and [[stdout()]] and STDERR for [[stderr()]].
* @param resource $stream
* @return boolean Whether to enable ANSI style in output.
*/
public function getColors($stream = STDOUT)
{
if ($this->_colors === null) {
return Console::streamSupportsAnsiColors($stream);
}
return $this->_colors;
}
/**
* Whether to enable ANSI style in output.
*/
public $colors;
public function setColors($value)
{
$this->_colors = (bool) $value;
}
/**
* Runs an action with the specified action ID and parameters.
......@@ -138,7 +161,7 @@ class Controller extends \yii\base\Controller
*/
public function ansiFormat($string)
{
if ($this->ansi === true || $this->ansi === null && Console::streamSupportsAnsiColors(STDOUT)) {
if ($this->getColors()) {
$args = func_get_args();
array_shift($args);
$string = Console::ansiFormat($string, $args);
......@@ -162,7 +185,7 @@ class Controller extends \yii\base\Controller
*/
public function stdout($string)
{
if ($this->ansi === true || $this->ansi === null && Console::streamSupportsAnsiColors(STDOUT)) {
if ($this->getColors()) {
$args = func_get_args();
array_shift($args);
$string = Console::ansiFormat($string, $args);
......@@ -186,7 +209,7 @@ class Controller extends \yii\base\Controller
*/
public function stderr($string)
{
if ($this->ansi === true || $this->ansi === null && Console::streamSupportsAnsiColors(STDERR)) {
if ($this->getColors(STDERR)) {
$args = func_get_args();
array_shift($args);
$string = Console::ansiFormat($string, $args);
......@@ -259,6 +282,6 @@ class Controller extends \yii\base\Controller
*/
public function globalOptions()
{
return array();
return array('colors', 'interactive');
}
}
......@@ -13,6 +13,7 @@ use yii\base\InlineAction;
use yii\console\Controller;
use yii\console\Exception;
use yii\console\Request;
use yii\helpers\Console;
use yii\helpers\Inflector;
/**
......@@ -56,7 +57,7 @@ class HelpController extends Controller
$result = Yii::$app->createController($command);
if ($result === false) {
throw new Exception(Yii::t('yii', 'No help for unknown command "{command}".', array(
'{command}' => $command,
'{command}' => $this->ansiFormat($command, Console::FG_YELLOW),
)));
}
......@@ -143,14 +144,15 @@ class HelpController extends Controller
{
$commands = $this->getCommands();
if (!empty($commands)) {
echo "The following commands are available:\n\n";
$this->stdout("\nThe following commands are available:\n\n", Console::BOLD);
foreach ($commands as $command) {
echo "* $command\n";
echo "- " . $this->ansiFormat($command, Console::FG_YELLOW) . "\n";
}
echo "\nTo see the help of each command, enter:\n";
echo "\n yii help <command-name>\n\n";
$this->stdout("\nTo see the help of each command, enter:\n", Console::BOLD);
echo "\n yii " . $this->ansiFormat('help', Console::FG_YELLOW) . ' '
. $this->ansiFormat('<command-name>', Console::FG_CYAN) . "\n\n";
} else {
echo "\nNo commands are found.\n";
$this->stdout("\nNo commands are found.\n\n", Console::BOLD);
}
}
......@@ -167,19 +169,18 @@ class HelpController extends Controller
}
if ($comment !== '') {
echo "\nDESCRIPTION\n";
echo "\n" . $comment . "\n\n";
$this->stdout("\nDESCRIPTION\n", Console::BOLD);
echo "\n" . Console::renderColoredString($comment) . "\n\n";
}
$actions = $this->getActions($controller);
if (!empty($actions)) {
echo "\nSUB-COMMANDS\n\n";
$this->stdout("\nSUB-COMMANDS\n\n", Console::BOLD);
$prefix = $controller->getUniqueId();
foreach ($actions as $action) {
echo '- ' . $this->ansiFormat($prefix.'/'.$action, Console::FG_YELLOW);
if ($action === $controller->defaultAction) {
echo "* $prefix/$action (default)";
} else {
echo "* $prefix/$action";
$this->stdout(' (default)', Console::FG_GREEN);
}
$summary = $this->getActionSummary($controller, $action);
if ($summary !== '') {
......@@ -187,8 +188,9 @@ class HelpController extends Controller
}
echo "\n";
}
echo "\n\nTo see the detailed information about individual sub-commands, enter:\n";
echo "\n yii help <sub-command>\n\n";
echo "\nTo see the detailed information about individual sub-commands, enter:\n";
echo "\n yii " . $this->ansiFormat('help', Console::FG_YELLOW) . ' '
. $this->ansiFormat('<sub-command>', Console::FG_CYAN) . "\n\n";
}
}
......@@ -253,25 +255,25 @@ class HelpController extends Controller
$options = $this->getOptionHelps($controller);
if ($tags['description'] !== '') {
echo "\nDESCRIPTION";
echo "\n\n" . $tags['description'] . "\n\n";
$this->stdout("\nDESCRIPTION\n", Console::BOLD);
echo "\n" . Console::renderColoredString($tags['description']) . "\n\n";
}
echo "\nUSAGE\n\n";
$this->stdout("\nUSAGE\n\n", Console::BOLD);
if ($action->id === $controller->defaultAction) {
echo 'yii ' . $controller->getUniqueId();
echo 'yii ' . $this->ansiFormat($controller->getUniqueId(), Console::FG_YELLOW);
} else {
echo "yii " . $action->getUniqueId();
echo 'yii ' . $this->ansiFormat($action->getUniqueId(), Console::FG_YELLOW);
}
list ($required, $optional) = $this->getArgHelps($method, isset($tags['param']) ? $tags['param'] : array());
if (!empty($required)) {
echo ' <' . implode('> <', array_keys($required)) . '>';
foreach ($required as $arg => $description) {
$this->stdout(' <' . $arg . '>', Console::FG_CYAN);
}
if (!empty($optional)) {
echo ' [' . implode('] [', array_keys($optional)) . ']';
foreach ($optional as $arg => $description) {
$this->stdout(' [' . $arg . ']', Console::FG_CYAN);
}
if (!empty($options)) {
echo ' [...options...]';
$this->stdout(' [...options...]', Console::FG_RED);
}
echo "\n\n";
......@@ -281,7 +283,7 @@ class HelpController extends Controller
$options = $this->getOptionHelps($controller);
if (!empty($options)) {
echo "\nOPTIONS\n\n";
$this->stdout("\nOPTIONS\n\n", Console::BOLD);
echo implode("\n\n", $options) . "\n\n";
}
}
......@@ -310,9 +312,9 @@ class HelpController extends Controller
$comment = $tag;
}
if ($param->isDefaultValueAvailable()) {
$optional[$name] = $this->formatOptionHelp('* ' . $name, false, $type, $param->getDefaultValue(), $comment);
$optional[$name] = $this->formatOptionHelp('- ' . $this->ansiFormat($name, Console::FG_CYAN), false, $type, $param->getDefaultValue(), $comment);
} else {
$required[$name] = $this->formatOptionHelp('* ' . $name, true, $type, null, $comment);
$required[$name] = $this->formatOptionHelp('- ' . $this->ansiFormat($name, Console::FG_CYAN), true, $type, null, $comment);
}
}
......@@ -352,9 +354,9 @@ class HelpController extends Controller
$type = null;
$comment = $doc;
}
$options[$name] = $this->formatOptionHelp('--' . $name, false, $type, $defaultValue, $comment);
$options[$name] = $this->formatOptionHelp($this->ansiFormat('--' . $name, Console::FG_RED), false, $type, $defaultValue, $comment);
} else {
$options[$name] = $this->formatOptionHelp('--' . $name, false, null, $defaultValue, '');
$options[$name] = $this->formatOptionHelp($this->ansiFormat('--' . $name, Console::FG_RED), false, null, $defaultValue, '');
}
}
ksort($options);
......
......@@ -45,6 +45,7 @@ class Console
const BG_CYAN = 46;
const BG_GREY = 47;
const RESET = 0;
const NORMAL = 0;
const BOLD = 1;
const ITALIC = 3;
......@@ -240,34 +241,41 @@ class Console
}
/**
* Sets the ANSI format for any text that is printed afterwards.
* Returns the ANSI format code.
*
* You can pass any of the FG_*, BG_* and TEXT_* constants and also [[xterm256ColorFg]] and [[xterm256ColorBg]].
* @param array $format You can pass any of the FG_*, BG_* and TEXT_* constants and also [[xtermFgColor]] and [[xtermBgColor]].
* TODO: documentation
* @return string
*/
public static function ansiFormatBegin()
public static function ansiFormatCode($format)
{
echo "\033[" . implode(';', func_get_args()) . 'm';
return "\033[" . implode(';', $format) . 'm';
}
/**
* Resets any ANSI format set by previous method [[ansiFormatBegin()]]
* Any output after this is will have default text style.
* Sets the ANSI format for any text that is printed afterwards.
*
* @param array $format You can pass any of the FG_*, BG_* and TEXT_* constants and also [[xtermFgColor]] and [[xtermBgColor]].
* TODO: documentation
* @see ansiFormatEnd()
*/
public static function ansiFormatReset()
public static function beginAnsiFormat($format)
{
echo "\033[0m";
echo "\033[" . implode(';', $format) . 'm';
}
/**
* Returns the ANSI format code.
* Resets any ANSI format set by previous method [[ansiFormatBegin()]]
* Any output after this is will have default text style.
* This is equal to
*
* You can pass any of the FG_*, BG_* and TEXT_* constants and also [[xterm256ColorFg]] and [[xterm256ColorBg]].
* TODO: documentation
* ```php
* echo Console::ansiFormatCode(array(Console::RESET))
* ```
*/
public static function ansiFormatCode($format)
public static function endAnsiFormat()
{
return "\033[" . implode(';', $format) . 'm';
echo "\033[0m";
}
/**
......@@ -275,7 +283,7 @@ class Console
*
* @param string $string the string to be formatted
* @param array $format array containing formatting values.
* You can pass any of the FG_*, BG_* and TEXT_* constants and also [[xterm256ColorFg]] and [[xterm256ColorBg]].
* You can pass any of the FG_*, BG_* and TEXT_* constants and also [[xtermFgColor]] and [[xtermBgColor]].
* @return string
*/
public static function ansiFormat($string, $format=array())
......@@ -284,15 +292,32 @@ class Console
return "\033[0m" . ($code !== '' ? "\033[" . $code . "m" : '') . $string . "\033[0m";
}
//const COLOR_XTERM256 = 38;// http://en.wikipedia.org/wiki/Talk:ANSI_escape_code#xterm-256colors
public static function xterm256ColorFg($i) // TODO naming!
/**
* Returns the ansi format code for xterm foreground color.
* You can pass the returnvalue of this to one of the formatting methods:
* [[ansiFormat]], [[ansiFormatCode]], [[beginAnsiFormat]]
*
* @param integer $colorCode xterm color code
* @return string
* @see http://en.wikipedia.org/wiki/Talk:ANSI_escape_code#xterm-256colors
*/
public static function xtermFgColor($colorCode)
{
return '38;5;' . $i;
return '38;5;' . $colorCode;
}
public static function xterm256ColorBg($i) // TODO naming!
/**
* Returns the ansi format code for xterm foreground color.
* You can pass the returnvalue of this to one of the formatting methods:
* [[ansiFormat]], [[ansiFormatCode]], [[beginAnsiFormat]]
*
* @param integer $colorCode xterm color code
* @return string
* @see http://en.wikipedia.org/wiki/Talk:ANSI_escape_code#xterm-256colors
*/
public static function xtermBgColor($colorCode)
{
return '48;5;' . $i;
return '48;5;' . $colorCode;
}
/**
......@@ -303,7 +328,7 @@ class Console
*/
public static function stripAnsiFormat($string)
{
return preg_replace('/\033\[[\d;]+m/', '', $string); // TODO currently only strips color
return preg_replace('/\033\[[\d;?]*\w/', '', $string);
}
// TODO refactor and review
......@@ -418,10 +443,11 @@ class Console
}
/**
* TODO syntax copied from https://github.com/pear/Console_Color2/blob/master/Console/Color2.php
* Converts a string to ansi formatted by replacing patterns like %y (for yellow) with ansi control codes
*
* Converts colorcodes in the format %y (for yellow) into ansi-control
* codes. The conversion table is: ('bold' meaning 'light' on some
* // TODO documentation
* Uses almost the same syntax as https://github.com/pear/Console_Color2/blob/master/Console/Color2.php
* The conversion table is: ('bold' meaning 'light' on some
* terminals). It's almost the same conversion table irssi uses.
* <pre>
* text text background
......@@ -450,7 +476,6 @@ class Console
*
* @param string $string String to convert
* @param bool $colored Should the string be colored?
*
* @return string
*/
public static function renderColoredString($string, $colored = true)
......@@ -508,7 +533,8 @@ class Console
}
/**
* Escapes % so they don't get interpreted as color codes
* Escapes % so they don't get interpreted as color codes when
* the string is parsed by [[renderColoredString]]
*
* @param string $string String to escape
*
......@@ -548,12 +574,38 @@ class Console
/**
* Usage: list($w, $h) = ConsoleHelper::getScreenSize();
*
* @return array
* @return array|boolean An array of ($width, $height) or false when it was not able to determine size.
*/
public static function getScreenSize()
public static function getScreenSize($refresh = false)
{
// TODO implement
return array(150, 50);
static $size;
if ($size !== null && !$refresh) {
return $size;
}
if (static::isRunningOnWindows()) {
// TODO implement for windows
return $size = false;
} else {
// try stty if available
$stty = array();
if (exec('stty -a 2>&1', $stty) && preg_match('/rows\s+(\d+);\s*columns\s+(\d+);/mi', implode(' ', $stty), $matches)) {
return $size = array($matches[2], $matches[1]);
}
// fallback to tput, which may not be updated on terminal resize
if (($width = (int) exec('tput cols 2>&1')) > 0 && ($height = (int) exec('tput lines 2>&1')) > 0) {
return $size = array($width, $height);
}
// fallback to ENV variables, which may not be updated on terminal resize
if (($width = (int) getenv('COLUMNS')) > 0 && ($height = (int) getenv('LINES')) > 0) {
return $size = array($width, $height);
}
}
return $size = false;
}
/**
......@@ -607,27 +659,23 @@ class Console
/**
* Prints text to STDOUT appended with a carriage return (PHP_EOL).
*
* @param string $text
* @param bool $raw
*
* @param string $string
* @return mixed Number of bytes printed or bool false on error
*/
public static function output($text = null)
public static function output($string = null)
{
return static::stdout($text . PHP_EOL);
return static::stdout($string . PHP_EOL);
}
/**
* Prints text to STDERR appended with a carriage return (PHP_EOL).
*
* @param string $text
* @param bool $raw
*
* @param string $string
* @return mixed Number of bytes printed or false on error
*/
public static function error($text = null)
public static function error($string = null)
{
return static::stderr($text . PHP_EOL);
return static::stderr($string . PHP_EOL);
}
/**
......
<?php
namespace yiiunit\framework\helpers;
use Yii;
use yii\helpers\Console;
use yiiunit\TestCase;
class ConsoleTest extends TestCase
{
public function testStripAnsiFormat()
{
ob_start();
ob_implicit_flush(false);
echo 'a';
Console::moveCursorForward(1);
echo 'a';
Console::moveCursorDown(1);
echo 'a';
Console::moveCursorUp(1);
echo 'a';
Console::moveCursorBackward(1);
echo 'a';
Console::moveCursorNextLine(1);
echo 'a';
Console::moveCursorPrevLine(1);
echo 'a';
Console::moveCursorTo(1);
echo 'a';
Console::moveCursorTo(1, 2);
echo 'a';
Console::clearLine();
echo 'a';
Console::clearLineAfterCursor();
echo 'a';
Console::clearLineBeforeCursor();
echo 'a';
Console::clearScreen();
echo 'a';
Console::clearScreenAfterCursor();
echo 'a';
Console::clearScreenBeforeCursor();
echo 'a';
Console::scrollDown();
echo 'a';
Console::scrollUp();
echo 'a';
Console::hideCursor();
echo 'a';
Console::showCursor();
echo 'a';
Console::saveCursorPosition();
echo 'a';
Console::restoreCursorPosition();
echo 'a';
Console::beginAnsiFormat(array(Console::FG_GREEN, Console::BG_BLUE, Console::UNDERLINE));
echo 'a';
Console::endAnsiFormat();
echo 'a';
Console::beginAnsiFormat(array(Console::xtermBgColor(128), Console::xtermFgColor(55)));
echo 'a';
Console::endAnsiFormat();
echo 'a';
$ouput = Console::stripAnsiFormat(ob_get_clean());
ob_implicit_flush(true);
// $output = str_replace("\033", 'X003', $ouput );// uncomment for debugging
$this->assertEquals(str_repeat('a', 25), $ouput);
}
/* public function testScreenSize()
{
for($i = 1; $i < 20; $i++) {
echo implode(', ', Console::getScreenSize(true)) . "\n";
ob_flush();
sleep(1);
}
}*/
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment