mirror of
https://github.com/facebook/sapling.git
synced 2024-10-07 07:17:55 +03:00
log: add a "graphwidth" template variable
Wrapping text in templates for 'hg log --graph' can't be done very well, because the template doesn't know how wide the graph drawing is. The edge drawing function needs to know the number of lines in the template output, so we need to also determine how wide that drawing would be before we call the edgefn or evaluate the template. This patch makes edgefn compute the graph width and pass it into the template so that we can do something like this: COLUMNS=10 hg log --graph --template "{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 Using extensions to do this would be relatively complicated due to a lack of hooks in this area of the code. In the future it may make sense to have a more generic "textwidth" that tells you how many columns you can expect to fill without causing the terminal to wrap your output. I'm not sure there are other situations to motivate this yet, or if it is entirely feasible. Differential Revision: https://phab.mercurial-scm.org/D360
This commit is contained in:
parent
76d1768227
commit
54e3286e1e
@ -2652,14 +2652,18 @@ def displaygraph(ui, repo, dag, displayer, edgefn, getrenamed=None,
|
||||
revmatchfn = None
|
||||
if filematcher is not None:
|
||||
revmatchfn = filematcher(ctx.rev())
|
||||
displayer.show(ctx, copies=copies, matchfn=revmatchfn)
|
||||
edges = edgefn(type, char, state, rev, parents)
|
||||
firstedge = next(edges)
|
||||
width = firstedge[2]
|
||||
displayer.show(ctx, copies=copies, matchfn=revmatchfn,
|
||||
_graphwidth=width)
|
||||
lines = displayer.hunk.pop(rev).split('\n')
|
||||
if not lines[-1]:
|
||||
del lines[-1]
|
||||
displayer.flush(ctx)
|
||||
edges = edgefn(type, char, lines, state, rev, parents)
|
||||
for type, char, lines, coldata in edges:
|
||||
for type, char, width, coldata in itertools.chain([firstedge], edges):
|
||||
graphmod.ascii(ui, state, type, char, lines, coldata)
|
||||
lines = []
|
||||
displayer.close()
|
||||
|
||||
def graphlog(ui, repo, pats, opts):
|
||||
|
@ -172,7 +172,7 @@ def colored(dag, repo):
|
||||
yield (cur, type, data, (col, color), edges)
|
||||
seen = next
|
||||
|
||||
def asciiedges(type, char, lines, state, rev, parents):
|
||||
def asciiedges(type, char, state, rev, parents):
|
||||
"""adds edge info to changelog DAG walk suitable for ascii()"""
|
||||
seen = state['seen']
|
||||
if rev not in seen:
|
||||
@ -192,6 +192,7 @@ def asciiedges(type, char, lines, state, rev, parents):
|
||||
state['edges'][parent] = state['styles'].get(ptype, '|')
|
||||
|
||||
ncols = len(seen)
|
||||
width = 1 + ncols * 2
|
||||
nextseen = seen[:]
|
||||
nextseen[nodeidx:nodeidx + 1] = newparents
|
||||
edges = [(nodeidx, nextseen.index(p)) for p in knownparents]
|
||||
@ -205,9 +206,9 @@ def asciiedges(type, char, lines, state, rev, parents):
|
||||
edges.append((nodeidx, nodeidx))
|
||||
edges.append((nodeidx, nodeidx + 1))
|
||||
nmorecols = 1
|
||||
yield (type, char, lines, (nodeidx, edges, ncols, nmorecols))
|
||||
width += 2
|
||||
yield (type, char, width, (nodeidx, edges, ncols, nmorecols))
|
||||
char = '\\'
|
||||
lines = []
|
||||
nodeidx += 1
|
||||
ncols += 1
|
||||
edges = []
|
||||
@ -218,9 +219,11 @@ def asciiedges(type, char, lines, state, rev, parents):
|
||||
if len(newparents) > 1:
|
||||
edges.append((nodeidx, nodeidx + 1))
|
||||
nmorecols = len(nextseen) - ncols
|
||||
if nmorecols > 0:
|
||||
width += 2
|
||||
# remove current node from edge characters, no longer needed
|
||||
state['edges'].pop(rev, None)
|
||||
yield (type, char, lines, (nodeidx, edges, ncols, nmorecols))
|
||||
yield (type, char, width, (nodeidx, edges, ncols, nmorecols))
|
||||
|
||||
def _fixlongrightedges(edges):
|
||||
for (i, (start, end)) in enumerate(edges):
|
||||
|
@ -469,6 +469,13 @@ def showgraphnode(repo, ctx, **args):
|
||||
else:
|
||||
return 'o'
|
||||
|
||||
@templatekeyword('graphwidth')
|
||||
def showgraphwidth(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('index')
|
||||
def showindex(**args):
|
||||
"""Integer. The current iteration of the loop. (0 indexed)"""
|
||||
|
@ -4319,3 +4319,155 @@ Test that template function in extension is registered as expected
|
||||
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 ..
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user