D360: log: add a "graphwidth" template variable
hooper (Danny Hooper)
phabricator at mercurial-scm.org
Fri Aug 11 20:35:17 EDT 2017
hooper updated this revision to Diff 822.
hooper edited the summary of this revision.
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D360?vs=821&id=822
REVISION DETAIL
https://phab.mercurial-scm.org/D360
AFFECTED FILES
hgext/show.py
mercurial/cmdutil.py
mercurial/commands.py
mercurial/graphmod.py
mercurial/templatekw.py
tests/test-command-template.t
CHANGE DETAILS
diff --git a/tests/test-command-template.t b/tests/test-command-template.t
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -4319,3 +4319,155 @@
custom
$ cd ..
+
+Test 'graphwidth' in 'hg log' on various topologies. The key here is that the
+printed graphwidths 3, 5, 7, etc. should all line up in their respective
+columns. We don't care about other aspects of the graph rendering here.
+
+ $ hg init graphwidth
+ $ cd graphwidth
+
+ $ wrappabletext="a a a a a a a a a a a a"
+
+ $ printf "first\n" > file
+ $ hg add file
+ $ hg commit -m "$wrappabletext"
+
+ $ printf "first\nsecond\n" > file
+ $ hg commit -m "$wrappabletext"
+
+ $ hg checkout 0
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ printf "third\nfirst\n" > file
+ $ hg commit -m "$wrappabletext"
+ created new head
+
+ $ hg merge
+ merging file
+ 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+ (branch merge, don't forget to commit)
+
+ $ hg log --graph -T "{graphwidth}"
+ @ 3
+ |
+ | @ 5
+ |/
+ o 3
+
+ $ hg commit -m "$wrappabletext"
+
+ $ hg log --graph -T "{graphwidth}"
+ @ 5
+ |\
+ | o 5
+ | |
+ o | 5
+ |/
+ o 3
+
+
+ $ hg checkout 0
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ printf "third\nfirst\nsecond\n" > file
+ $ hg commit -m "$wrappabletext"
+ created new head
+
+ $ hg log --graph -T "{graphwidth}"
+ @ 3
+ |
+ | o 7
+ | |\
+ +---o 7
+ | |
+ | o 5
+ |/
+ o 3
+
+
+ $ hg log --graph -T "{graphwidth}" -r 3
+ o 5
+ |\
+ ~ ~
+
+ $ hg log --graph -T "{graphwidth}" -r 1
+ o 3
+ |
+ ~
+
+ $ hg merge
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ (branch merge, don't forget to commit)
+ $ hg commit -m "$wrappabletext"
+
+ $ printf "seventh\n" >> file
+ $ hg commit -m "$wrappabletext"
+
+ $ hg log --graph -T "{graphwidth}"
+ @ 3
+ |
+ o 5
+ |\
+ | o 5
+ | |
+ o | 7
+ |\ \
+ | o | 7
+ | |/
+ o / 5
+ |/
+ o 3
+
+
+The point of graphwidth is to allow wrapping that accounts for the space taken
+by the graph.
+
+ $ COLUMNS=10 hg log --graph -T "{fill(desc, termwidth - graphwidth)}"
+ @ a a a a
+ | a a a a
+ | a a a a
+ o a a a
+ |\ a a a
+ | | a a a
+ | | a a a
+ | o a a a
+ | | a a a
+ | | a a a
+ | | a a a
+ o | a a
+ |\ \ a a
+ | | | a a
+ | | | a a
+ | | | a a
+ | | | a a
+ | o | a a
+ | |/ a a
+ | | a a
+ | | a a
+ | | a a
+ | | a a
+ o | a a a
+ |/ a a a
+ | a a a
+ | a a a
+ o a a a a
+ a a a a
+ a a a a
+
+Something tricky happens when there are elided nodes; the next drawn row of
+edges can be more than one column wider, but the graph width only increases by
+one column. The remaining columns are added in between the nodes.
+
+ $ hg log --graph -T "{graphwidth}" -r "0|2|4|5"
+ o 5
+ |\
+ | \
+ | :\
+ o : : 7
+ :/ /
+ : o 5
+ :/
+ o 3
+
+
+ $ cd ..
+
diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py
--- a/mercurial/templatekw.py
+++ b/mercurial/templatekw.py
@@ -764,6 +764,13 @@
"""Integer. The width of the current terminal."""
return repo.ui.termwidth()
+ at templatekeyword('graphwidth')
+def graphwidth(repo, ctx, templ, **args):
+ """Integer. The width of the graph drawn by 'log --graph' or zero."""
+ # The value args['graphwidth'] will be this function, so we use an internal
+ # name to pass the value through props into this function.
+ return args.get('_graphwidth', 0)
+
@templatekeyword('troubles')
def showtroubles(**args):
"""List of strings. Evolution troubles affecting the changeset.
diff --git a/mercurial/graphmod.py b/mercurial/graphmod.py
--- a/mercurial/graphmod.py
+++ b/mercurial/graphmod.py
@@ -222,6 +222,24 @@
state['edges'].pop(rev, None)
yield (type, char, lines, (nodeidx, edges, ncols, nmorecols))
+def asciiwidth(state, rev, parents):
+ """returns the width of the graph drawn by ascii() based on asciiedges()"""
+ seen = state['seen'][:]
+ if rev not in seen:
+ seen.append(rev)
+ columns = len(seen)
+
+ # We might be adding columns to handle previously unseen parents, but only
+ # one of them goes into the graph width for this rev.
+ newparents = 0
+ for ptype, parent in parents:
+ if parent != rev and parent not in seen:
+ newparents += 1
+ columns = max(columns, columns + min(2, newparents) - 1)
+
+ # Each column is 2 characters, and there's another character of padding.
+ return 1 + 2 * columns
+
def _fixlongrightedges(edges):
for (i, (start, end)) in enumerate(edges):
if end > start:
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -3123,7 +3123,8 @@
def display(other, chlist, displayer):
revdag = cmdutil.graphrevs(other, chlist, opts)
cmdutil.displaygraph(ui, repo, revdag, displayer,
- graphmod.asciiedges)
+ graphmod.asciiedges,
+ widthfn=graphmod.asciiwidth)
hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
return 0
@@ -3572,7 +3573,8 @@
revdag = cmdutil.graphrevs(repo, o, opts)
ui.pager('outgoing')
displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
- cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
+ cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges,
+ widthfn=graphmod.asciiwidth)
cmdutil.outgoinghooks(ui, repo, other, opts, o)
return 0
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -2508,7 +2508,7 @@
return formatnode
def displaygraph(ui, repo, dag, displayer, edgefn, getrenamed=None,
- filematcher=None):
+ filematcher=None, widthfn=None):
formatnode = _graphnodeformatter(ui, displayer)
state = graphmod.asciistate()
styles = state['styles']
@@ -2545,7 +2545,11 @@
revmatchfn = None
if filematcher is not None:
revmatchfn = filematcher(ctx.rev())
- displayer.show(ctx, copies=copies, matchfn=revmatchfn)
+ graphwidth = 0
+ if widthfn:
+ graphwidth = widthfn(state, rev, parents)
+ displayer.show(ctx, copies=copies, matchfn=revmatchfn,
+ _graphwidth=graphwidth)
lines = displayer.hunk.pop(rev).split('\n')
if not lines[-1]:
del lines[-1]
@@ -2570,7 +2574,7 @@
ui.pager('log')
displayer = show_changeset(ui, repo, opts, buffered=True)
displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges, getrenamed,
- filematcher)
+ filematcher, widthfn=graphmod.asciiwidth)
def checkunsupportedgraphflags(pats, opts):
for op in ["newest_first"]:
diff --git a/hgext/show.py b/hgext/show.py
--- a/hgext/show.py
+++ b/hgext/show.py
@@ -397,7 +397,8 @@
revdag = graphmod.dagwalker(repo, revs)
ui.setconfig('experimental', 'graphshorten', True)
- cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
+ cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges,
+ widthfn=graphmod.asciiwidth)
def extsetup(ui):
# Alias `hg <prefix><view>` to `hg show <view>`.
To: hooper, #hg-reviewers
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list