Record how lines run through the cells of the commit graph

A cell of the commit graph only records which of its edges are touched
by lines. That's all the box drawing characters can show, but it
doesn't say how the lines connect. A vertical line with a horizontal
line passing behind it touches all four edges. So does a cell in which
the line from above bends to the left, the line below comes in from the
left, and a horizontal line passes through.

For the lines at the top and bottom edges, record whether they run
straight on or bend to the left or right, and record whether a line
passes through horizontally. Nothing reads this yet. It prepares for
drawing the graph with symbols that can show these differences.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller
2026-10-04 18:47:01 +02:00
co-authored by Claude Opus 5.5
parent 91378b1e8a
commit e5c5a62cd9
2 changed files with 52 additions and 18 deletions
+36 -15
View File
@@ -21,17 +21,33 @@ const (
MERGE
)
// How a line that touches the top or bottom edge of a cell runs within it
type verticalLine uint8
const (
noLine verticalLine = iota
// On to the opposite edge, or into the commit symbol
straightLine
// Bends towards the left edge
lineToLeft
// Bends towards the right edge
lineToRight
)
type Cell struct {
up, down, left, right bool
cellType cellType
rightStyle *style.TextStyle
style *style.TextStyle
// The lines that touch the top and bottom edges
up, down verticalLine
// Whether lines touch the left and right edges
left, right bool
// Whether a line passes through from the left edge to the right edge
horizontal bool
cellType cellType
rightStyle *style.TextStyle
style *style.TextStyle
}
func (cell *Cell) render(writer io.StringWriter) {
up, down, left, right := cell.up, cell.down, cell.left, cell.right
first, second := getBoxDrawingChars(up, down, left, right)
first, second := getBoxDrawingChars(cell.up != noLine, cell.down != noLine, cell.left, cell.right)
var adjustedFirst string
switch cell.cellType {
case CONNECTION:
@@ -98,34 +114,34 @@ func cachedSprint(style style.TextStyle, str string) string {
}
func (cell *Cell) reset() {
cell.up = false
cell.down = false
cell.up = noLine
cell.down = noLine
cell.left = false
cell.right = false
cell.horizontal = false
}
func (cell *Cell) setUp(style *style.TextStyle) *Cell {
cell.up = true
func (cell *Cell) setUp(style *style.TextStyle, line verticalLine) *Cell {
cell.up = line
cell.style = style
return cell
}
func (cell *Cell) setDown(style *style.TextStyle) *Cell {
cell.down = true
func (cell *Cell) setDown(style *style.TextStyle, line verticalLine) *Cell {
cell.down = line
cell.style = style
return cell
}
func (cell *Cell) setLeft(style *style.TextStyle) *Cell {
cell.left = true
if !cell.up && !cell.down {
if cell.up == noLine && cell.down == noLine {
// vertical trumps left
cell.style = style
}
return cell
}
//nolint:unparam
func (cell *Cell) setRight(style *style.TextStyle, override bool) *Cell {
cell.right = true
if cell.rightStyle == nil || override {
@@ -134,6 +150,11 @@ func (cell *Cell) setRight(style *style.TextStyle, override bool) *Cell {
return cell
}
func (cell *Cell) setHorizontal(style *style.TextStyle, overrideRightStyle bool) *Cell {
cell.horizontal = true
return cell.setLeft(style).setRight(style, overrideRightStyle)
}
func (cell *Cell) setStyle(style *style.TextStyle) *Cell {
cell.style = style
return cell
+16 -3
View File
@@ -303,17 +303,17 @@ func renderPipeSet(
if left != right {
for i := left + 1; i < right; i++ {
cells[i].setLeft(style).setRight(style, overrideRightStyle)
cells[i].setHorizontal(style, overrideRightStyle)
}
cells[left].setRight(style, overrideRightStyle)
cells[right].setLeft(style)
}
if pipe.kind == STARTS || pipe.kind == CONTINUES {
cells[pipe.toPos].setDown(style)
cells[pipe.toPos].setDown(style, lineTowards(pipe.toPos, pipe.fromPos))
}
if pipe.kind == TERMINATES || pipe.kind == CONTINUES {
cells[pipe.fromPos].setUp(style)
cells[pipe.fromPos].setUp(style, lineTowards(pipe.fromPos, pipe.toPos))
}
}
@@ -375,6 +375,19 @@ func renderPipeSet(
return writer.String()
}
// The course of a line through the top or bottom edge of the cell at pos,
// given the column of the pipe's other end
func lineTowards(pos, otherPos int16) verticalLine {
switch {
case otherPos < pos:
return lineToLeft
case otherPos > pos:
return lineToRight
default:
return straightLine
}
}
func equalHashes(a, b *string) bool {
// if our selectedCommitHashPtr is nil, there is no selected commit
if a == nil || b == nil {