mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-25 16:22:42 +01:00
Add some support code for printing refs to stdout
Summary: Ref T13490. Make terminal strings work more like HTML does in Phabricator, and make it easier to display refs. Test Plan: Added some display code, ran `arc inspect` to hit it, saw a nice ref printed. Maniphest Tasks: T13490 Differential Revision: https://secure.phabricator.com/D21093
This commit is contained in:
parent
088b157444
commit
5fc50c226a
10 changed files with 184 additions and 8 deletions
|
@ -162,6 +162,8 @@ phutil_register_library_map(array(
|
|||
'ArcanistDifferentialDependencyGraph' => 'differential/ArcanistDifferentialDependencyGraph.php',
|
||||
'ArcanistDifferentialRevisionHash' => 'differential/constants/ArcanistDifferentialRevisionHash.php',
|
||||
'ArcanistDifferentialRevisionStatus' => 'differential/constants/ArcanistDifferentialRevisionStatus.php',
|
||||
'ArcanistDisplayRef' => 'ref/ArcanistDisplayRef.php',
|
||||
'ArcanistDisplayRefInterface' => 'ref/ArcanistDisplayRefInterface.php',
|
||||
'ArcanistDoubleQuoteXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistDoubleQuoteXHPASTLinterRule.php',
|
||||
'ArcanistDoubleQuoteXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistDoubleQuoteXHPASTLinterRuleTestCase.php',
|
||||
'ArcanistDownloadWorkflow' => 'workflow/ArcanistDownloadWorkflow.php',
|
||||
|
@ -441,6 +443,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistTasksWorkflow' => 'workflow/ArcanistTasksWorkflow.php',
|
||||
'ArcanistTautologicalExpressionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistTautologicalExpressionXHPASTLinterRule.php',
|
||||
'ArcanistTautologicalExpressionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistTautologicalExpressionXHPASTLinterRuleTestCase.php',
|
||||
'ArcanistTerminalStringInterface' => 'xsprintf/ArcanistTerminalStringInterface.php',
|
||||
'ArcanistTestResultParser' => 'unit/parser/ArcanistTestResultParser.php',
|
||||
'ArcanistTestXHPASTLintSwitchHook' => 'lint/linter/__tests__/ArcanistTestXHPASTLintSwitchHook.php',
|
||||
'ArcanistTextLinter' => 'lint/linter/ArcanistTextLinter.php',
|
||||
|
@ -915,6 +918,7 @@ phutil_register_library_map(array(
|
|||
'phutil_get_library_root_for_path' => 'init/lib/moduleutils.php',
|
||||
'phutil_get_signal_name' => 'future/exec/execx.php',
|
||||
'phutil_get_system_locale' => 'utils/utf8.php',
|
||||
'phutil_glue' => 'utils/utils.php',
|
||||
'phutil_hashes_are_identical' => 'utils/utils.php',
|
||||
'phutil_http_parameter_pair' => 'utils/utils.php',
|
||||
'phutil_ini_decode' => 'utils/utils.php',
|
||||
|
@ -1137,6 +1141,10 @@ phutil_register_library_map(array(
|
|||
'ArcanistDifferentialDependencyGraph' => 'AbstractDirectedGraph',
|
||||
'ArcanistDifferentialRevisionHash' => 'Phobject',
|
||||
'ArcanistDifferentialRevisionStatus' => 'Phobject',
|
||||
'ArcanistDisplayRef' => array(
|
||||
'Phobject',
|
||||
'ArcanistTerminalStringInterface',
|
||||
),
|
||||
'ArcanistDoubleQuoteXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
||||
'ArcanistDoubleQuoteXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||
'ArcanistDownloadWorkflow' => 'ArcanistWorkflow',
|
||||
|
@ -1461,7 +1469,10 @@ phutil_register_library_map(array(
|
|||
'ArcanistUselessOverridingMethodXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||
'ArcanistUserAbortException' => 'ArcanistUsageException',
|
||||
'ArcanistUserConfigurationSource' => 'ArcanistFilesystemConfigurationSource',
|
||||
'ArcanistUserRef' => 'ArcanistRef',
|
||||
'ArcanistUserRef' => array(
|
||||
'ArcanistRef',
|
||||
'ArcanistDisplayRefInterface',
|
||||
),
|
||||
'ArcanistUserSymbolHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
|
||||
'ArcanistUserSymbolRef' => 'ArcanistSymbolRef',
|
||||
'ArcanistUserSymbolRefInspector' => 'ArcanistRefInspector',
|
||||
|
|
68
src/ref/ArcanistDisplayRef.php
Normal file
68
src/ref/ArcanistDisplayRef.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistDisplayRef
|
||||
extends Phobject
|
||||
implements
|
||||
ArcanistTerminalStringInterface {
|
||||
|
||||
private $ref;
|
||||
|
||||
public function setRef(ArcanistRef $ref) {
|
||||
$this->ref = $ref;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRef() {
|
||||
return $this->ref;
|
||||
}
|
||||
|
||||
public function newTerminalString() {
|
||||
$ref = $this->getRef();
|
||||
|
||||
if ($ref instanceof ArcanistDisplayRefInterface) {
|
||||
$object_name = $ref->getDisplayRefObjectName();
|
||||
$title = $ref->getDisplayRefTitle();
|
||||
} else {
|
||||
$object_name = null;
|
||||
$title = $ref->getRefDisplayName();
|
||||
}
|
||||
|
||||
if ($object_name !== null) {
|
||||
$reserve_width = phutil_utf8_console_strlen($object_name) + 1;
|
||||
} else {
|
||||
$reserve_width = 0;
|
||||
}
|
||||
|
||||
$marker_width = 6;
|
||||
$display_width = phutil_console_get_terminal_width();
|
||||
|
||||
$usable_width = ($display_width - $marker_width - $reserve_width);
|
||||
|
||||
// If the terminal is extremely narrow, don't degrade so much that the
|
||||
// output is completely unusable.
|
||||
$usable_width = max($usable_width, 16);
|
||||
|
||||
// TODO: This should truncate based on console display width, not
|
||||
// glyphs, but there's currently no "setMaximumConsoleCharacterWidth()".
|
||||
|
||||
$title = id(new PhutilUTF8StringTruncator())
|
||||
->setMaximumGlyphs($usable_width)
|
||||
->truncateString($title);
|
||||
|
||||
if ($object_name !== null) {
|
||||
if (strlen($title)) {
|
||||
$display_text = tsprintf('**%s** %s', $object_name, $title);
|
||||
} else {
|
||||
$display_text = tsprintf('**%s**', $object_name);
|
||||
}
|
||||
} else {
|
||||
$display_text = $title;
|
||||
}
|
||||
|
||||
$ref = $this->getRef();
|
||||
return tsprintf(
|
||||
"<bg:cyan>** * **</bg> %s\n",
|
||||
$display_text);
|
||||
}
|
||||
|
||||
}
|
8
src/ref/ArcanistDisplayRefInterface.php
Normal file
8
src/ref/ArcanistDisplayRefInterface.php
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
interface ArcanistDisplayRefInterface {
|
||||
|
||||
public function getDisplayRefObjectName();
|
||||
public function getDisplayRefTitle();
|
||||
|
||||
}
|
|
@ -5,4 +5,8 @@ abstract class ArcanistRef
|
|||
|
||||
abstract public function getRefDisplayName();
|
||||
|
||||
final public function newDisplayRef() {
|
||||
return id(new ArcanistDisplayRef())
|
||||
->setRef($this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,4 +36,6 @@ abstract class ArcanistSymbolRef
|
|||
return $symbol;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistUserRef
|
||||
extends ArcanistRef {
|
||||
extends ArcanistRef
|
||||
implements
|
||||
ArcanistDisplayRefInterface {
|
||||
|
||||
private $parameters;
|
||||
|
||||
|
@ -21,6 +23,7 @@ final class ArcanistUserRef
|
|||
|
||||
$parameters['fields'] = array(
|
||||
'username' => idx($parameters, 'userName'),
|
||||
'realName' => idx($parameters, 'realName'),
|
||||
);
|
||||
|
||||
return self::newFromConduit($parameters);
|
||||
|
@ -30,4 +33,24 @@ final class ArcanistUserRef
|
|||
return idxv($this->parameters, array('fields', 'username'));
|
||||
}
|
||||
|
||||
public function getRealName() {
|
||||
var_dump($this->parameters);
|
||||
|
||||
return idxv($this->parameters, array('fields', 'realName'));
|
||||
}
|
||||
|
||||
public function getDisplayRefObjectName() {
|
||||
return '@'.$this->getUsername();
|
||||
}
|
||||
|
||||
public function getDisplayRefTitle() {
|
||||
$real_name = $this->getRealName();
|
||||
|
||||
if (strlen($real_name)) {
|
||||
$real_name = sprintf('(%s)', $real_name);
|
||||
}
|
||||
|
||||
return $real_name;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1930,3 +1930,31 @@ function phutil_is_noninteractive() {
|
|||
function phutil_encode_log($message) {
|
||||
return addcslashes($message, "\0..\37\\\177..\377");
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a value in between each pair of elements in a list.
|
||||
*
|
||||
* Keys in the input list are preserved.
|
||||
*/
|
||||
function phutil_glue(array $list, $glue) {
|
||||
if (!$list) {
|
||||
return $list;
|
||||
}
|
||||
|
||||
$last_key = last_key($list);
|
||||
|
||||
$keys = array();
|
||||
$values = array();
|
||||
|
||||
$tmp = $list;
|
||||
|
||||
foreach ($list as $key => $ignored) {
|
||||
$keys[] = $key;
|
||||
if ($key !== $last_key) {
|
||||
$tmp[] = $glue;
|
||||
$keys[] = last_key($tmp);
|
||||
}
|
||||
}
|
||||
|
||||
return array_select_keys($tmp, $keys);
|
||||
}
|
||||
|
|
|
@ -93,9 +93,9 @@ EOTEXT
|
|||
$list = array();
|
||||
foreach ($all_refs as $ref) {
|
||||
$out = $this->describeRef($ref, 0);
|
||||
$list[] = implode('', $out);
|
||||
$list[] = $out;
|
||||
}
|
||||
$list = implode("\n", $list);
|
||||
$list = phutil_glue($list, "\n");
|
||||
|
||||
echo tsprintf('%B', $list);
|
||||
|
||||
|
@ -106,6 +106,7 @@ EOTEXT
|
|||
$indent = str_repeat(' ', $depth);
|
||||
|
||||
$out = array();
|
||||
|
||||
$out[] = tsprintf(
|
||||
"%s+ [%s] %s\n",
|
||||
$indent,
|
||||
|
|
7
src/xsprintf/ArcanistTerminalStringInterface.php
Normal file
7
src/xsprintf/ArcanistTerminalStringInterface.php
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
interface ArcanistTerminalStringInterface {
|
||||
|
||||
public function newTerminalString();
|
||||
|
||||
}
|
|
@ -16,23 +16,47 @@ final class PhutilTerminalString extends Phobject {
|
|||
}
|
||||
|
||||
public function applyWrap() {
|
||||
$string = (string)$this;
|
||||
$string = phutil_string_cast($this);
|
||||
$string = phutil_console_wrap($string);
|
||||
return new self($string);
|
||||
}
|
||||
|
||||
public function applyIndent($depth, $with_prefix = true) {
|
||||
$string = (string)$this;
|
||||
$string = phutil_string_cast($this);
|
||||
$string = phutil_console_wrap($string, $depth, $with_prefix);
|
||||
return new self($string);
|
||||
}
|
||||
|
||||
public static function escapeStringValue($value, $allow_whitespace) {
|
||||
if ($value instanceof PhutilTerminalString) {
|
||||
return (string)$value;
|
||||
return phutil_string_cast($value);
|
||||
}
|
||||
|
||||
$value = (string)$value;
|
||||
if ($value instanceof ArcanistTerminalStringInterface) {
|
||||
$value = $value->newTerminalString();
|
||||
return self::escapeStringValue($value, $allow_whitespace);
|
||||
}
|
||||
|
||||
if ($value === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
if (!$value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$parts = array();
|
||||
|
||||
foreach ($value as $part) {
|
||||
$part = self::escapeStringValue($part, $allow_whitespace);
|
||||
$parts[] = $part;
|
||||
}
|
||||
|
||||
return implode('', $parts);
|
||||
}
|
||||
|
||||
$value = phutil_string_cast($value);
|
||||
|
||||
static $escape_map;
|
||||
if ($escape_map === null) {
|
||||
|
|
Loading…
Reference in a new issue