Page MenuHomePhabricator

D14136.id34158.diff
No OneTemporary

D14136.id34158.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -125,14 +125,18 @@
'PhutilCodeSnippetContextFreeGrammar' => 'grammar/code/PhutilCodeSnippetContextFreeGrammar.php',
'PhutilCommandString' => 'xsprintf/PhutilCommandString.php',
'PhutilConsole' => 'console/PhutilConsole.php',
+ 'PhutilConsoleBlock' => 'console/view/PhutilConsoleBlock.php',
+ 'PhutilConsoleConcatenatedView' => 'console/view/PhutilConsoleConcatenatedView.php',
'PhutilConsoleFormatter' => 'console/PhutilConsoleFormatter.php',
+ 'PhutilConsoleList' => 'console/view/PhutilConsoleList.php',
'PhutilConsoleMessage' => 'console/PhutilConsoleMessage.php',
'PhutilConsoleProgressBar' => 'console/PhutilConsoleProgressBar.php',
'PhutilConsoleServer' => 'console/PhutilConsoleServer.php',
'PhutilConsoleServerChannel' => 'console/PhutilConsoleServerChannel.php',
'PhutilConsoleStdinNotInteractiveException' => 'console/PhutilConsoleStdinNotInteractiveException.php',
'PhutilConsoleSyntaxHighlighter' => 'markup/syntax/highlighter/PhutilConsoleSyntaxHighlighter.php',
- 'PhutilConsoleTable' => 'console/PhutilConsoleTable.php',
+ 'PhutilConsoleTable' => 'console/view/PhutilConsoleTable.php',
+ 'PhutilConsoleView' => 'console/view/PhutilConsoleView.php',
'PhutilConsoleWrapTestCase' => 'console/__tests__/PhutilConsoleWrapTestCase.php',
'PhutilContextFreeGrammar' => 'grammar/PhutilContextFreeGrammar.php',
'PhutilCowsay' => 'utils/PhutilCowsay.php',
@@ -307,6 +311,7 @@
'PhutilRemarkupUnderlineRule' => 'markup/engine/remarkup/markuprule/PhutilRemarkupUnderlineRule.php',
'PhutilRope' => 'utils/PhutilRope.php',
'PhutilRopeTestCase' => 'utils/__tests__/PhutilRopeTestCase.php',
+ 'PhutilSafeConsoleString' => 'console/view/PhutilSafeConsoleString.php',
'PhutilSafeHTML' => 'markup/PhutilSafeHTML.php',
'PhutilSafeHTMLProducerInterface' => 'markup/PhutilSafeHTMLProducerInterface.php',
'PhutilSafeHTMLTestCase' => 'markup/__tests__/PhutilSafeHTMLTestCase.php',
@@ -635,14 +640,18 @@
'PhutilCodeSnippetContextFreeGrammar' => 'PhutilContextFreeGrammar',
'PhutilCommandString' => 'Phobject',
'PhutilConsole' => 'Phobject',
+ 'PhutilConsoleBlock' => 'PhutilConsoleView',
+ 'PhutilConsoleConcatenatedView' => 'PhutilConsoleView',
'PhutilConsoleFormatter' => 'Phobject',
+ 'PhutilConsoleList' => 'PhutilConsoleView',
'PhutilConsoleMessage' => 'Phobject',
'PhutilConsoleProgressBar' => 'Phobject',
'PhutilConsoleServer' => 'Phobject',
'PhutilConsoleServerChannel' => 'PhutilChannelChannel',
'PhutilConsoleStdinNotInteractiveException' => 'Exception',
'PhutilConsoleSyntaxHighlighter' => 'Phobject',
- 'PhutilConsoleTable' => 'Phobject',
+ 'PhutilConsoleTable' => 'PhutilConsoleView',
+ 'PhutilConsoleView' => 'Phobject',
'PhutilConsoleWrapTestCase' => 'PhutilTestCase',
'PhutilContextFreeGrammar' => 'Phobject',
'PhutilCowsay' => 'Phobject',
@@ -818,6 +827,7 @@
'PhutilRemarkupUnderlineRule' => 'PhutilRemarkupRule',
'PhutilRope' => 'Phobject',
'PhutilRopeTestCase' => 'PhutilTestCase',
+ 'PhutilSafeConsoleString' => 'Phobject',
'PhutilSafeHTML' => 'Phobject',
'PhutilSafeHTMLTestCase' => 'PhutilTestCase',
'PhutilSaturateStdoutDaemon' => 'PhutilTortureTestDaemon',
diff --git a/src/console/view/PhutilConsoleBlock.php b/src/console/view/PhutilConsoleBlock.php
new file mode 100644
--- /dev/null
+++ b/src/console/view/PhutilConsoleBlock.php
@@ -0,0 +1,45 @@
+<?php
+
+final class PhutilConsoleBlock extends PhutilConsoleView {
+
+ private $items = array();
+
+ public function addParagraph($item) {
+ $this->items[] = array(
+ 'type' => 'paragraph',
+ 'item' => $item,
+ );
+ return $this;
+ }
+
+ public function addList(PhutilConsoleList $list) {
+ $this->items[] = array(
+ 'type' => 'list',
+ 'item' => $list,
+ );
+ return $this;
+ }
+
+ protected function drawView() {
+ $output = array();
+
+ foreach ($this->items as $spec) {
+ $type = $spec['type'];
+ $item = $spec['item'];
+
+ switch ($type) {
+ case 'paragraph':
+ $item = phutil_console_wrap($item)."\n";
+ break;
+ case 'list':
+ $item = $item;
+ break;
+ }
+
+ $output[] = $item;
+ }
+
+ return $this->drawLines($output);
+ }
+
+}
diff --git a/src/console/view/PhutilConsoleConcatenatedView.php b/src/console/view/PhutilConsoleConcatenatedView.php
new file mode 100644
--- /dev/null
+++ b/src/console/view/PhutilConsoleConcatenatedView.php
@@ -0,0 +1,22 @@
+<?php
+
+final class PhutilConsoleConcatenatedView extends PhutilConsoleView {
+
+ private $items = array();
+
+ public function addItem($item) {
+ $this->items[] = $item;
+ return $this;
+ }
+
+ protected function drawView() {
+ $output = array();
+
+ foreach ($this->items as $item) {
+ $output[] = $this->flattenView($item);
+ }
+
+ return implode('', $output);
+ }
+
+}
diff --git a/src/console/view/PhutilConsoleList.php b/src/console/view/PhutilConsoleList.php
new file mode 100644
--- /dev/null
+++ b/src/console/view/PhutilConsoleList.php
@@ -0,0 +1,42 @@
+<?php
+
+final class PhutilConsoleList extends PhutilConsoleView {
+
+ private $items = array();
+ private $wrap = true;
+
+ public function addItem($item) {
+ $this->items[] = $item;
+ return $this;
+ }
+
+ public function addItems(array $items) {
+ foreach ($items as $item) {
+ $this->addItem($item);
+ }
+ return $this;
+ }
+
+ public function getItems() {
+ return $this->items;
+ }
+
+ public function setWrap($wrap) {
+ $this->wrap = $wrap;
+ return $this;
+ }
+
+ protected function drawView() {
+ $output = array();
+ foreach ($this->getItems() as $item) {
+ if ($this->wrap) {
+ $item = phutil_console_wrap($item, 8);
+ }
+ $item = ' - '.$item;
+ $output[] = $item;
+ }
+
+ return $this->drawLines($output);
+ }
+
+}
diff --git a/src/console/PhutilConsoleTable.php b/src/console/view/PhutilConsoleTable.php
rename from src/console/PhutilConsoleTable.php
rename to src/console/view/PhutilConsoleTable.php
--- a/src/console/PhutilConsoleTable.php
+++ b/src/console/view/PhutilConsoleTable.php
@@ -22,7 +22,7 @@
* ->setBorders(true)
* ->draw();
*/
-final class PhutilConsoleTable extends Phobject {
+final class PhutilConsoleTable extends PhutilConsoleView {
private $columns = array();
private $data = array();
@@ -30,30 +30,15 @@
private $borders = false;
private $padding = 1;
private $showHeader = true;
- private $console;
const ALIGN_LEFT = 'left';
const ALIGN_CENTER = 'center';
const ALIGN_RIGHT = 'right';
-/* -( Console )------------------------------------------------------------ */
-
- protected function getConsole() {
- if ($this->console) {
- return $this->console;
- }
- return PhutilConsole::getConsole();
- }
-
- public function setConsole(PhutilConsole $console) {
- $this->console = $console;
- return $this;
- }
-
-
/* -( Configuration )------------------------------------------------------ */
+
public function setBorders($borders) {
$this->borders = $borders;
return $this;
@@ -103,19 +88,19 @@
/* -( Drawing )------------------------------------------------------------ */
- public function draw() {
- $console = $this->getConsole();
-
- $console->writeOut('%s', $this->getHeader());
- $console->writeOut('%s', $this->getBody());
- $console->writeOut('%s', $this->getFooter());
+ protected function drawView() {
+ return $this->drawLines(
+ array_merge(
+ $this->getHeader(),
+ $this->getBody(),
+ $this->getFooter()));
}
private function getHeader() {
- $output = '';
+ $output = array();
if ($this->borders) {
- $output .= $this->formatSeparator('=');
+ $output[] = $this->formatSeparator('=');
}
if (!$this->showHeader) {
@@ -133,22 +118,27 @@
idx($column, 'align', self::ALIGN_LEFT));
}
- $columns[] = PhutilConsoleFormatter::formatString(
+ $header = PhutilConsoleFormatter::formatString(
'**%s**',
$column_str);
+
+ // TODO: This is gross but we don't have any helper functions for
+ // building PhutilSafeConsoleStrings yet.
+
+ $columns[] = new PhutilSafeConsoleString($header);
}
- $output .= $this->formatRow($columns);
+ $output[] = $this->formatRow($columns);
if ($this->borders) {
- $output .= $this->formatSeparator('=');
+ $output[] = $this->formatSeparator('=');
}
return $output;
}
private function getBody() {
- $output = '';
+ $output = array();
foreach ($this->data as $data) {
$columns = array();
@@ -164,14 +154,14 @@
}
}
- $output .= $this->formatRow($columns);
+ $output[] = $this->formatRow($columns);
}
return $output;
}
private function getFooter() {
- $output = '';
+ $output = array();
if ($this->borders) {
$columns = array();
@@ -180,7 +170,11 @@
$columns[] = str_repeat('=', $this->getWidth($column));
}
- $output .= '+'.implode('+', $columns)."+\n";
+ $output[] = array(
+ '+',
+ $this->implode('+', $columns),
+ '+',
+ );
}
return $output;
@@ -272,9 +266,13 @@
if ($this->borders) {
$separator = $padding.'|'.$padding;
- return '|'.$padding.implode($separator, $columns).$padding."|\n";
+ return array(
+ '|'.$padding,
+ $this->implode($separator, $columns),
+ $padding.'|',
+ );
} else {
- return implode($padding, $columns)."\n";
+ return $this->implode($padding, $columns);
}
}
@@ -291,7 +289,11 @@
$columns[] = str_repeat($string, $this->getWidth($column));
}
- return $separator.implode($separator, $columns).$separator."\n";
+ return array(
+ $separator,
+ $this->implode($separator, $columns),
+ $separator,
+ );
}
}
diff --git a/src/console/view/PhutilConsoleView.php b/src/console/view/PhutilConsoleView.php
new file mode 100644
--- /dev/null
+++ b/src/console/view/PhutilConsoleView.php
@@ -0,0 +1,116 @@
+<?php
+
+abstract class PhutilConsoleView extends Phobject {
+
+ private $console;
+
+ abstract protected function drawView();
+
+ final public function setConsole(PhutilConsole $console) {
+ $this->console = $console;
+ return $this;
+ }
+
+ final public function getConsole() {
+ if ($this->console) {
+ return $this->console;
+ }
+ return PhutilConsole::getConsole();
+ }
+
+
+ /**
+ * Draw a view to the console.
+ *
+ * @return this
+ * @task draw
+ */
+ final public function draw() {
+ $string = $this->drawConsoleString();
+
+ $console = $this->getConsole();
+ $console->writeOut('%s', $string);
+
+ return $this;
+ }
+
+
+ /**
+ * Draw a view to a string and return it.
+ *
+ * @return string Console-printable string.
+ * @task draw
+ */
+ final public function drawConsoleString() {
+ $view = $this->drawView();
+ $parts = $this->reduceView($view);
+
+ $out = array();
+ foreach ($parts as $part) {
+ if ($part instanceof PhutilSafeConsoleString) {
+ $out[] = $part->getConsoleStringContent();
+ } else {
+ $out[] = phutil_console_format('%s', $part);
+ }
+ }
+
+ return implode('', $out);
+ }
+
+
+ /**
+ * Reduce a view to a list of simple, unnested parts.
+ *
+ * @param wild Any drawable view.
+ * @return list<wild> List of unnested drawables.
+ * @task draw
+ */
+ private function reduceView($view) {
+ if ($view instanceof PhutilConsoleView) {
+ $view = $view->drawView();
+ return $this->reduceView($view);
+ }
+
+ if (is_array($view)) {
+ $parts = array();
+ foreach ($view as $item) {
+ foreach ($this->reduceView($item) as $part) {
+ $parts[] = $part;
+ }
+ }
+ return $parts;
+ }
+
+ return array($view);
+ }
+
+/* -( Drawing Utilities )-------------------------------------------------- */
+
+
+ /**
+ * @param list<wild> List of views, one per line.
+ * @return wild Each view rendered on a separate line.
+ */
+ final protected function drawLines(array $parts) {
+ $result = array();
+ foreach ($parts as $part) {
+ if ($part !== null) {
+ $result[] = $part;
+ $result[] = "\n";
+ }
+ }
+
+ return $result;
+ }
+
+ final protected function implode($separator, array $items) {
+ $result = array();
+ foreach ($items as $item) {
+ $result[] = $item;
+ $result[] = $separator;
+ }
+ array_pop($result);
+ return $result;
+ }
+
+}
diff --git a/src/console/view/PhutilSafeConsoleString.php b/src/console/view/PhutilSafeConsoleString.php
new file mode 100644
--- /dev/null
+++ b/src/console/view/PhutilSafeConsoleString.php
@@ -0,0 +1,15 @@
+<?php
+
+final class PhutilSafeConsoleString extends Phobject {
+
+ private $content;
+
+ public function __construct($content) {
+ $this->content = (string)$content;
+ }
+
+ public function getConsoleStringContent() {
+ return $this->content;
+ }
+
+}

File Metadata

Mime Type
text/plain
Expires
Mon, Oct 21, 7:48 AM (2 w, 23 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6738802
Default Alt Text
D14136.id34158.diff (13 KB)

Event Timeline