diff options
author | Ben Pfaff <blp@ovn.org> | 2016-12-28 12:41:31 -0800 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2017-01-25 13:53:31 -0800 |
commit | 902323d32ed7656b58c9c37d5ac9ebe7986b0a68 (patch) | |
tree | 4b0ffc319bc4aa922e963033f0a6d47fb8695932 /python | |
parent | bef503e8c094456ca82fefd044a8c3341d9d21ac (diff) | |
download | openvswitch-902323d32ed7656b58c9c37d5ac9ebe7986b0a68.tar.gz |
nroff: Improve formatting of ASCII diagrams.
This makes diagrams in ASCII output look about as good as one might
reasonably expect, so that in ovn-architecture(7), for example, this:
. 9 bits: reserved (0)
. 15 bits: ingress port
. 16 bits: egress port
. 24 bits: datapath
now gets formatted as:
9 15 16 24
+--------+------------+-----------+--------+
|reserved|ingress port|egress port|datapath|
+--------+------------+-----------+--------+
0
which isn't perfect but certainly more evocative than a bulleted list.
This will be more useful in upcoming commits that start using diagrams more
frequently.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'python')
-rw-r--r-- | python/build/nroff.py | 80 |
1 files changed, 61 insertions, 19 deletions
diff --git a/python/build/nroff.py b/python/build/nroff.py index ebb10e90d..2f31bb27e 100644 --- a/python/build/nroff.py +++ b/python/build/nroff.py @@ -121,7 +121,19 @@ def fatal(msg): sys.exit(1) -def diagram_header_to_nroff(header_node): +def put_text(text, x, y, s): + extend = x + len(s) - len(text[y]) + if extend > 0: + text[y] += ' ' * extend + text[y] = text[y][:x] + s + text[y][x + len(s):] + + +def put_centered(text, x, width, y, s): + put_text(text, x + (width - len(s)) / 2, y, s) + + +def diagram_header_to_nroff(header_node, text, x): + # Parse header. header_fields = [] i = 0 for node in header_node.childNodes: @@ -145,10 +157,11 @@ def diagram_header_to_nroff(header_node): else: fatal("unknown node %s in diagram <header> element" % node) + # Format pic version. pic_s = "" for f in header_fields: - pic_s += " %s: box \"%s\" width %s" % (f['tag'], f['name'], - f['width']) + name = f['name'].replace('...', '. . .') + pic_s += " %s: box \"%s\" width %s" % (f['tag'], name, f['width']) if f['fill'] == 'yes': pic_s += " fill" pic_s += '\n' @@ -164,43 +177,72 @@ def diagram_header_to_nroff(header_node): pic_s += "from %s.nw + (0,textht) " % header_fields[0]['tag'] pic_s += "to %s.ne + (0,textht)\n" % header_fields[-1]['tag'] - text_s = "" + # Format text version. + header_width = 1 + for f in header_fields: + field_width = max(len(f['above']), len(f['below']), len(f['name'])) + f['width'] = field_width + header_width += field_width + 1 + min_header_width = 2 + len(name) + while min_header_width > header_width: + for f in header_fields: + f['width'] += 1 + header_width += 1 + if header_width >= min_header_width: + break + + if name != "": + put_centered(text, x, header_width, 0, name) + if header_width >= 4: + arrow = '<' + '-' * (header_width - 4) + '>' + put_text(text, x + 1, 1, arrow) for f in header_fields: - text_s += """.IP \\(bu -%s bits""" % (f['above']) - if f['name']: - text_s += ": %s" % f['name'] - if f['below']: - text_s += " (%s)" % f['below'] - text_s += "\n" - return pic_s, text_s + box1 = '+' + '-' * f['width'] + '+' + box2 = '|' + ' ' * f['width'] + '|' + put_text(text, x, 3, box1) + put_text(text, x, 4, box2) + put_text(text, x, 5, box1) + + put_centered(text, x + 1, f['width'], 2, f['above']) + put_centered(text, x + 1, f['width'], 4, f['name']) + put_centered(text, x + 1, f['width'], 6, f['below']) + + x += f['width'] + 1 + + return pic_s, x + 1 def diagram_to_nroff(nodes, para): pic_s = '' - text_s = '' + text = [''] * 7 + x = 0 move = False for node in nodes: if node.nodeType == node.ELEMENT_NODE and node.tagName == 'header': if move: pic_s += "move .1\n" - text_s += ".sp\n" - pic_header, text_header = diagram_header_to_nroff(node) + x += 1 + elif x > 0: + x -= 1 + pic_header, x = diagram_header_to_nroff(node, text, x) pic_s += "[\n" + pic_header + "]\n" - text_s += text_header move = True elif node.nodeType == node.ELEMENT_NODE and node.tagName == 'nospace': move = False elif node.nodeType == node.ELEMENT_NODE and node.tagName == 'dots': pic_s += "move .1\n" pic_s += '". . ." ljust\n' - text_s += ".sp\n" + + put_text(text, x, 4, " ... ") + x += 5 elif node.nodeType == node.COMMENT_NODE: pass elif node.nodeType == node.TEXT_NODE and node.data.isspace(): pass else: fatal("unknown node %s in diagram <header> element" % node) + + text_s = '.br\n'.join(["\\fL%s\n" % s for s in text if s != ""]) return para + """ .\\" check if in troff mode (TTY) .if t \{ @@ -213,9 +255,9 @@ fillval = .2 \\} .\\" check if in nroff mode: .if n \{ -.RS +.nf """ + text_s + """\ -.RE +.fi \\}""" |