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
|
||||
CustomPatchBuilderSecondary types.Context
|
||||
MergeConflicts *MergeConflictsContext
|
||||
Confirmation types.Context
|
||||
CommitMessage types.Context
|
||||
Confirmation *ConfirmationContext
|
||||
CommitMessage *CommitMessageContext
|
||||
CommandLog types.Context
|
||||
|
||||
// display contexts
|
||||
|
@ -2,7 +2,6 @@ package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/generics/slices"
|
||||
"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"
|
||||
@ -16,11 +15,7 @@ type MenuContext struct {
|
||||
var _ types.IListContext = (*MenuContext)(nil)
|
||||
|
||||
func NewMenuContext(
|
||||
view *gocui.View,
|
||||
|
||||
c *types.HelperCommon,
|
||||
getOptionsMap func() map[string]string,
|
||||
renderToDescriptionView func(string),
|
||||
) *MenuContext {
|
||||
viewModel := NewMenuViewModel()
|
||||
|
||||
@ -28,11 +23,10 @@ func NewMenuContext(
|
||||
MenuViewModel: viewModel,
|
||||
ListContextTrait: &ListContextTrait{
|
||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||
View: view,
|
||||
View: c.Views().Menu,
|
||||
WindowName: "menu",
|
||||
Key: "menu",
|
||||
Kind: types.TEMPORARY_POPUP,
|
||||
OnGetOptionsMap: getOptionsMap,
|
||||
Focusable: true,
|
||||
HasUncontrolledBounds: true,
|
||||
}), ContextCallbackOpts{}),
|
||||
|
@ -30,7 +30,6 @@ func NewMergeConflictsContext(
|
||||
opts ContextCallbackOpts,
|
||||
|
||||
c *types.HelperCommon,
|
||||
getOptionsMap func() map[string]string,
|
||||
) *MergeConflictsContext {
|
||||
viewModel := &ConflictsViewModel{
|
||||
state: mergeconflicts.NewState(),
|
||||
@ -46,7 +45,6 @@ func NewMergeConflictsContext(
|
||||
View: view,
|
||||
WindowName: "main",
|
||||
Key: MERGE_CONFLICTS_CONTEXT_KEY,
|
||||
OnGetOptionsMap: getOptionsMap,
|
||||
Focusable: true,
|
||||
HighlightOnFocus: true,
|
||||
}),
|
||||
|
@ -24,8 +24,6 @@ func NewPatchExplorerContext(
|
||||
windowName string,
|
||||
key types.ContextKey,
|
||||
|
||||
onFocus func(types.OnFocusOpts) error,
|
||||
onFocusLost func(opts types.OnFocusLostOpts) error,
|
||||
getIncludedLineIndices func() []int,
|
||||
|
||||
c *types.HelperCommon,
|
||||
@ -43,10 +41,7 @@ func NewPatchExplorerContext(
|
||||
Kind: types.MAIN_CONTEXT,
|
||||
Focusable: true,
|
||||
HighlightOnFocus: true,
|
||||
}), ContextCallbackOpts{
|
||||
OnFocus: onFocus,
|
||||
OnFocusLost: onFocusLost,
|
||||
}),
|
||||
}), ContextCallbackOpts{}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,31 +1,53 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/tasks"
|
||||
)
|
||||
|
||||
type SuggestionsContext struct {
|
||||
*BasicViewModel[*types.Suggestion]
|
||||
*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)
|
||||
|
||||
func NewSuggestionsContext(
|
||||
getModel func() []*types.Suggestion,
|
||||
view *gocui.View,
|
||||
getDisplayStrings func(startIdx int, length int) [][]string,
|
||||
|
||||
c *types.HelperCommon,
|
||||
) *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)
|
||||
|
||||
return &SuggestionsContext{
|
||||
State: state,
|
||||
BasicViewModel: viewModel,
|
||||
ListContextTrait: &ListContextTrait{
|
||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||
View: view,
|
||||
View: c.Views().Suggestions,
|
||||
WindowName: "suggestions",
|
||||
Key: SUGGESTIONS_CONTEXT_KEY,
|
||||
Kind: types.PERSISTENT_POPUP,
|
||||
@ -47,3 +69,22 @@ func (self *SuggestionsContext) GetSelectedItemId() string {
|
||||
|
||||
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,
|
||||
"main",
|
||||
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 },
|
||||
gui.c,
|
||||
),
|
||||
@ -100,23 +83,6 @@ func (gui *Gui) contextTree() *context.ContextTree {
|
||||
gui.Views.StagingSecondary,
|
||||
"secondary",
|
||||
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 },
|
||||
gui.c,
|
||||
),
|
||||
@ -124,21 +90,6 @@ func (gui *Gui) contextTree() *context.ContextTree {
|
||||
gui.Views.PatchBuilding,
|
||||
"main",
|
||||
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 {
|
||||
filename := gui.State.Contexts.CommitFiles.GetSelectedPath()
|
||||
includedLineIndices, err := gui.git.Patch.PatchBuilder.GetFileIncLineIndices(filename)
|
||||
@ -165,37 +116,9 @@ func (gui *Gui) contextTree() *context.ContextTree {
|
||||
gui.Views.MergeConflicts,
|
||||
context.ContextCallbackOpts{},
|
||||
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(
|
||||
context.NewBaseContext(context.NewBaseContextOpts{
|
||||
Kind: types.PERSISTENT_POPUP,
|
||||
@ -214,12 +137,7 @@ func (gui *Gui) contextTree() *context.ContextTree {
|
||||
Key: context.COMMAND_LOG_CONTEXT_KEY,
|
||||
Focusable: true,
|
||||
}),
|
||||
context.ContextCallbackOpts{
|
||||
OnFocusLost: func(opts types.OnFocusLostOpts) error {
|
||||
gui.Views.Extras.Autoscroll = true
|
||||
return nil
|
||||
},
|
||||
},
|
||||
context.ContextCallbackOpts{},
|
||||
),
|
||||
Options: context.NewDisplayContext(context.OPTIONS_CONTEXT_KEY, gui.Views.Options, "options"),
|
||||
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)
|
||||
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 })
|
||||
getSavedCommitMessage := func() string {
|
||||
return gui.State.savedCommitMessage
|
||||
@ -66,6 +66,7 @@ func (gui *Gui) resetControllers() {
|
||||
Window: helpers.NewWindowHelper(helperCommon, viewHelper, gui.State.Contexts),
|
||||
View: viewHelper,
|
||||
Refresh: refreshHelper,
|
||||
Confirmation: helpers.NewConfirmationHelper(helperCommon, gui.State.Contexts),
|
||||
}
|
||||
|
||||
gui.CustomCommandsClient = custom_commands.NewClient(
|
||||
@ -151,6 +152,9 @@ func (gui *Gui) resetControllers() {
|
||||
reflogCommitsController := controllers.NewReflogCommitsController(common, gui.State.Contexts.ReflogCommits)
|
||||
subCommitsController := controllers.NewSubCommitsController(common, gui.State.Contexts.SubCommits)
|
||||
statusController := controllers.NewStatusController(common)
|
||||
commandLogController := controllers.NewCommandLogController(common)
|
||||
confirmationController := controllers.NewConfirmationController(common)
|
||||
suggestionsController := controllers.NewSuggestionsController(common)
|
||||
|
||||
setSubCommits := func(commits []*models.Commit) {
|
||||
gui.Mutexes.SubCommitsMutex.Lock()
|
||||
@ -279,6 +283,18 @@ func (gui *Gui) resetControllers() {
|
||||
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,
|
||||
syncController,
|
||||
undoController,
|
||||
@ -303,7 +319,7 @@ func (gui *Gui) getSetTextareaTextFn(getView func() *gocui.View) func(string) {
|
||||
view := getView()
|
||||
view.ClearTextArea()
|
||||
view.TextArea.TypeString(text)
|
||||
_ = gui.resizePopupPanel(view, view.TextArea.GetContent())
|
||||
_ = gui.helpers.Confirmation.ResizePopupPanel(view, view.TextArea.GetContent())
|
||||
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
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"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 {
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.SubmitEditorText),
|
||||
Handler: self.confirm,
|
||||
Key: opts.GetKey(opts.Config.Universal.SubmitEditorText),
|
||||
Handler: self.confirm,
|
||||
Description: self.c.Tr.LcConfirm,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||
Handler: self.close,
|
||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||
Handler: self.close,
|
||||
Description: self.c.Tr.LcClose,
|
||||
},
|
||||
}
|
||||
|
||||
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 {
|
||||
return self.context()
|
||||
}
|
||||
|
||||
// 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
|
||||
func (self *CommitMessageController) context() types.Context {
|
||||
func (self *CommitMessageController) context() *context.CommitMessageContext {
|
||||
return self.contexts.CommitMessage
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
@ -21,14 +22,36 @@ func NewConfirmationController(
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func (self *ConfirmationController) GetOnFocusLost() func(types.OnFocusLostOpts) error {
|
||||
return func(types.OnFocusLostOpts) error {
|
||||
deactivateConfirmationPrompt(self.controllerCommon)
|
||||
self.helpers.Confirmation.DeactivateConfirmationPrompt()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@ -37,17 +60,6 @@ func (self *ConfirmationController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
|
||||
func (self *ConfirmationController) context() types.Context {
|
||||
func (self *ConfirmationController) context() *context.ConfirmationContext {
|
||||
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
|
||||
View *ViewHelper
|
||||
Refresh *RefreshHelper
|
||||
Confirmation *ConfirmationHelper
|
||||
}
|
||||
|
||||
func NewStubHelpers() *Helpers {
|
||||
@ -52,5 +53,6 @@ func NewStubHelpers() *Helpers {
|
||||
Window: &WindowHelper{},
|
||||
View: &ViewHelper{},
|
||||
Refresh: &RefreshHelper{},
|
||||
Confirmation: &ConfirmationHelper{},
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,8 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||
"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) {
|
||||
self.context().GetMutex().Lock()
|
||||
defer self.context().GetMutex().Unlock()
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/jesseduffield/generics/slices"
|
||||
"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/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
@ -35,8 +36,8 @@ type ISuggestionsHelper interface {
|
||||
type SuggestionsHelper struct {
|
||||
c *types.HelperCommon
|
||||
|
||||
model *types.Model
|
||||
refreshSuggestionsFn func()
|
||||
model *types.Model
|
||||
contexts *context.ContextTree
|
||||
}
|
||||
|
||||
var _ ISuggestionsHelper = &SuggestionsHelper{}
|
||||
@ -44,12 +45,12 @@ var _ ISuggestionsHelper = &SuggestionsHelper{}
|
||||
func NewSuggestionsHelper(
|
||||
c *types.HelperCommon,
|
||||
model *types.Model,
|
||||
refreshSuggestionsFn func(),
|
||||
contexts *context.ContextTree,
|
||||
) *SuggestionsHelper {
|
||||
return &SuggestionsHelper{
|
||||
c: c,
|
||||
model: model,
|
||||
refreshSuggestionsFn: refreshSuggestionsFn,
|
||||
c: c,
|
||||
model: model,
|
||||
contexts: contexts,
|
||||
}
|
||||
}
|
||||
|
||||
@ -127,7 +128,7 @@ func (self *SuggestionsHelper) GetFilePathSuggestionsFunc() func(string) []*type
|
||||
// cache the trie for future use
|
||||
self.model.FilesTrie = trie
|
||||
|
||||
self.refreshSuggestionsFn()
|
||||
self.contexts.Suggestions.RefreshSuggestions()
|
||||
|
||||
return err
|
||||
})
|
||||
|
@ -28,12 +28,16 @@ func (self *MenuController) GetKeybindings(opts types.KeybindingsOpts) []*types.
|
||||
Handler: self.press,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
||||
Handler: self.press,
|
||||
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
||||
Handler: self.press,
|
||||
Description: self.c.Tr.LcExecute,
|
||||
Display: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||
Handler: self.close,
|
||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||
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),
|
||||
Handler: self.withRenderAndFocus(self.PrevConflict),
|
||||
Description: self.c.Tr.PrevConflict,
|
||||
Display: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.NextBlock),
|
||||
Handler: self.withRenderAndFocus(self.NextConflict),
|
||||
Description: self.c.Tr.NextConflict,
|
||||
Display: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.PrevItem),
|
||||
Handler: self.withRenderAndFocus(self.PrevConflictHunk),
|
||||
Description: self.c.Tr.SelectPrevHunk,
|
||||
Display: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.NextItem),
|
||||
Handler: self.withRenderAndFocus(self.NextConflictHunk),
|
||||
Description: self.c.Tr.SelectNextHunk,
|
||||
Display: true,
|
||||
},
|
||||
{
|
||||
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),
|
||||
Handler: self.withRenderAndFocus(self.HandleUndo),
|
||||
Description: self.c.Tr.LcUndo,
|
||||
Display: true,
|
||||
},
|
||||
{
|
||||
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),
|
||||
Handler: self.withRenderAndFocus(self.HandlePickHunk),
|
||||
Description: self.c.Tr.PickHunk,
|
||||
Display: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Main.PickBothHunks),
|
||||
Handler: self.withRenderAndFocus(self.HandlePickAllHunks),
|
||||
Description: self.c.Tr.PickAllHunks,
|
||||
Display: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||
|
@ -59,6 +59,27 @@ func (self *PatchBuildingController) GetMouseKeybindings(opts types.KeybindingsO
|
||||
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 {
|
||||
self.context().GetMutex().Lock()
|
||||
defer self.context().GetMutex().Unlock()
|
||||
|
@ -99,6 +99,29 @@ func (self *StagingController) GetMouseKeybindings(opts types.KeybindingsOpts) [
|
||||
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 {
|
||||
self.context.GetMutex().Lock()
|
||||
defer self.context.GetMutex().Unlock()
|
||||
|
@ -53,8 +53,8 @@ func (self *SubCommitsController) GetOnRenderToMain() func() error {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SubCommitsController) GetOnFocus() func() error {
|
||||
return func() error {
|
||||
func (self *SubCommitsController) GetOnFocus() func(types.OnFocusOpts) error {
|
||||
return func(types.OnFocusOpts) error {
|
||||
context := self.context
|
||||
if context.GetSelectedLineIdx() > COMMIT_THRESHOLD && context.GetLimitCommits() {
|
||||
context.SetLimitCommits(false)
|
||||
|
@ -22,14 +22,27 @@ func NewSuggestionsController(
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func (self *SuggestionsController) GetOnFocusLost() func(types.OnFocusLostOpts) error {
|
||||
return func(types.OnFocusLostOpts) error {
|
||||
deactivateConfirmationPrompt
|
||||
self.helpers.Confirmation.DeactivateConfirmationPrompt()
|
||||
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,
|
||||
// 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.
|
||||
err := gui.resizePopupPanel(v, v.TextArea.GetContent())
|
||||
err := gui.helpers.Confirmation.ResizePopupPanel(v, v.TextArea.GetContent())
|
||||
if err != nil {
|
||||
gui.c.Log.Error(err)
|
||||
}
|
||||
v.RenderTextArea()
|
||||
gui.RenderCommitLength()
|
||||
gui.State.Contexts.CommitMessage.RenderCommitLength()
|
||||
|
||||
return matched
|
||||
}
|
||||
@ -86,11 +86,12 @@ func (gui *Gui) defaultEditor(v *gocui.View, key gocui.Key, ch rune, mod gocui.M
|
||||
|
||||
v.RenderTextArea()
|
||||
|
||||
if gui.findSuggestions != nil {
|
||||
suggestionsContext := gui.State.Contexts.Suggestions
|
||||
if suggestionsContext.State.FindSuggestions != nil {
|
||||
input := v.TextArea.GetContent()
|
||||
gui.suggestionsAsyncHandler.Do(func() func() {
|
||||
suggestions := gui.findSuggestions(input)
|
||||
return func() { gui.setSuggestions(suggestions) }
|
||||
suggestionsContext.State.AsyncHandler.Do(func() func() {
|
||||
suggestions := suggestionsContext.State.FindSuggestions(input)
|
||||
return func() { suggestionsContext.SetSuggestions(suggestions) }
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -17,16 +17,6 @@ func (gui *Gui) validateNotInFilterMode() bool {
|
||||
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 {
|
||||
return gui.clearFiltering()
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package gui
|
||||
|
||||
import (
|
||||
goContext "context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@ -94,10 +95,6 @@ type Gui struct {
|
||||
|
||||
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
|
||||
// so that you can return to the superproject
|
||||
RepoPathStack *utils.StringStack
|
||||
@ -113,8 +110,6 @@ type Gui struct {
|
||||
// the extras window contains things like the command log
|
||||
ShowExtrasWindow bool
|
||||
|
||||
suggestionsAsyncHandler *tasks.AsyncHandler
|
||||
|
||||
PopupHandler types.IPopupHandler
|
||||
|
||||
IsNewRepo bool
|
||||
@ -198,9 +193,6 @@ type GuiRepoState struct {
|
||||
Model *types.Model
|
||||
Modes *types.Modes
|
||||
|
||||
// Suggestions will sometimes appear when typing into a prompt
|
||||
Suggestions []*types.Suggestion
|
||||
|
||||
SplitMainPanel bool
|
||||
LimitCommits bool
|
||||
|
||||
@ -412,18 +404,17 @@ func NewGui(
|
||||
initialDir string,
|
||||
) (*Gui, error) {
|
||||
gui := &Gui{
|
||||
Common: cmn,
|
||||
gitVersion: gitVersion,
|
||||
Config: config,
|
||||
Updater: updater,
|
||||
statusManager: &statusManager{},
|
||||
viewBufferManagerMap: map[string]*tasks.ViewBufferManager{},
|
||||
viewPtmxMap: map[string]*os.File{},
|
||||
showRecentRepos: showRecentRepos,
|
||||
RepoPathStack: &utils.StringStack{},
|
||||
RepoStateMap: map[Repo]*GuiRepoState{},
|
||||
CmdLog: []string{},
|
||||
suggestionsAsyncHandler: tasks.NewAsyncHandler(),
|
||||
Common: cmn,
|
||||
gitVersion: gitVersion,
|
||||
Config: config,
|
||||
Updater: updater,
|
||||
statusManager: &statusManager{},
|
||||
viewBufferManagerMap: map[string]*tasks.ViewBufferManager{},
|
||||
viewPtmxMap: map[string]*os.File{},
|
||||
showRecentRepos: showRecentRepos,
|
||||
RepoPathStack: &utils.StringStack{},
|
||||
RepoStateMap: map[Repo]*GuiRepoState{},
|
||||
CmdLog: []string{},
|
||||
|
||||
// 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
|
||||
@ -446,7 +437,9 @@ func NewGui(
|
||||
|
||||
gui.PopupHandler = popup.NewPopupHandler(
|
||||
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}) },
|
||||
gui.popContext,
|
||||
gui.currentContext,
|
||||
|
@ -144,3 +144,7 @@ func (self *guiCommon) MainViewPairs() types.MainViewPairs {
|
||||
func (self *guiCommon) State() types.IStateAccessor {
|
||||
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 {
|
||||
context, ok := self.gui.contextForView(viewName)
|
||||
context, ok := self.gui.helpers.View.ContextForView(viewName)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
@ -11,7 +11,17 @@ import (
|
||||
|
||||
func (gui *Gui) noPopupPanel(f func() error) 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
|
||||
}
|
||||
|
||||
@ -34,8 +44,7 @@ func (self *Gui) GetCheatsheetKeybindings() []*types.Binding {
|
||||
return bindings
|
||||
}
|
||||
|
||||
// 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) {
|
||||
func (self *Gui) keybindingOpts() types.KeybindingsOpts {
|
||||
config := self.c.UserConfig.Keybinding
|
||||
|
||||
guards := types.KeybindingGuards{
|
||||
@ -43,11 +52,18 @@ func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBi
|
||||
NoPopupPanel: self.noPopupPanel,
|
||||
}
|
||||
|
||||
opts := types.KeybindingsOpts{
|
||||
return types.KeybindingsOpts{
|
||||
GetKey: keybindings.GetKey,
|
||||
Config: config,
|
||||
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{
|
||||
{
|
||||
@ -486,7 +502,7 @@ func (gui *Gui) SetKeybinding(binding *types.Binding) error {
|
||||
if gocui.IsMouseKey(binding.Key) {
|
||||
handler = func() error {
|
||||
// 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
|
||||
}
|
||||
|
||||
@ -502,7 +518,7 @@ func (gui *Gui) SetMouseKeybinding(binding *gocui.ViewMouseBinding) error {
|
||||
baseHandler := binding.Handler
|
||||
newHandler := func(opts gocui.ViewMouseBindingOpts) error {
|
||||
// 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
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ func (gui *Gui) layout(g *gocui.Gui) error {
|
||||
// if you run `lazygit --logs`
|
||||
// this will let you see these branches as prettified json
|
||||
// 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) {
|
||||
@ -245,7 +245,7 @@ func (gui *Gui) getFocusLayout() func(g *gocui.Gui) error {
|
||||
return func(g *gocui.Gui) error {
|
||||
newView := gui.g.CurrentView()
|
||||
// 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 {
|
||||
return err
|
||||
}
|
||||
|
@ -14,14 +14,7 @@ import (
|
||||
)
|
||||
|
||||
func (gui *Gui) menuListContext() *context.MenuContext {
|
||||
return context.NewMenuContext(
|
||||
gui.Views.Menu,
|
||||
gui.c,
|
||||
gui.getMenuOptions,
|
||||
func(content string) {
|
||||
gui.Views.Tooltip.SetContent(content)
|
||||
},
|
||||
)
|
||||
return context.NewMenuContext(gui.c)
|
||||
}
|
||||
|
||||
func (gui *Gui) filesListContext() *context.WorkingTreeContext {
|
||||
@ -237,14 +230,7 @@ func (gui *Gui) submodulesListContext() *context.SubmodulesContext {
|
||||
}
|
||||
|
||||
func (gui *Gui) suggestionsListContext() *context.SuggestionsContext {
|
||||
return context.NewSuggestionsContext(
|
||||
func() []*types.Suggestion { return gui.State.Suggestions },
|
||||
gui.Views.Suggestions,
|
||||
func(startIdx int, length int) [][]string {
|
||||
return presentation.GetSuggestionListDisplayStrings(gui.State.Suggestions)
|
||||
},
|
||||
gui.c,
|
||||
)
|
||||
return context.NewSuggestionsContext(gui.c)
|
||||
}
|
||||
|
||||
func (gui *Gui) getListContexts() []types.IListContext {
|
||||
|
@ -1,25 +1,12 @@
|
||||
package gui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/theme"
|
||||
"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
|
||||
func (gui *Gui) createMenu(opts types.CreateMenuOptions) error {
|
||||
if !opts.HideCancel {
|
||||
|
@ -2,12 +2,11 @@ package gui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/generics/maps"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
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
|
||||
func (self *OptionsMapMgr) renderContextOptionsMap(c types.Context) {
|
||||
optionsMap := c.GetOptionsMap()
|
||||
if optionsMap == nil {
|
||||
optionsMap = self.globalOptionsMap()
|
||||
bindingsToDisplay := lo.Filter(c.GetKeybindings(self.c.KeybindingsOpts()), func(binding *types.Binding, _ int) bool {
|
||||
return binding.Display
|
||||
})
|
||||
|
||||
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 {
|
||||
options := maps.MapToSlice(optionsMap, func(key string, description string) string {
|
||||
return key + ": " + description
|
||||
})
|
||||
sort.Strings(options)
|
||||
return strings.Join(options, ", ")
|
||||
func (self *OptionsMapMgr) formatBindingInfos(bindingInfos []bindingInfo) string {
|
||||
return strings.Join(
|
||||
lo.Map(bindingInfos, func(bindingInfo bindingInfo, _ int) string {
|
||||
return fmt.Sprintf("%s: %s", bindingInfo.key, bindingInfo.description)
|
||||
}),
|
||||
", ")
|
||||
}
|
||||
|
||||
func (self *OptionsMapMgr) renderOptions(options string) {
|
||||
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
|
||||
|
||||
return map[string]string{
|
||||
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,
|
||||
keybindings.Label(keybindingConfig.Universal.Return): self.c.Tr.LcCancel,
|
||||
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,
|
||||
fmt.Sprintf("%s/%s", keybindings.Label(keybindingConfig.Universal.ScrollLeft), keybindings.Label(keybindingConfig.Universal.ScrollRight)): self.c.Tr.LcScrollLeftRight,
|
||||
return []bindingInfo{
|
||||
{
|
||||
key: fmt.Sprintf("%s/%s", keybindings.Label(keybindingConfig.Universal.ScrollUpMain), keybindings.Label(keybindingConfig.Universal.ScrollDownMain)),
|
||||
description: self.c.Tr.LcScroll,
|
||||
},
|
||||
{
|
||||
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)),
|
||||
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
|
||||
|
||||
State() IStateAccessor
|
||||
|
||||
KeybindingsOpts() KeybindingsOpts
|
||||
}
|
||||
|
||||
type IPopupHandler interface {
|
||||
|
@ -17,6 +17,12 @@ type Binding struct {
|
||||
Tag string // e.g. 'navigation'. Used for grouping things in the cheatsheet
|
||||
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
|
||||
Tooltip string
|
||||
}
|
||||
|
@ -62,71 +62,6 @@ func (gui *Gui) currentViewName() string {
|
||||
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 {
|
||||
tabs := gui.viewTabMap()[windowName]
|
||||
if len(tabs) == 0 {
|
||||
|
@ -156,6 +156,7 @@ func (gui *Gui) createAllViews() error {
|
||||
gui.Views.CommitMessage.Editor = gocui.EditorFunc(gui.commitMessageEditor)
|
||||
|
||||
gui.Views.Confirmation.Visible = false
|
||||
gui.Views.Confirmation.Editor = gocui.EditorFunc(gui.defaultEditor)
|
||||
|
||||
gui.Views.Suggestions.Visible = false
|
||||
|
||||
|
@ -94,9 +94,9 @@ func chineseTranslationSet() TranslationSet {
|
||||
LcNewBranch: "新分支",
|
||||
LcDeleteBranch: "删除分支",
|
||||
NoBranchesThisRepo: "此仓库中没有分支",
|
||||
CommitMessageConfirm: "{{.keyBindClose}}:关闭,{{.keyBindNewLine}}:新行,{{.keyBindConfirm}}:确认",
|
||||
CommitWithoutMessageErr: "您必须编写提交消息才能进行提交",
|
||||
CloseConfirm: "{{.keyBindClose}}:关闭,{{.keyBindConfirm}}:确认",
|
||||
LcCloseCancel: "关闭",
|
||||
LcConfirm: "确认",
|
||||
LcClose: "关闭",
|
||||
LcQuit: "退出",
|
||||
LcSquashDown: "向下压缩",
|
||||
@ -117,8 +117,6 @@ func chineseTranslationSet() TranslationSet {
|
||||
LcAmendToCommit: "用已暂存的更改来修补提交",
|
||||
LcRenameCommitEditor: "使用编辑器重命名提交",
|
||||
Error: "错误",
|
||||
LcSelectHunk: "切换区块",
|
||||
LcNavigateConflicts: "浏览冲突",
|
||||
LcPickHunk: "选中区块",
|
||||
LcPickAllHunks: "选中所有区块",
|
||||
LcUndo: "撤销",
|
||||
|
@ -60,9 +60,9 @@ func dutchTranslationSet() TranslationSet {
|
||||
LcNewBranch: "nieuwe branch",
|
||||
LcDeleteBranch: "verwijder branch",
|
||||
NoBranchesThisRepo: "Geen branches voor deze repo",
|
||||
CommitMessageConfirm: "{{.keyBindClose}}: Sluiten, {{.keyBindNewLine}}: Nieuwe lijn, {{.keyBindConfirm}}: Bevestig",
|
||||
CommitWithoutMessageErr: "Je kan geen commit maken zonder commit bericht",
|
||||
CloseConfirm: "{{.keyBindClose}}: Sluiten, {{.keyBindConfirm}}: Bevestig",
|
||||
LcCloseCancel: "sluiten",
|
||||
LcConfirm: "bevestig",
|
||||
LcClose: "sluiten",
|
||||
LcQuit: "quit",
|
||||
LcSquashDown: "squash beneden",
|
||||
@ -83,8 +83,6 @@ func dutchTranslationSet() TranslationSet {
|
||||
LcRenameCommitEditor: "hernoem commit met editor",
|
||||
NoCommitsThisBranch: "Geen commits in deze branch",
|
||||
Error: "Foutmelding",
|
||||
LcSelectHunk: "selecteer stuk",
|
||||
LcNavigateConflicts: "navigeer conflicts",
|
||||
LcPickHunk: "kies stuk",
|
||||
LcPickAllHunks: "kies beide stukken",
|
||||
LcUndo: "ongedaan maken",
|
||||
|
@ -80,10 +80,10 @@ type TranslationSet struct {
|
||||
LcNewBranch string
|
||||
LcDeleteBranch string
|
||||
NoBranchesThisRepo string
|
||||
CommitMessageConfirm string
|
||||
CommitWithoutMessageErr string
|
||||
CloseConfirm string
|
||||
LcClose string
|
||||
LcCloseCancel string
|
||||
LcConfirm string
|
||||
LcQuit string
|
||||
LcSquashDown string
|
||||
LcFixupCommit string
|
||||
@ -107,8 +107,6 @@ type TranslationSet struct {
|
||||
NoCommitsThisBranch string
|
||||
UpdateRefHere string
|
||||
Error string
|
||||
LcSelectHunk string
|
||||
LcNavigateConflicts string
|
||||
LcPickHunk string
|
||||
LcPickAllHunks string
|
||||
LcUndo string
|
||||
@ -750,10 +748,10 @@ func EnglishTranslationSet() TranslationSet {
|
||||
LcNewBranch: "new branch",
|
||||
LcDeleteBranch: "delete branch",
|
||||
NoBranchesThisRepo: "No branches for this repo",
|
||||
CommitMessageConfirm: "{{.keyBindClose}}: close, {{.keyBindNewLine}}: new line, {{.keyBindConfirm}}: confirm",
|
||||
CommitWithoutMessageErr: "You cannot commit without a commit message",
|
||||
CloseConfirm: "{{.keyBindClose}}: close/cancel, {{.keyBindConfirm}}: confirm",
|
||||
LcClose: "close",
|
||||
LcCloseCancel: "close/cancel",
|
||||
LcConfirm: "confirm",
|
||||
LcQuit: "quit",
|
||||
LcSquashDown: "squash down",
|
||||
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?",
|
||||
LcRenameCommitEditor: "reword commit with editor",
|
||||
Error: "Error",
|
||||
LcSelectHunk: "select hunk",
|
||||
LcNavigateConflicts: "navigate conflicts",
|
||||
LcPickHunk: "pick hunk",
|
||||
LcPickAllHunks: "pick all hunks",
|
||||
LcUndo: "undo",
|
||||
|
@ -85,9 +85,9 @@ func japaneseTranslationSet() TranslationSet {
|
||||
LcNewBranch: "新しいブランチを作成",
|
||||
LcDeleteBranch: "ブランチを削除",
|
||||
NoBranchesThisRepo: "リポジトリにブランチが存在しません",
|
||||
CommitMessageConfirm: "{{.keyBindClose}}: 閉じる, {{.keyBindNewLine}}: 改行, {{.keyBindConfirm}}: 確定",
|
||||
CommitWithoutMessageErr: "コミットメッセージを入力してください",
|
||||
CloseConfirm: "{{.keyBindClose}}: 閉じる/キャンセル, {{.keyBindConfirm}}: 確認",
|
||||
LcCloseCancel: "閉じる/キャンセル",
|
||||
LcConfirm: "確認",
|
||||
LcClose: "閉じる",
|
||||
LcQuit: "終了",
|
||||
// LcSquashDown: "squash down",
|
||||
@ -108,8 +108,6 @@ func japaneseTranslationSet() TranslationSet {
|
||||
LcAmendToCommit: "ステージされた変更でamendコミット",
|
||||
LcRenameCommitEditor: "エディタでコミットメッセージを編集",
|
||||
Error: "エラー",
|
||||
LcSelectHunk: "hunkを選択",
|
||||
LcNavigateConflicts: "コンフリクトを移動",
|
||||
// LcPickHunk: "pick hunk",
|
||||
// LcPickAllHunks: "pick all hunks",
|
||||
LcUndo: "アンドゥ",
|
||||
|
@ -84,9 +84,9 @@ func koreanTranslationSet() TranslationSet {
|
||||
LcNewBranch: "새 브랜치 생성",
|
||||
LcDeleteBranch: "브랜치 삭제",
|
||||
NoBranchesThisRepo: "저장소에 브랜치가 존재하지 않습니다.",
|
||||
CommitMessageConfirm: "{{.keyBindClose}}: 닫기, {{.keyBindNewLine}}: 개행, {{.keyBindConfirm}}: 확인",
|
||||
CommitWithoutMessageErr: "커밋 메시지를 입력하세요.",
|
||||
CloseConfirm: "{{.keyBindClose}}: 닫기/취소, {{.keyBindConfirm}}: 확인",
|
||||
LcCloseCancel: "닫기/취소",
|
||||
LcConfirm: "확인",
|
||||
LcClose: "닫기",
|
||||
LcQuit: "종료",
|
||||
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?",
|
||||
LcRenameCommitEditor: "에디터에서 커밋메시지 수정",
|
||||
Error: "오류",
|
||||
LcSelectHunk: "hunk를 선택",
|
||||
LcNavigateConflicts: "navigate conflicts",
|
||||
LcPickHunk: "pick hunk",
|
||||
LcPickAllHunks: "pick all hunks",
|
||||
LcUndo: "되돌리기",
|
||||
|
@ -55,9 +55,9 @@ func polishTranslationSet() TranslationSet {
|
||||
LcNewBranch: "nowa gałąź",
|
||||
LcDeleteBranch: "usuń gałąź",
|
||||
NoBranchesThisRepo: "Brak gałęzi dla tego repozytorium",
|
||||
CommitMessageConfirm: "{{.keyBindClose}}: zamknij, {{.keyBindNewLine}}: nowa linia, {{.keyBindConfirm}}: potwierdź",
|
||||
CommitWithoutMessageErr: "Nie możesz commitować bez komunikatu",
|
||||
CloseConfirm: "{{.keyBindClose}}: zamknij, {{.keyBindConfirm}}: potwierdź",
|
||||
LcCloseCancel: "zamknij",
|
||||
LcConfirm: "potwierdź",
|
||||
LcClose: "zamknij",
|
||||
LcSquashDown: "ściśnij",
|
||||
LcFixupCommit: "napraw commit",
|
||||
@ -68,8 +68,6 @@ func polishTranslationSet() TranslationSet {
|
||||
LcRewordCommit: "zmień nazwę commita",
|
||||
LcRenameCommitEditor: "zmień nazwę commita w edytorze",
|
||||
Error: "Błąd",
|
||||
LcSelectHunk: "wybierz kawałek",
|
||||
LcNavigateConflicts: "nawiguj konflikty",
|
||||
LcPickHunk: "wybierz kawałek",
|
||||
LcPickAllHunks: "wybierz oba kawałki",
|
||||
LcUndo: "cofnij",
|
||||
|
Loading…
x
Reference in New Issue
Block a user