1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-07-31 14:24:25 +03:00

render commit graph

This commit is contained in:
Jesse Duffield
2021-11-02 16:39:15 +11:00
parent 2fc1498517
commit 802cfb1a04
53 changed files with 543 additions and 284 deletions

View File

@ -1,11 +1,15 @@
package graph
import (
"io"
"sync"
"github.com/gookit/color"
"github.com/jesseduffield/lazygit/pkg/gui/style"
)
const mergeSymbol = '⏣'
const commitSymbol = '⎔'
const mergeSymbol = "⏣"
const commitSymbol = "⎔"
type cellType int
@ -22,11 +26,11 @@ type Cell struct {
style style.TextStyle
}
func (cell *Cell) render() string {
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)
var adjustedFirst rune
var adjustedFirst string
switch cell.cellType {
case CONNECTION:
adjustedFirst = first
@ -47,13 +51,46 @@ func (cell *Cell) render() string {
// assert on the style of a space given a space has no styling (assuming we
// stick to only using foreground styles)
var styledSecondChar string
if second == ' ' {
if second == " " {
styledSecondChar = " "
} else {
styledSecondChar = rightStyle.Sprint(string(second))
styledSecondChar = cachedSprint(*rightStyle, second)
}
return cell.style.Sprint(string(adjustedFirst)) + styledSecondChar
_, _ = writer.WriteString(cachedSprint(cell.style, adjustedFirst))
_, _ = writer.WriteString(styledSecondChar)
}
type rgbCacheKey struct {
*color.RGBStyle
str string
}
var rgbCache = make(map[rgbCacheKey]string)
var rgbCacheMutex sync.RWMutex
func cachedSprint(style style.TextStyle, str string) string {
switch v := style.Style.(type) {
case *color.RGBStyle:
rgbCacheMutex.RLock()
key := rgbCacheKey{v, str}
value, ok := rgbCache[key]
rgbCacheMutex.RUnlock()
if ok {
return value
}
value = style.Sprint(str)
rgbCacheMutex.Lock()
rgbCache[key] = value
rgbCacheMutex.Unlock()
return value
case color.Basic:
return style.Sprint(str)
case color.Style:
value := style.Sprint(str)
return value
}
return style.Sprint(str)
}
func (cell *Cell) reset() {
@ -102,39 +139,39 @@ func (cell *Cell) setType(cellType cellType) *Cell {
return cell
}
func getBoxDrawingChars(up, down, left, right bool) (rune, rune) {
func getBoxDrawingChars(up, down, left, right bool) (string, string) {
if up && down && left && right {
return '│', '─'
return "│", "─"
} else if up && down && left && !right {
return '│', ' '
return "│", " "
} else if up && down && !left && right {
return '│', '─'
return "│", "─"
} else if up && down && !left && !right {
return '│', ' '
return "│", " "
} else if up && !down && left && right {
return '┴', '─'
return "┴", "─"
} else if up && !down && left && !right {
return '╯', ' '
return "╯", " "
} else if up && !down && !left && right {
return '╰', '─'
return "╰", "─"
} else if up && !down && !left && !right {
return '╵', ' '
return "╵", " "
} else if !up && down && left && right {
return '┬', '─'
return "┬", "─"
} else if !up && down && left && !right {
return '╮', ' '
return "╮", " "
} else if !up && down && !left && right {
return '╭', '─'
return "╭", "─"
} else if !up && down && !left && !right {
return '╷', ' '
return "╷", " "
} else if !up && !down && left && right {
return '─', '─'
return "─", "─"
} else if !up && !down && left && !right {
return '─', ' '
return "─", " "
} else if !up && !down && !left && right {
return '╶', '─'
return "╶", "─"
} else if !up && !down && !left && !right {
return ' ', ' '
return " ", " "
} else {
panic("should not be possible")
}