Skip to content

Commit

Permalink
Add SpinnerConfig
Browse files Browse the repository at this point in the history
This new config section allows to customize frames and rate of
thespinner
  • Loading branch information
belyakov-am authored and stefanhaller committed Apr 6, 2024
1 parent 53f0c4a commit f3dba74
Show file tree
Hide file tree
Showing 15 changed files with 101 additions and 31 deletions.
3 changes: 3 additions & 0 deletions docs/Config.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ gui:
animateExplosion: true # shows an explosion animation when nuking the working tree
portraitMode: 'auto' # one of 'auto' | 'never' | 'always'
filterMode: 'substring' # one of 'substring' | 'fuzzy'; see 'Filtering' section below
spinner:
frames: ['|', '/', '-', '\\']
rate: 50 # spinner rate in milliseconds
git:
paging:
colorArg: always
Expand Down
13 changes: 13 additions & 0 deletions pkg/config/user_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ type GuiConfig struct {
// How things are filtered when typing '/'.
// One of 'substring' (default) | 'fuzzy'
FilterMode string `yaml:"filterMode" jsonschema:"enum=substring,enum=fuzzy"`
// Config relating to the spinner.
Spinner SpinnerConfig `yaml:"spinner"`
}

func (c *GuiConfig) UseFuzzySearch() bool {
Expand Down Expand Up @@ -182,6 +184,13 @@ type CommitLengthConfig struct {
Show bool `yaml:"show"`
}

type SpinnerConfig struct {
// The frames of the spinner animation.
Frames []string `yaml:"frames"`
// The "speed" of the spinner in milliseconds.
Rate int `yaml:"rate" jsonschema:"minimum=1"`
}

type GitConfig struct {
// See https://github.com/jesseduffield/lazygit/blob/master/docs/Custom_Pagers.md
Paging PagingConfig `yaml:"paging"`
Expand Down Expand Up @@ -671,6 +680,10 @@ func GetDefaultConfig() *UserConfig {
AnimateExplosion: true,
PortraitMode: "auto",
FilterMode: "substring",
Spinner: SpinnerConfig{
Frames: []string{"|", "/", "-", "\\"},
Rate: 50,
},
},
Git: GitConfig{
Paging: PagingConfig{
Expand Down
2 changes: 1 addition & 1 deletion pkg/gui/context/remotes_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func NewRemotesContext(c *ContextCommon) *RemotesContext {

getDisplayStrings := func(_ int, _ int) [][]string {
return presentation.GetRemoteListDisplayStrings(
viewModel.GetItems(), c.Modes().Diffing.Ref, c.State().GetItemOperation, c.Tr)
viewModel.GetItems(), c.Modes().Diffing.Ref, c.State().GetItemOperation, c.Tr, c.UserConfig)
}

return &RemotesContext{
Expand Down
2 changes: 1 addition & 1 deletion pkg/gui/context/tags_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func NewTagsContext(
return presentation.GetTagListDisplayStrings(
viewModel.GetItems(),
c.State().GetItemOperation,
c.Modes().Diffing.Ref, c.Tr)
c.Modes().Diffing.Ref, c.Tr, c.UserConfig)
}

return &TagsContext{
Expand Down
9 changes: 4 additions & 5 deletions pkg/gui/controllers/helpers/app_status_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/status"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
)

type AppStatusHelper struct {
Expand Down Expand Up @@ -88,16 +87,16 @@ func (self *AppStatusHelper) HasStatus() bool {
}

func (self *AppStatusHelper) GetStatusString() string {
appStatus, _ := self.statusMgr().GetStatusString()
appStatus, _ := self.statusMgr().GetStatusString(self.c.UserConfig)
return appStatus
}

func (self *AppStatusHelper) renderAppStatus() {
self.c.OnWorker(func(_ gocui.Task) {
ticker := time.NewTicker(time.Millisecond * utils.LoaderAnimationInterval)
ticker := time.NewTicker(time.Millisecond * time.Duration(self.c.UserConfig.Gui.Spinner.Rate))
defer ticker.Stop()
for range ticker.C {
appStatus, color := self.statusMgr().GetStatusString()
appStatus, color := self.statusMgr().GetStatusString(self.c.UserConfig)
self.c.Views().AppStatus.FgColor = color
self.c.OnUIThread(func() error {
self.c.SetViewContent(self.c.Views().AppStatus, appStatus)
Expand Down Expand Up @@ -130,7 +129,7 @@ func (self *AppStatusHelper) renderAppStatusSync(stop chan struct{}) {
for {
select {
case <-ticker.C:
appStatus, color := self.statusMgr().GetStatusString()
appStatus, color := self.statusMgr().GetStatusString(self.c.UserConfig)
self.c.Views().AppStatus.FgColor = color
self.c.SetViewContent(self.c.Views().AppStatus, appStatus)
// Redraw all views of the bottom line:
Expand Down
2 changes: 1 addition & 1 deletion pkg/gui/controllers/helpers/inline_status_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func (self *InlineStatusHelper) start(opts InlineStatusOpts) {
self.contextsWithInlineStatus[opts.ContextKey] = info

go utils.Safe(func() {
ticker := time.NewTicker(time.Millisecond * utils.LoaderAnimationInterval)
ticker := time.NewTicker(time.Millisecond * time.Duration(self.c.UserConfig.Gui.Spinner.Rate))
defer ticker.Stop()
outer:
for {
Expand Down
2 changes: 1 addition & 1 deletion pkg/gui/controllers/helpers/refresh_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ func (self *RefreshHelper) refreshStatus() {

repoName := self.c.Git().RepoPaths.RepoName()

status := presentation.FormatStatus(repoName, currentBranch, types.ItemOperationNone, linkedWorktreeName, workingTreeState, self.c.Tr)
status := presentation.FormatStatus(repoName, currentBranch, types.ItemOperationNone, linkedWorktreeName, workingTreeState, self.c.Tr, self.c.UserConfig)

self.c.SetViewContent(self.c.Views().Status, status)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/gui/controllers/status_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func (self *StatusController) onClick() error {
}

cx, _ := self.c.Views().Status.Cursor()
upstreamStatus := presentation.BranchStatus(currentBranch, types.ItemOperationNone, self.c.Tr, time.Now())
upstreamStatus := presentation.BranchStatus(currentBranch, types.ItemOperationNone, self.c.Tr, time.Now(), self.c.UserConfig)
repoName := self.c.Git().RepoPaths.RepoName()
workingTreeState := self.c.Git().Status.WorkingTreeState()
switch workingTreeState {
Expand Down
21 changes: 16 additions & 5 deletions pkg/gui/presentation/branches.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func getBranchDisplayStrings(
) []string {
checkedOutByWorkTree := git_commands.CheckedOutByOtherWorktree(b, worktrees)
showCommitHash := fullDescription || userConfig.Gui.ShowBranchCommitHash
branchStatus := BranchStatus(b, itemOperation, tr, now)
branchStatus := BranchStatus(b, itemOperation, tr, now, userConfig)
worktreeIcon := lo.Ternary(icons.IsIconEnabled(), icons.LINKED_WORKTREE_ICON, fmt.Sprintf("(%s)", tr.LcWorktree))

// Recency is always three characters, plus one for the space
Expand Down Expand Up @@ -159,14 +159,25 @@ func branchStatusColor(branch *models.Branch, itemOperation types.ItemOperation)
return colour
}

func ColoredBranchStatus(branch *models.Branch, itemOperation types.ItemOperation, tr *i18n.TranslationSet) string {
return branchStatusColor(branch, itemOperation).Sprint(BranchStatus(branch, itemOperation, tr, time.Now()))
func ColoredBranchStatus(
branch *models.Branch,
itemOperation types.ItemOperation,
tr *i18n.TranslationSet,
userConfig *config.UserConfig,
) string {
return branchStatusColor(branch, itemOperation).Sprint(BranchStatus(branch, itemOperation, tr, time.Now(), userConfig))
}

func BranchStatus(branch *models.Branch, itemOperation types.ItemOperation, tr *i18n.TranslationSet, now time.Time) string {
func BranchStatus(
branch *models.Branch,
itemOperation types.ItemOperation,
tr *i18n.TranslationSet,
now time.Time,
userConfig *config.UserConfig,
) string {
itemOperationStr := ItemOperationToString(itemOperation, tr)
if itemOperationStr != "" {
return itemOperationStr + " " + utils.Loader(now)
return itemOperationStr + " " + utils.Loader(now, userConfig.Gui.Spinner)
}

if !branch.IsTrackingRemote() {
Expand Down
7 changes: 5 additions & 2 deletions pkg/gui/presentation/remotes.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"time"

"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gui/presentation/icons"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
Expand All @@ -18,10 +19,11 @@ func GetRemoteListDisplayStrings(
diffName string,
getItemOperation func(item types.HasUrn) types.ItemOperation,
tr *i18n.TranslationSet,
userConfig *config.UserConfig,
) [][]string {
return lo.Map(remotes, func(remote *models.Remote, _ int) []string {
diffed := remote.Name == diffName
return getRemoteDisplayStrings(remote, diffed, getItemOperation(remote), tr)
return getRemoteDisplayStrings(remote, diffed, getItemOperation(remote), tr, userConfig)
})
}

Expand All @@ -31,6 +33,7 @@ func getRemoteDisplayStrings(
diffed bool,
itemOperation types.ItemOperation,
tr *i18n.TranslationSet,
userConfig *config.UserConfig,
) []string {
branchCount := len(r.Branches)

Expand All @@ -46,7 +49,7 @@ func getRemoteDisplayStrings(
descriptionStr := style.FgBlue.Sprintf("%d branches", branchCount)
itemOperationStr := ItemOperationToString(itemOperation, tr)
if itemOperationStr != "" {
descriptionStr += " " + style.FgCyan.Sprint(itemOperationStr+" "+utils.Loader(time.Now()))
descriptionStr += " " + style.FgCyan.Sprint(itemOperationStr+" "+utils.Loader(time.Now(), userConfig.Gui.Spinner))
}
res = append(res, textStyle.Sprint(r.Name), descriptionStr)
return res
Expand Down
13 changes: 11 additions & 2 deletions pkg/gui/presentation/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,26 @@ import (

"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gui/presentation/icons"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/i18n"
)

func FormatStatus(repoName string, currentBranch *models.Branch, itemOperation types.ItemOperation, linkedWorktreeName string, workingTreeState enums.RebaseMode, tr *i18n.TranslationSet) string {
func FormatStatus(
repoName string,
currentBranch *models.Branch,
itemOperation types.ItemOperation,
linkedWorktreeName string,
workingTreeState enums.RebaseMode,
tr *i18n.TranslationSet,
userConfig *config.UserConfig,
) string {
status := ""

if currentBranch.IsRealBranch() {
status += ColoredBranchStatus(currentBranch, itemOperation, tr) + " "
status += ColoredBranchStatus(currentBranch, itemOperation, tr, userConfig) + " "
}

if workingTreeState != enums.REBASE_MODE_NONE {
Expand Down
14 changes: 11 additions & 3 deletions pkg/gui/presentation/tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"time"

"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gui/presentation/icons"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
Expand All @@ -18,15 +19,22 @@ func GetTagListDisplayStrings(
getItemOperation func(item types.HasUrn) types.ItemOperation,
diffName string,
tr *i18n.TranslationSet,
userConfig *config.UserConfig,
) [][]string {
return lo.Map(tags, func(tag *models.Tag, _ int) []string {
diffed := tag.Name == diffName
return getTagDisplayStrings(tag, getItemOperation(tag), diffed, tr)
return getTagDisplayStrings(tag, getItemOperation(tag), diffed, tr, userConfig)
})
}

// getTagDisplayStrings returns the display string of branch
func getTagDisplayStrings(t *models.Tag, itemOperation types.ItemOperation, diffed bool, tr *i18n.TranslationSet) []string {
func getTagDisplayStrings(
t *models.Tag,
itemOperation types.ItemOperation,
diffed bool,
tr *i18n.TranslationSet,
userConfig *config.UserConfig,
) []string {
textStyle := theme.DefaultTextColor
if diffed {
textStyle = theme.DiffTerminalColor
Expand All @@ -39,7 +47,7 @@ func getTagDisplayStrings(t *models.Tag, itemOperation types.ItemOperation, diff
descriptionStr := descriptionColor.Sprint(t.Description())
itemOperationStr := ItemOperationToString(itemOperation, tr)
if itemOperationStr != "" {
descriptionStr = style.FgCyan.Sprint(itemOperationStr+" "+utils.Loader(time.Now())) + " " + descriptionStr
descriptionStr = style.FgCyan.Sprint(itemOperationStr+" "+utils.Loader(time.Now(), userConfig.Gui.Spinner)) + " " + descriptionStr
}
res = append(res, textStyle.Sprint(t.Name), descriptionStr)
return res
Expand Down
5 changes: 3 additions & 2 deletions pkg/gui/status/status_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"time"

"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
Expand Down Expand Up @@ -69,13 +70,13 @@ func (self *StatusManager) AddToastStatus(message string, kind types.ToastKind)
return id
}

func (self *StatusManager) GetStatusString() (string, gocui.Attribute) {
func (self *StatusManager) GetStatusString(userConfig *config.UserConfig) (string, gocui.Attribute) {
if len(self.statuses) == 0 {
return "", gocui.ColorDefault
}
topStatus := self.statuses[0]
if topStatus.statusType == "waiting" {
return topStatus.message + " " + utils.Loader(time.Now()), topStatus.color
return topStatus.message + " " + utils.Loader(time.Now(), userConfig.Gui.Spinner), topStatus.color
}
return topStatus.message, topStatus.color
}
Expand Down
11 changes: 4 additions & 7 deletions pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"time"

"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/config"
)

// GetProjectRoot returns the path to the root of the project. Only to be used
Expand All @@ -24,15 +25,11 @@ func GetProjectRoot() string {
return strings.Split(dir, "lazygit")[0] + "lazygit"
}

// The duration between two frames of the loader animation in milliseconds
const LoaderAnimationInterval = 50

// Loader dumps a string to be displayed as a loader
func Loader(now time.Time) string {
characters := "|/-\\"
func Loader(now time.Time, config config.SpinnerConfig) string {
milliseconds := now.UnixMilli()
index := milliseconds / LoaderAnimationInterval % int64(len(characters))
return characters[index : index+1]
index := milliseconds / int64(config.Rate) % int64(len(config.Frames))
return config.Frames[index]
}

// Min returns the minimum of two integers
Expand Down
26 changes: 26 additions & 0 deletions schema/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,32 @@
],
"description": "How things are filtered when typing '/'.\nOne of 'substring' (default) | 'fuzzy'",
"default": "substring"
},
"spinner": {
"properties": {
"frames": {
"items": {
"type": "string"
},
"type": "array",
"description": "The frames of the spinner animation.",
"default": [
"|",
"/",
"-",
"\\"
]
},
"rate": {
"type": "integer",
"minimum": 1,
"description": "The \"speed\" of the spinner in milliseconds.",
"default": 50
}
},
"additionalProperties": false,
"type": "object",
"description": "Config relating to the spinner."
}
},
"additionalProperties": false,
Expand Down

0 comments on commit f3dba74

Please sign in to comment.