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 @@ -162,6 +162,8 @@ '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 @@ '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_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 @@ 'ArcanistDifferentialDependencyGraph' => 'AbstractDirectedGraph', 'ArcanistDifferentialRevisionHash' => 'Phobject', 'ArcanistDifferentialRevisionStatus' => 'Phobject', + 'ArcanistDisplayRef' => array( + 'Phobject', + 'ArcanistTerminalStringInterface', + ), 'ArcanistDoubleQuoteXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistDoubleQuoteXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistDownloadWorkflow' => 'ArcanistWorkflow', @@ -1461,7 +1469,10 @@ 'ArcanistUselessOverridingMethodXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistUserAbortException' => 'ArcanistUsageException', 'ArcanistUserConfigurationSource' => 'ArcanistFilesystemConfigurationSource', - 'ArcanistUserRef' => 'ArcanistRef', + 'ArcanistUserRef' => array( + 'ArcanistRef', + 'ArcanistDisplayRefInterface', + ), 'ArcanistUserSymbolHardpointQuery' => 'ArcanistWorkflowHardpointQuery', 'ArcanistUserSymbolRef' => 'ArcanistSymbolRef', 'ArcanistUserSymbolRefInspector' => 'ArcanistRefInspector', diff --git a/src/ref/ArcanistDisplayRef.php b/src/ref/ArcanistDisplayRef.php new file mode 100644 --- /dev/null +++ b/src/ref/ArcanistDisplayRef.php @@ -0,0 +1,68 @@ +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( + "** * ** %s\n", + $display_text); + } + +} diff --git a/src/ref/ArcanistDisplayRefInterface.php b/src/ref/ArcanistDisplayRefInterface.php new file mode 100644 --- /dev/null +++ b/src/ref/ArcanistDisplayRefInterface.php @@ -0,0 +1,8 @@ +setRef($this); + } } diff --git a/src/ref/symbol/ArcanistSymbolRef.php b/src/ref/symbol/ArcanistSymbolRef.php --- a/src/ref/symbol/ArcanistSymbolRef.php +++ b/src/ref/symbol/ArcanistSymbolRef.php @@ -36,4 +36,6 @@ return $symbol; } + + } diff --git a/src/ref/user/ArcanistUserRef.php b/src/ref/user/ArcanistUserRef.php --- a/src/ref/user/ArcanistUserRef.php +++ b/src/ref/user/ArcanistUserRef.php @@ -1,7 +1,9 @@ idx($parameters, 'userName'), + 'realName' => idx($parameters, 'realName'), ); return self::newFromConduit($parameters); @@ -30,4 +33,24 @@ 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; + } + } diff --git a/src/utils/utils.php b/src/utils/utils.php --- a/src/utils/utils.php +++ b/src/utils/utils.php @@ -1930,3 +1930,31 @@ 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); +} diff --git a/src/workflow/ArcanistInspectWorkflow.php b/src/workflow/ArcanistInspectWorkflow.php --- a/src/workflow/ArcanistInspectWorkflow.php +++ b/src/workflow/ArcanistInspectWorkflow.php @@ -93,9 +93,9 @@ $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 @@ $indent = str_repeat(' ', $depth); $out = array(); + $out[] = tsprintf( "%s+ [%s] %s\n", $indent, diff --git a/src/xsprintf/ArcanistTerminalStringInterface.php b/src/xsprintf/ArcanistTerminalStringInterface.php new file mode 100644 --- /dev/null +++ b/src/xsprintf/ArcanistTerminalStringInterface.php @@ -0,0 +1,7 @@ +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) {