[bitbake-devel] [PATCH 3/3] knotty: Add automatic paging for bitbake -s and -e

Rob Woolley rob.woolley at windriver.com
Fri Feb 27 14:32:24 UTC 2015


The bitbake show environment and show versions commands provide a
large volume of output to the user.  The knotty user interface changes
the output it provides based on whether it detects a TTY.

By checking for the presense of a TTY, we can automatically pipe
the output to a child process that pages the output for the user.
The logic for the automatic paging is based on pager.c found in git.

Some users may have a preferred pager already set in the PAGER
environment variable.  If it is set, found in PATH, and executable
then we use the user's preferred pager.  If it is set to "cat", then
paging is disabled.  If no pager is set, then we set it to "less" as
the default.

The LESS and LV environment variables are also set with sane defaults
in the event that either of these pagers are used.

We cleanly close the pipe before the summary message is displayed.  This 
is done intentionally so that the user does not miss any of the summary 
information if they close the pipe early.

Tested with both bitbake -s and -e with and without an explicit pipe
to a pager.  This includes testing broken pipe conditions caused by 
quitting the pager before the full output has been sent through the pipe.

Pagers tested include: less, more, cat, more, lv, and vim less.sh

Signed-off-by: Rob Woolley <rob.woolley at windriver.com>
---
 lib/bb/ui/knotty.py | 47 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 45 insertions(+), 2 deletions(-)

Index: b/lib/bb/ui/knotty.py
===================================================================
--- a/lib/bb/ui/knotty.py
+++ b/lib/bb/ui/knotty.py
@@ -32,6 +32,7 @@ import fcntl
 import struct
 import copy
 import atexit
+import subprocess
 from bb.ui import uihelper
 
 featureSet = [bb.cooker.CookerFeatures.SEND_SANITYEVENTS]
@@ -138,7 +139,7 @@ class TerminalFilter(object):
         self.helper = helper
         self.cuu = None
         self.stdinbackup = None
-        self.interactive = sys.stdout.isatty()
+        self.interactive = console.stream.isatty()
         self.footer_present = False
         self.lastpids = []
 
@@ -256,8 +257,42 @@ def main(server, eventHandler, params, t
 
     helper = uihelper.BBUIHelper()
 
-    console = logging.StreamHandler(sys.stdout)
-    errconsole = logging.StreamHandler(sys.stderr)
+    pager_bin = None
+    pager_process = None
+
+    if (os.getenv("PAGER")):
+        pager_bin = os.getenv("PAGER")
+    else:
+        pager_bin = "less"
+
+    if pager_bin == "cat":
+        pager_bin = None
+
+    if pager_bin and (not os.path.isfile(pager_bin) or not os.access(pager_bin, os.X_OK)):
+        found_pager = False
+        for path in os.environ["PATH"].split(os.pathsep):
+             pager_path = os.path.join(path,pager_bin)
+             if os.path.isfile(pager_path) and os.access(pager_path, os.X_OK):
+                 found_pager = True
+                 break
+
+        if not found_pager:
+            pager_bin = None
+
+    if (os.getenv("LESS") == None):
+        os.environ['LESS'] = 'FRX'
+
+    if (os.getenv("LV") == None):
+        os.environ['LV'] = '-c'
+
+    if interactive and pager_bin and (params.options.show_versions or params.options.show_environment):
+        pager_process = subprocess.Popen(pager_bin, stdin=subprocess.PIPE)
+        console = logging.StreamHandler(pager_process.stdin)
+        errconsole = logging.StreamHandler(pager_process.stdin)
+    else:
+        console = logging.StreamHandler(sys.stdout)
+        errconsole = logging.StreamHandler(sys.stderr)
+
     format_str = "%(levelname)s: %(message)s"
     format = bb.msg.BBLogFormatter(format_str)
     bb.msg.addDefaultlogFilter(console, bb.msg.BBLogFilterStdOut)
@@ -536,6 +571,11 @@ def main(server, eventHandler, params, t
             if not params.observe_only:
                 _, error = server.runCommand(["stateForceShutdown"])
             main.shutdown = 2
+
+    if pager_process:
+        pager_process.stdin.close()
+        pager_process.wait()
+
     try:
          summary = ""
          if taskfailures:



More information about the bitbake-devel mailing list