mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-10-05 21:46:49 -04:00
Use the detailed commit graph automatically in terminals that draw it
The detailed commit graph is only drawn for users who set gui.commitGraphStyle to 'detailed'. Many users of terminals that can draw it will never find out about it. A terminal can't be asked whether it draws a given character, but it does tell us its name and version when tcell asks for them with XTVERSION at startup. Add an 'auto' value and make it the default. It uses the detailed graph in kitty from 0.36.2 and in Ghostty from 1.0.0 on. These are the first versions that draw all of the symbols. Everywhere else it stays with the classic graph. This includes tmux, because tmux answers XTVERSION itself. So far, WezTerm draws the symbols only in its nightly builds, so it isn't detected until a release has them. VS Code isn't detected either, because it only draws the symbols with GPU acceleration. The expected output of the integration tests has the classic graph, so pin it in their config. Otherwise they would fail when run with a visible UI in one of these terminals. Log the terminal's name and version at startup, to make it possible to find out why 'auto' picked what it did. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
da5b9b54eb
commit
4780c8bb72
@@ -302,14 +302,16 @@ gui:
|
||||
showFileIcons: true
|
||||
|
||||
# How the commit graph is drawn.
|
||||
# One of: 'classic' (default) | 'detailed'
|
||||
# One of: 'auto' (default) | 'classic' | 'detailed'
|
||||
# 'detailed' connects the lines to the commit circles, and shows exactly where
|
||||
# branches fork off and merge. It draws the graph with the git branch drawing
|
||||
# symbols (U+F5D0 to U+F60D), so it needs a terminal that draws these itself:
|
||||
# kitty, Ghostty, WezTerm (nightly builds), Contour, or VS Code's terminal with
|
||||
# GPU acceleration. Other terminals need a font that contains them, such as
|
||||
# https://github.com/rbong/flog-symbols.
|
||||
commitGraphStyle: classic
|
||||
# 'auto' uses 'detailed' if lazygit recognizes the terminal as one that draws
|
||||
# these symbols (kitty and Ghostty), and 'classic' otherwise.
|
||||
commitGraphStyle: auto
|
||||
|
||||
# Length of author name in (non-expanded) commits view. 2 means show initials
|
||||
# only.
|
||||
|
||||
@@ -180,9 +180,10 @@ type GuiConfig struct {
|
||||
// If true (default), file icons are shown in the file views. Only relevant if NerdFontsVersion is not empty.
|
||||
ShowFileIcons bool `yaml:"showFileIcons"`
|
||||
// How the commit graph is drawn.
|
||||
// One of: 'classic' (default) | 'detailed'
|
||||
// One of: 'auto' (default) | 'classic' | 'detailed'
|
||||
// 'detailed' connects the lines to the commit circles, and shows exactly where branches fork off and merge. It draws the graph with the git branch drawing symbols (U+F5D0 to U+F60D), so it needs a terminal that draws these itself: kitty, Ghostty, WezTerm (nightly builds), Contour, or VS Code's terminal with GPU acceleration. Other terminals need a font that contains them, such as https://github.com/rbong/flog-symbols.
|
||||
CommitGraphStyle string `yaml:"commitGraphStyle" jsonschema:"enum=classic,enum=detailed"`
|
||||
// 'auto' uses 'detailed' if lazygit recognizes the terminal as one that draws these symbols (kitty and Ghostty), and 'classic' otherwise.
|
||||
CommitGraphStyle string `yaml:"commitGraphStyle" jsonschema:"enum=auto,enum=classic,enum=detailed"`
|
||||
// Length of author name in (non-expanded) commits view. 2 means show initials only.
|
||||
CommitAuthorShortLength int `yaml:"commitAuthorShortLength"`
|
||||
// Length of author name in expanded commits view. 2 means show initials only.
|
||||
@@ -926,7 +927,7 @@ func GetDefaultConfigForPlatform(platform string) *UserConfig {
|
||||
ShowIcons: false,
|
||||
NerdFontsVersion: "",
|
||||
ShowFileIcons: true,
|
||||
CommitGraphStyle: "classic",
|
||||
CommitGraphStyle: "auto",
|
||||
CommitAuthorShortLength: 2,
|
||||
CommitAuthorLongLength: 17,
|
||||
CommitHashLength: 8,
|
||||
|
||||
@@ -31,7 +31,7 @@ func (config *UserConfig) Validate() error {
|
||||
return err
|
||||
}
|
||||
if err := validateEnum("gui.commitGraphStyle", config.Gui.CommitGraphStyle,
|
||||
[]string{"classic", "detailed"}); err != nil {
|
||||
[]string{"auto", "classic", "detailed"}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validateEnum("git.autoForwardBranches", config.Git.AutoForwardBranches,
|
||||
|
||||
@@ -733,6 +733,12 @@ func (g *Gui) DetectedColorScheme() DetectedColorScheme {
|
||||
return g.colorScheme
|
||||
}
|
||||
|
||||
// Terminal returns the name and version that the terminal reported at
|
||||
// startup. Both are empty if it didn't report them.
|
||||
func (g *Gui) Terminal() (string, string) {
|
||||
return g.screen.Terminal()
|
||||
}
|
||||
|
||||
// SetColorSchemeChangeHandler sets a function to call on the UI thread whenever
|
||||
// the terminal's colors change after startup.
|
||||
func (g *Gui) SetColorSchemeChangeHandler(handler func(DetectedColorScheme) error) {
|
||||
|
||||
@@ -352,8 +352,13 @@ func shouldShowGraph(c *ContextCommon) bool {
|
||||
}
|
||||
|
||||
func commitGraphSymbolSet(c *ContextCommon) graph.SymbolSet {
|
||||
if c.UserConfig().Gui.CommitGraphStyle == "detailed" {
|
||||
switch c.UserConfig().Gui.CommitGraphStyle {
|
||||
case "detailed":
|
||||
return graph.BranchDrawingSymbols
|
||||
case "auto":
|
||||
if graph.TerminalDrawsBranchDrawingSymbols(c.GocuiGui().Terminal()) {
|
||||
return graph.BranchDrawingSymbols
|
||||
}
|
||||
}
|
||||
return graph.BoxDrawingSymbols
|
||||
}
|
||||
|
||||
@@ -934,6 +934,8 @@ func (gui *Gui) Run(startArgs appTypes.StartArgs) error {
|
||||
|
||||
g.ErrorHandler = gui.PopupHandler.ErrorHandler
|
||||
|
||||
terminalName, terminalVersion := g.Terminal()
|
||||
gui.c.Log.Infof("Terminal: %s %s", terminalName, terminalVersion)
|
||||
gui.c.Log.Infof("Terminal color scheme: %s", g.DetectedColorScheme())
|
||||
g.SetColorSchemeChangeHandler(func(colorScheme gocui.DetectedColorScheme) error {
|
||||
gui.c.Log.Infof("Terminal color scheme changed: %s", colorScheme)
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
package graph
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// The branch drawing symbols are characters in the Unicode Private Use Area
|
||||
// (U+F5D0 to U+F60D) for drawing git graphs, introduced by kitty in
|
||||
// https://github.com/kovidgoyal/kitty/pull/7681. Unlike the box drawing
|
||||
@@ -95,3 +101,32 @@ func (cell *Cell) branchDrawingChars() (string, string) {
|
||||
return first, second
|
||||
}
|
||||
}
|
||||
|
||||
// The terminals that draw the branch drawing symbols themselves, with the
|
||||
// first version that draws all of them
|
||||
var terminalsWithBranchDrawingSymbols = map[string][]int{
|
||||
"kitty": {0, 36, 2},
|
||||
"ghostty": {1, 0, 0},
|
||||
}
|
||||
|
||||
// TerminalDrawsBranchDrawingSymbols says whether a terminal is known to draw
|
||||
// the branch drawing symbols itself, given the name and version it reports
|
||||
func TerminalDrawsBranchDrawingSymbols(name, version string) bool {
|
||||
minVersion, ok := terminalsWithBranchDrawingSymbols[strings.ToLower(name)]
|
||||
return ok && slices.Compare(versionNumbers(version), minVersion) >= 0
|
||||
}
|
||||
|
||||
// The numbers at the start of the dot-separated parts of a version, e.g.
|
||||
// [1 3 0] for "1.3.0-dev+abc"
|
||||
func versionNumbers(version string) []int {
|
||||
var numbers []int
|
||||
for part := range strings.SplitSeq(version, ".") {
|
||||
digits := part[:len(part)-len(strings.TrimLeft(part, "0123456789"))]
|
||||
number, err := strconv.Atoi(digits)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
numbers = append(numbers, number)
|
||||
}
|
||||
return numbers
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package graph
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTerminalDrawsBranchDrawingSymbols(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
version string
|
||||
expected bool
|
||||
}{
|
||||
{name: "kitty", version: "0.36.1", expected: false},
|
||||
{name: "kitty", version: "0.36.2", expected: true},
|
||||
{name: "kitty", version: "0.44.0", expected: true},
|
||||
{name: "ghostty", version: "0.9.0", expected: false},
|
||||
{name: "ghostty", version: "1.0.0", expected: true},
|
||||
{name: "ghostty", version: "1.3.0-main+0123abcd", expected: true},
|
||||
{name: "WezTerm", version: "20250601-102030-89abcdef", expected: false},
|
||||
{name: "tmux", version: "3.5a", expected: false},
|
||||
{name: "iTerm2", version: "3.6.4", expected: false},
|
||||
{name: "kitty", version: "", expected: false},
|
||||
{name: "", version: "", expected: false},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name+" "+test.version, func(t *testing.T) {
|
||||
assert.Equal(t, test.expected, TerminalDrawsBranchDrawingSymbols(test.name, test.version))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1224,11 +1224,12 @@
|
||||
"commitGraphStyle": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"auto",
|
||||
"classic",
|
||||
"detailed"
|
||||
],
|
||||
"description": "How the commit graph is drawn.\nOne of: 'classic' (default) | 'detailed'\n'detailed' connects the lines to the commit circles, and shows exactly where branches fork off and merge. It draws the graph with the git branch drawing symbols (U+F5D0 to U+F60D), so it needs a terminal that draws these itself: kitty, Ghostty, WezTerm (nightly builds), Contour, or VS Code's terminal with GPU acceleration. Other terminals need a font that contains them, such as https://github.com/rbong/flog-symbols.",
|
||||
"default": "classic"
|
||||
"description": "How the commit graph is drawn.\nOne of: 'auto' (default) | 'classic' | 'detailed'\n'detailed' connects the lines to the commit circles, and shows exactly where branches fork off and merge. It draws the graph with the git branch drawing symbols (U+F5D0 to U+F60D), so it needs a terminal that draws these itself: kitty, Ghostty, WezTerm (nightly builds), Contour, or VS Code's terminal with GPU acceleration. Other terminals need a font that contains them, such as https://github.com/rbong/flog-symbols.\n'auto' uses 'detailed' if lazygit recognizes the terminal as one that draws these symbols (kitty and Ghostty), and 'classic' otherwise.",
|
||||
"default": "auto"
|
||||
},
|
||||
"commitAuthorShortLength": {
|
||||
"type": "integer",
|
||||
|
||||
@@ -12,6 +12,9 @@ gui:
|
||||
- black
|
||||
# Not important in tests but it creates clutter in demos
|
||||
showRandomTip: false
|
||||
# The expected output of the tests draws the commit graph with box drawing
|
||||
# characters, whichever terminal a test runs in
|
||||
commitGraphStyle: classic
|
||||
animateExplosion: false # takes too long
|
||||
git:
|
||||
# We don't want to run any periodic background git commands because it'll introduce race conditions and flakiness.
|
||||
|
||||
Reference in New Issue
Block a user