mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-02-09 13:47:11 +02:00
lots more refactoring
This commit is contained in:
parent
8edad826ca
commit
509e3efa70
@ -1,38 +0,0 @@
|
|||||||
package gui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/jesseduffield/gocui"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (gui *Gui) handleCommitMessageFocused() error {
|
|
||||||
message := utils.ResolvePlaceholderString(
|
|
||||||
gui.c.Tr.CommitMessageConfirm,
|
|
||||||
map[string]string{
|
|
||||||
"keyBindClose": keybindings.Label(gui.c.UserConfig.Keybinding.Universal.Return),
|
|
||||||
"keyBindConfirm": keybindings.Label(gui.c.UserConfig.Keybinding.Universal.Confirm),
|
|
||||||
"keyBindNewLine": keybindings.Label(gui.c.UserConfig.Keybinding.Universal.AppendNewline),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
gui.RenderCommitLength()
|
|
||||||
|
|
||||||
gui.c.SetViewContent(gui.Views.Options, message)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) RenderCommitLength() {
|
|
||||||
if !gui.c.UserConfig.Gui.CommitLength.Show {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
gui.Views.CommitMessage.Subtitle = getBufferLength(gui.Views.CommitMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getBufferLength(view *gocui.View) string {
|
|
||||||
return " " + strconv.Itoa(strings.Count(view.TextArea.GetContent(), "")-1) + " "
|
|
||||||
}
|
|
@ -1,316 +0,0 @@
|
|||||||
package gui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/jesseduffield/gocui"
|
|
||||||
"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/mattn/go-runewidth"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This file is for the rendering of confirmation panels along with setting and handling associated
|
|
||||||
// keybindings.
|
|
||||||
|
|
||||||
func (gui *Gui) wrappedConfirmationFunction(cancel context.CancelFunc, function func() error) func() error {
|
|
||||||
return func() error {
|
|
||||||
cancel()
|
|
||||||
|
|
||||||
if err := gui.c.PopContext(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if function != nil {
|
|
||||||
if err := function(); err != nil {
|
|
||||||
return gui.c.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) wrappedPromptConfirmationFunction(cancel context.CancelFunc, function func(string) error, getResponse func() string) func() error {
|
|
||||||
return func() error {
|
|
||||||
cancel()
|
|
||||||
|
|
||||||
if err := gui.c.PopContext(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if function != nil {
|
|
||||||
if err := function(getResponse()); err != nil {
|
|
||||||
return gui.c.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) deactivateConfirmationPrompt() {
|
|
||||||
gui.Mutexes.PopupMutex.Lock()
|
|
||||||
gui.State.CurrentPopupOpts = nil
|
|
||||||
gui.Mutexes.PopupMutex.Unlock()
|
|
||||||
|
|
||||||
gui.Views.Confirmation.Visible = false
|
|
||||||
gui.Views.Suggestions.Visible = false
|
|
||||||
|
|
||||||
gui.clearConfirmationViewKeyBindings()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getMessageHeight(wrap bool, message string, width int) int {
|
|
||||||
lines := strings.Split(message, "\n")
|
|
||||||
lineCount := 0
|
|
||||||
// if we need to wrap, calculate height to fit content within view's width
|
|
||||||
if wrap {
|
|
||||||
for _, line := range lines {
|
|
||||||
lineCount += runewidth.StringWidth(line)/width + 1
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lineCount = len(lines)
|
|
||||||
}
|
|
||||||
return lineCount
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getConfirmationPanelDimensions(wrap bool, prompt string) (int, int, int, int) {
|
|
||||||
panelWidth := gui.getConfirmationPanelWidth()
|
|
||||||
panelHeight := gui.getMessageHeight(wrap, prompt, panelWidth)
|
|
||||||
return gui.getConfirmationPanelDimensionsAux(panelWidth, panelHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getConfirmationPanelDimensionsForContentHeight(panelWidth, contentHeight int) (int, int, int, int) {
|
|
||||||
return gui.getConfirmationPanelDimensionsAux(panelWidth, contentHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getConfirmationPanelDimensionsAux(panelWidth int, panelHeight int) (int, int, int, int) {
|
|
||||||
width, height := gui.g.Size()
|
|
||||||
if panelHeight > height*3/4 {
|
|
||||||
panelHeight = height * 3 / 4
|
|
||||||
}
|
|
||||||
return width/2 - panelWidth/2,
|
|
||||||
height/2 - panelHeight/2 - panelHeight%2 - 1,
|
|
||||||
width/2 + panelWidth/2,
|
|
||||||
height/2 + panelHeight/2
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getConfirmationPanelWidth() int {
|
|
||||||
width, _ := gui.g.Size()
|
|
||||||
// we want a minimum width up to a point, then we do it based on ratio.
|
|
||||||
panelWidth := 4 * width / 7
|
|
||||||
minWidth := 80
|
|
||||||
if panelWidth < minWidth {
|
|
||||||
if width-2 < minWidth {
|
|
||||||
panelWidth = width - 2
|
|
||||||
} else {
|
|
||||||
panelWidth = minWidth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return panelWidth
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) prepareConfirmationPanel(
|
|
||||||
ctx context.Context,
|
|
||||||
opts types.ConfirmOpts,
|
|
||||||
) error {
|
|
||||||
gui.Views.Confirmation.HasLoader = opts.HasLoader
|
|
||||||
if opts.HasLoader {
|
|
||||||
gui.g.StartTicking(ctx)
|
|
||||||
}
|
|
||||||
gui.Views.Confirmation.Title = opts.Title
|
|
||||||
// for now we do not support wrapping in our editor
|
|
||||||
gui.Views.Confirmation.Wrap = !opts.Editable
|
|
||||||
gui.Views.Confirmation.FgColor = theme.GocuiDefaultTextColor
|
|
||||||
gui.Views.Confirmation.Mask = runeForMask(opts.Mask)
|
|
||||||
_ = gui.Views.Confirmation.SetOrigin(0, 0)
|
|
||||||
|
|
||||||
gui.findSuggestions = opts.FindSuggestionsFunc
|
|
||||||
if opts.FindSuggestionsFunc != nil {
|
|
||||||
suggestionsView := gui.Views.Suggestions
|
|
||||||
suggestionsView.Wrap = false
|
|
||||||
suggestionsView.FgColor = theme.GocuiDefaultTextColor
|
|
||||||
gui.setSuggestions(opts.FindSuggestionsFunc(""))
|
|
||||||
suggestionsView.Visible = true
|
|
||||||
suggestionsView.Title = fmt.Sprintf(gui.c.Tr.SuggestionsTitle, gui.c.UserConfig.Keybinding.Universal.TogglePanel)
|
|
||||||
}
|
|
||||||
|
|
||||||
gui.resizeConfirmationPanel()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func runeForMask(mask bool) rune {
|
|
||||||
if mask {
|
|
||||||
return '*'
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) createPopupPanel(ctx context.Context, opts types.CreatePopupPanelOpts) error {
|
|
||||||
gui.Mutexes.PopupMutex.Lock()
|
|
||||||
defer gui.Mutexes.PopupMutex.Unlock()
|
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
|
||||||
|
|
||||||
// we don't allow interruptions of non-loader popups in case we get stuck somehow
|
|
||||||
// e.g. a credentials popup never gets its required user input so a process hangs
|
|
||||||
// forever.
|
|
||||||
// The proper solution is to have a queue of popup options
|
|
||||||
if gui.State.CurrentPopupOpts != nil && !gui.State.CurrentPopupOpts.HasLoader {
|
|
||||||
gui.Log.Error("ignoring create popup panel because a popup panel is already open")
|
|
||||||
cancel()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove any previous keybindings
|
|
||||||
gui.clearConfirmationViewKeyBindings()
|
|
||||||
|
|
||||||
err := gui.prepareConfirmationPanel(
|
|
||||||
ctx,
|
|
||||||
types.ConfirmOpts{
|
|
||||||
Title: opts.Title,
|
|
||||||
Prompt: opts.Prompt,
|
|
||||||
HasLoader: opts.HasLoader,
|
|
||||||
FindSuggestionsFunc: opts.FindSuggestionsFunc,
|
|
||||||
Editable: opts.Editable,
|
|
||||||
Mask: opts.Mask,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
cancel()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
confirmationView := gui.Views.Confirmation
|
|
||||||
confirmationView.Editable = opts.Editable
|
|
||||||
confirmationView.Editor = gocui.EditorFunc(gui.defaultEditor)
|
|
||||||
|
|
||||||
if opts.Editable {
|
|
||||||
textArea := confirmationView.TextArea
|
|
||||||
textArea.Clear()
|
|
||||||
textArea.TypeString(opts.Prompt)
|
|
||||||
gui.resizeConfirmationPanel()
|
|
||||||
confirmationView.RenderTextArea()
|
|
||||||
} else {
|
|
||||||
gui.c.ResetViewOrigin(confirmationView)
|
|
||||||
gui.c.SetViewContent(confirmationView, style.AttrBold.Sprint(opts.Prompt))
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := gui.setKeyBindings(cancel, opts); err != nil {
|
|
||||||
cancel()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
gui.State.CurrentPopupOpts = &opts
|
|
||||||
|
|
||||||
return gui.c.PushContext(gui.State.Contexts.Confirmation)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) setKeyBindings(cancel context.CancelFunc, opts types.CreatePopupPanelOpts) error {
|
|
||||||
actions := utils.ResolvePlaceholderString(
|
|
||||||
gui.c.Tr.CloseConfirm,
|
|
||||||
map[string]string{
|
|
||||||
"keyBindClose": "esc",
|
|
||||||
"keyBindConfirm": "enter",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
gui.c.SetViewContent(gui.Views.Options, actions)
|
|
||||||
var onConfirm func() error
|
|
||||||
if opts.HandleConfirmPrompt != nil {
|
|
||||||
onConfirm = gui.wrappedPromptConfirmationFunction(cancel, opts.HandleConfirmPrompt, func() string { return gui.Views.Confirmation.TextArea.GetContent() })
|
|
||||||
} else {
|
|
||||||
onConfirm = gui.wrappedConfirmationFunction(cancel, opts.HandleConfirm)
|
|
||||||
}
|
|
||||||
|
|
||||||
keybindingConfig := gui.c.UserConfig.Keybinding
|
|
||||||
onSuggestionConfirm := gui.wrappedPromptConfirmationFunction(
|
|
||||||
cancel,
|
|
||||||
opts.HandleConfirmPrompt,
|
|
||||||
gui.getSelectedSuggestionValue,
|
|
||||||
)
|
|
||||||
|
|
||||||
bindings := []*types.Binding{
|
|
||||||
{
|
|
||||||
ViewName: "confirmation",
|
|
||||||
Key: keybindings.GetKey(keybindingConfig.Universal.Confirm),
|
|
||||||
Handler: onConfirm,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ViewName: "confirmation",
|
|
||||||
Key: keybindings.GetKey(keybindingConfig.Universal.Return),
|
|
||||||
Handler: gui.wrappedConfirmationFunction(cancel, opts.HandleClose),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ViewName: "confirmation",
|
|
||||||
Key: keybindings.GetKey(keybindingConfig.Universal.TogglePanel),
|
|
||||||
Handler: func() error {
|
|
||||||
if len(gui.State.Suggestions) > 0 {
|
|
||||||
return gui.c.ReplaceContext(gui.State.Contexts.Suggestions)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ViewName: "suggestions",
|
|
||||||
Key: keybindings.GetKey(keybindingConfig.Universal.Confirm),
|
|
||||||
Handler: onSuggestionConfirm,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ViewName: "suggestions",
|
|
||||||
Key: keybindings.GetKey(keybindingConfig.Universal.Return),
|
|
||||||
Handler: gui.wrappedConfirmationFunction(cancel, opts.HandleClose),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ViewName: "suggestions",
|
|
||||||
Key: keybindings.GetKey(keybindingConfig.Universal.TogglePanel),
|
|
||||||
Handler: func() error { return gui.c.ReplaceContext(gui.State.Contexts.Confirmation) },
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, binding := range bindings {
|
|
||||||
if err := gui.SetKeybinding(binding); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) clearConfirmationViewKeyBindings() {
|
|
||||||
keybindingConfig := gui.c.UserConfig.Keybinding
|
|
||||||
_ = gui.g.DeleteKeybinding("confirmation", keybindings.GetKey(keybindingConfig.Universal.Confirm), gocui.ModNone)
|
|
||||||
_ = gui.g.DeleteKeybinding("confirmation", keybindings.GetKey(keybindingConfig.Universal.Return), gocui.ModNone)
|
|
||||||
_ = gui.g.DeleteKeybinding("suggestions", keybindings.GetKey(keybindingConfig.Universal.Confirm), gocui.ModNone)
|
|
||||||
_ = gui.g.DeleteKeybinding("suggestions", keybindings.GetKey(keybindingConfig.Universal.Return), gocui.ModNone)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) refreshSuggestions() {
|
|
||||||
gui.suggestionsAsyncHandler.Do(func() func() {
|
|
||||||
findSuggestionsFn := gui.findSuggestions
|
|
||||||
if findSuggestionsFn != nil {
|
|
||||||
suggestions := gui.findSuggestions(gui.c.GetPromptInput())
|
|
||||||
return func() { gui.setSuggestions(suggestions) }
|
|
||||||
} else {
|
|
||||||
return func() {}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) handleAskFocused() error {
|
|
||||||
keybindingConfig := gui.c.UserConfig.Keybinding
|
|
||||||
|
|
||||||
message := utils.ResolvePlaceholderString(
|
|
||||||
gui.c.Tr.CloseConfirm,
|
|
||||||
map[string]string{
|
|
||||||
"keyBindClose": keybindings.Label(keybindingConfig.Universal.Return),
|
|
||||||
"keyBindConfirm": keybindings.Label(keybindingConfig.Universal.Confirm),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
gui.c.SetViewContent(gui.Views.Options, message)
|
|
||||||
return nil
|
|
||||||
}
|
|
47
pkg/gui/context/commit_message_context.go
Normal file
47
pkg/gui/context/commit_message_context.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package context
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/gocui"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CommitMessageContext struct {
|
||||||
|
*SimpleContext
|
||||||
|
c *types.HelperCommon
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ types.Context = (*CommitMessageContext)(nil)
|
||||||
|
|
||||||
|
func NewCommitMessageContext(
|
||||||
|
c *types.HelperCommon,
|
||||||
|
) *CommitMessageContext {
|
||||||
|
return &CommitMessageContext{
|
||||||
|
c: c,
|
||||||
|
SimpleContext: NewSimpleContext(
|
||||||
|
NewBaseContext(NewBaseContextOpts{
|
||||||
|
Kind: types.PERSISTENT_POPUP,
|
||||||
|
View: c.Views().CommitMessage,
|
||||||
|
WindowName: "commitMessage",
|
||||||
|
Key: COMMIT_MESSAGE_CONTEXT_KEY,
|
||||||
|
Focusable: true,
|
||||||
|
HasUncontrolledBounds: true,
|
||||||
|
}),
|
||||||
|
ContextCallbackOpts{},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessageContext) RenderCommitLength() {
|
||||||
|
if !self.c.UserConfig.Gui.CommitLength.Show {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.c.Views().CommitMessage.Subtitle = getBufferLength(self.c.Views().CommitMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBufferLength(view *gocui.View) string {
|
||||||
|
return " " + strconv.Itoa(strings.Count(view.TextArea.GetContent(), "")-1) + " "
|
||||||
|
}
|
35
pkg/gui/context/confirmation_context.go
Normal file
35
pkg/gui/context/confirmation_context.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package context
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConfirmationContext struct {
|
||||||
|
*SimpleContext
|
||||||
|
c *types.HelperCommon
|
||||||
|
|
||||||
|
State ConfirmationContextState
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConfirmationContextState struct {
|
||||||
|
OnConfirm func() error
|
||||||
|
OnClose func() error
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ types.Context = (*ConfirmationContext)(nil)
|
||||||
|
|
||||||
|
func NewConfirmationContext(
|
||||||
|
c *types.HelperCommon,
|
||||||
|
) *ConfirmationContext {
|
||||||
|
return &ConfirmationContext{
|
||||||
|
c: c,
|
||||||
|
SimpleContext: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||||
|
View: c.Views().Confirmation,
|
||||||
|
WindowName: "confirmation",
|
||||||
|
Key: CONFIRMATION_CONTEXT_KEY,
|
||||||
|
Kind: types.TEMPORARY_POPUP,
|
||||||
|
Focusable: true,
|
||||||
|
HasUncontrolledBounds: true,
|
||||||
|
}), ContextCallbackOpts{}),
|
||||||
|
}
|
||||||
|
}
|
@ -96,8 +96,8 @@ type ContextTree struct {
|
|||||||
CustomPatchBuilder *PatchExplorerContext
|
CustomPatchBuilder *PatchExplorerContext
|
||||||
CustomPatchBuilderSecondary types.Context
|
CustomPatchBuilderSecondary types.Context
|
||||||
MergeConflicts *MergeConflictsContext
|
MergeConflicts *MergeConflictsContext
|
||||||
Confirmation types.Context
|
Confirmation *ConfirmationContext
|
||||||
CommitMessage types.Context
|
CommitMessage *CommitMessageContext
|
||||||
CommandLog types.Context
|
CommandLog types.Context
|
||||||
|
|
||||||
// display contexts
|
// display contexts
|
||||||
|
@ -2,7 +2,6 @@ package context
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jesseduffield/generics/slices"
|
"github.com/jesseduffield/generics/slices"
|
||||||
"github.com/jesseduffield/gocui"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/style"
|
"github.com/jesseduffield/lazygit/pkg/gui/style"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
@ -16,11 +15,7 @@ type MenuContext struct {
|
|||||||
var _ types.IListContext = (*MenuContext)(nil)
|
var _ types.IListContext = (*MenuContext)(nil)
|
||||||
|
|
||||||
func NewMenuContext(
|
func NewMenuContext(
|
||||||
view *gocui.View,
|
|
||||||
|
|
||||||
c *types.HelperCommon,
|
c *types.HelperCommon,
|
||||||
getOptionsMap func() map[string]string,
|
|
||||||
renderToDescriptionView func(string),
|
|
||||||
) *MenuContext {
|
) *MenuContext {
|
||||||
viewModel := NewMenuViewModel()
|
viewModel := NewMenuViewModel()
|
||||||
|
|
||||||
@ -28,11 +23,10 @@ func NewMenuContext(
|
|||||||
MenuViewModel: viewModel,
|
MenuViewModel: viewModel,
|
||||||
ListContextTrait: &ListContextTrait{
|
ListContextTrait: &ListContextTrait{
|
||||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||||
View: view,
|
View: c.Views().Menu,
|
||||||
WindowName: "menu",
|
WindowName: "menu",
|
||||||
Key: "menu",
|
Key: "menu",
|
||||||
Kind: types.TEMPORARY_POPUP,
|
Kind: types.TEMPORARY_POPUP,
|
||||||
OnGetOptionsMap: getOptionsMap,
|
|
||||||
Focusable: true,
|
Focusable: true,
|
||||||
HasUncontrolledBounds: true,
|
HasUncontrolledBounds: true,
|
||||||
}), ContextCallbackOpts{}),
|
}), ContextCallbackOpts{}),
|
||||||
|
@ -30,7 +30,6 @@ func NewMergeConflictsContext(
|
|||||||
opts ContextCallbackOpts,
|
opts ContextCallbackOpts,
|
||||||
|
|
||||||
c *types.HelperCommon,
|
c *types.HelperCommon,
|
||||||
getOptionsMap func() map[string]string,
|
|
||||||
) *MergeConflictsContext {
|
) *MergeConflictsContext {
|
||||||
viewModel := &ConflictsViewModel{
|
viewModel := &ConflictsViewModel{
|
||||||
state: mergeconflicts.NewState(),
|
state: mergeconflicts.NewState(),
|
||||||
@ -46,7 +45,6 @@ func NewMergeConflictsContext(
|
|||||||
View: view,
|
View: view,
|
||||||
WindowName: "main",
|
WindowName: "main",
|
||||||
Key: MERGE_CONFLICTS_CONTEXT_KEY,
|
Key: MERGE_CONFLICTS_CONTEXT_KEY,
|
||||||
OnGetOptionsMap: getOptionsMap,
|
|
||||||
Focusable: true,
|
Focusable: true,
|
||||||
HighlightOnFocus: true,
|
HighlightOnFocus: true,
|
||||||
}),
|
}),
|
||||||
|
@ -24,8 +24,6 @@ func NewPatchExplorerContext(
|
|||||||
windowName string,
|
windowName string,
|
||||||
key types.ContextKey,
|
key types.ContextKey,
|
||||||
|
|
||||||
onFocus func(types.OnFocusOpts) error,
|
|
||||||
onFocusLost func(opts types.OnFocusLostOpts) error,
|
|
||||||
getIncludedLineIndices func() []int,
|
getIncludedLineIndices func() []int,
|
||||||
|
|
||||||
c *types.HelperCommon,
|
c *types.HelperCommon,
|
||||||
@ -43,10 +41,7 @@ func NewPatchExplorerContext(
|
|||||||
Kind: types.MAIN_CONTEXT,
|
Kind: types.MAIN_CONTEXT,
|
||||||
Focusable: true,
|
Focusable: true,
|
||||||
HighlightOnFocus: true,
|
HighlightOnFocus: true,
|
||||||
}), ContextCallbackOpts{
|
}), ContextCallbackOpts{}),
|
||||||
OnFocus: onFocus,
|
|
||||||
OnFocusLost: onFocusLost,
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,31 +1,53 @@
|
|||||||
package context
|
package context
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/tasks"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SuggestionsContext struct {
|
type SuggestionsContext struct {
|
||||||
*BasicViewModel[*types.Suggestion]
|
*BasicViewModel[*types.Suggestion]
|
||||||
*ListContextTrait
|
*ListContextTrait
|
||||||
|
|
||||||
|
State *SuggestionsContextState
|
||||||
|
}
|
||||||
|
|
||||||
|
type SuggestionsContextState struct {
|
||||||
|
Suggestions []*types.Suggestion
|
||||||
|
OnConfirm func() error
|
||||||
|
OnClose func() error
|
||||||
|
AsyncHandler *tasks.AsyncHandler
|
||||||
|
|
||||||
|
// FindSuggestions will take a string that the user has typed into a prompt
|
||||||
|
// and return a slice of suggestions which match that string.
|
||||||
|
FindSuggestions func(string) []*types.Suggestion
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ types.IListContext = (*SuggestionsContext)(nil)
|
var _ types.IListContext = (*SuggestionsContext)(nil)
|
||||||
|
|
||||||
func NewSuggestionsContext(
|
func NewSuggestionsContext(
|
||||||
getModel func() []*types.Suggestion,
|
|
||||||
view *gocui.View,
|
|
||||||
getDisplayStrings func(startIdx int, length int) [][]string,
|
|
||||||
|
|
||||||
c *types.HelperCommon,
|
c *types.HelperCommon,
|
||||||
) *SuggestionsContext {
|
) *SuggestionsContext {
|
||||||
|
state := &SuggestionsContextState{
|
||||||
|
AsyncHandler: tasks.NewAsyncHandler(),
|
||||||
|
}
|
||||||
|
getModel := func() []*types.Suggestion {
|
||||||
|
return state.Suggestions
|
||||||
|
}
|
||||||
|
|
||||||
|
getDisplayStrings := func(startIdx int, length int) [][]string {
|
||||||
|
return presentation.GetSuggestionListDisplayStrings(state.Suggestions)
|
||||||
|
}
|
||||||
|
|
||||||
viewModel := NewBasicViewModel(getModel)
|
viewModel := NewBasicViewModel(getModel)
|
||||||
|
|
||||||
return &SuggestionsContext{
|
return &SuggestionsContext{
|
||||||
|
State: state,
|
||||||
BasicViewModel: viewModel,
|
BasicViewModel: viewModel,
|
||||||
ListContextTrait: &ListContextTrait{
|
ListContextTrait: &ListContextTrait{
|
||||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||||
View: view,
|
View: c.Views().Suggestions,
|
||||||
WindowName: "suggestions",
|
WindowName: "suggestions",
|
||||||
Key: SUGGESTIONS_CONTEXT_KEY,
|
Key: SUGGESTIONS_CONTEXT_KEY,
|
||||||
Kind: types.PERSISTENT_POPUP,
|
Kind: types.PERSISTENT_POPUP,
|
||||||
@ -47,3 +69,22 @@ func (self *SuggestionsContext) GetSelectedItemId() string {
|
|||||||
|
|
||||||
return item.Value
|
return item.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *SuggestionsContext) SetSuggestions(suggestions []*types.Suggestion) {
|
||||||
|
self.State.Suggestions = suggestions
|
||||||
|
self.SetSelectedLineIdx(0)
|
||||||
|
self.c.ResetViewOrigin(self.GetView())
|
||||||
|
_ = self.HandleRender()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *SuggestionsContext) RefreshSuggestions() {
|
||||||
|
self.State.AsyncHandler.Do(func() func() {
|
||||||
|
findSuggestionsFn := self.State.FindSuggestions
|
||||||
|
if findSuggestionsFn != nil {
|
||||||
|
suggestions := findSuggestionsFn(self.c.GetPromptInput())
|
||||||
|
return func() { self.SetSuggestions(suggestions) }
|
||||||
|
} else {
|
||||||
|
return func() {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -76,23 +76,6 @@ func (gui *Gui) contextTree() *context.ContextTree {
|
|||||||
gui.Views.Staging,
|
gui.Views.Staging,
|
||||||
"main",
|
"main",
|
||||||
context.STAGING_MAIN_CONTEXT_KEY,
|
context.STAGING_MAIN_CONTEXT_KEY,
|
||||||
func(opts types.OnFocusOpts) error {
|
|
||||||
gui.Views.Staging.Wrap = false
|
|
||||||
gui.Views.StagingSecondary.Wrap = false
|
|
||||||
|
|
||||||
return gui.helpers.Staging.RefreshStagingPanel(opts)
|
|
||||||
},
|
|
||||||
func(opts types.OnFocusLostOpts) error {
|
|
||||||
gui.State.Contexts.Staging.SetState(nil)
|
|
||||||
|
|
||||||
if opts.NewContextKey != context.STAGING_SECONDARY_CONTEXT_KEY {
|
|
||||||
gui.Views.Staging.Wrap = true
|
|
||||||
gui.Views.StagingSecondary.Wrap = true
|
|
||||||
_ = gui.State.Contexts.Staging.Render(false)
|
|
||||||
_ = gui.State.Contexts.StagingSecondary.Render(false)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
func() []int { return nil },
|
func() []int { return nil },
|
||||||
gui.c,
|
gui.c,
|
||||||
),
|
),
|
||||||
@ -100,23 +83,6 @@ func (gui *Gui) contextTree() *context.ContextTree {
|
|||||||
gui.Views.StagingSecondary,
|
gui.Views.StagingSecondary,
|
||||||
"secondary",
|
"secondary",
|
||||||
context.STAGING_SECONDARY_CONTEXT_KEY,
|
context.STAGING_SECONDARY_CONTEXT_KEY,
|
||||||
func(opts types.OnFocusOpts) error {
|
|
||||||
gui.Views.Staging.Wrap = false
|
|
||||||
gui.Views.StagingSecondary.Wrap = false
|
|
||||||
|
|
||||||
return gui.helpers.Staging.RefreshStagingPanel(opts)
|
|
||||||
},
|
|
||||||
func(opts types.OnFocusLostOpts) error {
|
|
||||||
gui.State.Contexts.StagingSecondary.SetState(nil)
|
|
||||||
|
|
||||||
if opts.NewContextKey != context.STAGING_MAIN_CONTEXT_KEY {
|
|
||||||
gui.Views.Staging.Wrap = true
|
|
||||||
gui.Views.StagingSecondary.Wrap = true
|
|
||||||
_ = gui.State.Contexts.Staging.Render(false)
|
|
||||||
_ = gui.State.Contexts.StagingSecondary.Render(false)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
func() []int { return nil },
|
func() []int { return nil },
|
||||||
gui.c,
|
gui.c,
|
||||||
),
|
),
|
||||||
@ -124,21 +90,6 @@ func (gui *Gui) contextTree() *context.ContextTree {
|
|||||||
gui.Views.PatchBuilding,
|
gui.Views.PatchBuilding,
|
||||||
"main",
|
"main",
|
||||||
context.PATCH_BUILDING_MAIN_CONTEXT_KEY,
|
context.PATCH_BUILDING_MAIN_CONTEXT_KEY,
|
||||||
func(opts types.OnFocusOpts) error {
|
|
||||||
// no need to change wrap on the secondary view because it can't be interacted with
|
|
||||||
gui.Views.PatchBuilding.Wrap = false
|
|
||||||
|
|
||||||
return gui.helpers.PatchBuilding.RefreshPatchBuildingPanel(opts)
|
|
||||||
},
|
|
||||||
func(opts types.OnFocusLostOpts) error {
|
|
||||||
gui.Views.PatchBuilding.Wrap = true
|
|
||||||
|
|
||||||
if gui.git.Patch.PatchBuilder.IsEmpty() {
|
|
||||||
gui.git.Patch.PatchBuilder.Reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
func() []int {
|
func() []int {
|
||||||
filename := gui.State.Contexts.CommitFiles.GetSelectedPath()
|
filename := gui.State.Contexts.CommitFiles.GetSelectedPath()
|
||||||
includedLineIndices, err := gui.git.Patch.PatchBuilder.GetFileIncLineIndices(filename)
|
includedLineIndices, err := gui.git.Patch.PatchBuilder.GetFileIncLineIndices(filename)
|
||||||
@ -165,37 +116,9 @@ func (gui *Gui) contextTree() *context.ContextTree {
|
|||||||
gui.Views.MergeConflicts,
|
gui.Views.MergeConflicts,
|
||||||
context.ContextCallbackOpts{},
|
context.ContextCallbackOpts{},
|
||||||
gui.c,
|
gui.c,
|
||||||
func() map[string]string {
|
|
||||||
// wrapping in a function because contexts are initialized before helpers
|
|
||||||
return gui.helpers.MergeConflicts.GetMergingOptions()
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Confirmation: context.NewSimpleContext(
|
|
||||||
context.NewBaseContext(context.NewBaseContextOpts{
|
|
||||||
Kind: types.TEMPORARY_POPUP,
|
|
||||||
View: gui.Views.Confirmation,
|
|
||||||
WindowName: "confirmation",
|
|
||||||
Key: context.CONFIRMATION_CONTEXT_KEY,
|
|
||||||
Focusable: true,
|
|
||||||
HasUncontrolledBounds: true,
|
|
||||||
}),
|
|
||||||
context.ContextCallbackOpts{
|
|
||||||
OnFocus: OnFocusWrapper(gui.handleAskFocused),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
CommitMessage: context.NewSimpleContext(
|
|
||||||
context.NewBaseContext(context.NewBaseContextOpts{
|
|
||||||
Kind: types.PERSISTENT_POPUP,
|
|
||||||
View: gui.Views.CommitMessage,
|
|
||||||
WindowName: "commitMessage",
|
|
||||||
Key: context.COMMIT_MESSAGE_CONTEXT_KEY,
|
|
||||||
Focusable: true,
|
|
||||||
HasUncontrolledBounds: true,
|
|
||||||
}),
|
|
||||||
context.ContextCallbackOpts{
|
|
||||||
OnFocus: OnFocusWrapper(gui.handleCommitMessageFocused),
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
|
Confirmation: context.NewConfirmationContext(gui.c),
|
||||||
|
CommitMessage: context.NewCommitMessageContext(gui.c),
|
||||||
Search: context.NewSimpleContext(
|
Search: context.NewSimpleContext(
|
||||||
context.NewBaseContext(context.NewBaseContextOpts{
|
context.NewBaseContext(context.NewBaseContextOpts{
|
||||||
Kind: types.PERSISTENT_POPUP,
|
Kind: types.PERSISTENT_POPUP,
|
||||||
@ -214,12 +137,7 @@ func (gui *Gui) contextTree() *context.ContextTree {
|
|||||||
Key: context.COMMAND_LOG_CONTEXT_KEY,
|
Key: context.COMMAND_LOG_CONTEXT_KEY,
|
||||||
Focusable: true,
|
Focusable: true,
|
||||||
}),
|
}),
|
||||||
context.ContextCallbackOpts{
|
context.ContextCallbackOpts{},
|
||||||
OnFocusLost: func(opts types.OnFocusLostOpts) error {
|
|
||||||
gui.Views.Extras.Autoscroll = true
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
Options: context.NewDisplayContext(context.OPTIONS_CONTEXT_KEY, gui.Views.Options, "options"),
|
Options: context.NewDisplayContext(context.OPTIONS_CONTEXT_KEY, gui.Views.Options, "options"),
|
||||||
AppStatus: context.NewDisplayContext(context.APP_STATUS_CONTEXT_KEY, gui.Views.AppStatus, "appStatus"),
|
AppStatus: context.NewDisplayContext(context.APP_STATUS_CONTEXT_KEY, gui.Views.AppStatus, "appStatus"),
|
||||||
|
@ -24,7 +24,7 @@ func (gui *Gui) resetControllers() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
rebaseHelper := helpers.NewMergeAndRebaseHelper(helperCommon, gui.State.Contexts, gui.git, refsHelper)
|
rebaseHelper := helpers.NewMergeAndRebaseHelper(helperCommon, gui.State.Contexts, gui.git, refsHelper)
|
||||||
suggestionsHelper := helpers.NewSuggestionsHelper(helperCommon, model, gui.refreshSuggestions)
|
suggestionsHelper := helpers.NewSuggestionsHelper(helperCommon, model, gui.State.Contexts)
|
||||||
setCommitMessage := gui.getSetTextareaTextFn(func() *gocui.View { return gui.Views.CommitMessage })
|
setCommitMessage := gui.getSetTextareaTextFn(func() *gocui.View { return gui.Views.CommitMessage })
|
||||||
getSavedCommitMessage := func() string {
|
getSavedCommitMessage := func() string {
|
||||||
return gui.State.savedCommitMessage
|
return gui.State.savedCommitMessage
|
||||||
@ -66,6 +66,7 @@ func (gui *Gui) resetControllers() {
|
|||||||
Window: helpers.NewWindowHelper(helperCommon, viewHelper, gui.State.Contexts),
|
Window: helpers.NewWindowHelper(helperCommon, viewHelper, gui.State.Contexts),
|
||||||
View: viewHelper,
|
View: viewHelper,
|
||||||
Refresh: refreshHelper,
|
Refresh: refreshHelper,
|
||||||
|
Confirmation: helpers.NewConfirmationHelper(helperCommon, gui.State.Contexts),
|
||||||
}
|
}
|
||||||
|
|
||||||
gui.CustomCommandsClient = custom_commands.NewClient(
|
gui.CustomCommandsClient = custom_commands.NewClient(
|
||||||
@ -151,6 +152,9 @@ func (gui *Gui) resetControllers() {
|
|||||||
reflogCommitsController := controllers.NewReflogCommitsController(common, gui.State.Contexts.ReflogCommits)
|
reflogCommitsController := controllers.NewReflogCommitsController(common, gui.State.Contexts.ReflogCommits)
|
||||||
subCommitsController := controllers.NewSubCommitsController(common, gui.State.Contexts.SubCommits)
|
subCommitsController := controllers.NewSubCommitsController(common, gui.State.Contexts.SubCommits)
|
||||||
statusController := controllers.NewStatusController(common)
|
statusController := controllers.NewStatusController(common)
|
||||||
|
commandLogController := controllers.NewCommandLogController(common)
|
||||||
|
confirmationController := controllers.NewConfirmationController(common)
|
||||||
|
suggestionsController := controllers.NewSuggestionsController(common)
|
||||||
|
|
||||||
setSubCommits := func(commits []*models.Commit) {
|
setSubCommits := func(commits []*models.Commit) {
|
||||||
gui.Mutexes.SubCommitsMutex.Lock()
|
gui.Mutexes.SubCommitsMutex.Lock()
|
||||||
@ -279,6 +283,18 @@ func (gui *Gui) resetControllers() {
|
|||||||
statusController,
|
statusController,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
controllers.AttachControllers(gui.State.Contexts.CommandLog,
|
||||||
|
commandLogController,
|
||||||
|
)
|
||||||
|
|
||||||
|
controllers.AttachControllers(gui.State.Contexts.Confirmation,
|
||||||
|
confirmationController,
|
||||||
|
)
|
||||||
|
|
||||||
|
controllers.AttachControllers(gui.State.Contexts.Suggestions,
|
||||||
|
suggestionsController,
|
||||||
|
)
|
||||||
|
|
||||||
controllers.AttachControllers(gui.State.Contexts.Global,
|
controllers.AttachControllers(gui.State.Contexts.Global,
|
||||||
syncController,
|
syncController,
|
||||||
undoController,
|
undoController,
|
||||||
@ -303,7 +319,7 @@ func (gui *Gui) getSetTextareaTextFn(getView func() *gocui.View) func(string) {
|
|||||||
view := getView()
|
view := getView()
|
||||||
view.ClearTextArea()
|
view.ClearTextArea()
|
||||||
view.TextArea.TypeString(text)
|
view.TextArea.TypeString(text)
|
||||||
_ = gui.resizePopupPanel(view, view.TextArea.GetContent())
|
_ = gui.helpers.Confirmation.ResizePopupPanel(view, view.TextArea.GetContent())
|
||||||
view.RenderTextArea()
|
view.RenderTextArea()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
42
pkg/gui/controllers/command_log_controller.go
Normal file
42
pkg/gui/controllers/command_log_controller.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CommandLogController struct {
|
||||||
|
baseController
|
||||||
|
*controllerCommon
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ types.IController = &CommandLogController{}
|
||||||
|
|
||||||
|
func NewCommandLogController(
|
||||||
|
common *controllerCommon,
|
||||||
|
) *CommandLogController {
|
||||||
|
return &CommandLogController{
|
||||||
|
baseController: baseController{},
|
||||||
|
controllerCommon: common,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommandLogController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
|
bindings := []*types.Binding{}
|
||||||
|
|
||||||
|
return bindings
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommandLogController) GetOnFocusLost() func(types.OnFocusLostOpts) error {
|
||||||
|
return func(types.OnFocusLostOpts) error {
|
||||||
|
self.c.Views().Extras.Autoscroll = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommandLogController) Context() types.Context {
|
||||||
|
return self.context()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommandLogController) context() types.Context {
|
||||||
|
return self.contexts.CommandLog
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -31,28 +32,39 @@ func NewCommitMessageController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: merge that commit panel PR because we're not currently showing how to add a newline as it's
|
||||||
|
// handled by the editor func rather than by the controller here.
|
||||||
func (self *CommitMessageController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *CommitMessageController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
bindings := []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.SubmitEditorText),
|
Key: opts.GetKey(opts.Config.Universal.SubmitEditorText),
|
||||||
Handler: self.confirm,
|
Handler: self.confirm,
|
||||||
|
Description: self.c.Tr.LcConfirm,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||||
Handler: self.close,
|
Handler: self.close,
|
||||||
|
Description: self.c.Tr.LcClose,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return bindings
|
return bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *CommitMessageController) GetOnFocusLost() func(types.OnFocusLostOpts) error {
|
||||||
|
return func(types.OnFocusLostOpts) error {
|
||||||
|
self.context().RenderCommitLength()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (self *CommitMessageController) Context() types.Context {
|
func (self *CommitMessageController) Context() types.Context {
|
||||||
return self.context()
|
return self.context()
|
||||||
}
|
}
|
||||||
|
|
||||||
// this method is pointless in this context but I'm keeping it consistent
|
// this method is pointless in this context but I'm keeping it consistent
|
||||||
// with other contexts so that when generics arrive it's easier to refactor
|
// with other contexts so that when generics arrive it's easier to refactor
|
||||||
func (self *CommitMessageController) context() types.Context {
|
func (self *CommitMessageController) context() *context.CommitMessageContext {
|
||||||
return self.contexts.CommitMessage
|
return self.contexts.CommitMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,14 +22,36 @@ func NewConfirmationController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *ConfirmationController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *ConfirmationController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
bindings := []*types.Binding{}
|
bindings := []*types.Binding{
|
||||||
|
{
|
||||||
|
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
||||||
|
Handler: func() error { return self.context().State.OnConfirm() },
|
||||||
|
Description: self.c.Tr.LcConfirm,
|
||||||
|
Display: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||||
|
Handler: func() error { return self.context().State.OnClose() },
|
||||||
|
Description: self.c.Tr.LcCloseCancel,
|
||||||
|
Display: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: opts.GetKey(opts.Config.Universal.TogglePanel),
|
||||||
|
Handler: func() error {
|
||||||
|
if len(self.contexts.Suggestions.State.Suggestions) > 0 {
|
||||||
|
return self.c.ReplaceContext(self.contexts.Suggestions)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
return bindings
|
return bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ConfirmationController) GetOnFocusLost() func(types.OnFocusLostOpts) error {
|
func (self *ConfirmationController) GetOnFocusLost() func(types.OnFocusLostOpts) error {
|
||||||
return func(types.OnFocusLostOpts) error {
|
return func(types.OnFocusLostOpts) error {
|
||||||
deactivateConfirmationPrompt(self.controllerCommon)
|
self.helpers.Confirmation.DeactivateConfirmationPrompt()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -37,17 +60,6 @@ func (self *ConfirmationController) Context() types.Context {
|
|||||||
return self.context()
|
return self.context()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ConfirmationController) context() types.Context {
|
func (self *ConfirmationController) context() *context.ConfirmationContext {
|
||||||
return self.contexts.Confirmation
|
return self.contexts.Confirmation
|
||||||
}
|
}
|
||||||
|
|
||||||
func deactivateConfirmationPrompt(c *controllerCommon) {
|
|
||||||
c.mutexes.PopupMutex.Lock()
|
|
||||||
c.c.State().GetRepoState().SetCurrentPopupOpts(nil)
|
|
||||||
c.mutexes.PopupMutex.Unlock()
|
|
||||||
|
|
||||||
c.c.Views().Confirmation.Visible = false
|
|
||||||
c.c.Views().Suggestions.Visible = false
|
|
||||||
|
|
||||||
gui.clearConfirmationViewKeyBindings()
|
|
||||||
}
|
|
||||||
|
321
pkg/gui/controllers/helpers/confirmation_helper.go
Normal file
321
pkg/gui/controllers/helpers/confirmation_helper.go
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
package helpers
|
||||||
|
|
||||||
|
import (
|
||||||
|
goContext "context"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/gocui"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/gui/style"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/theme"
|
||||||
|
"github.com/mattn/go-runewidth"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConfirmationHelper struct {
|
||||||
|
c *types.HelperCommon
|
||||||
|
contexts *context.ContextTree
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewConfirmationHelper(
|
||||||
|
c *types.HelperCommon,
|
||||||
|
contexts *context.ContextTree,
|
||||||
|
) *ConfirmationHelper {
|
||||||
|
return &ConfirmationHelper{
|
||||||
|
c: c,
|
||||||
|
contexts: contexts,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This file is for the rendering of confirmation panels along with setting and handling associated
|
||||||
|
// keybindings.
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) wrappedConfirmationFunction(cancel goContext.CancelFunc, function func() error) func() error {
|
||||||
|
return func() error {
|
||||||
|
cancel()
|
||||||
|
|
||||||
|
if err := self.c.PopContext(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if function != nil {
|
||||||
|
if err := function(); err != nil {
|
||||||
|
return self.c.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) wrappedPromptConfirmationFunction(cancel goContext.CancelFunc, function func(string) error, getResponse func() string) func() error {
|
||||||
|
return self.wrappedConfirmationFunction(cancel, func() error {
|
||||||
|
return function(getResponse())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) DeactivateConfirmationPrompt() {
|
||||||
|
self.c.Mutexes().PopupMutex.Lock()
|
||||||
|
self.c.State().GetRepoState().SetCurrentPopupOpts(nil)
|
||||||
|
self.c.Mutexes().PopupMutex.Unlock()
|
||||||
|
|
||||||
|
self.c.Views().Confirmation.Visible = false
|
||||||
|
self.c.Views().Suggestions.Visible = false
|
||||||
|
|
||||||
|
self.clearConfirmationViewKeyBindings()
|
||||||
|
}
|
||||||
|
|
||||||
|
func getMessageHeight(wrap bool, message string, width int) int {
|
||||||
|
lines := strings.Split(message, "\n")
|
||||||
|
lineCount := 0
|
||||||
|
// if we need to wrap, calculate height to fit content within view's width
|
||||||
|
if wrap {
|
||||||
|
for _, line := range lines {
|
||||||
|
lineCount += runewidth.StringWidth(line)/width + 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lineCount = len(lines)
|
||||||
|
}
|
||||||
|
return lineCount
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) getConfirmationPanelDimensions(wrap bool, prompt string) (int, int, int, int) {
|
||||||
|
panelWidth := self.getConfirmationPanelWidth()
|
||||||
|
panelHeight := getMessageHeight(wrap, prompt, panelWidth)
|
||||||
|
return self.getConfirmationPanelDimensionsAux(panelWidth, panelHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) getConfirmationPanelDimensionsForContentHeight(panelWidth, contentHeight int) (int, int, int, int) {
|
||||||
|
return self.getConfirmationPanelDimensionsAux(panelWidth, contentHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) getConfirmationPanelDimensionsAux(panelWidth int, panelHeight int) (int, int, int, int) {
|
||||||
|
width, height := self.c.GocuiGui().Size()
|
||||||
|
if panelHeight > height*3/4 {
|
||||||
|
panelHeight = height * 3 / 4
|
||||||
|
}
|
||||||
|
return width/2 - panelWidth/2,
|
||||||
|
height/2 - panelHeight/2 - panelHeight%2 - 1,
|
||||||
|
width/2 + panelWidth/2,
|
||||||
|
height/2 + panelHeight/2
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) getConfirmationPanelWidth() int {
|
||||||
|
width, _ := self.c.GocuiGui().Size()
|
||||||
|
// we want a minimum width up to a point, then we do it based on ratio.
|
||||||
|
panelWidth := 4 * width / 7
|
||||||
|
minWidth := 80
|
||||||
|
if panelWidth < minWidth {
|
||||||
|
if width-2 < minWidth {
|
||||||
|
panelWidth = width - 2
|
||||||
|
} else {
|
||||||
|
panelWidth = minWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return panelWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) prepareConfirmationPanel(
|
||||||
|
ctx goContext.Context,
|
||||||
|
opts types.ConfirmOpts,
|
||||||
|
) error {
|
||||||
|
self.c.Views().Confirmation.HasLoader = opts.HasLoader
|
||||||
|
if opts.HasLoader {
|
||||||
|
self.c.GocuiGui().StartTicking(ctx)
|
||||||
|
}
|
||||||
|
self.c.Views().Confirmation.Title = opts.Title
|
||||||
|
// for now we do not support wrapping in our editor
|
||||||
|
self.c.Views().Confirmation.Wrap = !opts.Editable
|
||||||
|
self.c.Views().Confirmation.FgColor = theme.GocuiDefaultTextColor
|
||||||
|
self.c.Views().Confirmation.Mask = runeForMask(opts.Mask)
|
||||||
|
_ = self.c.Views().Confirmation.SetOrigin(0, 0)
|
||||||
|
|
||||||
|
suggestionsContext := self.contexts.Suggestions
|
||||||
|
suggestionsContext.State.FindSuggestions = opts.FindSuggestionsFunc
|
||||||
|
if opts.FindSuggestionsFunc != nil {
|
||||||
|
suggestionsView := self.c.Views().Suggestions
|
||||||
|
suggestionsView.Wrap = false
|
||||||
|
suggestionsView.FgColor = theme.GocuiDefaultTextColor
|
||||||
|
suggestionsContext.SetSuggestions(opts.FindSuggestionsFunc(""))
|
||||||
|
suggestionsView.Visible = true
|
||||||
|
suggestionsView.Title = fmt.Sprintf(self.c.Tr.SuggestionsTitle, self.c.UserConfig.Keybinding.Universal.TogglePanel)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ResizeConfirmationPanel()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func runeForMask(mask bool) rune {
|
||||||
|
if mask {
|
||||||
|
return '*'
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) CreatePopupPanel(ctx goContext.Context, opts types.CreatePopupPanelOpts) error {
|
||||||
|
self.c.Mutexes().PopupMutex.Lock()
|
||||||
|
defer self.c.Mutexes().PopupMutex.Unlock()
|
||||||
|
|
||||||
|
ctx, cancel := goContext.WithCancel(ctx)
|
||||||
|
|
||||||
|
// we don't allow interruptions of non-loader popups in case we get stuck somehow
|
||||||
|
// e.g. a credentials popup never gets its required user input so a process hangs
|
||||||
|
// forever.
|
||||||
|
// The proper solution is to have a queue of popup options
|
||||||
|
currentPopupOpts := self.c.State().GetRepoState().GetCurrentPopupOpts()
|
||||||
|
if currentPopupOpts != nil && !currentPopupOpts.HasLoader {
|
||||||
|
self.c.Log.Error("ignoring create popup panel because a popup panel is already open")
|
||||||
|
cancel()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove any previous keybindings
|
||||||
|
self.clearConfirmationViewKeyBindings()
|
||||||
|
|
||||||
|
err := self.prepareConfirmationPanel(
|
||||||
|
ctx,
|
||||||
|
types.ConfirmOpts{
|
||||||
|
Title: opts.Title,
|
||||||
|
Prompt: opts.Prompt,
|
||||||
|
HasLoader: opts.HasLoader,
|
||||||
|
FindSuggestionsFunc: opts.FindSuggestionsFunc,
|
||||||
|
Editable: opts.Editable,
|
||||||
|
Mask: opts.Mask,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
cancel()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
confirmationView := self.c.Views().Confirmation
|
||||||
|
confirmationView.Editable = opts.Editable
|
||||||
|
|
||||||
|
if opts.Editable {
|
||||||
|
textArea := confirmationView.TextArea
|
||||||
|
textArea.Clear()
|
||||||
|
textArea.TypeString(opts.Prompt)
|
||||||
|
self.ResizeConfirmationPanel()
|
||||||
|
confirmationView.RenderTextArea()
|
||||||
|
} else {
|
||||||
|
self.c.ResetViewOrigin(confirmationView)
|
||||||
|
self.c.SetViewContent(confirmationView, style.AttrBold.Sprint(opts.Prompt))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := self.setKeyBindings(cancel, opts); err != nil {
|
||||||
|
cancel()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
self.c.State().GetRepoState().SetCurrentPopupOpts(&opts)
|
||||||
|
|
||||||
|
return self.c.PushContext(self.contexts.Confirmation)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) setKeyBindings(cancel goContext.CancelFunc, opts types.CreatePopupPanelOpts) error {
|
||||||
|
var onConfirm func() error
|
||||||
|
if opts.HandleConfirmPrompt != nil {
|
||||||
|
onConfirm = self.wrappedPromptConfirmationFunction(cancel, opts.HandleConfirmPrompt, func() string { return self.c.Views().Confirmation.TextArea.GetContent() })
|
||||||
|
} else {
|
||||||
|
onConfirm = self.wrappedConfirmationFunction(cancel, opts.HandleConfirm)
|
||||||
|
}
|
||||||
|
|
||||||
|
onSuggestionConfirm := self.wrappedPromptConfirmationFunction(
|
||||||
|
cancel,
|
||||||
|
opts.HandleConfirmPrompt,
|
||||||
|
self.getSelectedSuggestionValue,
|
||||||
|
)
|
||||||
|
|
||||||
|
onClose := self.wrappedConfirmationFunction(cancel, opts.HandleClose)
|
||||||
|
|
||||||
|
self.contexts.Confirmation.State.OnConfirm = onConfirm
|
||||||
|
self.contexts.Confirmation.State.OnClose = onClose
|
||||||
|
self.contexts.Suggestions.State.OnConfirm = onSuggestionConfirm
|
||||||
|
self.contexts.Suggestions.State.OnClose = onClose
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) clearConfirmationViewKeyBindings() {
|
||||||
|
noop := func() error { return nil }
|
||||||
|
self.contexts.Confirmation.State.OnConfirm = noop
|
||||||
|
self.contexts.Confirmation.State.OnClose = noop
|
||||||
|
self.contexts.Suggestions.State.OnConfirm = noop
|
||||||
|
self.contexts.Suggestions.State.OnClose = noop
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) getSelectedSuggestionValue() string {
|
||||||
|
selectedSuggestion := self.contexts.Suggestions.GetSelected()
|
||||||
|
|
||||||
|
if selectedSuggestion != nil {
|
||||||
|
return selectedSuggestion.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) ResizeConfirmationPanel() {
|
||||||
|
suggestionsViewHeight := 0
|
||||||
|
if self.c.Views().Suggestions.Visible {
|
||||||
|
suggestionsViewHeight = 11
|
||||||
|
}
|
||||||
|
panelWidth := self.getConfirmationPanelWidth()
|
||||||
|
prompt := self.c.Views().Confirmation.Buffer()
|
||||||
|
wrap := true
|
||||||
|
if self.c.Views().Confirmation.Editable {
|
||||||
|
prompt = self.c.Views().Confirmation.TextArea.GetContent()
|
||||||
|
wrap = false
|
||||||
|
}
|
||||||
|
panelHeight := getMessageHeight(wrap, prompt, panelWidth) + suggestionsViewHeight
|
||||||
|
x0, y0, x1, y1 := self.getConfirmationPanelDimensionsAux(panelWidth, panelHeight)
|
||||||
|
confirmationViewBottom := y1 - suggestionsViewHeight
|
||||||
|
_, _ = self.c.GocuiGui().SetView(self.c.Views().Confirmation.Name(), x0, y0, x1, confirmationViewBottom, 0)
|
||||||
|
|
||||||
|
suggestionsViewTop := confirmationViewBottom + 1
|
||||||
|
_, _ = self.c.GocuiGui().SetView(self.c.Views().Suggestions.Name(), x0, suggestionsViewTop, x1, suggestionsViewTop+suggestionsViewHeight, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) ResizeCurrentPopupPanel() error {
|
||||||
|
v := self.c.GocuiGui().CurrentView()
|
||||||
|
if v == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if v == self.c.Views().Menu {
|
||||||
|
self.resizeMenu()
|
||||||
|
} else if v == self.c.Views().Confirmation || v == self.c.Views().Suggestions {
|
||||||
|
self.ResizeConfirmationPanel()
|
||||||
|
} else if self.IsPopupPanel(v.Name()) {
|
||||||
|
return self.ResizePopupPanel(v, v.Buffer())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) ResizePopupPanel(v *gocui.View, content string) error {
|
||||||
|
x0, y0, x1, y1 := self.getConfirmationPanelDimensions(v.Wrap, content)
|
||||||
|
_, err := self.c.GocuiGui().SetView(v.Name(), x0, y0, x1, y1, 0)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) resizeMenu() {
|
||||||
|
itemCount := self.contexts.Menu.GetList().Len()
|
||||||
|
offset := 3
|
||||||
|
panelWidth := self.getConfirmationPanelWidth()
|
||||||
|
x0, y0, x1, y1 := self.getConfirmationPanelDimensionsForContentHeight(panelWidth, itemCount+offset)
|
||||||
|
menuBottom := y1 - offset
|
||||||
|
_, _ = self.c.GocuiGui().SetView(self.c.Views().Menu.Name(), x0, y0, x1, menuBottom, 0)
|
||||||
|
|
||||||
|
tooltipTop := menuBottom + 1
|
||||||
|
tooltipHeight := getMessageHeight(true, self.contexts.Menu.GetSelected().Tooltip, panelWidth) + 2 // plus 2 for the frame
|
||||||
|
_, _ = self.c.GocuiGui().SetView(self.c.Views().Tooltip.Name(), x0, tooltipTop, x1, tooltipTop+tooltipHeight-1, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) IsPopupPanel(viewName string) bool {
|
||||||
|
return viewName == "commitMessage" || viewName == "confirmation" || viewName == "menu"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ConfirmationHelper) IsPopupPanelFocused() bool {
|
||||||
|
return self.IsPopupPanel(self.c.CurrentContext().GetViewName())
|
||||||
|
}
|
@ -25,6 +25,7 @@ type Helpers struct {
|
|||||||
Window *WindowHelper
|
Window *WindowHelper
|
||||||
View *ViewHelper
|
View *ViewHelper
|
||||||
Refresh *RefreshHelper
|
Refresh *RefreshHelper
|
||||||
|
Confirmation *ConfirmationHelper
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStubHelpers() *Helpers {
|
func NewStubHelpers() *Helpers {
|
||||||
@ -52,5 +53,6 @@ func NewStubHelpers() *Helpers {
|
|||||||
Window: &WindowHelper{},
|
Window: &WindowHelper{},
|
||||||
View: &ViewHelper{},
|
View: &ViewHelper{},
|
||||||
Refresh: &RefreshHelper{},
|
Refresh: &RefreshHelper{},
|
||||||
|
Confirmation: &ConfirmationHelper{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
package helpers
|
package helpers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands"
|
"github.com/jesseduffield/lazygit/pkg/commands"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,18 +24,6 @@ func NewMergeConflictsHelper(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *MergeConflictsHelper) GetMergingOptions() map[string]string {
|
|
||||||
keybindingConfig := self.c.UserConfig.Keybinding
|
|
||||||
|
|
||||||
return map[string]string{
|
|
||||||
fmt.Sprintf("%s %s", keybindings.Label(keybindingConfig.Universal.PrevItem), keybindings.Label(keybindingConfig.Universal.NextItem)): self.c.Tr.LcSelectHunk,
|
|
||||||
fmt.Sprintf("%s %s", keybindings.Label(keybindingConfig.Universal.PrevBlock), keybindings.Label(keybindingConfig.Universal.NextBlock)): self.c.Tr.LcNavigateConflicts,
|
|
||||||
keybindings.Label(keybindingConfig.Universal.Select): self.c.Tr.LcPickHunk,
|
|
||||||
keybindings.Label(keybindingConfig.Main.PickBothHunks): self.c.Tr.LcPickAllHunks,
|
|
||||||
keybindings.Label(keybindingConfig.Universal.Undo): self.c.Tr.LcUndo,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *MergeConflictsHelper) SetMergeState(path string) (bool, error) {
|
func (self *MergeConflictsHelper) SetMergeState(path string) (bool, error) {
|
||||||
self.context().GetMutex().Lock()
|
self.context().GetMutex().Lock()
|
||||||
defer self.context().GetMutex().Unlock()
|
defer self.context().GetMutex().Unlock()
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/jesseduffield/generics/slices"
|
"github.com/jesseduffield/generics/slices"
|
||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
@ -35,8 +36,8 @@ type ISuggestionsHelper interface {
|
|||||||
type SuggestionsHelper struct {
|
type SuggestionsHelper struct {
|
||||||
c *types.HelperCommon
|
c *types.HelperCommon
|
||||||
|
|
||||||
model *types.Model
|
model *types.Model
|
||||||
refreshSuggestionsFn func()
|
contexts *context.ContextTree
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ ISuggestionsHelper = &SuggestionsHelper{}
|
var _ ISuggestionsHelper = &SuggestionsHelper{}
|
||||||
@ -44,12 +45,12 @@ var _ ISuggestionsHelper = &SuggestionsHelper{}
|
|||||||
func NewSuggestionsHelper(
|
func NewSuggestionsHelper(
|
||||||
c *types.HelperCommon,
|
c *types.HelperCommon,
|
||||||
model *types.Model,
|
model *types.Model,
|
||||||
refreshSuggestionsFn func(),
|
contexts *context.ContextTree,
|
||||||
) *SuggestionsHelper {
|
) *SuggestionsHelper {
|
||||||
return &SuggestionsHelper{
|
return &SuggestionsHelper{
|
||||||
c: c,
|
c: c,
|
||||||
model: model,
|
model: model,
|
||||||
refreshSuggestionsFn: refreshSuggestionsFn,
|
contexts: contexts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +128,7 @@ func (self *SuggestionsHelper) GetFilePathSuggestionsFunc() func(string) []*type
|
|||||||
// cache the trie for future use
|
// cache the trie for future use
|
||||||
self.model.FilesTrie = trie
|
self.model.FilesTrie = trie
|
||||||
|
|
||||||
self.refreshSuggestionsFn()
|
self.contexts.Suggestions.RefreshSuggestions()
|
||||||
|
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
@ -28,12 +28,16 @@ func (self *MenuController) GetKeybindings(opts types.KeybindingsOpts) []*types.
|
|||||||
Handler: self.press,
|
Handler: self.press,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
||||||
Handler: self.press,
|
Handler: self.press,
|
||||||
|
Description: self.c.Tr.LcExecute,
|
||||||
|
Display: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||||
Handler: self.close,
|
Handler: self.close,
|
||||||
|
Description: self.c.Tr.LcClose,
|
||||||
|
Display: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,21 +41,25 @@ func (self *MergeConflictsController) GetKeybindings(opts types.KeybindingsOpts)
|
|||||||
Key: opts.GetKey(opts.Config.Universal.PrevBlock),
|
Key: opts.GetKey(opts.Config.Universal.PrevBlock),
|
||||||
Handler: self.withRenderAndFocus(self.PrevConflict),
|
Handler: self.withRenderAndFocus(self.PrevConflict),
|
||||||
Description: self.c.Tr.PrevConflict,
|
Description: self.c.Tr.PrevConflict,
|
||||||
|
Display: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.NextBlock),
|
Key: opts.GetKey(opts.Config.Universal.NextBlock),
|
||||||
Handler: self.withRenderAndFocus(self.NextConflict),
|
Handler: self.withRenderAndFocus(self.NextConflict),
|
||||||
Description: self.c.Tr.NextConflict,
|
Description: self.c.Tr.NextConflict,
|
||||||
|
Display: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.PrevItem),
|
Key: opts.GetKey(opts.Config.Universal.PrevItem),
|
||||||
Handler: self.withRenderAndFocus(self.PrevConflictHunk),
|
Handler: self.withRenderAndFocus(self.PrevConflictHunk),
|
||||||
Description: self.c.Tr.SelectPrevHunk,
|
Description: self.c.Tr.SelectPrevHunk,
|
||||||
|
Display: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.NextItem),
|
Key: opts.GetKey(opts.Config.Universal.NextItem),
|
||||||
Handler: self.withRenderAndFocus(self.NextConflictHunk),
|
Handler: self.withRenderAndFocus(self.NextConflictHunk),
|
||||||
Description: self.c.Tr.SelectNextHunk,
|
Description: self.c.Tr.SelectNextHunk,
|
||||||
|
Display: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.PrevBlockAlt),
|
Key: opts.GetKey(opts.Config.Universal.PrevBlockAlt),
|
||||||
@ -89,6 +93,7 @@ func (self *MergeConflictsController) GetKeybindings(opts types.KeybindingsOpts)
|
|||||||
Key: opts.GetKey(opts.Config.Universal.Undo),
|
Key: opts.GetKey(opts.Config.Universal.Undo),
|
||||||
Handler: self.withRenderAndFocus(self.HandleUndo),
|
Handler: self.withRenderAndFocus(self.HandleUndo),
|
||||||
Description: self.c.Tr.LcUndo,
|
Description: self.c.Tr.LcUndo,
|
||||||
|
Display: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Files.OpenMergeTool),
|
Key: opts.GetKey(opts.Config.Files.OpenMergeTool),
|
||||||
@ -99,11 +104,13 @@ func (self *MergeConflictsController) GetKeybindings(opts types.KeybindingsOpts)
|
|||||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||||
Handler: self.withRenderAndFocus(self.HandlePickHunk),
|
Handler: self.withRenderAndFocus(self.HandlePickHunk),
|
||||||
Description: self.c.Tr.PickHunk,
|
Description: self.c.Tr.PickHunk,
|
||||||
|
Display: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Main.PickBothHunks),
|
Key: opts.GetKey(opts.Config.Main.PickBothHunks),
|
||||||
Handler: self.withRenderAndFocus(self.HandlePickAllHunks),
|
Handler: self.withRenderAndFocus(self.HandlePickAllHunks),
|
||||||
Description: self.c.Tr.PickAllHunks,
|
Description: self.c.Tr.PickAllHunks,
|
||||||
|
Display: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||||
|
@ -59,6 +59,27 @@ func (self *PatchBuildingController) GetMouseKeybindings(opts types.KeybindingsO
|
|||||||
return []*gocui.ViewMouseBinding{}
|
return []*gocui.ViewMouseBinding{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *PatchBuildingController) GetOnFocus() func(types.OnFocusOpts) error {
|
||||||
|
return func(opts types.OnFocusOpts) error {
|
||||||
|
// no need to change wrap on the secondary view because it can't be interacted with
|
||||||
|
self.c.Views().PatchBuilding.Wrap = false
|
||||||
|
|
||||||
|
return self.helpers.PatchBuilding.RefreshPatchBuildingPanel(opts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *PatchBuildingController) GetOnFocusLost() func(types.OnFocusLostOpts) error {
|
||||||
|
return func(opts types.OnFocusLostOpts) error {
|
||||||
|
self.c.Views().PatchBuilding.Wrap = true
|
||||||
|
|
||||||
|
if self.git.Patch.PatchBuilder.IsEmpty() {
|
||||||
|
self.git.Patch.PatchBuilder.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (self *PatchBuildingController) OpenFile() error {
|
func (self *PatchBuildingController) OpenFile() error {
|
||||||
self.context().GetMutex().Lock()
|
self.context().GetMutex().Lock()
|
||||||
defer self.context().GetMutex().Unlock()
|
defer self.context().GetMutex().Unlock()
|
||||||
|
@ -99,6 +99,29 @@ func (self *StagingController) GetMouseKeybindings(opts types.KeybindingsOpts) [
|
|||||||
return []*gocui.ViewMouseBinding{}
|
return []*gocui.ViewMouseBinding{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *StagingController) GetOnFocus() func(types.OnFocusOpts) error {
|
||||||
|
return func(opts types.OnFocusOpts) error {
|
||||||
|
self.c.Views().Staging.Wrap = false
|
||||||
|
self.c.Views().StagingSecondary.Wrap = false
|
||||||
|
|
||||||
|
return self.helpers.Staging.RefreshStagingPanel(opts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *StagingController) GetOnFocusLost() func(types.OnFocusLostOpts) error {
|
||||||
|
return func(opts types.OnFocusLostOpts) error {
|
||||||
|
self.context.SetState(nil)
|
||||||
|
|
||||||
|
if opts.NewContextKey != self.otherContext.GetKey() {
|
||||||
|
self.c.Views().Staging.Wrap = true
|
||||||
|
self.c.Views().StagingSecondary.Wrap = true
|
||||||
|
_ = self.contexts.Staging.Render(false)
|
||||||
|
_ = self.contexts.StagingSecondary.Render(false)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (self *StagingController) OpenFile() error {
|
func (self *StagingController) OpenFile() error {
|
||||||
self.context.GetMutex().Lock()
|
self.context.GetMutex().Lock()
|
||||||
defer self.context.GetMutex().Unlock()
|
defer self.context.GetMutex().Unlock()
|
||||||
|
@ -53,8 +53,8 @@ func (self *SubCommitsController) GetOnRenderToMain() func() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SubCommitsController) GetOnFocus() func() error {
|
func (self *SubCommitsController) GetOnFocus() func(types.OnFocusOpts) error {
|
||||||
return func() error {
|
return func(types.OnFocusOpts) error {
|
||||||
context := self.context
|
context := self.context
|
||||||
if context.GetSelectedLineIdx() > COMMIT_THRESHOLD && context.GetLimitCommits() {
|
if context.GetSelectedLineIdx() > COMMIT_THRESHOLD && context.GetLimitCommits() {
|
||||||
context.SetLimitCommits(false)
|
context.SetLimitCommits(false)
|
||||||
|
@ -22,14 +22,27 @@ func NewSuggestionsController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *SuggestionsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
func (self *SuggestionsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||||
bindings := []*types.Binding{}
|
bindings := []*types.Binding{
|
||||||
|
{
|
||||||
|
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
||||||
|
Handler: func() error { return self.context().State.OnConfirm() },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||||
|
Handler: func() error { return self.context().State.OnClose() },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: opts.GetKey(opts.Config.Universal.TogglePanel),
|
||||||
|
Handler: func() error { return self.c.ReplaceContext(self.contexts.Confirmation) },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
return bindings
|
return bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SuggestionsController) GetOnFocusLost() func(types.OnFocusLostOpts) error {
|
func (self *SuggestionsController) GetOnFocusLost() func(types.OnFocusLostOpts) error {
|
||||||
return func(types.OnFocusLostOpts) error {
|
return func(types.OnFocusLostOpts) error {
|
||||||
deactivateConfirmationPrompt
|
self.helpers.Confirmation.DeactivateConfirmationPrompt()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,12 +71,12 @@ func (gui *Gui) commitMessageEditor(v *gocui.View, key gocui.Key, ch rune, mod g
|
|||||||
// This function is called again on refresh as part of the general resize popup call,
|
// This function is called again on refresh as part of the general resize popup call,
|
||||||
// but we need to call it here so that when we go to render the text area it's not
|
// but we need to call it here so that when we go to render the text area it's not
|
||||||
// considered out of bounds to add a newline, meaning we can avoid unnecessary scrolling.
|
// considered out of bounds to add a newline, meaning we can avoid unnecessary scrolling.
|
||||||
err := gui.resizePopupPanel(v, v.TextArea.GetContent())
|
err := gui.helpers.Confirmation.ResizePopupPanel(v, v.TextArea.GetContent())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gui.c.Log.Error(err)
|
gui.c.Log.Error(err)
|
||||||
}
|
}
|
||||||
v.RenderTextArea()
|
v.RenderTextArea()
|
||||||
gui.RenderCommitLength()
|
gui.State.Contexts.CommitMessage.RenderCommitLength()
|
||||||
|
|
||||||
return matched
|
return matched
|
||||||
}
|
}
|
||||||
@ -86,11 +86,12 @@ func (gui *Gui) defaultEditor(v *gocui.View, key gocui.Key, ch rune, mod gocui.M
|
|||||||
|
|
||||||
v.RenderTextArea()
|
v.RenderTextArea()
|
||||||
|
|
||||||
if gui.findSuggestions != nil {
|
suggestionsContext := gui.State.Contexts.Suggestions
|
||||||
|
if suggestionsContext.State.FindSuggestions != nil {
|
||||||
input := v.TextArea.GetContent()
|
input := v.TextArea.GetContent()
|
||||||
gui.suggestionsAsyncHandler.Do(func() func() {
|
suggestionsContext.State.AsyncHandler.Do(func() func() {
|
||||||
suggestions := gui.findSuggestions(input)
|
suggestions := suggestionsContext.State.FindSuggestions(input)
|
||||||
return func() { gui.setSuggestions(suggestions) }
|
return func() { suggestionsContext.SetSuggestions(suggestions) }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,16 +17,6 @@ func (gui *Gui) validateNotInFilterMode() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) outsideFilterMode(f func() error) func() error {
|
|
||||||
return func() error {
|
|
||||||
if !gui.validateNotInFilterMode() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return f()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) exitFilterMode() error {
|
func (gui *Gui) exitFilterMode() error {
|
||||||
return gui.clearFiltering()
|
return gui.clearFiltering()
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package gui
|
package gui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
goContext "context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@ -94,10 +95,6 @@ type Gui struct {
|
|||||||
|
|
||||||
Mutexes types.Mutexes
|
Mutexes types.Mutexes
|
||||||
|
|
||||||
// findSuggestions will take a string that the user has typed into a prompt
|
|
||||||
// and return a slice of suggestions which match that string.
|
|
||||||
findSuggestions func(string) []*types.Suggestion
|
|
||||||
|
|
||||||
// when you enter into a submodule we'll append the superproject's path to this array
|
// when you enter into a submodule we'll append the superproject's path to this array
|
||||||
// so that you can return to the superproject
|
// so that you can return to the superproject
|
||||||
RepoPathStack *utils.StringStack
|
RepoPathStack *utils.StringStack
|
||||||
@ -113,8 +110,6 @@ type Gui struct {
|
|||||||
// the extras window contains things like the command log
|
// the extras window contains things like the command log
|
||||||
ShowExtrasWindow bool
|
ShowExtrasWindow bool
|
||||||
|
|
||||||
suggestionsAsyncHandler *tasks.AsyncHandler
|
|
||||||
|
|
||||||
PopupHandler types.IPopupHandler
|
PopupHandler types.IPopupHandler
|
||||||
|
|
||||||
IsNewRepo bool
|
IsNewRepo bool
|
||||||
@ -198,9 +193,6 @@ type GuiRepoState struct {
|
|||||||
Model *types.Model
|
Model *types.Model
|
||||||
Modes *types.Modes
|
Modes *types.Modes
|
||||||
|
|
||||||
// Suggestions will sometimes appear when typing into a prompt
|
|
||||||
Suggestions []*types.Suggestion
|
|
||||||
|
|
||||||
SplitMainPanel bool
|
SplitMainPanel bool
|
||||||
LimitCommits bool
|
LimitCommits bool
|
||||||
|
|
||||||
@ -412,18 +404,17 @@ func NewGui(
|
|||||||
initialDir string,
|
initialDir string,
|
||||||
) (*Gui, error) {
|
) (*Gui, error) {
|
||||||
gui := &Gui{
|
gui := &Gui{
|
||||||
Common: cmn,
|
Common: cmn,
|
||||||
gitVersion: gitVersion,
|
gitVersion: gitVersion,
|
||||||
Config: config,
|
Config: config,
|
||||||
Updater: updater,
|
Updater: updater,
|
||||||
statusManager: &statusManager{},
|
statusManager: &statusManager{},
|
||||||
viewBufferManagerMap: map[string]*tasks.ViewBufferManager{},
|
viewBufferManagerMap: map[string]*tasks.ViewBufferManager{},
|
||||||
viewPtmxMap: map[string]*os.File{},
|
viewPtmxMap: map[string]*os.File{},
|
||||||
showRecentRepos: showRecentRepos,
|
showRecentRepos: showRecentRepos,
|
||||||
RepoPathStack: &utils.StringStack{},
|
RepoPathStack: &utils.StringStack{},
|
||||||
RepoStateMap: map[Repo]*GuiRepoState{},
|
RepoStateMap: map[Repo]*GuiRepoState{},
|
||||||
CmdLog: []string{},
|
CmdLog: []string{},
|
||||||
suggestionsAsyncHandler: tasks.NewAsyncHandler(),
|
|
||||||
|
|
||||||
// originally we could only hide the command log permanently via the config
|
// originally we could only hide the command log permanently via the config
|
||||||
// but now we do it via state. So we need to still support the config for the
|
// but now we do it via state. So we need to still support the config for the
|
||||||
@ -446,7 +437,9 @@ func NewGui(
|
|||||||
|
|
||||||
gui.PopupHandler = popup.NewPopupHandler(
|
gui.PopupHandler = popup.NewPopupHandler(
|
||||||
cmn,
|
cmn,
|
||||||
gui.createPopupPanel,
|
func(ctx goContext.Context, opts types.CreatePopupPanelOpts) error {
|
||||||
|
return gui.helpers.Confirmation.CreatePopupPanel(ctx, opts)
|
||||||
|
},
|
||||||
func() error { return gui.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) },
|
func() error { return gui.c.Refresh(types.RefreshOptions{Mode: types.ASYNC}) },
|
||||||
gui.popContext,
|
gui.popContext,
|
||||||
gui.currentContext,
|
gui.currentContext,
|
||||||
|
@ -144,3 +144,7 @@ func (self *guiCommon) MainViewPairs() types.MainViewPairs {
|
|||||||
func (self *guiCommon) State() types.IStateAccessor {
|
func (self *guiCommon) State() types.IStateAccessor {
|
||||||
return self.gui.stateAccessor
|
return self.gui.stateAccessor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *guiCommon) KeybindingsOpts() types.KeybindingsOpts {
|
||||||
|
return self.gui.keybindingOpts()
|
||||||
|
}
|
||||||
|
@ -50,7 +50,7 @@ func (self *GuiDriver) CurrentContext() types.Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *GuiDriver) ContextForView(viewName string) types.Context {
|
func (self *GuiDriver) ContextForView(viewName string) types.Context {
|
||||||
context, ok := self.gui.contextForView(viewName)
|
context, ok := self.gui.helpers.View.ContextForView(viewName)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,17 @@ import (
|
|||||||
|
|
||||||
func (gui *Gui) noPopupPanel(f func() error) func() error {
|
func (gui *Gui) noPopupPanel(f func() error) func() error {
|
||||||
return func() error {
|
return func() error {
|
||||||
if gui.popupPanelFocused() {
|
if gui.helpers.Confirmation.IsPopupPanelFocused() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return f()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gui *Gui) outsideFilterMode(f func() error) func() error {
|
||||||
|
return func() error {
|
||||||
|
if !gui.validateNotInFilterMode() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,8 +44,7 @@ func (self *Gui) GetCheatsheetKeybindings() []*types.Binding {
|
|||||||
return bindings
|
return bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
// renaming receiver to 'self' to aid refactoring. Will probably end up moving all Gui handlers to this pattern eventually.
|
func (self *Gui) keybindingOpts() types.KeybindingsOpts {
|
||||||
func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBinding) {
|
|
||||||
config := self.c.UserConfig.Keybinding
|
config := self.c.UserConfig.Keybinding
|
||||||
|
|
||||||
guards := types.KeybindingGuards{
|
guards := types.KeybindingGuards{
|
||||||
@ -43,11 +52,18 @@ func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBi
|
|||||||
NoPopupPanel: self.noPopupPanel,
|
NoPopupPanel: self.noPopupPanel,
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := types.KeybindingsOpts{
|
return types.KeybindingsOpts{
|
||||||
GetKey: keybindings.GetKey,
|
GetKey: keybindings.GetKey,
|
||||||
Config: config,
|
Config: config,
|
||||||
Guards: guards,
|
Guards: guards,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// renaming receiver to 'self' to aid refactoring. Will probably end up moving all Gui handlers to this pattern eventually.
|
||||||
|
func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBinding) {
|
||||||
|
config := self.c.UserConfig.Keybinding
|
||||||
|
|
||||||
|
opts := self.c.KeybindingsOpts()
|
||||||
|
|
||||||
bindings := []*types.Binding{
|
bindings := []*types.Binding{
|
||||||
{
|
{
|
||||||
@ -486,7 +502,7 @@ func (gui *Gui) SetKeybinding(binding *types.Binding) error {
|
|||||||
if gocui.IsMouseKey(binding.Key) {
|
if gocui.IsMouseKey(binding.Key) {
|
||||||
handler = func() error {
|
handler = func() error {
|
||||||
// we ignore click events on views that aren't popup panels, when a popup panel is focused
|
// we ignore click events on views that aren't popup panels, when a popup panel is focused
|
||||||
if gui.popupPanelFocused() && gui.currentViewName() != binding.ViewName {
|
if gui.helpers.Confirmation.IsPopupPanelFocused() && gui.currentViewName() != binding.ViewName {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,7 +518,7 @@ func (gui *Gui) SetMouseKeybinding(binding *gocui.ViewMouseBinding) error {
|
|||||||
baseHandler := binding.Handler
|
baseHandler := binding.Handler
|
||||||
newHandler := func(opts gocui.ViewMouseBindingOpts) error {
|
newHandler := func(opts gocui.ViewMouseBindingOpts) error {
|
||||||
// we ignore click events on views that aren't popup panels, when a popup panel is focused
|
// we ignore click events on views that aren't popup panels, when a popup panel is focused
|
||||||
if gui.popupPanelFocused() && gui.currentViewName() != binding.ViewName {
|
if gui.helpers.Confirmation.IsPopupPanelFocused() && gui.currentViewName() != binding.ViewName {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
|||||||
// if you run `lazygit --logs`
|
// if you run `lazygit --logs`
|
||||||
// this will let you see these branches as prettified json
|
// this will let you see these branches as prettified json
|
||||||
// gui.c.Log.Info(utils.AsJson(gui.State.Model.Branches[0:4]))
|
// gui.c.Log.Info(utils.AsJson(gui.State.Model.Branches[0:4]))
|
||||||
return gui.resizeCurrentPopupPanel()
|
return gui.helpers.Confirmation.ResizeCurrentPopupPanel()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) prepareView(viewName string) (*gocui.View, error) {
|
func (gui *Gui) prepareView(viewName string) (*gocui.View, error) {
|
||||||
@ -245,7 +245,7 @@ func (gui *Gui) getFocusLayout() func(g *gocui.Gui) error {
|
|||||||
return func(g *gocui.Gui) error {
|
return func(g *gocui.Gui) error {
|
||||||
newView := gui.g.CurrentView()
|
newView := gui.g.CurrentView()
|
||||||
// for now we don't consider losing focus to a popup panel as actually losing focus
|
// for now we don't consider losing focus to a popup panel as actually losing focus
|
||||||
if newView != previousView && !gui.isPopupPanel(newView.Name()) {
|
if newView != previousView && !gui.helpers.Confirmation.IsPopupPanel(newView.Name()) {
|
||||||
if err := gui.onViewFocusLost(previousView); err != nil {
|
if err := gui.onViewFocusLost(previousView); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -14,14 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (gui *Gui) menuListContext() *context.MenuContext {
|
func (gui *Gui) menuListContext() *context.MenuContext {
|
||||||
return context.NewMenuContext(
|
return context.NewMenuContext(gui.c)
|
||||||
gui.Views.Menu,
|
|
||||||
gui.c,
|
|
||||||
gui.getMenuOptions,
|
|
||||||
func(content string) {
|
|
||||||
gui.Views.Tooltip.SetContent(content)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) filesListContext() *context.WorkingTreeContext {
|
func (gui *Gui) filesListContext() *context.WorkingTreeContext {
|
||||||
@ -237,14 +230,7 @@ func (gui *Gui) submodulesListContext() *context.SubmodulesContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) suggestionsListContext() *context.SuggestionsContext {
|
func (gui *Gui) suggestionsListContext() *context.SuggestionsContext {
|
||||||
return context.NewSuggestionsContext(
|
return context.NewSuggestionsContext(gui.c)
|
||||||
func() []*types.Suggestion { return gui.State.Suggestions },
|
|
||||||
gui.Views.Suggestions,
|
|
||||||
func(startIdx int, length int) [][]string {
|
|
||||||
return presentation.GetSuggestionListDisplayStrings(gui.State.Suggestions)
|
|
||||||
},
|
|
||||||
gui.c,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) getListContexts() []types.IListContext {
|
func (gui *Gui) getListContexts() []types.IListContext {
|
||||||
|
@ -1,25 +1,12 @@
|
|||||||
package gui
|
package gui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/theme"
|
"github.com/jesseduffield/lazygit/pkg/theme"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (gui *Gui) getMenuOptions() map[string]string {
|
|
||||||
keybindingConfig := gui.c.UserConfig.Keybinding
|
|
||||||
|
|
||||||
return map[string]string{
|
|
||||||
keybindings.Label(keybindingConfig.Universal.Return): gui.c.Tr.LcClose,
|
|
||||||
fmt.Sprintf("%s %s", keybindings.Label(keybindingConfig.Universal.PrevItem), keybindings.Label(keybindingConfig.Universal.NextItem)): gui.c.Tr.LcNavigate,
|
|
||||||
keybindings.Label(keybindingConfig.Universal.Select): gui.c.Tr.LcExecute,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// note: items option is mutated by this function
|
// note: items option is mutated by this function
|
||||||
func (gui *Gui) createMenu(opts types.CreateMenuOptions) error {
|
func (gui *Gui) createMenu(opts types.CreateMenuOptions) error {
|
||||||
if !opts.HideCancel {
|
if !opts.HideCancel {
|
||||||
|
@ -2,12 +2,11 @@ package gui
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jesseduffield/generics/maps"
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OptionsMapMgr struct {
|
type OptionsMapMgr struct {
|
||||||
@ -21,36 +20,73 @@ func (gui *Gui) renderContextOptionsMap(c types.Context) {
|
|||||||
|
|
||||||
// render the options available for the current context at the bottom of the screen
|
// render the options available for the current context at the bottom of the screen
|
||||||
func (self *OptionsMapMgr) renderContextOptionsMap(c types.Context) {
|
func (self *OptionsMapMgr) renderContextOptionsMap(c types.Context) {
|
||||||
optionsMap := c.GetOptionsMap()
|
bindingsToDisplay := lo.Filter(c.GetKeybindings(self.c.KeybindingsOpts()), func(binding *types.Binding, _ int) bool {
|
||||||
if optionsMap == nil {
|
return binding.Display
|
||||||
optionsMap = self.globalOptionsMap()
|
})
|
||||||
|
|
||||||
|
var optionsMap []bindingInfo
|
||||||
|
if len(bindingsToDisplay) == 0 {
|
||||||
|
optionsMap = self.globalOptions()
|
||||||
|
} else {
|
||||||
|
optionsMap = lo.Map(bindingsToDisplay, func(binding *types.Binding, _ int) bindingInfo {
|
||||||
|
return bindingInfo{
|
||||||
|
key: keybindings.LabelFromKey(binding.Key),
|
||||||
|
description: binding.Description,
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
self.renderOptions(self.optionsMapToString(optionsMap))
|
self.renderOptions(self.formatBindingInfos(optionsMap))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *OptionsMapMgr) optionsMapToString(optionsMap map[string]string) string {
|
func (self *OptionsMapMgr) formatBindingInfos(bindingInfos []bindingInfo) string {
|
||||||
options := maps.MapToSlice(optionsMap, func(key string, description string) string {
|
return strings.Join(
|
||||||
return key + ": " + description
|
lo.Map(bindingInfos, func(bindingInfo bindingInfo, _ int) string {
|
||||||
})
|
return fmt.Sprintf("%s: %s", bindingInfo.key, bindingInfo.description)
|
||||||
sort.Strings(options)
|
}),
|
||||||
return strings.Join(options, ", ")
|
", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *OptionsMapMgr) renderOptions(options string) {
|
func (self *OptionsMapMgr) renderOptions(options string) {
|
||||||
self.c.SetViewContent(self.c.Views().Options, options)
|
self.c.SetViewContent(self.c.Views().Options, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *OptionsMapMgr) globalOptionsMap() map[string]string {
|
func (self *OptionsMapMgr) globalOptions() []bindingInfo {
|
||||||
keybindingConfig := self.c.UserConfig.Keybinding
|
keybindingConfig := self.c.UserConfig.Keybinding
|
||||||
|
|
||||||
return map[string]string{
|
return []bindingInfo{
|
||||||
fmt.Sprintf("%s/%s", keybindings.Label(keybindingConfig.Universal.ScrollUpMain), keybindings.Label(keybindingConfig.Universal.ScrollDownMain)): self.c.Tr.LcScroll,
|
{
|
||||||
fmt.Sprintf("%s %s %s %s", keybindings.Label(keybindingConfig.Universal.PrevBlock), keybindings.Label(keybindingConfig.Universal.NextBlock), keybindings.Label(keybindingConfig.Universal.PrevItem), keybindings.Label(keybindingConfig.Universal.NextItem)): self.c.Tr.LcNavigate,
|
key: fmt.Sprintf("%s/%s", keybindings.Label(keybindingConfig.Universal.ScrollUpMain), keybindings.Label(keybindingConfig.Universal.ScrollDownMain)),
|
||||||
keybindings.Label(keybindingConfig.Universal.Return): self.c.Tr.LcCancel,
|
description: self.c.Tr.LcScroll,
|
||||||
keybindings.Label(keybindingConfig.Universal.Quit): self.c.Tr.LcQuit,
|
},
|
||||||
keybindings.Label(keybindingConfig.Universal.OptionMenuAlt1): self.c.Tr.LcMenu,
|
{
|
||||||
fmt.Sprintf("%s-%s", keybindings.Label(keybindingConfig.Universal.JumpToBlock[0]), keybindings.Label(keybindingConfig.Universal.JumpToBlock[len(keybindingConfig.Universal.JumpToBlock)-1])): self.c.Tr.LcJump,
|
key: fmt.Sprintf("%s %s %s %s", keybindings.Label(keybindingConfig.Universal.PrevBlock), keybindings.Label(keybindingConfig.Universal.NextBlock), keybindings.Label(keybindingConfig.Universal.PrevItem), keybindings.Label(keybindingConfig.Universal.NextItem)),
|
||||||
fmt.Sprintf("%s/%s", keybindings.Label(keybindingConfig.Universal.ScrollLeft), keybindings.Label(keybindingConfig.Universal.ScrollRight)): self.c.Tr.LcScrollLeftRight,
|
description: self.c.Tr.LcNavigate,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: keybindings.Label(keybindingConfig.Universal.Return),
|
||||||
|
description: self.c.Tr.LcCancel,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: keybindings.Label(keybindingConfig.Universal.Quit),
|
||||||
|
description: self.c.Tr.LcQuit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: keybindings.Label(keybindingConfig.Universal.OptionMenuAlt1),
|
||||||
|
description: self.c.Tr.LcMenu,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: fmt.Sprintf("%s-%s", keybindings.Label(keybindingConfig.Universal.JumpToBlock[0]), keybindings.Label(keybindingConfig.Universal.JumpToBlock[len(keybindingConfig.Universal.JumpToBlock)-1])),
|
||||||
|
description: self.c.Tr.LcJump,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: fmt.Sprintf("%s/%s", keybindings.Label(keybindingConfig.Universal.ScrollLeft), keybindings.Label(keybindingConfig.Universal.ScrollRight)),
|
||||||
|
description: self.c.Tr.LcScrollLeftRight,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type bindingInfo struct {
|
||||||
|
key string
|
||||||
|
description string
|
||||||
|
}
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
package gui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (gui *Gui) getSelectedSuggestionValue() string {
|
|
||||||
selectedSuggestion := gui.getSelectedSuggestion()
|
|
||||||
|
|
||||||
if selectedSuggestion != nil {
|
|
||||||
return selectedSuggestion.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) getSelectedSuggestion() *types.Suggestion {
|
|
||||||
return gui.State.Contexts.Suggestions.GetSelected()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) setSuggestions(suggestions []*types.Suggestion) {
|
|
||||||
gui.State.Suggestions = suggestions
|
|
||||||
gui.State.Contexts.Suggestions.SetSelectedLineIdx(0)
|
|
||||||
gui.c.ResetViewOrigin(gui.Views.Suggestions)
|
|
||||||
_ = gui.State.Contexts.Suggestions.HandleRender()
|
|
||||||
}
|
|
@ -82,6 +82,8 @@ type IGuiCommon interface {
|
|||||||
Mutexes() Mutexes
|
Mutexes() Mutexes
|
||||||
|
|
||||||
State() IStateAccessor
|
State() IStateAccessor
|
||||||
|
|
||||||
|
KeybindingsOpts() KeybindingsOpts
|
||||||
}
|
}
|
||||||
|
|
||||||
type IPopupHandler interface {
|
type IPopupHandler interface {
|
||||||
|
@ -17,6 +17,12 @@ type Binding struct {
|
|||||||
Tag string // e.g. 'navigation'. Used for grouping things in the cheatsheet
|
Tag string // e.g. 'navigation'. Used for grouping things in the cheatsheet
|
||||||
OpensMenu bool
|
OpensMenu bool
|
||||||
|
|
||||||
|
// If true, the keybinding will appear at the bottom of the screen. If
|
||||||
|
// the given view has no bindings with Display: true, the default keybindings
|
||||||
|
// will be displayed instead.
|
||||||
|
// TODO: implement this
|
||||||
|
Display bool
|
||||||
|
|
||||||
// to be displayed if the keybinding is highlighted from within a menu
|
// to be displayed if the keybinding is highlighted from within a menu
|
||||||
Tooltip string
|
Tooltip string
|
||||||
}
|
}
|
||||||
|
@ -62,71 +62,6 @@ func (gui *Gui) currentViewName() string {
|
|||||||
return currentView.Name()
|
return currentView.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *Gui) resizeCurrentPopupPanel() error {
|
|
||||||
v := gui.g.CurrentView()
|
|
||||||
if v == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if v == gui.Views.Menu {
|
|
||||||
gui.resizeMenu()
|
|
||||||
} else if v == gui.Views.Confirmation || v == gui.Views.Suggestions {
|
|
||||||
gui.resizeConfirmationPanel()
|
|
||||||
} else if gui.isPopupPanel(v.Name()) {
|
|
||||||
return gui.resizePopupPanel(v, v.Buffer())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) resizePopupPanel(v *gocui.View, content string) error {
|
|
||||||
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(v.Wrap, content)
|
|
||||||
_, err := gui.g.SetView(v.Name(), x0, y0, x1, y1, 0)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) resizeMenu() {
|
|
||||||
itemCount := gui.State.Contexts.Menu.GetList().Len()
|
|
||||||
offset := 3
|
|
||||||
panelWidth := gui.getConfirmationPanelWidth()
|
|
||||||
x0, y0, x1, y1 := gui.getConfirmationPanelDimensionsForContentHeight(panelWidth, itemCount+offset)
|
|
||||||
menuBottom := y1 - offset
|
|
||||||
_, _ = gui.g.SetView(gui.Views.Menu.Name(), x0, y0, x1, menuBottom, 0)
|
|
||||||
|
|
||||||
tooltipTop := menuBottom + 1
|
|
||||||
tooltipHeight := gui.getMessageHeight(true, gui.State.Contexts.Menu.GetSelected().Tooltip, panelWidth) + 2 // plus 2 for the frame
|
|
||||||
_, _ = gui.g.SetView(gui.Views.Tooltip.Name(), x0, tooltipTop, x1, tooltipTop+tooltipHeight-1, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) resizeConfirmationPanel() {
|
|
||||||
suggestionsViewHeight := 0
|
|
||||||
if gui.Views.Suggestions.Visible {
|
|
||||||
suggestionsViewHeight = 11
|
|
||||||
}
|
|
||||||
panelWidth := gui.getConfirmationPanelWidth()
|
|
||||||
prompt := gui.Views.Confirmation.Buffer()
|
|
||||||
wrap := true
|
|
||||||
if gui.Views.Confirmation.Editable {
|
|
||||||
prompt = gui.Views.Confirmation.TextArea.GetContent()
|
|
||||||
wrap = false
|
|
||||||
}
|
|
||||||
panelHeight := gui.getMessageHeight(wrap, prompt, panelWidth) + suggestionsViewHeight
|
|
||||||
x0, y0, x1, y1 := gui.getConfirmationPanelDimensionsAux(panelWidth, panelHeight)
|
|
||||||
confirmationViewBottom := y1 - suggestionsViewHeight
|
|
||||||
_, _ = gui.g.SetView(gui.Views.Confirmation.Name(), x0, y0, x1, confirmationViewBottom, 0)
|
|
||||||
|
|
||||||
suggestionsViewTop := confirmationViewBottom + 1
|
|
||||||
_, _ = gui.g.SetView(gui.Views.Suggestions.Name(), x0, suggestionsViewTop, x1, suggestionsViewTop+suggestionsViewHeight, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) isPopupPanel(viewName string) bool {
|
|
||||||
return viewName == "commitMessage" || viewName == "confirmation" || viewName == "menu"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) popupPanelFocused() bool {
|
|
||||||
return gui.isPopupPanel(gui.currentViewName())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gui *Gui) onViewTabClick(windowName string, tabIndex int) error {
|
func (gui *Gui) onViewTabClick(windowName string, tabIndex int) error {
|
||||||
tabs := gui.viewTabMap()[windowName]
|
tabs := gui.viewTabMap()[windowName]
|
||||||
if len(tabs) == 0 {
|
if len(tabs) == 0 {
|
||||||
|
@ -156,6 +156,7 @@ func (gui *Gui) createAllViews() error {
|
|||||||
gui.Views.CommitMessage.Editor = gocui.EditorFunc(gui.commitMessageEditor)
|
gui.Views.CommitMessage.Editor = gocui.EditorFunc(gui.commitMessageEditor)
|
||||||
|
|
||||||
gui.Views.Confirmation.Visible = false
|
gui.Views.Confirmation.Visible = false
|
||||||
|
gui.Views.Confirmation.Editor = gocui.EditorFunc(gui.defaultEditor)
|
||||||
|
|
||||||
gui.Views.Suggestions.Visible = false
|
gui.Views.Suggestions.Visible = false
|
||||||
|
|
||||||
|
@ -94,9 +94,9 @@ func chineseTranslationSet() TranslationSet {
|
|||||||
LcNewBranch: "新分支",
|
LcNewBranch: "新分支",
|
||||||
LcDeleteBranch: "删除分支",
|
LcDeleteBranch: "删除分支",
|
||||||
NoBranchesThisRepo: "此仓库中没有分支",
|
NoBranchesThisRepo: "此仓库中没有分支",
|
||||||
CommitMessageConfirm: "{{.keyBindClose}}:关闭,{{.keyBindNewLine}}:新行,{{.keyBindConfirm}}:确认",
|
|
||||||
CommitWithoutMessageErr: "您必须编写提交消息才能进行提交",
|
CommitWithoutMessageErr: "您必须编写提交消息才能进行提交",
|
||||||
CloseConfirm: "{{.keyBindClose}}:关闭,{{.keyBindConfirm}}:确认",
|
LcCloseCancel: "关闭",
|
||||||
|
LcConfirm: "确认",
|
||||||
LcClose: "关闭",
|
LcClose: "关闭",
|
||||||
LcQuit: "退出",
|
LcQuit: "退出",
|
||||||
LcSquashDown: "向下压缩",
|
LcSquashDown: "向下压缩",
|
||||||
@ -117,8 +117,6 @@ func chineseTranslationSet() TranslationSet {
|
|||||||
LcAmendToCommit: "用已暂存的更改来修补提交",
|
LcAmendToCommit: "用已暂存的更改来修补提交",
|
||||||
LcRenameCommitEditor: "使用编辑器重命名提交",
|
LcRenameCommitEditor: "使用编辑器重命名提交",
|
||||||
Error: "错误",
|
Error: "错误",
|
||||||
LcSelectHunk: "切换区块",
|
|
||||||
LcNavigateConflicts: "浏览冲突",
|
|
||||||
LcPickHunk: "选中区块",
|
LcPickHunk: "选中区块",
|
||||||
LcPickAllHunks: "选中所有区块",
|
LcPickAllHunks: "选中所有区块",
|
||||||
LcUndo: "撤销",
|
LcUndo: "撤销",
|
||||||
|
@ -60,9 +60,9 @@ func dutchTranslationSet() TranslationSet {
|
|||||||
LcNewBranch: "nieuwe branch",
|
LcNewBranch: "nieuwe branch",
|
||||||
LcDeleteBranch: "verwijder branch",
|
LcDeleteBranch: "verwijder branch",
|
||||||
NoBranchesThisRepo: "Geen branches voor deze repo",
|
NoBranchesThisRepo: "Geen branches voor deze repo",
|
||||||
CommitMessageConfirm: "{{.keyBindClose}}: Sluiten, {{.keyBindNewLine}}: Nieuwe lijn, {{.keyBindConfirm}}: Bevestig",
|
|
||||||
CommitWithoutMessageErr: "Je kan geen commit maken zonder commit bericht",
|
CommitWithoutMessageErr: "Je kan geen commit maken zonder commit bericht",
|
||||||
CloseConfirm: "{{.keyBindClose}}: Sluiten, {{.keyBindConfirm}}: Bevestig",
|
LcCloseCancel: "sluiten",
|
||||||
|
LcConfirm: "bevestig",
|
||||||
LcClose: "sluiten",
|
LcClose: "sluiten",
|
||||||
LcQuit: "quit",
|
LcQuit: "quit",
|
||||||
LcSquashDown: "squash beneden",
|
LcSquashDown: "squash beneden",
|
||||||
@ -83,8 +83,6 @@ func dutchTranslationSet() TranslationSet {
|
|||||||
LcRenameCommitEditor: "hernoem commit met editor",
|
LcRenameCommitEditor: "hernoem commit met editor",
|
||||||
NoCommitsThisBranch: "Geen commits in deze branch",
|
NoCommitsThisBranch: "Geen commits in deze branch",
|
||||||
Error: "Foutmelding",
|
Error: "Foutmelding",
|
||||||
LcSelectHunk: "selecteer stuk",
|
|
||||||
LcNavigateConflicts: "navigeer conflicts",
|
|
||||||
LcPickHunk: "kies stuk",
|
LcPickHunk: "kies stuk",
|
||||||
LcPickAllHunks: "kies beide stukken",
|
LcPickAllHunks: "kies beide stukken",
|
||||||
LcUndo: "ongedaan maken",
|
LcUndo: "ongedaan maken",
|
||||||
|
@ -80,10 +80,10 @@ type TranslationSet struct {
|
|||||||
LcNewBranch string
|
LcNewBranch string
|
||||||
LcDeleteBranch string
|
LcDeleteBranch string
|
||||||
NoBranchesThisRepo string
|
NoBranchesThisRepo string
|
||||||
CommitMessageConfirm string
|
|
||||||
CommitWithoutMessageErr string
|
CommitWithoutMessageErr string
|
||||||
CloseConfirm string
|
|
||||||
LcClose string
|
LcClose string
|
||||||
|
LcCloseCancel string
|
||||||
|
LcConfirm string
|
||||||
LcQuit string
|
LcQuit string
|
||||||
LcSquashDown string
|
LcSquashDown string
|
||||||
LcFixupCommit string
|
LcFixupCommit string
|
||||||
@ -107,8 +107,6 @@ type TranslationSet struct {
|
|||||||
NoCommitsThisBranch string
|
NoCommitsThisBranch string
|
||||||
UpdateRefHere string
|
UpdateRefHere string
|
||||||
Error string
|
Error string
|
||||||
LcSelectHunk string
|
|
||||||
LcNavigateConflicts string
|
|
||||||
LcPickHunk string
|
LcPickHunk string
|
||||||
LcPickAllHunks string
|
LcPickAllHunks string
|
||||||
LcUndo string
|
LcUndo string
|
||||||
@ -750,10 +748,10 @@ func EnglishTranslationSet() TranslationSet {
|
|||||||
LcNewBranch: "new branch",
|
LcNewBranch: "new branch",
|
||||||
LcDeleteBranch: "delete branch",
|
LcDeleteBranch: "delete branch",
|
||||||
NoBranchesThisRepo: "No branches for this repo",
|
NoBranchesThisRepo: "No branches for this repo",
|
||||||
CommitMessageConfirm: "{{.keyBindClose}}: close, {{.keyBindNewLine}}: new line, {{.keyBindConfirm}}: confirm",
|
|
||||||
CommitWithoutMessageErr: "You cannot commit without a commit message",
|
CommitWithoutMessageErr: "You cannot commit without a commit message",
|
||||||
CloseConfirm: "{{.keyBindClose}}: close/cancel, {{.keyBindConfirm}}: confirm",
|
|
||||||
LcClose: "close",
|
LcClose: "close",
|
||||||
|
LcCloseCancel: "close/cancel",
|
||||||
|
LcConfirm: "confirm",
|
||||||
LcQuit: "quit",
|
LcQuit: "quit",
|
||||||
LcSquashDown: "squash down",
|
LcSquashDown: "squash down",
|
||||||
LcFixupCommit: "fixup commit",
|
LcFixupCommit: "fixup commit",
|
||||||
@ -777,8 +775,6 @@ func EnglishTranslationSet() TranslationSet {
|
|||||||
SureResetCommitAuthor: "The author field of this commit will be updated to match the configured user. This also renews the author timestamp. Continue?",
|
SureResetCommitAuthor: "The author field of this commit will be updated to match the configured user. This also renews the author timestamp. Continue?",
|
||||||
LcRenameCommitEditor: "reword commit with editor",
|
LcRenameCommitEditor: "reword commit with editor",
|
||||||
Error: "Error",
|
Error: "Error",
|
||||||
LcSelectHunk: "select hunk",
|
|
||||||
LcNavigateConflicts: "navigate conflicts",
|
|
||||||
LcPickHunk: "pick hunk",
|
LcPickHunk: "pick hunk",
|
||||||
LcPickAllHunks: "pick all hunks",
|
LcPickAllHunks: "pick all hunks",
|
||||||
LcUndo: "undo",
|
LcUndo: "undo",
|
||||||
|
@ -85,9 +85,9 @@ func japaneseTranslationSet() TranslationSet {
|
|||||||
LcNewBranch: "新しいブランチを作成",
|
LcNewBranch: "新しいブランチを作成",
|
||||||
LcDeleteBranch: "ブランチを削除",
|
LcDeleteBranch: "ブランチを削除",
|
||||||
NoBranchesThisRepo: "リポジトリにブランチが存在しません",
|
NoBranchesThisRepo: "リポジトリにブランチが存在しません",
|
||||||
CommitMessageConfirm: "{{.keyBindClose}}: 閉じる, {{.keyBindNewLine}}: 改行, {{.keyBindConfirm}}: 確定",
|
|
||||||
CommitWithoutMessageErr: "コミットメッセージを入力してください",
|
CommitWithoutMessageErr: "コミットメッセージを入力してください",
|
||||||
CloseConfirm: "{{.keyBindClose}}: 閉じる/キャンセル, {{.keyBindConfirm}}: 確認",
|
LcCloseCancel: "閉じる/キャンセル",
|
||||||
|
LcConfirm: "確認",
|
||||||
LcClose: "閉じる",
|
LcClose: "閉じる",
|
||||||
LcQuit: "終了",
|
LcQuit: "終了",
|
||||||
// LcSquashDown: "squash down",
|
// LcSquashDown: "squash down",
|
||||||
@ -108,8 +108,6 @@ func japaneseTranslationSet() TranslationSet {
|
|||||||
LcAmendToCommit: "ステージされた変更でamendコミット",
|
LcAmendToCommit: "ステージされた変更でamendコミット",
|
||||||
LcRenameCommitEditor: "エディタでコミットメッセージを編集",
|
LcRenameCommitEditor: "エディタでコミットメッセージを編集",
|
||||||
Error: "エラー",
|
Error: "エラー",
|
||||||
LcSelectHunk: "hunkを選択",
|
|
||||||
LcNavigateConflicts: "コンフリクトを移動",
|
|
||||||
// LcPickHunk: "pick hunk",
|
// LcPickHunk: "pick hunk",
|
||||||
// LcPickAllHunks: "pick all hunks",
|
// LcPickAllHunks: "pick all hunks",
|
||||||
LcUndo: "アンドゥ",
|
LcUndo: "アンドゥ",
|
||||||
|
@ -84,9 +84,9 @@ func koreanTranslationSet() TranslationSet {
|
|||||||
LcNewBranch: "새 브랜치 생성",
|
LcNewBranch: "새 브랜치 생성",
|
||||||
LcDeleteBranch: "브랜치 삭제",
|
LcDeleteBranch: "브랜치 삭제",
|
||||||
NoBranchesThisRepo: "저장소에 브랜치가 존재하지 않습니다.",
|
NoBranchesThisRepo: "저장소에 브랜치가 존재하지 않습니다.",
|
||||||
CommitMessageConfirm: "{{.keyBindClose}}: 닫기, {{.keyBindNewLine}}: 개행, {{.keyBindConfirm}}: 확인",
|
|
||||||
CommitWithoutMessageErr: "커밋 메시지를 입력하세요.",
|
CommitWithoutMessageErr: "커밋 메시지를 입력하세요.",
|
||||||
CloseConfirm: "{{.keyBindClose}}: 닫기/취소, {{.keyBindConfirm}}: 확인",
|
LcCloseCancel: "닫기/취소",
|
||||||
|
LcConfirm: "확인",
|
||||||
LcClose: "닫기",
|
LcClose: "닫기",
|
||||||
LcQuit: "종료",
|
LcQuit: "종료",
|
||||||
LcSquashDown: "squash down",
|
LcSquashDown: "squash down",
|
||||||
@ -109,8 +109,6 @@ func koreanTranslationSet() TranslationSet {
|
|||||||
SureResetCommitAuthor: "The author field of this commit will be updated to match the configured user. This also renews the author timestamp. Continue?",
|
SureResetCommitAuthor: "The author field of this commit will be updated to match the configured user. This also renews the author timestamp. Continue?",
|
||||||
LcRenameCommitEditor: "에디터에서 커밋메시지 수정",
|
LcRenameCommitEditor: "에디터에서 커밋메시지 수정",
|
||||||
Error: "오류",
|
Error: "오류",
|
||||||
LcSelectHunk: "hunk를 선택",
|
|
||||||
LcNavigateConflicts: "navigate conflicts",
|
|
||||||
LcPickHunk: "pick hunk",
|
LcPickHunk: "pick hunk",
|
||||||
LcPickAllHunks: "pick all hunks",
|
LcPickAllHunks: "pick all hunks",
|
||||||
LcUndo: "되돌리기",
|
LcUndo: "되돌리기",
|
||||||
|
@ -55,9 +55,9 @@ func polishTranslationSet() TranslationSet {
|
|||||||
LcNewBranch: "nowa gałąź",
|
LcNewBranch: "nowa gałąź",
|
||||||
LcDeleteBranch: "usuń gałąź",
|
LcDeleteBranch: "usuń gałąź",
|
||||||
NoBranchesThisRepo: "Brak gałęzi dla tego repozytorium",
|
NoBranchesThisRepo: "Brak gałęzi dla tego repozytorium",
|
||||||
CommitMessageConfirm: "{{.keyBindClose}}: zamknij, {{.keyBindNewLine}}: nowa linia, {{.keyBindConfirm}}: potwierdź",
|
|
||||||
CommitWithoutMessageErr: "Nie możesz commitować bez komunikatu",
|
CommitWithoutMessageErr: "Nie możesz commitować bez komunikatu",
|
||||||
CloseConfirm: "{{.keyBindClose}}: zamknij, {{.keyBindConfirm}}: potwierdź",
|
LcCloseCancel: "zamknij",
|
||||||
|
LcConfirm: "potwierdź",
|
||||||
LcClose: "zamknij",
|
LcClose: "zamknij",
|
||||||
LcSquashDown: "ściśnij",
|
LcSquashDown: "ściśnij",
|
||||||
LcFixupCommit: "napraw commit",
|
LcFixupCommit: "napraw commit",
|
||||||
@ -68,8 +68,6 @@ func polishTranslationSet() TranslationSet {
|
|||||||
LcRewordCommit: "zmień nazwę commita",
|
LcRewordCommit: "zmień nazwę commita",
|
||||||
LcRenameCommitEditor: "zmień nazwę commita w edytorze",
|
LcRenameCommitEditor: "zmień nazwę commita w edytorze",
|
||||||
Error: "Błąd",
|
Error: "Błąd",
|
||||||
LcSelectHunk: "wybierz kawałek",
|
|
||||||
LcNavigateConflicts: "nawiguj konflikty",
|
|
||||||
LcPickHunk: "wybierz kawałek",
|
LcPickHunk: "wybierz kawałek",
|
||||||
LcPickAllHunks: "wybierz oba kawałki",
|
LcPickAllHunks: "wybierz oba kawałki",
|
||||||
LcUndo: "cofnij",
|
LcUndo: "cofnij",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user