bitbake: knotty2: Handle long lines of text and terminal window size changes

Long lines of text which wrapped on the terminal corrupted the output shown by
knotty2. This patch catches such errors by becomming aware of the terminal size.

It also catches terminal window size change events and adapting to those
changes using a signal handler.

Based on a patch from Jason Wessel with several tweaks and enhancements
such as use of chained signal handlers and covering all output messages.

(Bitbake rev: 9afc9e4d14abec5ac326851d4bb689c1e8d45a43)

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Richard Purdie 2012-08-15 17:00:40 +01:00
parent 2718537b4b
commit c49a2529bf
1 changed files with 46 additions and 6 deletions

View File

@ -21,6 +21,10 @@
from bb.ui import knotty
import logging
import sys
import os
import fcntl
import struct
import copy
logger = logging.getLogger("BitBake")
class InteractConsoleLogFilter(logging.Filter):
@ -35,6 +39,35 @@ class InteractConsoleLogFilter(logging.Filter):
return True
class TerminalFilter2(object):
columns = 80
def sigwinch_handle(self, signum, frame):
self.columns = self.getTerminalColumns()
if self._sigwinch_default:
self._sigwinch_default(signum, frame)
def getTerminalColumns(self):
def ioctl_GWINSZ(fd):
try:
cr = struct.unpack('hh', fcntl.ioctl(fd, self.termios.TIOCGWINSZ, '1234'))
except:
return None
return cr
cr = ioctl_GWINSZ(sys.stdout.fileno())
if not cr:
try:
fd = os.open(os.ctermid(), os.O_RDONLY)
cr = ioctl_GWINSZ(fd)
os.close(fd)
except:
pass
if not cr:
try:
cr = (env['LINES'], env['COLUMNS'])
except:
cr = (25, 80)
return cr[1]
def __init__(self, main, helper, console, format):
self.main = main
self.helper = helper
@ -49,7 +82,6 @@ class TerminalFilter2(object):
import curses
import termios
import copy
self.curses = curses
self.termios = termios
try:
@ -62,6 +94,12 @@ class TerminalFilter2(object):
self.ed = curses.tigetstr("ed")
if self.ed:
self.cuu = curses.tigetstr("cuu")
try:
self._sigwinch_default = signal.getsignal(signal.SIGWINCH)
signal.signal(signal.SIGWINCH, self.sigwinch_handle)
except:
pass
self.columns = self.getTerminalColumns()
except:
self.cuu = None
console.addFilter(InteractConsoleLogFilter(self, format))
@ -85,18 +123,20 @@ class TerminalFilter2(object):
self.clearFooter()
if not activetasks:
return
lines = 1
tasks = []
for t in runningpids:
tasks.append("%s (pid %s)" % (activetasks[t]["title"], t))
if self.main.shutdown:
print("Waiting for %s running tasks to finish:" % len(activetasks))
content = "Waiting for %s running tasks to finish:" % len(activetasks)
else:
print("Currently %s running tasks (%s of %s):" % (len(activetasks), self.helper.tasknumber_current, self.helper.tasknumber_total))
content = "Currently %s running tasks (%s of %s):" % (len(activetasks), self.helper.tasknumber_current, self.helper.tasknumber_total)
print content
lines = 1 + int(len(content) / (self.columns + 1))
for tasknum, task in enumerate(tasks):
print("%s: %s" % (tasknum, task))
lines = lines + 1
content = "%s: %s" % (tasknum, task)
print content
lines = lines + 1 + int(len(content) / (self.columns + 1))
self.footer_present = lines
self.lastpids = runningpids[:]