mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-07-30 03:23:08 +03:00
refactor contexts
This commit is contained in:
86
pkg/gui/context/branches_context.go
Normal file
86
pkg/gui/context/branches_context.go
Normal file
@ -0,0 +1,86 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type BranchesContext struct {
|
||||
*BranchesViewModel
|
||||
*ListContextTrait
|
||||
}
|
||||
|
||||
var _ types.IListContext = (*BranchesContext)(nil)
|
||||
|
||||
func NewBranchesContext(
|
||||
getModel func() []*models.Branch,
|
||||
view *gocui.View,
|
||||
getDisplayStrings func(startIdx int, length int) [][]string,
|
||||
|
||||
onFocus func(...types.OnFocusOpts) error,
|
||||
onRenderToMain func(...types.OnFocusOpts) error,
|
||||
onFocusLost func() error,
|
||||
|
||||
c *types.ControllerCommon,
|
||||
) *BranchesContext {
|
||||
viewModel := NewBranchesViewModel(getModel)
|
||||
|
||||
return &BranchesContext{
|
||||
BranchesViewModel: viewModel,
|
||||
ListContextTrait: &ListContextTrait{
|
||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "branches",
|
||||
WindowName: "branches",
|
||||
Key: LOCAL_BRANCHES_CONTEXT_KEY,
|
||||
Kind: types.SIDE_CONTEXT,
|
||||
Focusable: true,
|
||||
}), ContextCallbackOpts{
|
||||
OnFocus: onFocus,
|
||||
OnFocusLost: onFocusLost,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
}),
|
||||
list: viewModel,
|
||||
viewTrait: NewViewTrait(view),
|
||||
getDisplayStrings: getDisplayStrings,
|
||||
c: c,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *BranchesContext) GetSelectedItemId() string {
|
||||
item := self.GetSelected()
|
||||
if item == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return item.ID()
|
||||
}
|
||||
|
||||
type BranchesViewModel struct {
|
||||
*traits.ListCursor
|
||||
getModel func() []*models.Branch
|
||||
}
|
||||
|
||||
func NewBranchesViewModel(getModel func() []*models.Branch) *BranchesViewModel {
|
||||
self := &BranchesViewModel{
|
||||
getModel: getModel,
|
||||
}
|
||||
|
||||
self.ListCursor = traits.NewListCursor(self)
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *BranchesViewModel) GetItemsLength() int {
|
||||
return len(self.getModel())
|
||||
}
|
||||
|
||||
func (self *BranchesViewModel) GetSelected() *models.Branch {
|
||||
if self.GetItemsLength() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.getModel()[self.GetSelectedLineIdx()]
|
||||
}
|
@ -9,7 +9,6 @@ import (
|
||||
|
||||
type CommitFilesContext struct {
|
||||
*filetree.CommitFileTreeViewModel
|
||||
*BaseContext
|
||||
*ListContextTrait
|
||||
}
|
||||
|
||||
@ -17,7 +16,7 @@ var _ types.IListContext = (*CommitFilesContext)(nil)
|
||||
|
||||
func NewCommitFilesContext(
|
||||
getModel func() []*models.CommitFile,
|
||||
getView func() *gocui.View,
|
||||
view *gocui.View,
|
||||
getDisplayStrings func(startIdx int, length int) [][]string,
|
||||
|
||||
onFocus func(...types.OnFocusOpts) error,
|
||||
@ -26,43 +25,30 @@ func NewCommitFilesContext(
|
||||
|
||||
c *types.ControllerCommon,
|
||||
) *CommitFilesContext {
|
||||
baseContext := NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "commitFiles",
|
||||
WindowName: "commits",
|
||||
Key: COMMIT_FILES_CONTEXT_KEY,
|
||||
Kind: types.SIDE_CONTEXT,
|
||||
Focusable: true,
|
||||
})
|
||||
|
||||
self := &CommitFilesContext{}
|
||||
takeFocus := func() error { return c.PushContext(self) }
|
||||
|
||||
viewModel := filetree.NewCommitFileTreeViewModel(getModel, c.Log, c.UserConfig.Gui.ShowFileTree)
|
||||
viewTrait := NewViewTrait(getView)
|
||||
listContextTrait := &ListContextTrait{
|
||||
base: baseContext,
|
||||
list: viewModel,
|
||||
viewTrait: viewTrait,
|
||||
|
||||
GetDisplayStrings: getDisplayStrings,
|
||||
OnFocus: onFocus,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
OnFocusLost: onFocusLost,
|
||||
takeFocus: takeFocus,
|
||||
|
||||
// TODO: handle this in a trait
|
||||
RenderSelection: false,
|
||||
|
||||
c: c,
|
||||
return &CommitFilesContext{
|
||||
CommitFileTreeViewModel: viewModel,
|
||||
ListContextTrait: &ListContextTrait{
|
||||
Context: NewSimpleContext(
|
||||
NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "commitFiles",
|
||||
WindowName: "commits",
|
||||
Key: COMMIT_FILES_CONTEXT_KEY,
|
||||
Kind: types.SIDE_CONTEXT,
|
||||
Focusable: true,
|
||||
}),
|
||||
ContextCallbackOpts{
|
||||
OnFocus: onFocus,
|
||||
OnFocusLost: onFocusLost,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
}),
|
||||
list: viewModel,
|
||||
viewTrait: NewViewTrait(view),
|
||||
getDisplayStrings: getDisplayStrings,
|
||||
c: c,
|
||||
},
|
||||
}
|
||||
|
||||
baseContext.AddKeybindingsFn(listContextTrait.keybindings)
|
||||
|
||||
self.BaseContext = baseContext
|
||||
self.ListContextTrait = listContextTrait
|
||||
self.CommitFileTreeViewModel = viewModel
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *CommitFilesContext) GetSelectedItemId() string {
|
||||
|
@ -1,6 +1,10 @@
|
||||
package context
|
||||
|
||||
import "github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
const (
|
||||
GLOBAL_CONTEXT_KEY types.ContextKey = "global"
|
||||
@ -60,18 +64,18 @@ type ContextTree struct {
|
||||
Global types.Context
|
||||
Status types.Context
|
||||
Files *WorkingTreeContext
|
||||
Submodules types.IListContext
|
||||
Menu types.IListContext
|
||||
Branches types.IListContext
|
||||
Remotes types.IListContext
|
||||
RemoteBranches types.IListContext
|
||||
Menu *MenuContext
|
||||
Branches *BranchesContext
|
||||
Tags *TagsContext
|
||||
BranchCommits types.IListContext
|
||||
BranchCommits *LocalCommitsContext
|
||||
CommitFiles *CommitFilesContext
|
||||
ReflogCommits types.IListContext
|
||||
SubCommits types.IListContext
|
||||
Stash types.IListContext
|
||||
Suggestions types.IListContext
|
||||
Remotes *RemotesContext
|
||||
Submodules *SubmodulesContext
|
||||
RemoteBranches *RemoteBranchesContext
|
||||
ReflogCommits *ReflogCommitsContext
|
||||
SubCommits *SubCommitsContext
|
||||
Stash *StashContext
|
||||
Suggestions *SuggestionsContext
|
||||
Normal types.Context
|
||||
Staging types.Context
|
||||
PatchBuilding types.Context
|
||||
@ -113,6 +117,7 @@ func (self *ContextTree) Flatten() []types.Context {
|
||||
|
||||
type ViewContextMap struct {
|
||||
content map[string]types.Context
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
func NewViewContextMap() *ViewContextMap {
|
||||
@ -120,10 +125,15 @@ func NewViewContextMap() *ViewContextMap {
|
||||
}
|
||||
|
||||
func (self *ViewContextMap) Get(viewName string) types.Context {
|
||||
self.RLock()
|
||||
defer self.RUnlock()
|
||||
|
||||
return self.content[viewName]
|
||||
}
|
||||
|
||||
func (self *ViewContextMap) Set(viewName string, context types.Context) {
|
||||
self.Lock()
|
||||
defer self.Unlock()
|
||||
self.content[viewName] = context
|
||||
}
|
||||
|
||||
|
@ -3,44 +3,35 @@ package context
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
|
||||
type ListContextTrait struct {
|
||||
base types.IBaseContext
|
||||
list types.IList
|
||||
viewTrait *ViewTrait
|
||||
types.Context
|
||||
|
||||
takeFocus func() error
|
||||
|
||||
GetDisplayStrings func(startIdx int, length int) [][]string
|
||||
OnFocus func(...types.OnFocusOpts) error
|
||||
OnRenderToMain func(...types.OnFocusOpts) error
|
||||
OnFocusLost func() error
|
||||
|
||||
// if this is true, we'll call GetDisplayStrings for just the visible part of the
|
||||
// view and re-render that. This is useful when you need to render different
|
||||
// content based on the selection (e.g. for showing the selected commit)
|
||||
RenderSelection bool
|
||||
|
||||
c *types.ControllerCommon
|
||||
c *types.ControllerCommon
|
||||
list types.IList
|
||||
viewTrait *ViewTrait
|
||||
getDisplayStrings func(startIdx int, length int) [][]string
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) GetList() types.IList {
|
||||
return self.list
|
||||
}
|
||||
|
||||
// TODO: remove
|
||||
func (self *ListContextTrait) GetPanelState() types.IListPanelState {
|
||||
return self.list
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) GetViewTrait() types.IViewTrait {
|
||||
return self.viewTrait
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) FocusLine() {
|
||||
// we need a way of knowing whether we've rendered to the view yet.
|
||||
self.viewTrait.FocusPoint(self.list.GetSelectedLineIdx())
|
||||
if self.RenderSelection {
|
||||
min, max := self.viewTrait.ViewPortYBounds()
|
||||
displayStrings := self.GetDisplayStrings(min, max)
|
||||
content := utils.RenderDisplayStrings(displayStrings)
|
||||
self.viewTrait.SetViewPortContent(content)
|
||||
}
|
||||
self.viewTrait.SetFooter(formatListFooter(self.list.GetSelectedLineIdx(), self.list.GetItemsLength()))
|
||||
}
|
||||
|
||||
@ -48,164 +39,29 @@ func formatListFooter(selectedLineIdx int, length int) string {
|
||||
return fmt.Sprintf("%d of %d", selectedLineIdx+1, length)
|
||||
}
|
||||
|
||||
// OnFocus assumes that the content of the context has already been rendered to the view. OnRender is the function which actually renders the content to the view
|
||||
func (self *ListContextTrait) HandleRender() error {
|
||||
if self.GetDisplayStrings != nil {
|
||||
self.list.RefreshSelectedIdx()
|
||||
content := utils.RenderDisplayStrings(self.GetDisplayStrings(0, self.list.GetItemsLength()))
|
||||
self.viewTrait.SetContent(content)
|
||||
self.c.Render()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) HandleFocusLost() error {
|
||||
if self.OnFocusLost != nil {
|
||||
return self.OnFocusLost()
|
||||
}
|
||||
|
||||
self.viewTrait.SetOriginX(0)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) HandleFocus(opts ...types.OnFocusOpts) error {
|
||||
self.FocusLine()
|
||||
|
||||
if self.OnFocus != nil {
|
||||
if err := self.OnFocus(opts...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return self.Context.HandleFocus(opts...)
|
||||
}
|
||||
|
||||
if self.OnRenderToMain != nil {
|
||||
if err := self.OnRenderToMain(opts...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
func (self *ListContextTrait) HandleFocusLost() error {
|
||||
self.viewTrait.SetOriginX(0)
|
||||
|
||||
return self.Context.HandleFocus()
|
||||
}
|
||||
|
||||
// OnFocus assumes that the content of the context has already been rendered to the view. OnRender is the function which actually renders the content to the view
|
||||
func (self *ListContextTrait) HandleRender() error {
|
||||
self.list.RefreshSelectedIdx()
|
||||
content := utils.RenderDisplayStrings(self.getDisplayStrings(0, self.list.GetItemsLength()))
|
||||
self.viewTrait.SetContent(content)
|
||||
self.c.Render()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) HandlePrevLine() error {
|
||||
return self.handleLineChange(-1)
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) HandleNextLine() error {
|
||||
return self.handleLineChange(1)
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) HandleScrollLeft() error {
|
||||
return self.scroll(self.viewTrait.ScrollLeft)
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) HandleScrollRight() error {
|
||||
return self.scroll(self.viewTrait.ScrollRight)
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) scroll(scrollFunc func()) error {
|
||||
scrollFunc()
|
||||
|
||||
return self.HandleFocus()
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) handleLineChange(change int) error {
|
||||
before := self.list.GetSelectedLineIdx()
|
||||
self.list.MoveSelectedLine(change)
|
||||
after := self.list.GetSelectedLineIdx()
|
||||
|
||||
// doing this check so that if we're holding the up key at the start of the list
|
||||
// we're not constantly re-rendering the main view.
|
||||
if before != after {
|
||||
return self.HandleFocus()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) HandlePrevPage() error {
|
||||
return self.handleLineChange(-self.viewTrait.PageDelta())
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) HandleNextPage() error {
|
||||
return self.handleLineChange(self.viewTrait.PageDelta())
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) HandleGotoTop() error {
|
||||
return self.handleLineChange(-self.list.GetItemsLength())
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) HandleGotoBottom() error {
|
||||
return self.handleLineChange(self.list.GetItemsLength())
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) HandleClick(onClick func() error) error {
|
||||
prevSelectedLineIdx := self.list.GetSelectedLineIdx()
|
||||
// because we're handling a click, we need to determine the new line idx based
|
||||
// on the view itself.
|
||||
newSelectedLineIdx := self.viewTrait.SelectedLineIdx()
|
||||
|
||||
currentContextKey := self.c.CurrentContext().GetKey()
|
||||
alreadyFocused := currentContextKey == self.base.GetKey()
|
||||
|
||||
// we need to focus the view
|
||||
if !alreadyFocused {
|
||||
if err := self.takeFocus(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if newSelectedLineIdx > self.list.GetItemsLength()-1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.list.SetSelectedLineIdx(newSelectedLineIdx)
|
||||
|
||||
if prevSelectedLineIdx == newSelectedLineIdx && alreadyFocused && onClick != nil {
|
||||
return onClick()
|
||||
}
|
||||
return self.HandleFocus()
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) OnSearchSelect(selectedLineIdx int) error {
|
||||
self.list.SetSelectedLineIdx(selectedLineIdx)
|
||||
self.GetList().SetSelectedLineIdx(selectedLineIdx)
|
||||
return self.HandleFocus()
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) HandleRenderToMain() error {
|
||||
if self.OnRenderToMain != nil {
|
||||
return self.OnRenderToMain()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *ListContextTrait) keybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
return []*types.Binding{
|
||||
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.PrevItemAlt), Modifier: gocui.ModNone, Handler: self.HandlePrevLine},
|
||||
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.PrevItem), Modifier: gocui.ModNone, Handler: self.HandlePrevLine},
|
||||
{Tag: "navigation", Key: gocui.MouseWheelUp, Modifier: gocui.ModNone, Handler: self.HandlePrevLine},
|
||||
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.NextItemAlt), Modifier: gocui.ModNone, Handler: self.HandleNextLine},
|
||||
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.NextItem), Modifier: gocui.ModNone, Handler: self.HandleNextLine},
|
||||
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.PrevPage), Modifier: gocui.ModNone, Handler: self.HandlePrevPage, Description: self.c.Tr.LcPrevPage},
|
||||
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.NextPage), Modifier: gocui.ModNone, Handler: self.HandleNextPage, Description: self.c.Tr.LcNextPage},
|
||||
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.GotoTop), Modifier: gocui.ModNone, Handler: self.HandleGotoTop, Description: self.c.Tr.LcGotoTop},
|
||||
{Key: gocui.MouseLeft, Modifier: gocui.ModNone, Handler: func() error { return self.HandleClick(nil) }},
|
||||
{Tag: "navigation", Key: gocui.MouseWheelDown, Modifier: gocui.ModNone, Handler: self.HandleNextLine},
|
||||
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.ScrollLeft), Modifier: gocui.ModNone, Handler: self.HandleScrollLeft},
|
||||
{Tag: "navigation", Key: opts.GetKey(opts.Config.Universal.ScrollRight), Modifier: gocui.ModNone, Handler: self.HandleScrollRight},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.StartSearch),
|
||||
Handler: func() error { self.c.OpenSearch(); return nil },
|
||||
Description: self.c.Tr.LcStartSearch,
|
||||
Tag: "navigation",
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.GotoBottom),
|
||||
Description: self.c.Tr.LcGotoBottom,
|
||||
Handler: self.HandleGotoBottom,
|
||||
Tag: "navigation",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
87
pkg/gui/context/local_commits_context.go
Normal file
87
pkg/gui/context/local_commits_context.go
Normal file
@ -0,0 +1,87 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type LocalCommitsContext struct {
|
||||
*LocalCommitsViewModel
|
||||
*ViewportListContextTrait
|
||||
}
|
||||
|
||||
var _ types.IListContext = (*LocalCommitsContext)(nil)
|
||||
|
||||
func NewLocalCommitsContext(
|
||||
getModel func() []*models.Commit,
|
||||
view *gocui.View,
|
||||
getDisplayStrings func(startIdx int, length int) [][]string,
|
||||
|
||||
onFocus func(...types.OnFocusOpts) error,
|
||||
onRenderToMain func(...types.OnFocusOpts) error,
|
||||
onFocusLost func() error,
|
||||
|
||||
c *types.ControllerCommon,
|
||||
) *LocalCommitsContext {
|
||||
viewModel := NewLocalCommitsViewModel(getModel)
|
||||
|
||||
return &LocalCommitsContext{
|
||||
LocalCommitsViewModel: viewModel,
|
||||
ViewportListContextTrait: &ViewportListContextTrait{
|
||||
ListContextTrait: &ListContextTrait{
|
||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "commits",
|
||||
WindowName: "commits",
|
||||
Key: BRANCH_COMMITS_CONTEXT_KEY,
|
||||
Kind: types.SIDE_CONTEXT,
|
||||
Focusable: true,
|
||||
}), ContextCallbackOpts{
|
||||
OnFocus: onFocus,
|
||||
OnFocusLost: onFocusLost,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
}),
|
||||
list: viewModel,
|
||||
viewTrait: NewViewTrait(view),
|
||||
getDisplayStrings: getDisplayStrings,
|
||||
c: c,
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *LocalCommitsContext) GetSelectedItemId() string {
|
||||
item := self.GetSelected()
|
||||
if item == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return item.ID()
|
||||
}
|
||||
|
||||
type LocalCommitsViewModel struct {
|
||||
*traits.ListCursor
|
||||
getModel func() []*models.Commit
|
||||
}
|
||||
|
||||
func NewLocalCommitsViewModel(getModel func() []*models.Commit) *LocalCommitsViewModel {
|
||||
self := &LocalCommitsViewModel{
|
||||
getModel: getModel,
|
||||
}
|
||||
|
||||
self.ListCursor = traits.NewListCursor(self)
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *LocalCommitsViewModel) GetItemsLength() int {
|
||||
return len(self.getModel())
|
||||
}
|
||||
|
||||
func (self *LocalCommitsViewModel) GetSelected() *models.Commit {
|
||||
if self.GetItemsLength() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.getModel()[self.GetSelectedLineIdx()]
|
||||
}
|
108
pkg/gui/context/menu_context.go
Normal file
108
pkg/gui/context/menu_context.go
Normal file
@ -0,0 +1,108 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type MenuContext struct {
|
||||
*MenuViewModel
|
||||
*ListContextTrait
|
||||
}
|
||||
|
||||
var _ types.IListContext = (*MenuContext)(nil)
|
||||
|
||||
func NewMenuContext(
|
||||
view *gocui.View,
|
||||
|
||||
onFocus func(...types.OnFocusOpts) error,
|
||||
onRenderToMain func(...types.OnFocusOpts) error,
|
||||
onFocusLost func() error,
|
||||
|
||||
c *types.ControllerCommon,
|
||||
getOptionsMap func() map[string]string,
|
||||
) *MenuContext {
|
||||
viewModel := NewMenuViewModel()
|
||||
|
||||
return &MenuContext{
|
||||
MenuViewModel: viewModel,
|
||||
ListContextTrait: &ListContextTrait{
|
||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "menu",
|
||||
Key: "menu",
|
||||
Kind: types.PERSISTENT_POPUP,
|
||||
OnGetOptionsMap: getOptionsMap,
|
||||
Focusable: true,
|
||||
}), ContextCallbackOpts{
|
||||
OnFocus: onFocus,
|
||||
OnFocusLost: onFocusLost,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
}),
|
||||
getDisplayStrings: viewModel.GetDisplayStrings,
|
||||
list: viewModel,
|
||||
viewTrait: NewViewTrait(view),
|
||||
c: c,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove this thing.
|
||||
func (self *MenuContext) GetSelectedItemId() string {
|
||||
item := self.GetSelected()
|
||||
if item == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return item.DisplayString
|
||||
}
|
||||
|
||||
type MenuViewModel struct {
|
||||
*traits.ListCursor
|
||||
menuItems []*types.MenuItem
|
||||
}
|
||||
|
||||
func NewMenuViewModel() *MenuViewModel {
|
||||
self := &MenuViewModel{
|
||||
menuItems: nil,
|
||||
}
|
||||
|
||||
self.ListCursor = traits.NewListCursor(self)
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *MenuViewModel) GetItemsLength() int {
|
||||
return len(self.menuItems)
|
||||
}
|
||||
|
||||
func (self *MenuViewModel) GetSelected() *types.MenuItem {
|
||||
if self.GetItemsLength() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.menuItems[self.GetSelectedLineIdx()]
|
||||
}
|
||||
|
||||
func (self *MenuViewModel) SetMenuItems(items []*types.MenuItem) {
|
||||
self.menuItems = items
|
||||
}
|
||||
|
||||
// TODO: move into presentation package
|
||||
func (self *MenuViewModel) GetDisplayStrings(startIdx int, length int) [][]string {
|
||||
stringArrays := make([][]string, len(self.menuItems))
|
||||
for i, item := range self.menuItems {
|
||||
if item.DisplayStrings == nil {
|
||||
styledStr := item.DisplayString
|
||||
if item.OpensMenu {
|
||||
styledStr = presentation.OpensMenuStyle(styledStr)
|
||||
}
|
||||
stringArrays[i] = []string{styledStr}
|
||||
} else {
|
||||
stringArrays[i] = item.DisplayStrings
|
||||
}
|
||||
}
|
||||
|
||||
return stringArrays
|
||||
}
|
86
pkg/gui/context/reflog_commits_context.go
Normal file
86
pkg/gui/context/reflog_commits_context.go
Normal file
@ -0,0 +1,86 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type ReflogCommitsContext struct {
|
||||
*ReflogCommitsViewModel
|
||||
*ListContextTrait
|
||||
}
|
||||
|
||||
var _ types.IListContext = (*ReflogCommitsContext)(nil)
|
||||
|
||||
func NewReflogCommitsContext(
|
||||
getModel func() []*models.Commit,
|
||||
view *gocui.View,
|
||||
getDisplayStrings func(startIdx int, length int) [][]string,
|
||||
|
||||
onFocus func(...types.OnFocusOpts) error,
|
||||
onRenderToMain func(...types.OnFocusOpts) error,
|
||||
onFocusLost func() error,
|
||||
|
||||
c *types.ControllerCommon,
|
||||
) *ReflogCommitsContext {
|
||||
viewModel := NewReflogCommitsViewModel(getModel)
|
||||
|
||||
return &ReflogCommitsContext{
|
||||
ReflogCommitsViewModel: viewModel,
|
||||
ListContextTrait: &ListContextTrait{
|
||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "commits",
|
||||
WindowName: "commits",
|
||||
Key: REFLOG_COMMITS_CONTEXT_KEY,
|
||||
Kind: types.SIDE_CONTEXT,
|
||||
Focusable: true,
|
||||
}), ContextCallbackOpts{
|
||||
OnFocus: onFocus,
|
||||
OnFocusLost: onFocusLost,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
}),
|
||||
list: viewModel,
|
||||
viewTrait: NewViewTrait(view),
|
||||
getDisplayStrings: getDisplayStrings,
|
||||
c: c,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *ReflogCommitsContext) GetSelectedItemId() string {
|
||||
item := self.GetSelected()
|
||||
if item == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return item.ID()
|
||||
}
|
||||
|
||||
type ReflogCommitsViewModel struct {
|
||||
*traits.ListCursor
|
||||
getModel func() []*models.Commit
|
||||
}
|
||||
|
||||
func NewReflogCommitsViewModel(getModel func() []*models.Commit) *ReflogCommitsViewModel {
|
||||
self := &ReflogCommitsViewModel{
|
||||
getModel: getModel,
|
||||
}
|
||||
|
||||
self.ListCursor = traits.NewListCursor(self)
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *ReflogCommitsViewModel) GetItemsLength() int {
|
||||
return len(self.getModel())
|
||||
}
|
||||
|
||||
func (self *ReflogCommitsViewModel) GetSelected() *models.Commit {
|
||||
if self.GetItemsLength() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.getModel()[self.GetSelectedLineIdx()]
|
||||
}
|
86
pkg/gui/context/remote_branches_context.go
Normal file
86
pkg/gui/context/remote_branches_context.go
Normal file
@ -0,0 +1,86 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type RemoteBranchesContext struct {
|
||||
*RemoteBranchesViewModel
|
||||
*ListContextTrait
|
||||
}
|
||||
|
||||
var _ types.IListContext = (*RemoteBranchesContext)(nil)
|
||||
|
||||
func NewRemoteBranchesContext(
|
||||
getModel func() []*models.RemoteBranch,
|
||||
view *gocui.View,
|
||||
getDisplayStrings func(startIdx int, length int) [][]string,
|
||||
|
||||
onFocus func(...types.OnFocusOpts) error,
|
||||
onRenderToMain func(...types.OnFocusOpts) error,
|
||||
onFocusLost func() error,
|
||||
|
||||
c *types.ControllerCommon,
|
||||
) *RemoteBranchesContext {
|
||||
viewModel := NewRemoteBranchesViewModel(getModel)
|
||||
|
||||
return &RemoteBranchesContext{
|
||||
RemoteBranchesViewModel: viewModel,
|
||||
ListContextTrait: &ListContextTrait{
|
||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "branches",
|
||||
WindowName: "branches",
|
||||
Key: REMOTE_BRANCHES_CONTEXT_KEY,
|
||||
Kind: types.SIDE_CONTEXT,
|
||||
Focusable: true,
|
||||
}), ContextCallbackOpts{
|
||||
OnFocus: onFocus,
|
||||
OnFocusLost: onFocusLost,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
}),
|
||||
list: viewModel,
|
||||
viewTrait: NewViewTrait(view),
|
||||
getDisplayStrings: getDisplayStrings,
|
||||
c: c,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *RemoteBranchesContext) GetSelectedItemId() string {
|
||||
item := self.GetSelected()
|
||||
if item == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return item.ID()
|
||||
}
|
||||
|
||||
type RemoteBranchesViewModel struct {
|
||||
*traits.ListCursor
|
||||
getModel func() []*models.RemoteBranch
|
||||
}
|
||||
|
||||
func NewRemoteBranchesViewModel(getModel func() []*models.RemoteBranch) *RemoteBranchesViewModel {
|
||||
self := &RemoteBranchesViewModel{
|
||||
getModel: getModel,
|
||||
}
|
||||
|
||||
self.ListCursor = traits.NewListCursor(self)
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *RemoteBranchesViewModel) GetItemsLength() int {
|
||||
return len(self.getModel())
|
||||
}
|
||||
|
||||
func (self *RemoteBranchesViewModel) GetSelected() *models.RemoteBranch {
|
||||
if self.GetItemsLength() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.getModel()[self.GetSelectedLineIdx()]
|
||||
}
|
86
pkg/gui/context/remotes_context.go
Normal file
86
pkg/gui/context/remotes_context.go
Normal file
@ -0,0 +1,86 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type RemotesContext struct {
|
||||
*RemotesViewModel
|
||||
*ListContextTrait
|
||||
}
|
||||
|
||||
var _ types.IListContext = (*RemotesContext)(nil)
|
||||
|
||||
func NewRemotesContext(
|
||||
getModel func() []*models.Remote,
|
||||
view *gocui.View,
|
||||
getDisplayStrings func(startIdx int, length int) [][]string,
|
||||
|
||||
onFocus func(...types.OnFocusOpts) error,
|
||||
onRenderToMain func(...types.OnFocusOpts) error,
|
||||
onFocusLost func() error,
|
||||
|
||||
c *types.ControllerCommon,
|
||||
) *RemotesContext {
|
||||
viewModel := NewRemotesViewModel(getModel)
|
||||
|
||||
return &RemotesContext{
|
||||
RemotesViewModel: viewModel,
|
||||
ListContextTrait: &ListContextTrait{
|
||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "branches",
|
||||
WindowName: "branches",
|
||||
Key: REMOTES_CONTEXT_KEY,
|
||||
Kind: types.SIDE_CONTEXT,
|
||||
Focusable: true,
|
||||
}), ContextCallbackOpts{
|
||||
OnFocus: onFocus,
|
||||
OnFocusLost: onFocusLost,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
}),
|
||||
list: viewModel,
|
||||
viewTrait: NewViewTrait(view),
|
||||
getDisplayStrings: getDisplayStrings,
|
||||
c: c,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *RemotesContext) GetSelectedItemId() string {
|
||||
item := self.GetSelected()
|
||||
if item == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return item.ID()
|
||||
}
|
||||
|
||||
type RemotesViewModel struct {
|
||||
*traits.ListCursor
|
||||
getModel func() []*models.Remote
|
||||
}
|
||||
|
||||
func NewRemotesViewModel(getModel func() []*models.Remote) *RemotesViewModel {
|
||||
self := &RemotesViewModel{
|
||||
getModel: getModel,
|
||||
}
|
||||
|
||||
self.ListCursor = traits.NewListCursor(self)
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *RemotesViewModel) GetItemsLength() int {
|
||||
return len(self.getModel())
|
||||
}
|
||||
|
||||
func (self *RemotesViewModel) GetSelected() *models.Remote {
|
||||
if self.GetItemsLength() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.getModel()[self.GetSelectedLineIdx()]
|
||||
}
|
73
pkg/gui/context/simple_context.go
Normal file
73
pkg/gui/context/simple_context.go
Normal file
@ -0,0 +1,73 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type SimpleContext struct {
|
||||
OnFocus func(opts ...types.OnFocusOpts) error
|
||||
OnFocusLost func() error
|
||||
OnRender func() error
|
||||
// this is for pushing some content to the main view
|
||||
OnRenderToMain func(opts ...types.OnFocusOpts) error
|
||||
|
||||
*BaseContext
|
||||
}
|
||||
|
||||
type ContextCallbackOpts struct {
|
||||
OnFocus func(opts ...types.OnFocusOpts) error
|
||||
OnFocusLost func() error
|
||||
OnRender func() error
|
||||
// this is for pushing some content to the main view
|
||||
OnRenderToMain func(opts ...types.OnFocusOpts) error
|
||||
}
|
||||
|
||||
func NewSimpleContext(baseContext *BaseContext, opts ContextCallbackOpts) *SimpleContext {
|
||||
return &SimpleContext{
|
||||
OnFocus: opts.OnFocus,
|
||||
OnFocusLost: opts.OnFocusLost,
|
||||
OnRender: opts.OnRender,
|
||||
OnRenderToMain: opts.OnRenderToMain,
|
||||
BaseContext: baseContext,
|
||||
}
|
||||
}
|
||||
|
||||
var _ types.Context = &SimpleContext{}
|
||||
|
||||
func (self *SimpleContext) HandleFocus(opts ...types.OnFocusOpts) error {
|
||||
if self.OnFocus != nil {
|
||||
if err := self.OnFocus(opts...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if self.OnRenderToMain != nil {
|
||||
if err := self.OnRenderToMain(opts...); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SimpleContext) HandleFocusLost() error {
|
||||
if self.OnFocusLost != nil {
|
||||
return self.OnFocusLost()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SimpleContext) HandleRender() error {
|
||||
if self.OnRender != nil {
|
||||
return self.OnRender()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SimpleContext) HandleRenderToMain() error {
|
||||
if self.OnRenderToMain != nil {
|
||||
return self.OnRenderToMain()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
86
pkg/gui/context/stash_context.go
Normal file
86
pkg/gui/context/stash_context.go
Normal file
@ -0,0 +1,86 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type StashContext struct {
|
||||
*StashViewModel
|
||||
*ListContextTrait
|
||||
}
|
||||
|
||||
var _ types.IListContext = (*StashContext)(nil)
|
||||
|
||||
func NewStashContext(
|
||||
getModel func() []*models.StashEntry,
|
||||
view *gocui.View,
|
||||
getDisplayStrings func(startIdx int, length int) [][]string,
|
||||
|
||||
onFocus func(...types.OnFocusOpts) error,
|
||||
onRenderToMain func(...types.OnFocusOpts) error,
|
||||
onFocusLost func() error,
|
||||
|
||||
c *types.ControllerCommon,
|
||||
) *StashContext {
|
||||
viewModel := NewStashViewModel(getModel)
|
||||
|
||||
return &StashContext{
|
||||
StashViewModel: viewModel,
|
||||
ListContextTrait: &ListContextTrait{
|
||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "stash",
|
||||
WindowName: "stash",
|
||||
Key: STASH_CONTEXT_KEY,
|
||||
Kind: types.SIDE_CONTEXT,
|
||||
Focusable: true,
|
||||
}), ContextCallbackOpts{
|
||||
OnFocus: onFocus,
|
||||
OnFocusLost: onFocusLost,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
}),
|
||||
list: viewModel,
|
||||
viewTrait: NewViewTrait(view),
|
||||
getDisplayStrings: getDisplayStrings,
|
||||
c: c,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *StashContext) GetSelectedItemId() string {
|
||||
item := self.GetSelected()
|
||||
if item == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return item.ID()
|
||||
}
|
||||
|
||||
type StashViewModel struct {
|
||||
*traits.ListCursor
|
||||
getModel func() []*models.StashEntry
|
||||
}
|
||||
|
||||
func NewStashViewModel(getModel func() []*models.StashEntry) *StashViewModel {
|
||||
self := &StashViewModel{
|
||||
getModel: getModel,
|
||||
}
|
||||
|
||||
self.ListCursor = traits.NewListCursor(self)
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *StashViewModel) GetItemsLength() int {
|
||||
return len(self.getModel())
|
||||
}
|
||||
|
||||
func (self *StashViewModel) GetSelected() *models.StashEntry {
|
||||
if self.GetItemsLength() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.getModel()[self.GetSelectedLineIdx()]
|
||||
}
|
87
pkg/gui/context/sub_commits_context.go
Normal file
87
pkg/gui/context/sub_commits_context.go
Normal file
@ -0,0 +1,87 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type SubCommitsContext struct {
|
||||
*SubCommitsViewModel
|
||||
*ViewportListContextTrait
|
||||
}
|
||||
|
||||
var _ types.IListContext = (*SubCommitsContext)(nil)
|
||||
|
||||
func NewSubCommitsContext(
|
||||
getModel func() []*models.Commit,
|
||||
view *gocui.View,
|
||||
getDisplayStrings func(startIdx int, length int) [][]string,
|
||||
|
||||
onFocus func(...types.OnFocusOpts) error,
|
||||
onRenderToMain func(...types.OnFocusOpts) error,
|
||||
onFocusLost func() error,
|
||||
|
||||
c *types.ControllerCommon,
|
||||
) *SubCommitsContext {
|
||||
viewModel := NewSubCommitsViewModel(getModel)
|
||||
|
||||
return &SubCommitsContext{
|
||||
SubCommitsViewModel: viewModel,
|
||||
ViewportListContextTrait: &ViewportListContextTrait{
|
||||
ListContextTrait: &ListContextTrait{
|
||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "branches",
|
||||
WindowName: "branches",
|
||||
Key: SUB_COMMITS_CONTEXT_KEY,
|
||||
Kind: types.SIDE_CONTEXT,
|
||||
Focusable: true,
|
||||
}), ContextCallbackOpts{
|
||||
OnFocus: onFocus,
|
||||
OnFocusLost: onFocusLost,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
}),
|
||||
list: viewModel,
|
||||
viewTrait: NewViewTrait(view),
|
||||
getDisplayStrings: getDisplayStrings,
|
||||
c: c,
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SubCommitsContext) GetSelectedItemId() string {
|
||||
item := self.GetSelected()
|
||||
if item == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return item.ID()
|
||||
}
|
||||
|
||||
type SubCommitsViewModel struct {
|
||||
*traits.ListCursor
|
||||
getModel func() []*models.Commit
|
||||
}
|
||||
|
||||
func NewSubCommitsViewModel(getModel func() []*models.Commit) *SubCommitsViewModel {
|
||||
self := &SubCommitsViewModel{
|
||||
getModel: getModel,
|
||||
}
|
||||
|
||||
self.ListCursor = traits.NewListCursor(self)
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *SubCommitsViewModel) GetItemsLength() int {
|
||||
return len(self.getModel())
|
||||
}
|
||||
|
||||
func (self *SubCommitsViewModel) GetSelected() *models.Commit {
|
||||
if self.GetItemsLength() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.getModel()[self.GetSelectedLineIdx()]
|
||||
}
|
86
pkg/gui/context/submodules_context.go
Normal file
86
pkg/gui/context/submodules_context.go
Normal file
@ -0,0 +1,86 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type SubmodulesContext struct {
|
||||
*SubmodulesViewModel
|
||||
*ListContextTrait
|
||||
}
|
||||
|
||||
var _ types.IListContext = (*SubmodulesContext)(nil)
|
||||
|
||||
func NewSubmodulesContext(
|
||||
getModel func() []*models.SubmoduleConfig,
|
||||
view *gocui.View,
|
||||
getDisplayStrings func(startIdx int, length int) [][]string,
|
||||
|
||||
onFocus func(...types.OnFocusOpts) error,
|
||||
onRenderToMain func(...types.OnFocusOpts) error,
|
||||
onFocusLost func() error,
|
||||
|
||||
c *types.ControllerCommon,
|
||||
) *SubmodulesContext {
|
||||
viewModel := NewSubmodulesViewModel(getModel)
|
||||
|
||||
return &SubmodulesContext{
|
||||
SubmodulesViewModel: viewModel,
|
||||
ListContextTrait: &ListContextTrait{
|
||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "files",
|
||||
WindowName: "files",
|
||||
Key: SUBMODULES_CONTEXT_KEY,
|
||||
Kind: types.SIDE_CONTEXT,
|
||||
Focusable: true,
|
||||
}), ContextCallbackOpts{
|
||||
OnFocus: onFocus,
|
||||
OnFocusLost: onFocusLost,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
}),
|
||||
list: viewModel,
|
||||
viewTrait: NewViewTrait(view),
|
||||
getDisplayStrings: getDisplayStrings,
|
||||
c: c,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SubmodulesContext) GetSelectedItemId() string {
|
||||
item := self.GetSelected()
|
||||
if item == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return item.ID()
|
||||
}
|
||||
|
||||
type SubmodulesViewModel struct {
|
||||
*traits.ListCursor
|
||||
getModel func() []*models.SubmoduleConfig
|
||||
}
|
||||
|
||||
func NewSubmodulesViewModel(getModel func() []*models.SubmoduleConfig) *SubmodulesViewModel {
|
||||
self := &SubmodulesViewModel{
|
||||
getModel: getModel,
|
||||
}
|
||||
|
||||
self.ListCursor = traits.NewListCursor(self)
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *SubmodulesViewModel) GetItemsLength() int {
|
||||
return len(self.getModel())
|
||||
}
|
||||
|
||||
func (self *SubmodulesViewModel) GetSelected() *models.SubmoduleConfig {
|
||||
if self.GetItemsLength() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.getModel()[self.GetSelectedLineIdx()]
|
||||
}
|
85
pkg/gui/context/suggestions_context.go
Normal file
85
pkg/gui/context/suggestions_context.go
Normal file
@ -0,0 +1,85 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type SuggestionsContext struct {
|
||||
*SuggestionsViewModel
|
||||
*ListContextTrait
|
||||
}
|
||||
|
||||
var _ types.IListContext = (*SuggestionsContext)(nil)
|
||||
|
||||
func NewSuggestionsContext(
|
||||
getModel func() []*types.Suggestion,
|
||||
view *gocui.View,
|
||||
getDisplayStrings func(startIdx int, length int) [][]string,
|
||||
|
||||
onFocus func(...types.OnFocusOpts) error,
|
||||
onRenderToMain func(...types.OnFocusOpts) error,
|
||||
onFocusLost func() error,
|
||||
|
||||
c *types.ControllerCommon,
|
||||
) *SuggestionsContext {
|
||||
viewModel := NewSuggestionsViewModel(getModel)
|
||||
|
||||
return &SuggestionsContext{
|
||||
SuggestionsViewModel: viewModel,
|
||||
ListContextTrait: &ListContextTrait{
|
||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "suggestions",
|
||||
WindowName: "suggestions",
|
||||
Key: SUGGESTIONS_CONTEXT_KEY,
|
||||
Kind: types.PERSISTENT_POPUP,
|
||||
Focusable: true,
|
||||
}), ContextCallbackOpts{
|
||||
OnFocus: onFocus,
|
||||
OnFocusLost: onFocusLost,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
}),
|
||||
list: viewModel,
|
||||
viewTrait: NewViewTrait(view),
|
||||
getDisplayStrings: getDisplayStrings,
|
||||
c: c,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SuggestionsContext) GetSelectedItemId() string {
|
||||
item := self.GetSelected()
|
||||
if item == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return item.Value
|
||||
}
|
||||
|
||||
type SuggestionsViewModel struct {
|
||||
*traits.ListCursor
|
||||
getModel func() []*types.Suggestion
|
||||
}
|
||||
|
||||
func NewSuggestionsViewModel(getModel func() []*types.Suggestion) *SuggestionsViewModel {
|
||||
self := &SuggestionsViewModel{
|
||||
getModel: getModel,
|
||||
}
|
||||
|
||||
self.ListCursor = traits.NewListCursor(self)
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *SuggestionsViewModel) GetItemsLength() int {
|
||||
return len(self.getModel())
|
||||
}
|
||||
|
||||
func (self *SuggestionsViewModel) GetSelected() *types.Suggestion {
|
||||
if self.GetItemsLength() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.getModel()[self.GetSelectedLineIdx()]
|
||||
}
|
@ -9,7 +9,6 @@ import (
|
||||
|
||||
type TagsContext struct {
|
||||
*TagsViewModel
|
||||
*BaseContext
|
||||
*ListContextTrait
|
||||
}
|
||||
|
||||
@ -17,7 +16,7 @@ var _ types.IListContext = (*TagsContext)(nil)
|
||||
|
||||
func NewTagsContext(
|
||||
getModel func() []*models.Tag,
|
||||
getView func() *gocui.View,
|
||||
view *gocui.View,
|
||||
getDisplayStrings func(startIdx int, length int) [][]string,
|
||||
|
||||
onFocus func(...types.OnFocusOpts) error,
|
||||
@ -26,47 +25,32 @@ func NewTagsContext(
|
||||
|
||||
c *types.ControllerCommon,
|
||||
) *TagsContext {
|
||||
baseContext := NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "branches",
|
||||
WindowName: "branches",
|
||||
Key: TAGS_CONTEXT_KEY,
|
||||
Kind: types.SIDE_CONTEXT,
|
||||
Focusable: true,
|
||||
})
|
||||
viewModel := NewTagsViewModel(getModel)
|
||||
|
||||
self := &TagsContext{}
|
||||
takeFocus := func() error { return c.PushContext(self) }
|
||||
|
||||
list := NewTagsViewModel(getModel)
|
||||
viewTrait := NewViewTrait(getView)
|
||||
listContextTrait := &ListContextTrait{
|
||||
base: baseContext,
|
||||
list: list,
|
||||
viewTrait: viewTrait,
|
||||
|
||||
GetDisplayStrings: getDisplayStrings,
|
||||
OnFocus: onFocus,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
OnFocusLost: onFocusLost,
|
||||
takeFocus: takeFocus,
|
||||
|
||||
// TODO: handle this in a trait
|
||||
RenderSelection: false,
|
||||
|
||||
c: c,
|
||||
return &TagsContext{
|
||||
TagsViewModel: viewModel,
|
||||
ListContextTrait: &ListContextTrait{
|
||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "branches",
|
||||
WindowName: "branches",
|
||||
Key: TAGS_CONTEXT_KEY,
|
||||
Kind: types.SIDE_CONTEXT,
|
||||
Focusable: true,
|
||||
}), ContextCallbackOpts{
|
||||
OnFocus: onFocus,
|
||||
OnFocusLost: onFocusLost,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
}),
|
||||
list: viewModel,
|
||||
viewTrait: NewViewTrait(view),
|
||||
getDisplayStrings: getDisplayStrings,
|
||||
c: c,
|
||||
},
|
||||
}
|
||||
|
||||
baseContext.AddKeybindingsFn(listContextTrait.keybindings)
|
||||
|
||||
self.BaseContext = baseContext
|
||||
self.ListContextTrait = listContextTrait
|
||||
self.TagsViewModel = list
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *TagsContext) GetSelectedItemId() string {
|
||||
item := self.GetSelectedTag()
|
||||
item := self.GetSelected()
|
||||
if item == nil {
|
||||
return ""
|
||||
}
|
||||
@ -79,18 +63,6 @@ type TagsViewModel struct {
|
||||
getModel func() []*models.Tag
|
||||
}
|
||||
|
||||
func (self *TagsViewModel) GetItemsLength() int {
|
||||
return len(self.getModel())
|
||||
}
|
||||
|
||||
func (self *TagsViewModel) GetSelectedTag() *models.Tag {
|
||||
if self.GetItemsLength() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.getModel()[self.GetSelectedLineIdx()]
|
||||
}
|
||||
|
||||
func NewTagsViewModel(getModel func() []*models.Tag) *TagsViewModel {
|
||||
self := &TagsViewModel{
|
||||
getModel: getModel,
|
||||
@ -100,3 +72,15 @@ func NewTagsViewModel(getModel func() []*models.Tag) *TagsViewModel {
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *TagsViewModel) GetItemsLength() int {
|
||||
return len(self.getModel())
|
||||
}
|
||||
|
||||
func (self *TagsViewModel) GetSelected() *models.Tag {
|
||||
if self.GetItemsLength() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return self.getModel()[self.GetSelectedLineIdx()]
|
||||
}
|
||||
|
@ -2,70 +2,62 @@ package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
|
||||
const HORIZONTAL_SCROLL_FACTOR = 3
|
||||
|
||||
type ViewTrait struct {
|
||||
getView func() *gocui.View
|
||||
view *gocui.View
|
||||
}
|
||||
|
||||
func NewViewTrait(getView func() *gocui.View) *ViewTrait {
|
||||
return &ViewTrait{getView: getView}
|
||||
var _ types.IViewTrait = &ViewTrait{}
|
||||
|
||||
func NewViewTrait(view *gocui.View) *ViewTrait {
|
||||
return &ViewTrait{view: view}
|
||||
}
|
||||
|
||||
func (self *ViewTrait) FocusPoint(yIdx int) {
|
||||
view := self.getView()
|
||||
view.FocusPoint(view.OriginX(), yIdx)
|
||||
self.view.FocusPoint(self.view.OriginX(), yIdx)
|
||||
}
|
||||
|
||||
func (self *ViewTrait) SetViewPortContent(content string) {
|
||||
view := self.getView()
|
||||
|
||||
_, y := view.Origin()
|
||||
view.OverwriteLines(y, content)
|
||||
_, y := self.view.Origin()
|
||||
self.view.OverwriteLines(y, content)
|
||||
}
|
||||
|
||||
func (self *ViewTrait) SetContent(content string) {
|
||||
self.getView().SetContent(content)
|
||||
self.view.SetContent(content)
|
||||
}
|
||||
|
||||
func (self *ViewTrait) SetFooter(value string) {
|
||||
self.getView().Footer = value
|
||||
self.view.Footer = value
|
||||
}
|
||||
|
||||
func (self *ViewTrait) SetOriginX(value int) {
|
||||
_ = self.getView().SetOriginX(value)
|
||||
_ = self.view.SetOriginX(value)
|
||||
}
|
||||
|
||||
// tells us the bounds of line indexes shown in the view currently
|
||||
func (self *ViewTrait) ViewPortYBounds() (int, int) {
|
||||
view := self.getView()
|
||||
|
||||
_, min := view.Origin()
|
||||
max := view.InnerHeight() + 1
|
||||
_, min := self.view.Origin()
|
||||
max := self.view.InnerHeight() + 1
|
||||
return min, max
|
||||
}
|
||||
|
||||
func (self *ViewTrait) ScrollLeft() {
|
||||
view := self.getView()
|
||||
|
||||
newOriginX := utils.Max(view.OriginX()-view.InnerWidth()/HORIZONTAL_SCROLL_FACTOR, 0)
|
||||
_ = view.SetOriginX(newOriginX)
|
||||
newOriginX := utils.Max(self.view.OriginX()-self.view.InnerWidth()/HORIZONTAL_SCROLL_FACTOR, 0)
|
||||
_ = self.view.SetOriginX(newOriginX)
|
||||
}
|
||||
|
||||
func (self *ViewTrait) ScrollRight() {
|
||||
view := self.getView()
|
||||
|
||||
_ = view.SetOriginX(view.OriginX() + view.InnerWidth()/HORIZONTAL_SCROLL_FACTOR)
|
||||
_ = self.view.SetOriginX(self.view.OriginX() + self.view.InnerWidth()/HORIZONTAL_SCROLL_FACTOR)
|
||||
}
|
||||
|
||||
// this returns the amount we'll scroll if we want to scroll by a page.
|
||||
func (self *ViewTrait) PageDelta() int {
|
||||
view := self.getView()
|
||||
|
||||
_, height := view.Size()
|
||||
_, height := self.view.Size()
|
||||
|
||||
delta := height - 1
|
||||
if delta == 0 {
|
||||
@ -76,5 +68,5 @@ func (self *ViewTrait) PageDelta() int {
|
||||
}
|
||||
|
||||
func (self *ViewTrait) SelectedLineIdx() int {
|
||||
return self.getView().SelectedLineIdx()
|
||||
return self.view.SelectedLineIdx()
|
||||
}
|
||||
|
22
pkg/gui/context/viewport_list_context_trait.go
Normal file
22
pkg/gui/context/viewport_list_context_trait.go
Normal file
@ -0,0 +1,22 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
|
||||
// This embeds a list context trait and adds logic to re-render the viewport
|
||||
// whenever a line is focused. We use this in the commits panel because different
|
||||
// sections of the log graph need to be highlighted depending on the currently selected line
|
||||
|
||||
type ViewportListContextTrait struct {
|
||||
*ListContextTrait
|
||||
}
|
||||
|
||||
func (self *ViewportListContextTrait) FocusLine() {
|
||||
self.ListContextTrait.FocusLine()
|
||||
|
||||
min, max := self.GetViewTrait().ViewPortYBounds()
|
||||
displayStrings := self.ListContextTrait.getDisplayStrings(min, max)
|
||||
content := utils.RenderDisplayStrings(displayStrings)
|
||||
self.GetViewTrait().SetViewPortContent(content)
|
||||
}
|
@ -9,7 +9,6 @@ import (
|
||||
|
||||
type WorkingTreeContext struct {
|
||||
*filetree.FileTreeViewModel
|
||||
*BaseContext
|
||||
*ListContextTrait
|
||||
}
|
||||
|
||||
@ -17,7 +16,7 @@ var _ types.IListContext = (*WorkingTreeContext)(nil)
|
||||
|
||||
func NewWorkingTreeContext(
|
||||
getModel func() []*models.File,
|
||||
getView func() *gocui.View,
|
||||
view *gocui.View,
|
||||
getDisplayStrings func(startIdx int, length int) [][]string,
|
||||
|
||||
onFocus func(...types.OnFocusOpts) error,
|
||||
@ -26,43 +25,28 @@ func NewWorkingTreeContext(
|
||||
|
||||
c *types.ControllerCommon,
|
||||
) *WorkingTreeContext {
|
||||
baseContext := NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "files",
|
||||
WindowName: "files",
|
||||
Key: FILES_CONTEXT_KEY,
|
||||
Kind: types.SIDE_CONTEXT,
|
||||
Focusable: true,
|
||||
})
|
||||
|
||||
self := &WorkingTreeContext{}
|
||||
takeFocus := func() error { return c.PushContext(self) }
|
||||
|
||||
viewModel := filetree.NewFileTreeViewModel(getModel, c.Log, c.UserConfig.Gui.ShowFileTree)
|
||||
viewTrait := NewViewTrait(getView)
|
||||
listContextTrait := &ListContextTrait{
|
||||
base: baseContext,
|
||||
list: viewModel,
|
||||
viewTrait: viewTrait,
|
||||
|
||||
GetDisplayStrings: getDisplayStrings,
|
||||
OnFocus: onFocus,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
OnFocusLost: onFocusLost,
|
||||
takeFocus: takeFocus,
|
||||
|
||||
// TODO: handle this in a trait
|
||||
RenderSelection: false,
|
||||
|
||||
c: c,
|
||||
return &WorkingTreeContext{
|
||||
FileTreeViewModel: viewModel,
|
||||
ListContextTrait: &ListContextTrait{
|
||||
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
||||
ViewName: "files",
|
||||
WindowName: "files",
|
||||
Key: FILES_CONTEXT_KEY,
|
||||
Kind: types.SIDE_CONTEXT,
|
||||
Focusable: true,
|
||||
}), ContextCallbackOpts{
|
||||
OnFocus: onFocus,
|
||||
OnFocusLost: onFocusLost,
|
||||
OnRenderToMain: onRenderToMain,
|
||||
}),
|
||||
list: viewModel,
|
||||
viewTrait: NewViewTrait(view),
|
||||
getDisplayStrings: getDisplayStrings,
|
||||
c: c,
|
||||
},
|
||||
}
|
||||
|
||||
baseContext.AddKeybindingsFn(listContextTrait.keybindings)
|
||||
|
||||
self.BaseContext = baseContext
|
||||
self.ListContextTrait = listContextTrait
|
||||
self.FileTreeViewModel = viewModel
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *WorkingTreeContext) GetSelectedItemId() string {
|
||||
|
Reference in New Issue
Block a user