diff options
Diffstat (limited to 'src/browse.py')
-rwxr-xr-x | src/browse.py | 131 |
1 files changed, 78 insertions, 53 deletions
diff --git a/src/browse.py b/src/browse.py index ca95197..17e67cf 100755 --- a/src/browse.py +++ b/src/browse.py @@ -24,36 +24,66 @@ import BaseHTTPServer import subprocess import sys import webbrowser +from collections import namedtuple -def match_strip(prefix, line): +Node = namedtuple('Node', ['inputs', 'rule', 'target', 'outputs']) + +# Ideally we'd allow you to navigate to a build edge or a build node, +# with appropriate views for each. But there's no way to *name* a build +# edge so we can only display nodes. +# +# For a given node, it has at most one input edge, which has n +# different inputs. This becomes node.inputs. (We leave out the +# outputs of the input edge due to what follows.) The node can have +# multiple dependent output edges. Rather than attempting to display +# those, they are summarized by taking the union of all their outputs. +# +# This means there's no single view that shows you all inputs and outputs +# of an edge. But I think it's less confusing than alternatives. + +def match_strip(line, prefix): if not line.startswith(prefix): - print prefix, line - assert line.startswith(prefix) - return line[len(prefix):] + return (False, line) + return (True, line[len(prefix):]) def parse(text): - lines = text.split('\n') - node = lines.pop(0) - node = node[:-1] # strip trailing colon - - input = [] - if lines and lines[0].startswith(' input:'): - input.append(match_strip(' input: ', lines.pop(0))) - while lines and lines[0].startswith(' '): - input.append(lines.pop(0).strip()) + lines = iter(text.split('\n')) + target = None + rule = None + inputs = [] outputs = [] - while lines: - output = [] - output.append(match_strip(' output: ', lines.pop(0))) - while lines and lines[0].startswith(' '): - output.append(lines.pop(0).strip()) - outputs.append(output) - - return (node, input, outputs) -def generate_html(data): - node, input, outputs = data + try: + target = lines.next()[:-1] # strip trailing colon + + line = lines.next() + (match, rule) = match_strip(line, ' input: ') + if match: + (match, line) = match_strip(lines.next(), ' ') + while match: + type = None + (match, line) = match_strip(line, '| ') + if match: + type = 'implicit' + (match, line) = match_strip(line, '|| ') + if match: + type = 'order-only' + inputs.append((line, type)) + (match, line) = match_strip(lines.next(), ' ') + + match, _ = match_strip(line, ' outputs:') + if match: + (match, line) = match_strip(lines.next(), ' ') + while match: + outputs.append(line) + (match, line) = match_strip(lines.next(), ' ') + except StopIteration: + pass + + return Node(inputs, rule, target, outputs) + +def generate_html(node): print '''<!DOCTYPE html> <style> body { @@ -63,47 +93,42 @@ body { } h1 { font-weight: normal; + font-size: 140%; text-align: center; margin: 0; } h2 { font-weight: normal; + font-size: 120%; } tt { font-family: WebKitHack, monospace; + white-space: nowrap; } -ul { - margin-top: 0; - padding-left: 20px; +.filelist { + -webkit-columns: auto 2; } </style>''' - print '<table width=500><tr><td colspan=3>' - print '<h1><tt>%s</tt></h1>' % node - print '</td></tr>' - - print '<tr><td valign=top>' - if input: - print '<h2>built by rule: <tt>%s</tt></h2>' % input[0] - if len(input) > 0: - print 'inputs:' - print '<ul>' - for i in input[1:]: - print '<li><tt><a href="?%s">%s</a></tt></li>' % (i, i) - print '</ul>' - else: - print '<h2>no input rule</h2>' - print '</td>' - print '<td width=50> </td>' - - print '<td valign=top>' - print '<h2>dependents</h2>' - for output in outputs: - print '<tt>%s</tt>' % output[0] - print '<ul>' - for i in output[1:]: - print '<li><tt><a href="?%s">%s</a></tt></li>' % (i, i) - print '</ul>' - print '</td></tr></table>' + + print '<h1><tt>%s</tt></h1>' % node.target + + if node.inputs: + print '<h2>target is built using rule <tt>%s</tt> of</h2>' % node.rule + if len(node.inputs) > 0: + print '<div class=filelist>' + for input, type in sorted(node.inputs): + extra = '' + if type: + extra = ' (%s)' % type + print '<tt><a href="?%s">%s</a>%s</tt><br>' % (input, input, extra) + print '</div>' + + if node.outputs: + print '<h2>dependent edges build:</h2>' + print '<div class=filelist>' + for output in sorted(node.outputs): + print '<tt><a href="?%s">%s</a></tt><br>' % (output, output) + print '</div>' def ninja_dump(target): proc = subprocess.Popen([sys.argv[1], '-t', 'query', target], |