mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-25 08:12:40 +01:00
Improve grid layout in "arc branches" at various terminal widths
Summary: Ref T13546. Make "arc branches" use a flexible grid width and try to match the content to the display width in a reasonable way. Test Plan: Ran "arc branches" at various terminal widths, got generally sensible output. Maniphest Tasks: T13546 Differential Revision: https://secure.phabricator.com/D21365
This commit is contained in:
parent
10c4a551ae
commit
0ad3222d59
5 changed files with 106 additions and 23 deletions
|
@ -6,6 +6,7 @@ final class ArcanistGridColumn
|
||||||
private $key;
|
private $key;
|
||||||
private $alignment = self::ALIGNMENT_LEFT;
|
private $alignment = self::ALIGNMENT_LEFT;
|
||||||
private $displayWidth;
|
private $displayWidth;
|
||||||
|
private $minimumWidth;
|
||||||
|
|
||||||
const ALIGNMENT_LEFT = 'align.left';
|
const ALIGNMENT_LEFT = 'align.left';
|
||||||
const ALIGNMENT_CENTER = 'align.center';
|
const ALIGNMENT_CENTER = 'align.center';
|
||||||
|
@ -38,4 +39,13 @@ final class ArcanistGridColumn
|
||||||
return $this->displayWidth;
|
return $this->displayWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setMinimumWidth($minimum_width) {
|
||||||
|
$this->minimumWidth = $minimum_width;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMinimumWidth() {
|
||||||
|
return $this->minimumWidth;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ final class ArcanistGridView
|
||||||
|
|
||||||
public function setColumns(array $columns) {
|
public function setColumns(array $columns) {
|
||||||
assert_instances_of($columns, 'ArcanistGridColumn');
|
assert_instances_of($columns, 'ArcanistGridColumn');
|
||||||
$this->columns = $columns;
|
$this->columns = mpull($columns, null, 'getKey');
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,27 +56,70 @@ final class ArcanistGridView
|
||||||
return tsprintf("%s\n", $rows);
|
return tsprintf("%s\n", $rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getDisplayWidth($key) {
|
private function getDisplayWidth($display_key) {
|
||||||
if (!isset($this->displayWidths[$key])) {
|
if (!isset($this->displayWidths[$display_key])) {
|
||||||
$column = $this->getColumn($key);
|
$flexible_columns = array();
|
||||||
|
|
||||||
$width = $column->getDisplayWidth();
|
$columns = $this->getColumns();
|
||||||
if ($width === null) {
|
foreach ($columns as $key => $column) {
|
||||||
$width = 1;
|
$width = $column->getDisplayWidth();
|
||||||
foreach ($this->getRows() as $row) {
|
|
||||||
if (!$row->hasCell($key)) {
|
if ($width === null) {
|
||||||
continue;
|
$width = 1;
|
||||||
|
foreach ($this->getRows() as $row) {
|
||||||
|
if (!$row->hasCell($key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cell = $row->getCell($key);
|
||||||
|
$width = max($width, $cell->getContentDisplayWidth());
|
||||||
}
|
}
|
||||||
|
|
||||||
$cell = $row->getCell($key);
|
|
||||||
$width = max($width, $cell->getContentDisplayWidth());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($column->getMinimumWidth() !== null) {
|
||||||
|
$flexible_columns[] = $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->displayWidths[$key] = $width;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->displayWidths[$key] = $width;
|
$available_width = phutil_console_get_terminal_width();
|
||||||
|
|
||||||
|
// Adjust the available width to account for cell spacing.
|
||||||
|
$available_width -= (2 * (count($columns) - 1));
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
$total_width = array_sum($this->displayWidths);
|
||||||
|
|
||||||
|
if ($total_width <= $available_width) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$flexible_columns) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: This is very unsophisticated, and just shortcuts us to a
|
||||||
|
// reasonable result when only one column is flexible.
|
||||||
|
|
||||||
|
foreach ($flexible_columns as $flexible_key) {
|
||||||
|
$column = $columns[$flexible_key];
|
||||||
|
|
||||||
|
$need_width = ($total_width - $available_width);
|
||||||
|
$old_width = $this->displayWidths[$flexible_key];
|
||||||
|
$new_width = ($old_width - $need_width);
|
||||||
|
|
||||||
|
$new_width = max($new_width, $column->getMinimumWidth());
|
||||||
|
|
||||||
|
$this->displayWidths[$flexible_key] = $new_width;
|
||||||
|
|
||||||
|
$flexible_columns = array();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->displayWidths[$key];
|
return $this->displayWidths[$display_key];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getColumn($key) {
|
public function getColumn($key) {
|
||||||
|
@ -241,7 +284,12 @@ final class ArcanistGridView
|
||||||
$src_width,
|
$src_width,
|
||||||
$dst_width,
|
$dst_width,
|
||||||
$alignment) {
|
$alignment) {
|
||||||
return $line;
|
|
||||||
|
$line = phutil_string_cast($line);
|
||||||
|
|
||||||
|
return id(new PhutilUTF8StringTruncator())
|
||||||
|
->setMaximumGlyphs($dst_width)
|
||||||
|
->truncateString($line);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,13 @@ final class ArcanistRevisionRef
|
||||||
return 'D'.$this->getID();
|
return 'D'.$this->getID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getStatusShortDisplayName() {
|
||||||
|
if ($this->isStatusNeedsReview()) {
|
||||||
|
return pht('Review');
|
||||||
|
}
|
||||||
|
return idxv($this->parameters, array('fields', 'status', 'name'));
|
||||||
|
}
|
||||||
|
|
||||||
public function getStatusDisplayName() {
|
public function getStatusDisplayName() {
|
||||||
return idxv($this->parameters, array('fields', 'status', 'name'));
|
return idxv($this->parameters, array('fields', 'status', 'name'));
|
||||||
}
|
}
|
||||||
|
@ -117,6 +124,11 @@ final class ArcanistRevisionRef
|
||||||
return ($status === 'accepted');
|
return ($status === 'accepted');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isStatusNeedsReview() {
|
||||||
|
$status = $this->getStatus();
|
||||||
|
return ($status === 'needs-review');
|
||||||
|
}
|
||||||
|
|
||||||
public function getStatus() {
|
public function getStatus() {
|
||||||
return idxv($this->parameters, array('fields', 'status', 'value'));
|
return idxv($this->parameters, array('fields', 'status', 'value'));
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,9 +249,8 @@ final class ArcanistCommitGraphSetView
|
||||||
substr($max->getCommitHash(), 0, 7));
|
substr($max->getCommitHash(), 0, 7));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Make this a function of terminal width?
|
$terminal_width = phutil_console_get_terminal_width();
|
||||||
|
$max_depth = (int)floor(3 + (max(0, $terminal_width - 72) / 6));
|
||||||
$max_depth = 25;
|
|
||||||
if ($depth <= $max_depth) {
|
if ($depth <= $max_depth) {
|
||||||
$indent = str_repeat(' ', ($depth * 2));
|
$indent = str_repeat(' ', ($depth * 2));
|
||||||
} else {
|
} else {
|
||||||
|
@ -262,20 +261,29 @@ final class ArcanistCommitGraphSetView
|
||||||
|
|
||||||
$empty_indent = str_repeat(' ', strlen($indent));
|
$empty_indent = str_repeat(' ', strlen($indent));
|
||||||
|
|
||||||
|
$max_width = ($max_depth * 2) + 16;
|
||||||
|
$available_width = $max_width - (min($max_depth, $depth) * 2);
|
||||||
|
|
||||||
$is_first = true;
|
$is_first = true;
|
||||||
$cell = array();
|
$cell = array();
|
||||||
foreach ($items as $item) {
|
foreach ($items as $item) {
|
||||||
$marker_ref = idx($item, 'marker');
|
$marker_ref = idx($item, 'marker');
|
||||||
|
|
||||||
if ($marker_ref) {
|
if ($marker_ref) {
|
||||||
|
$marker_name = $marker_ref->getName();
|
||||||
|
|
||||||
|
$marker_name = id(new PhutilUTF8StringTruncator())
|
||||||
|
->setMaximumGlyphs($available_width)
|
||||||
|
->truncateString($marker_name);
|
||||||
|
|
||||||
if ($marker_ref->getIsActive()) {
|
if ($marker_ref->getIsActive()) {
|
||||||
$label = tsprintf(
|
$label = tsprintf(
|
||||||
'<bg:green>**%s**</bg>',
|
'<bg:green>**%s**</bg>',
|
||||||
$marker_ref->getName());
|
$marker_name);
|
||||||
} else {
|
} else {
|
||||||
$label = tsprintf(
|
$label = tsprintf(
|
||||||
'**%s**',
|
'**%s**',
|
||||||
$marker_ref->getName());
|
$marker_name);
|
||||||
}
|
}
|
||||||
} else if ($is_first) {
|
} else if ($is_first) {
|
||||||
$label = $commit_label;
|
$label = $commit_label;
|
||||||
|
@ -391,7 +399,11 @@ final class ArcanistCommitGraphSetView
|
||||||
|
|
||||||
|
|
||||||
private function drawRevisionStatus(ArcanistRevisionRef $revision_ref) {
|
private function drawRevisionStatus(ArcanistRevisionRef $revision_ref) {
|
||||||
$status = $revision_ref->getStatusDisplayName();
|
if (phutil_console_get_terminal_width() < 120) {
|
||||||
|
$status = $revision_ref->getStatusShortDisplayName();
|
||||||
|
} else {
|
||||||
|
$status = $revision_ref->getStatusDisplayName();
|
||||||
|
}
|
||||||
|
|
||||||
$ansi_color = $revision_ref->getStatusANSIColor();
|
$ansi_color = $revision_ref->getStatusANSIColor();
|
||||||
if ($ansi_color) {
|
if ($ansi_color) {
|
||||||
|
|
|
@ -151,7 +151,8 @@ abstract class ArcanistMarkersWorkflow
|
||||||
$grid->newColumn('commits');
|
$grid->newColumn('commits');
|
||||||
$grid->newColumn('status');
|
$grid->newColumn('status');
|
||||||
$grid->newColumn('revisions');
|
$grid->newColumn('revisions');
|
||||||
$grid->newColumn('messages');
|
$grid->newColumn('messages')
|
||||||
|
->setMinimumWidth(12);
|
||||||
|
|
||||||
foreach ($partition_lists as $row_lists) {
|
foreach ($partition_lists as $row_lists) {
|
||||||
foreach ($row_lists as $row_list) {
|
foreach ($row_lists as $row_list) {
|
||||||
|
|
Loading…
Reference in a new issue