graphlog: simplify ascii drawing to process one cset at a time
authorDirkjan Ochtman <dirkjan@ochtman.nl>
Thu, 20 Aug 2009 08:49:01 +0200
changeset 9371 571a7acb4544
parent 9370 b360addfbe0e
child 9372 2484868cffde
graphlog: simplify ascii drawing to process one cset at a time
hgext/graphlog.py
--- a/hgext/graphlog.py	Thu Aug 20 08:36:20 2009 +0200
+++ b/hgext/graphlog.py	Thu Aug 20 08:49:01 2009 +0200
@@ -100,11 +100,13 @@
     line.extend(["|", " "] * (n_columns - ni - 1))
     return line
 
-def ascii(ui, dag):
+def ascii(ui, base, type, char, text, coldata):
     """prints an ASCII graph of the DAG
 
-    dag is a generator that emits tuples with the following elements:
+    takes the following arguments (one call per node in the graph):
 
+      - ui to write to
+      - A list we can keep the needed state in
       - Column of the current node in the set of ongoing edges.
       - Type indicator of node data == ASCIIDATA.
       - Payload: (char, lines):
@@ -119,89 +121,86 @@
         0 means no columns added or removed; 1 means one column added.
     """
 
-    base = [0, 0]
-    for idx, type, (char, text), edges, ncols, coldiff in dag:
-
-        assert -2 < coldiff < 2
-        if coldiff == -1:
-            # Transform
-            #
-            #     | | |        | | |
-            #     o | |  into  o---+
-            #     |X /         |/ /
-            #     | |          | |
-            fix_long_right_edges(edges)
-
-        # add_padding_line says whether to rewrite
+    idx, edges, ncols, coldiff = coldata
+    assert -2 < coldiff < 2
+    if coldiff == -1:
+        # Transform
         #
-        #     | | | |        | | | |
-        #     | o---+  into  | o---+
-        #     |  / /         |   | |  # <--- padding line
-        #     o | |          |  / /
-        #                    o | |
-        add_padding_line = (len(text) > 2 and
-                            coldiff == -1 and
-                            [x for (x, y) in edges if x + 1 < y])
+        #     | | |        | | |
+        #     o | |  into  o---+
+        #     |X /         |/ /
+        #     | |          | |
+        fix_long_right_edges(edges)
+
+    # add_padding_line says whether to rewrite
+    #
+    #     | | | |        | | | |
+    #     | o---+  into  | o---+
+    #     |  / /         |   | |  # <--- padding line
+    #     o | |          |  / /
+    #                    o | |
+    add_padding_line = (len(text) > 2 and coldiff == -1 and
+                        [x for (x, y) in edges if x + 1 < y])
 
-        # fix_nodeline_tail says whether to rewrite
-        #
-        #     | | o | |        | | o | |
-        #     | | |/ /         | | |/ /
-        #     | o | |    into  | o / /   # <--- fixed nodeline tail
-        #     | |/ /           | |/ /
-        #     o | |            o | |
-        fix_nodeline_tail = len(text) <= 2 and not add_padding_line
+    # fix_nodeline_tail says whether to rewrite
+    #
+    #     | | o | |        | | o | |
+    #     | | |/ /         | | |/ /
+    #     | o | |    into  | o / /   # <--- fixed nodeline tail
+    #     | |/ /           | |/ /
+    #     o | |            o | |
+    fix_nodeline_tail = len(text) <= 2 and not add_padding_line
 
-        # nodeline is the line containing the node character (typically o)
-        nodeline = ["|", " "] * idx
-        nodeline.extend([char, " "])
+    # nodeline is the line containing the node character (typically o)
+    nodeline = ["|", " "] * idx
+    nodeline.extend([char, " "])
 
-        nodeline.extend(
-            get_nodeline_edges_tail(idx, base[1], ncols, coldiff,
-                                    base[0], fix_nodeline_tail))
+    nodeline.extend(
+        get_nodeline_edges_tail(idx, base[1], ncols, coldiff,
+                                base[0], fix_nodeline_tail))
 
-        # shift_interline is the line containing the non-vertical
-        # edges between this entry and the next
-        shift_interline = ["|", " "] * idx
-        if coldiff == -1:
-            n_spaces = 1
-            edge_ch = "/"
-        elif coldiff == 0:
-            n_spaces = 2
-            edge_ch = "|"
-        else:
-            n_spaces = 3
-            edge_ch = "\\"
-        shift_interline.extend(n_spaces * [" "])
-        shift_interline.extend([edge_ch, " "] * (ncols - idx - 1))
+    # shift_interline is the line containing the non-vertical
+    # edges between this entry and the next
+    shift_interline = ["|", " "] * idx
+    if coldiff == -1:
+        n_spaces = 1
+        edge_ch = "/"
+    elif coldiff == 0:
+        n_spaces = 2
+        edge_ch = "|"
+    else:
+        n_spaces = 3
+        edge_ch = "\\"
+    shift_interline.extend(n_spaces * [" "])
+    shift_interline.extend([edge_ch, " "] * (ncols - idx - 1))
 
-        # draw edges from the current node to its parents
-        draw_edges(edges, nodeline, shift_interline)
+    # draw edges from the current node to its parents
+    draw_edges(edges, nodeline, shift_interline)
 
-        # lines is the list of all graph lines to print
-        lines = [nodeline]
-        if add_padding_line:
-            lines.append(get_padding_line(idx, ncols, edges))
-        lines.append(shift_interline)
+    # lines is the list of all graph lines to print
+    lines = [nodeline]
+    if add_padding_line:
+        lines.append(get_padding_line(idx, ncols, edges))
+    lines.append(shift_interline)
 
-        # make sure that there are as many graph lines as there are
-        # log strings
-        while len(text) < len(lines):
-            text.append("")
-        if len(lines) < len(text):
-            extra_interline = ["|", " "] * (ncols + coldiff)
-            while len(lines) < len(text):
-                lines.append(extra_interline)
+    # make sure that there are as many graph lines as there are
+    # log strings
+    while len(text) < len(lines):
+        text.append("")
+    if len(lines) < len(text):
+        extra_interline = ["|", " "] * (ncols + coldiff)
+        while len(lines) < len(text):
+            lines.append(extra_interline)
 
-        # print lines
-        indentation_level = max(ncols, ncols + coldiff)
-        for (line, logstr) in zip(lines, text):
-            ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr)
-            ui.write(ln.rstrip() + '\n')
+    # print lines
+    indentation_level = max(ncols, ncols + coldiff)
+    for (line, logstr) in zip(lines, text):
+        ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr)
+        ui.write(ln.rstrip() + '\n')
 
-        # ... and start over
-        base[0] = coldiff
-        base[1] = idx
+    # ... and start over
+    base[0] = coldiff
+    base[1] = idx
 
 def get_revs(repo, rev_opt):
     if rev_opt:
@@ -217,14 +216,13 @@
         if op in opts and opts[op]:
             raise util.Abort(_("--graph option is incompatible with --%s") % op)
 
-def generate(dag, displayer, showparents, edgefn):
-    seen = []
+def generate(ui, dag, displayer, showparents, edgefn):
+    seen, base = [], [0, 0]
     for rev, type, ctx, parents in dag:
         char = ctx.node() in showparents and '@' or 'o'
         displayer.show(ctx)
         lines = displayer.hunk.pop(rev).split('\n')[:-1]
-        cols = edgefn(seen, rev, parents)
-        yield cols[0], type, (char, lines), cols[1], cols[2], cols[3]
+        ascii(ui, base, type, char, lines, edgefn(seen, rev, parents))
 
 def graphlog(ui, repo, path=None, **opts):
     """show revision history alongside an ASCII revision graph
@@ -252,8 +250,7 @@
 
     displayer = show_changeset(ui, repo, opts, buffered=True)
     showparents = [ctx.node() for ctx in repo[None].parents()]
-    gen = generate(revdag, displayer, showparents, asciiedges)
-    ascii(ui, gen)
+    generate(ui, revdag, displayer, showparents, asciiedges)
 
 def graphrevs(repo, nodes, opts):
     limit = cmdutil.loglimit(opts)
@@ -289,8 +286,7 @@
     revdag = graphrevs(repo, o, opts)
     displayer = show_changeset(ui, repo, opts, buffered=True)
     showparents = [ctx.node() for ctx in repo[None].parents()]
-    gen = generate(revdag, displayer, showparents, asciiedges)
-    ascii(ui, gen)
+    generate(ui, revdag, displayer, showparents, asciiedges)
 
 def gincoming(ui, repo, source="default", **opts):
     """show the incoming changesets alongside an ASCII revision graph
@@ -340,8 +336,7 @@
         revdag = graphrevs(other, chlist, opts)
         displayer = show_changeset(ui, other, opts, buffered=True)
         showparents = [ctx.node() for ctx in repo[None].parents()]
-        gen = generate(revdag, displayer, showparents, asciiedges)
-        ascii(ui, gen)
+        generate(ui, revdag, displayer, showparents, asciiedges)
 
     finally:
         if hasattr(other, 'close'):