mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-10 07:36:27 -04:00
feat: add per-file-status theme colors for the files panel
Add configurable colors for each git file status character (modified,
deleted, untracked, added, renamed, copied) in the theme config. Each
color falls back to unstagedChangesColor when not set, preserving
existing behavior.
New theme config keys:
- modifiedColor: color for modified files (M)
- deletedColor: color for deleted files (D)
- untrackedColor: color for untracked files (?)
- addedColor: color for added/staged new files (A)
- renamedColor: color for renamed files (R)
- copiedColor: color for copied files (C)
Example config:
gui:
theme:
modifiedColor:
- '#e0af68'
deletedColor:
- '#f7768e'
untrackedColor:
- '#9ece6a'
This commit is contained in:
parent
4c2c0ce32d
commit
aca5b7516e
|
|
@ -233,8 +233,20 @@ type ThemeConfig struct {
|
|||
MarkedBaseCommitFgColor []string `yaml:"markedBaseCommitFgColor"`
|
||||
// Background color of marked base commit (for rebase)
|
||||
MarkedBaseCommitBgColor []string `yaml:"markedBaseCommitBgColor"`
|
||||
// Color for file with unstaged changes
|
||||
// Color for file with unstaged changes (used as fallback when per-status colors are not set)
|
||||
UnstagedChangesColor []string `yaml:"unstagedChangesColor" jsonschema:"minItems=1,uniqueItems=true"`
|
||||
// Color for modified files. Defaults to unstagedChangesColor if empty.
|
||||
ModifiedColor []string `yaml:"modifiedColor"`
|
||||
// Color for deleted files. Defaults to unstagedChangesColor if empty.
|
||||
DeletedColor []string `yaml:"deletedColor"`
|
||||
// Color for untracked (new) files. Defaults to unstagedChangesColor if empty.
|
||||
UntrackedColor []string `yaml:"untrackedColor"`
|
||||
// Color for added (staged new) files. Defaults to green if empty.
|
||||
AddedColor []string `yaml:"addedColor"`
|
||||
// Color for renamed files. Defaults to unstagedChangesColor if empty.
|
||||
RenamedColor []string `yaml:"renamedColor"`
|
||||
// Color for copied files. Defaults to cyan if empty.
|
||||
CopiedColor []string `yaml:"copiedColor"`
|
||||
// Default text color
|
||||
DefaultFgColor []string `yaml:"defaultFgColor" jsonschema:"minItems=1,uniqueItems=true"`
|
||||
}
|
||||
|
|
@ -796,6 +808,12 @@ func GetDefaultConfig() *UserConfig {
|
|||
MarkedBaseCommitBgColor: []string{"yellow"},
|
||||
MarkedBaseCommitFgColor: []string{"blue"},
|
||||
UnstagedChangesColor: []string{"red"},
|
||||
ModifiedColor: []string{},
|
||||
DeletedColor: []string{},
|
||||
UntrackedColor: []string{},
|
||||
AddedColor: []string{},
|
||||
RenamedColor: []string{},
|
||||
CopiedColor: []string{},
|
||||
DefaultFgColor: []string{"default"},
|
||||
},
|
||||
CommitLength: CommitLengthConfig{Show: true},
|
||||
|
|
|
|||
|
|
@ -183,23 +183,46 @@ func getFileLine(
|
|||
|
||||
func formatFileStatus(file *models.File, restColor style.TextStyle) string {
|
||||
firstChar := file.ShortStatus[0:1]
|
||||
firstCharCl := style.FgGreen
|
||||
switch firstChar {
|
||||
case "?":
|
||||
firstCharCl = theme.UnstagedChangesColor
|
||||
case " ":
|
||||
firstCharCl := colorForStatusChar(firstChar, true)
|
||||
if firstCharCl == (style.TextStyle{}) {
|
||||
firstCharCl = restColor
|
||||
}
|
||||
|
||||
secondChar := file.ShortStatus[1:2]
|
||||
secondCharCl := theme.UnstagedChangesColor
|
||||
if secondChar == " " {
|
||||
secondCharCl := colorForStatusChar(secondChar, false)
|
||||
if secondCharCl == (style.TextStyle{}) {
|
||||
secondCharCl = restColor
|
||||
}
|
||||
|
||||
return firstCharCl.Sprint(firstChar) + secondCharCl.Sprint(secondChar)
|
||||
}
|
||||
|
||||
// colorForStatusChar returns the color for a single status character from git short status.
|
||||
// isStagedColumn indicates whether this is the first (index/staged) or second (worktree) column.
|
||||
func colorForStatusChar(ch string, isStagedColumn bool) style.TextStyle {
|
||||
switch ch {
|
||||
case "M":
|
||||
return theme.ModifiedColor
|
||||
case "D":
|
||||
return theme.DeletedColor
|
||||
case "?":
|
||||
return theme.UntrackedColor
|
||||
case "A":
|
||||
return theme.AddedColor
|
||||
case "R":
|
||||
return theme.RenamedColor
|
||||
case "C":
|
||||
return theme.CopiedColor
|
||||
case "T":
|
||||
return theme.ModifiedColor
|
||||
case " ":
|
||||
// space means no change in this column — use rest/name color (caller handles this)
|
||||
return style.TextStyle{}
|
||||
default:
|
||||
return theme.UnstagedChangesColor
|
||||
}
|
||||
}
|
||||
|
||||
func formatLineChanges(linesAdded, linesDeleted int) string {
|
||||
output := ""
|
||||
|
||||
|
|
@ -285,15 +308,17 @@ func getCommitFileLine(
|
|||
func getColorForChangeStatus(changeStatus string) style.TextStyle {
|
||||
switch changeStatus {
|
||||
case "A":
|
||||
return style.FgGreen
|
||||
case "M", "R":
|
||||
return style.FgYellow
|
||||
return theme.AddedColor
|
||||
case "M":
|
||||
return theme.ModifiedColor
|
||||
case "R":
|
||||
return theme.RenamedColor
|
||||
case "D":
|
||||
return theme.UnstagedChangesColor
|
||||
return theme.DeletedColor
|
||||
case "C":
|
||||
return style.FgCyan
|
||||
return theme.CopiedColor
|
||||
case "T":
|
||||
return style.FgMagenta
|
||||
return theme.ModifiedColor
|
||||
default:
|
||||
return theme.DefaultTextColor
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,13 @@ var (
|
|||
DiffTerminalColor = style.FgMagenta
|
||||
|
||||
UnstagedChangesColor = style.New()
|
||||
|
||||
ModifiedColor = style.New()
|
||||
DeletedColor = style.New()
|
||||
UntrackedColor = style.New()
|
||||
AddedColor = style.New()
|
||||
RenamedColor = style.New()
|
||||
CopiedColor = style.New()
|
||||
)
|
||||
|
||||
// UpdateTheme updates all theme variables
|
||||
|
|
@ -66,6 +73,38 @@ func UpdateTheme(themeConfig config.ThemeConfig) {
|
|||
unstagedChangesTextStyle := GetTextStyle(themeConfig.UnstagedChangesColor, false)
|
||||
UnstagedChangesColor = unstagedChangesTextStyle
|
||||
|
||||
// Per-status colors — fall back to UnstagedChangesColor or hardcoded defaults if not set
|
||||
if len(themeConfig.ModifiedColor) > 0 {
|
||||
ModifiedColor = GetTextStyle(themeConfig.ModifiedColor, false)
|
||||
} else {
|
||||
ModifiedColor = UnstagedChangesColor
|
||||
}
|
||||
if len(themeConfig.DeletedColor) > 0 {
|
||||
DeletedColor = GetTextStyle(themeConfig.DeletedColor, false)
|
||||
} else {
|
||||
DeletedColor = UnstagedChangesColor
|
||||
}
|
||||
if len(themeConfig.UntrackedColor) > 0 {
|
||||
UntrackedColor = GetTextStyle(themeConfig.UntrackedColor, false)
|
||||
} else {
|
||||
UntrackedColor = UnstagedChangesColor
|
||||
}
|
||||
if len(themeConfig.AddedColor) > 0 {
|
||||
AddedColor = GetTextStyle(themeConfig.AddedColor, false)
|
||||
} else {
|
||||
AddedColor = style.FgGreen
|
||||
}
|
||||
if len(themeConfig.RenamedColor) > 0 {
|
||||
RenamedColor = GetTextStyle(themeConfig.RenamedColor, false)
|
||||
} else {
|
||||
RenamedColor = UnstagedChangesColor
|
||||
}
|
||||
if len(themeConfig.CopiedColor) > 0 {
|
||||
CopiedColor = GetTextStyle(themeConfig.CopiedColor, false)
|
||||
} else {
|
||||
CopiedColor = style.FgCyan
|
||||
}
|
||||
|
||||
GocuiSelectedLineBgColor = GetGocuiStyle(themeConfig.SelectedLineBgColor)
|
||||
GocuiInactiveViewSelectedLineBgColor = GetGocuiStyle(themeConfig.InactiveViewSelectedLineBgColor)
|
||||
OptionsColor = GetGocuiStyle(themeConfig.OptionsTextColor)
|
||||
|
|
|
|||
Loading…
Reference in a new issue