Columnate oversized WorkQueue UIs.
The new machines will spawn more jobs than my console has rows...
Test: ./run_tests.py
Bug: None
Change-Id: I61d1ee079488974c8d1641f5cca89c99069b045d
diff --git a/ndk/ansi.py b/ndk/ansi.py
index 379656e..3a9f6f6 100644
--- a/ndk/ansi.py
+++ b/ndk/ansi.py
@@ -19,6 +19,7 @@
import contextlib
import os
+import subprocess
import sys
try:
@@ -81,6 +82,14 @@
return DumbConsole(stream)
+def get_console_size_linux():
+ return [int(s) for s in subprocess.check_output(['stty', 'size']).split()]
+
+
+def get_console_size_windows():
+ raise NotImplementedError
+
+
class Console(object):
def __init__(self, stream):
self.stream = stream
@@ -117,6 +126,8 @@
def __init__(self, stream):
super(AnsiConsole, self).__init__(stream)
self.smart_console = True
+ self._width = None
+ self._height = None
def _do(self, cmd):
print(cmd, end='', file=self.stream)
@@ -138,6 +149,24 @@
def show_cursor(self):
self._do(self.SHOW_CURSOR)
+ def init_window_size(self):
+ if os.name == 'nt':
+ self._height, self._width = get_console_size_windows()
+ else:
+ self._height, self._width = get_console_size_linux()
+
+ @property
+ def height(self):
+ if self._height is None:
+ self.init_window_size()
+ return self._height
+
+ @property
+ def width(self):
+ if self._width is None:
+ self.init_window_size()
+ return self._width
+
class DumbConsole(Console):
def __init__(self, stream):
diff --git a/ndk/test/ui.py b/ndk/test/ui.py
index c94cdeb..858ccbb 100644
--- a/ndk/test/ui.py
+++ b/ndk/test/ui.py
@@ -100,6 +100,13 @@
for worker in self.workqueue.restricted_work_queue.workers:
lines.append(worker.status)
+ if self.ui_renderer.console.smart_console:
+ # Keep some space at the top of the UI so we can see messages.
+ ui_height = self.ui_renderer.console.height - 10
+ if ui_height > 0:
+ lines = ndk.ui.columnate(lines, self.ui_renderer.console.width,
+ ui_height)
+
lines.append('{: >{width}} tests remaining'.format(
self.workqueue.num_tasks, width=self.NUM_TESTS_DIGITS))
return lines
diff --git a/ndk/ui.py b/ndk/ui.py
index 4d7667e..9a47b1b 100644
--- a/ndk/ui.py
+++ b/ndk/ui.py
@@ -16,7 +16,9 @@
"""UI classes for build output."""
from __future__ import absolute_import
from __future__ import print_function
+from __future__ import division
+import math
import os
import sys
import time
@@ -44,9 +46,6 @@
self.last_rendered_lines = []
self.debug_draw = debug_draw
- def get_ui_lines(self):
- raise NotImplementedError
-
def changed_lines(self, new_lines):
assert len(new_lines) == len(self.last_rendered_lines)
old_lines = self.last_rendered_lines
@@ -177,6 +176,23 @@
ui_renderer, show_worker_status, workqueue)
+def columnate(lines, max_width, max_height):
+ if os.name == 'nt':
+ # Not yet implemented.
+ return lines
+
+ num_columns = int(math.ceil(len(lines) / max_height))
+ if num_columns == 1:
+ return lines
+
+ # Keep the columns roughly balanced.
+ num_rows = int(math.ceil(len(lines) / num_columns))
+ rows = [lines[r::num_rows] for r in range(num_rows)]
+
+ column_width = max_width // num_columns
+ return [''.join(s.ljust(column_width) for s in row) for row in rows]
+
+
class WorkQueueUi(Ui):
NUM_TESTS_DIGITS = 6
@@ -192,6 +208,13 @@
for worker in self.workqueue.workers:
lines.append(worker.status)
+ if self.ui_renderer.console.smart_console:
+ # Keep some space at the top of the UI so we can see messages.
+ ui_height = self.ui_renderer.console.height - 10
+ if ui_height > 0:
+ lines = columnate(lines, self.ui_renderer.console.width,
+ ui_height)
+
lines.append('{: >{width}} jobs remaining'.format(
self.workqueue.num_tasks, width=self.NUM_TESTS_DIGITS))
return lines