1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
package gui
import (
"fmt"
"strings"
"github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/theme"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
)
type OptionsMapMgr struct {
c *helpers.HelperCommon
}
func (gui *Gui) renderContextOptionsMap() {
// In demos, we render our own content to this view
if gui.integrationTest != nil && gui.integrationTest.IsDemo() {
return
}
mgr := OptionsMapMgr{c: gui.c}
mgr.renderContextOptionsMap()
}
// Render the options available for the current context at the bottom of the screen
// STYLE GUIDE: we use the default options fg color for most keybindings. We can
// only use a different color if we're in a specific mode where the user is likely
// to want to press that key. For example, when in cherry-picking mode, we
// want to prominently show the keybinding for pasting commits.
func (self *OptionsMapMgr) renderContextOptionsMap() {
currentContext := self.c.Context().Current()
currentContextBindings := currentContext.GetKeybindings(self.c.KeybindingsOpts())
globalBindings := self.c.Contexts().Global.GetKeybindings(self.c.KeybindingsOpts())
allBindings := append(currentContextBindings, globalBindings...)
bindingsToDisplay := lo.Filter(allBindings, func(binding *types.Binding, _ int) bool {
return binding.DisplayOnScreen && !binding.IsDisabled()
})
optionsMap := lo.Map(bindingsToDisplay, func(binding *types.Binding, _ int) bindingInfo {
displayStyle := theme.OptionsFgColor
if binding.DisplayStyle != nil {
displayStyle = *binding.DisplayStyle
}
description := binding.Description
if binding.ShortDescription != "" {
description = binding.ShortDescription
}
return bindingInfo{
key: keybindings.LabelFromKey(binding.Key),
description: description,
style: displayStyle,
}
})
// Mode-specific local keybindings
if currentContext.GetKey() == context.LOCAL_COMMITS_CONTEXT_KEY {
if self.c.Modes().CherryPicking.Active() {
optionsMap = utils.Prepend(optionsMap, bindingInfo{
key: keybindings.Label(self.c.KeybindingsOpts().Config.Commits.PasteCommits),
description: self.c.Tr.PasteCommits,
style: style.FgCyan,
})
}
if self.c.Model().BisectInfo.Started() {
optionsMap = utils.Prepend(optionsMap, bindingInfo{
key: keybindings.Label(self.c.KeybindingsOpts().Config.Commits.ViewBisectOptions),
description: self.c.Tr.ViewBisectOptions,
style: style.FgGreen,
})
}
}
// Mode-specific global keybindings
if state := self.c.Model().WorkingTreeStateAtLastCommitRefresh; state.Any() {
optionsMap = utils.Prepend(optionsMap, bindingInfo{
key: keybindings.Label(self.c.KeybindingsOpts().Config.Universal.CreateRebaseOptionsMenu),
description: state.OptionsMapTitle(self.c.Tr),
style: style.FgYellow,
})
}
if self.c.Git().Patch.PatchBuilder.Active() {
optionsMap = utils.Prepend(optionsMap, bindingInfo{
key: keybindings.Label(self.c.KeybindingsOpts().Config.Universal.CreatePatchOptionsMenu),
description: self.c.Tr.ViewPatchOptions,
style: style.FgYellow,
})
}
self.renderOptions(self.formatBindingInfos(optionsMap))
}
func (self *OptionsMapMgr) formatBindingInfos(bindingInfos []bindingInfo) string {
width := self.c.Views().Options.InnerWidth() - 2 // -2 for some padding
var builder strings.Builder
ellipsis := "…"
separator := " | "
length := 0
for i, info := range bindingInfos {
plainText := fmt.Sprintf("%s: %s", info.description, info.key)
// Check if adding the next formatted string exceeds the available width
textLen := utils.StringWidth(plainText)
if i > 0 && length+len(separator)+textLen > width {
builder.WriteString(theme.OptionsFgColor.Sprint(separator + ellipsis))
break
}
formatted := info.style.Sprintf(plainText)
if i > 0 {
builder.WriteString(theme.OptionsFgColor.Sprint(separator))
length += len(separator)
}
builder.WriteString(formatted)
length += textLen
}
return builder.String()
}
func (self *OptionsMapMgr) renderOptions(options string) {
self.c.SetViewContent(self.c.Views().Options, options)
}
type bindingInfo struct {
key string
description string
style style.TextStyle
}
|