mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-06-17 00:18:05 +02:00
Set groundwork for better disabled reasons with range select
Something dumb that we're currently doing is expecting list items to define an ID method which returns a string. We use that when copying items to clipboard with ctrl+o and when getting a ref name for diffing. This commit gets us a little deeper into that hole by explicitly requiring list items to implement that method so that we can easily use the new helper functions in list_controller_trait.go. In future we need to just remove the whole ID thing entirely but I'm too lazy to do that right now.
This commit is contained in:
@ -59,15 +59,6 @@ func NewBranchesContext(c *ContextCommon) *BranchesContext {
|
|||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *BranchesContext) GetSelectedItemId() string {
|
|
||||||
item := self.GetSelected()
|
|
||||||
if item == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.ID()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *BranchesContext) GetSelectedRef() types.Ref {
|
func (self *BranchesContext) GetSelectedRef() types.Ref {
|
||||||
branch := self.GetSelected()
|
branch := self.GetSelected()
|
||||||
if branch == nil {
|
if branch == nil {
|
||||||
|
@ -72,15 +72,6 @@ func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
|
|||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CommitFilesContext) GetSelectedItemId() string {
|
|
||||||
item := self.GetSelected()
|
|
||||||
if item == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.ID()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *CommitFilesContext) GetDiffTerminals() []string {
|
func (self *CommitFilesContext) GetDiffTerminals() []string {
|
||||||
return []string{self.GetRef().RefName()}
|
return []string{self.GetRef().RefName()}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package context
|
package context
|
||||||
|
|
||||||
type FilteredListViewModel[T any] struct {
|
type FilteredListViewModel[T HasID] struct {
|
||||||
*FilteredList[T]
|
*FilteredList[T]
|
||||||
*ListViewModel[T]
|
*ListViewModel[T]
|
||||||
*SearchHistory
|
*SearchHistory
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFilteredListViewModel[T any](getList func() []T, getFilterFields func(T) []string) *FilteredListViewModel[T] {
|
func NewFilteredListViewModel[T HasID](getList func() []T, getFilterFields func(T) []string) *FilteredListViewModel[T] {
|
||||||
filteredList := NewFilteredList(getList, getFilterFields)
|
filteredList := NewFilteredList(getList, getFilterFields)
|
||||||
|
|
||||||
self := &FilteredListViewModel[T]{
|
self := &FilteredListViewModel[T]{
|
||||||
|
@ -9,10 +9,17 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// wrapping string in my own type to give it an ID method which is required for list items
|
||||||
|
type mystring string
|
||||||
|
|
||||||
|
func (self mystring) ID() string {
|
||||||
|
return string(self)
|
||||||
|
}
|
||||||
|
|
||||||
func TestListRenderer_renderLines(t *testing.T) {
|
func TestListRenderer_renderLines(t *testing.T) {
|
||||||
scenarios := []struct {
|
scenarios := []struct {
|
||||||
name string
|
name string
|
||||||
modelStrings []string
|
modelStrings []mystring
|
||||||
nonModelIndices []int
|
nonModelIndices []int
|
||||||
startIdx int
|
startIdx int
|
||||||
endIdx int
|
endIdx int
|
||||||
@ -20,7 +27,7 @@ func TestListRenderer_renderLines(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "Render whole list",
|
name: "Render whole list",
|
||||||
modelStrings: []string{"a", "b", "c"},
|
modelStrings: []mystring{"a", "b", "c"},
|
||||||
startIdx: 0,
|
startIdx: 0,
|
||||||
endIdx: 3,
|
endIdx: 3,
|
||||||
expectedOutput: `
|
expectedOutput: `
|
||||||
@ -30,7 +37,7 @@ func TestListRenderer_renderLines(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Partial list, beginning",
|
name: "Partial list, beginning",
|
||||||
modelStrings: []string{"a", "b", "c"},
|
modelStrings: []mystring{"a", "b", "c"},
|
||||||
startIdx: 0,
|
startIdx: 0,
|
||||||
endIdx: 2,
|
endIdx: 2,
|
||||||
expectedOutput: `
|
expectedOutput: `
|
||||||
@ -39,7 +46,7 @@ func TestListRenderer_renderLines(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Partial list, end",
|
name: "Partial list, end",
|
||||||
modelStrings: []string{"a", "b", "c"},
|
modelStrings: []mystring{"a", "b", "c"},
|
||||||
startIdx: 1,
|
startIdx: 1,
|
||||||
endIdx: 3,
|
endIdx: 3,
|
||||||
expectedOutput: `
|
expectedOutput: `
|
||||||
@ -48,7 +55,7 @@ func TestListRenderer_renderLines(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Pass an endIdx greater than the model length",
|
name: "Pass an endIdx greater than the model length",
|
||||||
modelStrings: []string{"a", "b", "c"},
|
modelStrings: []mystring{"a", "b", "c"},
|
||||||
startIdx: 2,
|
startIdx: 2,
|
||||||
endIdx: 5,
|
endIdx: 5,
|
||||||
expectedOutput: `
|
expectedOutput: `
|
||||||
@ -56,7 +63,7 @@ func TestListRenderer_renderLines(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Whole list with section headers",
|
name: "Whole list with section headers",
|
||||||
modelStrings: []string{"a", "b", "c"},
|
modelStrings: []mystring{"a", "b", "c"},
|
||||||
nonModelIndices: []int{1, 3},
|
nonModelIndices: []int{1, 3},
|
||||||
startIdx: 0,
|
startIdx: 0,
|
||||||
endIdx: 5,
|
endIdx: 5,
|
||||||
@ -69,7 +76,7 @@ func TestListRenderer_renderLines(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Multiple consecutive headers",
|
name: "Multiple consecutive headers",
|
||||||
modelStrings: []string{"a", "b", "c"},
|
modelStrings: []mystring{"a", "b", "c"},
|
||||||
nonModelIndices: []int{0, 0, 2, 2, 2},
|
nonModelIndices: []int{0, 0, 2, 2, 2},
|
||||||
startIdx: 0,
|
startIdx: 0,
|
||||||
endIdx: 8,
|
endIdx: 8,
|
||||||
@ -85,7 +92,7 @@ func TestListRenderer_renderLines(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Partial list with headers, beginning",
|
name: "Partial list with headers, beginning",
|
||||||
modelStrings: []string{"a", "b", "c"},
|
modelStrings: []mystring{"a", "b", "c"},
|
||||||
nonModelIndices: []int{1, 3},
|
nonModelIndices: []int{1, 3},
|
||||||
startIdx: 0,
|
startIdx: 0,
|
||||||
endIdx: 3,
|
endIdx: 3,
|
||||||
@ -96,7 +103,7 @@ func TestListRenderer_renderLines(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Partial list with headers, end (beyond end index)",
|
name: "Partial list with headers, end (beyond end index)",
|
||||||
modelStrings: []string{"a", "b", "c"},
|
modelStrings: []mystring{"a", "b", "c"},
|
||||||
nonModelIndices: []int{1, 3},
|
nonModelIndices: []int{1, 3},
|
||||||
startIdx: 2,
|
startIdx: 2,
|
||||||
endIdx: 7,
|
endIdx: 7,
|
||||||
@ -108,7 +115,7 @@ func TestListRenderer_renderLines(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, s := range scenarios {
|
for _, s := range scenarios {
|
||||||
t.Run(s.name, func(t *testing.T) {
|
t.Run(s.name, func(t *testing.T) {
|
||||||
viewModel := NewListViewModel[string](func() []string { return s.modelStrings })
|
viewModel := NewListViewModel[mystring](func() []mystring { return s.modelStrings })
|
||||||
var getNonModelItems func() []*NonModelItem
|
var getNonModelItems func() []*NonModelItem
|
||||||
if s.nonModelIndices != nil {
|
if s.nonModelIndices != nil {
|
||||||
getNonModelItems = func() []*NonModelItem {
|
getNonModelItems = func() []*NonModelItem {
|
||||||
@ -124,7 +131,7 @@ func TestListRenderer_renderLines(t *testing.T) {
|
|||||||
list: viewModel,
|
list: viewModel,
|
||||||
getDisplayStrings: func(startIdx int, endIdx int) [][]string {
|
getDisplayStrings: func(startIdx int, endIdx int) [][]string {
|
||||||
return lo.Map(s.modelStrings[startIdx:endIdx],
|
return lo.Map(s.modelStrings[startIdx:endIdx],
|
||||||
func(s string, _ int) []string { return []string{s} })
|
func(s mystring, _ int) []string { return []string{string(s)} })
|
||||||
},
|
},
|
||||||
getNonModelItems: getNonModelItems,
|
getNonModelItems: getNonModelItems,
|
||||||
}
|
}
|
||||||
@ -138,6 +145,12 @@ func TestListRenderer_renderLines(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type myint int
|
||||||
|
|
||||||
|
func (self myint) ID() string {
|
||||||
|
return fmt.Sprint(int(self))
|
||||||
|
}
|
||||||
|
|
||||||
func TestListRenderer_ModelIndexToViewIndex_and_back(t *testing.T) {
|
func TestListRenderer_ModelIndexToViewIndex_and_back(t *testing.T) {
|
||||||
scenarios := []struct {
|
scenarios := []struct {
|
||||||
name string
|
name string
|
||||||
@ -222,8 +235,8 @@ func TestListRenderer_ModelIndexToViewIndex_and_back(t *testing.T) {
|
|||||||
assert.Equal(t, len(s.modelIndices), len(s.expectedViewIndices))
|
assert.Equal(t, len(s.modelIndices), len(s.expectedViewIndices))
|
||||||
assert.Equal(t, len(s.viewIndices), len(s.expectedModelIndices))
|
assert.Equal(t, len(s.viewIndices), len(s.expectedModelIndices))
|
||||||
|
|
||||||
modelInts := lo.Range(s.numModelItems)
|
modelInts := lo.Map(lo.Range(s.numModelItems), func(i int, _ int) myint { return myint(i) })
|
||||||
viewModel := NewListViewModel[int](func() []int { return modelInts })
|
viewModel := NewListViewModel[myint](func() []myint { return modelInts })
|
||||||
var getNonModelItems func() []*NonModelItem
|
var getNonModelItems func() []*NonModelItem
|
||||||
if s.nonModelIndices != nil {
|
if s.nonModelIndices != nil {
|
||||||
getNonModelItems = func() []*NonModelItem {
|
getNonModelItems = func() []*NonModelItem {
|
||||||
@ -236,7 +249,7 @@ func TestListRenderer_ModelIndexToViewIndex_and_back(t *testing.T) {
|
|||||||
list: viewModel,
|
list: viewModel,
|
||||||
getDisplayStrings: func(startIdx int, endIdx int) [][]string {
|
getDisplayStrings: func(startIdx int, endIdx int) [][]string {
|
||||||
return lo.Map(modelInts[startIdx:endIdx],
|
return lo.Map(modelInts[startIdx:endIdx],
|
||||||
func(i int, _ int) []string { return []string{fmt.Sprint(i)} })
|
func(i myint, _ int) []string { return []string{fmt.Sprint(i)} })
|
||||||
},
|
},
|
||||||
getNonModelItems: getNonModelItems,
|
getNonModelItems: getNonModelItems,
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,19 @@ package context
|
|||||||
import (
|
import (
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ListViewModel[T any] struct {
|
type HasID interface {
|
||||||
|
ID() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListViewModel[T HasID] struct {
|
||||||
*traits.ListCursor
|
*traits.ListCursor
|
||||||
getModel func() []T
|
getModel func() []T
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewListViewModel[T any](getModel func() []T) *ListViewModel[T] {
|
func NewListViewModel[T HasID](getModel func() []T) *ListViewModel[T] {
|
||||||
self := &ListViewModel[T]{
|
self := &ListViewModel[T]{
|
||||||
getModel: getModel,
|
getModel: getModel,
|
||||||
}
|
}
|
||||||
@ -32,6 +37,34 @@ func (self *ListViewModel[T]) GetSelected() T {
|
|||||||
return self.getModel()[self.GetSelectedLineIdx()]
|
return self.getModel()[self.GetSelectedLineIdx()]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *ListViewModel[T]) GetSelectedItemId() string {
|
||||||
|
if self.Len() == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.GetSelected().ID()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListViewModel[T]) GetSelectedItems() ([]T, int, int) {
|
||||||
|
if self.Len() == 0 {
|
||||||
|
return nil, -1, -1
|
||||||
|
}
|
||||||
|
|
||||||
|
startIdx, endIdx := self.GetSelectionRange()
|
||||||
|
|
||||||
|
return self.getModel()[startIdx : endIdx+1], startIdx, endIdx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListViewModel[T]) GetSelectedItemIds() ([]string, int, int) {
|
||||||
|
selectedItems, startIdx, endIdx := self.GetSelectedItems()
|
||||||
|
|
||||||
|
ids := lo.Map(selectedItems, func(item T, _ int) string {
|
||||||
|
return item.ID()
|
||||||
|
})
|
||||||
|
|
||||||
|
return ids, startIdx, endIdx
|
||||||
|
}
|
||||||
|
|
||||||
func (self *ListViewModel[T]) GetItems() []T {
|
func (self *ListViewModel[T]) GetItems() []T {
|
||||||
return self.getModel()
|
return self.getModel()
|
||||||
}
|
}
|
||||||
|
@ -92,15 +92,6 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
|
|||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *LocalCommitsContext) GetSelectedItemId() string {
|
|
||||||
item := self.GetSelected()
|
|
||||||
if item == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.ID()
|
|
||||||
}
|
|
||||||
|
|
||||||
type LocalCommitsViewModel struct {
|
type LocalCommitsViewModel struct {
|
||||||
*ListViewModel[*models.Commit]
|
*ListViewModel[*models.Commit]
|
||||||
|
|
||||||
|
@ -45,16 +45,6 @@ func NewMenuContext(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove this thing.
|
|
||||||
func (self *MenuContext) GetSelectedItemId() string {
|
|
||||||
item := self.GetSelected()
|
|
||||||
if item == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.Label
|
|
||||||
}
|
|
||||||
|
|
||||||
type MenuViewModel struct {
|
type MenuViewModel struct {
|
||||||
c *ContextCommon
|
c *ContextCommon
|
||||||
menuItems []*types.MenuItem
|
menuItems []*types.MenuItem
|
||||||
|
@ -59,15 +59,6 @@ func NewReflogCommitsContext(c *ContextCommon) *ReflogCommitsContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ReflogCommitsContext) GetSelectedItemId() string {
|
|
||||||
item := self.GetSelected()
|
|
||||||
if item == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.ID()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *ReflogCommitsContext) CanRebase() bool {
|
func (self *ReflogCommitsContext) CanRebase() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
"github.com/samber/lo"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RemoteBranchesContext struct {
|
type RemoteBranchesContext struct {
|
||||||
@ -53,15 +54,6 @@ func NewRemoteBranchesContext(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RemoteBranchesContext) GetSelectedItemId() string {
|
|
||||||
item := self.GetSelected()
|
|
||||||
if item == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.ID()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *RemoteBranchesContext) GetSelectedRef() types.Ref {
|
func (self *RemoteBranchesContext) GetSelectedRef() types.Ref {
|
||||||
remoteBranch := self.GetSelected()
|
remoteBranch := self.GetSelected()
|
||||||
if remoteBranch == nil {
|
if remoteBranch == nil {
|
||||||
@ -70,6 +62,16 @@ func (self *RemoteBranchesContext) GetSelectedRef() types.Ref {
|
|||||||
return remoteBranch
|
return remoteBranch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *RemoteBranchesContext) GetSelectedRefs() ([]types.Ref, int, int) {
|
||||||
|
items, startIdx, endIdx := self.GetSelectedItems()
|
||||||
|
|
||||||
|
refs := lo.Map(items, func(item *models.RemoteBranch, _ int) types.Ref {
|
||||||
|
return item
|
||||||
|
})
|
||||||
|
|
||||||
|
return refs, startIdx, endIdx
|
||||||
|
}
|
||||||
|
|
||||||
func (self *RemoteBranchesContext) GetDiffTerminals() []string {
|
func (self *RemoteBranchesContext) GetDiffTerminals() []string {
|
||||||
itemId := self.GetSelectedItemId()
|
itemId := self.GetSelectedItemId()
|
||||||
|
|
||||||
|
@ -47,15 +47,6 @@ func NewRemotesContext(c *ContextCommon) *RemotesContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *RemotesContext) GetSelectedItemId() string {
|
|
||||||
item := self.GetSelected()
|
|
||||||
if item == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.ID()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *RemotesContext) GetDiffTerminals() []string {
|
func (self *RemotesContext) GetDiffTerminals() []string {
|
||||||
itemId := self.GetSelectedItemId()
|
itemId := self.GetSelectedItemId()
|
||||||
|
|
||||||
|
@ -49,15 +49,6 @@ func NewStashContext(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *StashContext) GetSelectedItemId() string {
|
|
||||||
item := self.GetSelected()
|
|
||||||
if item == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.ID()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *StashContext) CanRebase() bool {
|
func (self *StashContext) CanRebase() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -175,15 +175,6 @@ func (self *SubCommitsViewModel) GetShowBranchHeads() bool {
|
|||||||
return self.showBranchHeads
|
return self.showBranchHeads
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SubCommitsContext) GetSelectedItemId() string {
|
|
||||||
item := self.GetSelected()
|
|
||||||
if item == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.ID()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *SubCommitsContext) CanRebase() bool {
|
func (self *SubCommitsContext) CanRebase() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -43,12 +43,3 @@ func NewSubmodulesContext(c *ContextCommon) *SubmodulesContext {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SubmodulesContext) GetSelectedItemId() string {
|
|
||||||
item := self.GetSelected()
|
|
||||||
if item == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.ID()
|
|
||||||
}
|
|
||||||
|
@ -63,15 +63,6 @@ func NewSuggestionsContext(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SuggestionsContext) GetSelectedItemId() string {
|
|
||||||
item := self.GetSelected()
|
|
||||||
if item == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *SuggestionsContext) SetSuggestions(suggestions []*types.Suggestion) {
|
func (self *SuggestionsContext) SetSuggestions(suggestions []*types.Suggestion) {
|
||||||
self.State.Suggestions = suggestions
|
self.State.Suggestions = suggestions
|
||||||
self.SetSelection(0)
|
self.SetSelection(0)
|
||||||
|
@ -52,15 +52,6 @@ func NewTagsContext(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *TagsContext) GetSelectedItemId() string {
|
|
||||||
item := self.GetSelected()
|
|
||||||
if item == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.ID()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (self *TagsContext) GetSelectedRef() types.Ref {
|
func (self *TagsContext) GetSelectedRef() types.Ref {
|
||||||
tag := self.GetSelected()
|
tag := self.GetSelected()
|
||||||
if tag == nil {
|
if tag == nil {
|
||||||
|
@ -58,12 +58,3 @@ func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
|
|||||||
|
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorkingTreeContext) GetSelectedItemId() string {
|
|
||||||
item := self.GetSelected()
|
|
||||||
if item == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.ID()
|
|
||||||
}
|
|
||||||
|
@ -46,12 +46,3 @@ func NewWorktreesContext(c *ContextCommon) *WorktreesContext {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *WorktreesContext) GetSelectedItemId() string {
|
|
||||||
item := self.GetSelected()
|
|
||||||
if item == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.ID()
|
|
||||||
}
|
|
||||||
|
@ -16,6 +16,7 @@ type ContainsCommits interface {
|
|||||||
types.Context
|
types.Context
|
||||||
types.IListContext
|
types.IListContext
|
||||||
GetSelected() *models.Commit
|
GetSelected() *models.Commit
|
||||||
|
GetSelectedItems() ([]*models.Commit, int, int)
|
||||||
GetCommits() []*models.Commit
|
GetCommits() []*models.Commit
|
||||||
GetSelectedLineIdx() int
|
GetSelectedLineIdx() int
|
||||||
}
|
}
|
||||||
@ -36,6 +37,7 @@ func NewBasicCommitsController(c *ControllerCommon, context ContainsCommits) *Ba
|
|||||||
c,
|
c,
|
||||||
context,
|
context,
|
||||||
context.GetSelected,
|
context.GetSelected,
|
||||||
|
context.GetSelectedItems,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ func NewBisectController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().LocalCommits,
|
c.Contexts().LocalCommits,
|
||||||
c.Contexts().LocalCommits.GetSelected,
|
c.Contexts().LocalCommits.GetSelected,
|
||||||
|
c.Contexts().LocalCommits.GetSelectedItems,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ func NewBranchesController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().Branches,
|
c.Contexts().Branches,
|
||||||
c.Contexts().Branches.GetSelected,
|
c.Contexts().Branches.GetSelected,
|
||||||
|
c.Contexts().Branches.GetSelectedItems,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ func NewCommitFilesController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().CommitFiles,
|
c.Contexts().CommitFiles,
|
||||||
c.Contexts().CommitFiles.GetSelected,
|
c.Contexts().CommitFiles.GetSelected,
|
||||||
|
c.Contexts().CommitFiles.GetSelectedItems,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ func NewFilesController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().Files,
|
c.Contexts().Files,
|
||||||
c.Contexts().Files.GetSelected,
|
c.Contexts().Files.GetSelected,
|
||||||
|
c.Contexts().Files.GetSelectedItems,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ func NewFilesRemoveController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().Files,
|
c.Contexts().Files,
|
||||||
c.Contexts().Files.GetSelected,
|
c.Contexts().Files.GetSelected,
|
||||||
|
c.Contexts().Files.GetSelectedItems,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ func NewGitFlowController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().Branches,
|
c.Contexts().Branches,
|
||||||
c.Contexts().Branches.GetSelected,
|
c.Contexts().Branches.GetSelected,
|
||||||
|
c.Contexts().Branches.GetSelectedItems,
|
||||||
),
|
),
|
||||||
c: c,
|
c: c,
|
||||||
}
|
}
|
||||||
|
@ -8,18 +8,21 @@ import "github.com/jesseduffield/lazygit/pkg/gui/types"
|
|||||||
type ListControllerTrait[T comparable] struct {
|
type ListControllerTrait[T comparable] struct {
|
||||||
c *ControllerCommon
|
c *ControllerCommon
|
||||||
context types.IListContext
|
context types.IListContext
|
||||||
getSelected func() T
|
getSelectedItem func() T
|
||||||
|
getSelectedItems func() ([]T, int, int)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewListControllerTrait[T comparable](
|
func NewListControllerTrait[T comparable](
|
||||||
c *ControllerCommon,
|
c *ControllerCommon,
|
||||||
context types.IListContext,
|
context types.IListContext,
|
||||||
getSelected func() T,
|
getSelected func() T,
|
||||||
|
getSelectedItems func() ([]T, int, int),
|
||||||
) *ListControllerTrait[T] {
|
) *ListControllerTrait[T] {
|
||||||
return &ListControllerTrait[T]{
|
return &ListControllerTrait[T]{
|
||||||
c: c,
|
c: c,
|
||||||
context: context,
|
context: context,
|
||||||
getSelected: getSelected,
|
getSelectedItem: getSelected,
|
||||||
|
getSelectedItems: getSelectedItems,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +50,7 @@ func (self *ListControllerTrait[T]) singleItemSelected(callbacks ...func(T) *typ
|
|||||||
}
|
}
|
||||||
|
|
||||||
var zeroValue T
|
var zeroValue T
|
||||||
item := self.getSelected()
|
item := self.getSelectedItem()
|
||||||
if item == zeroValue {
|
if item == zeroValue {
|
||||||
return &types.DisabledReason{Text: self.c.Tr.NoItemSelected}
|
return &types.DisabledReason{Text: self.c.Tr.NoItemSelected}
|
||||||
}
|
}
|
||||||
@ -62,11 +65,46 @@ func (self *ListControllerTrait[T]) singleItemSelected(callbacks ...func(T) *typ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensures that at least one item is selected.
|
||||||
|
func (self *ListControllerTrait[T]) itemRangeSelected(callbacks ...func([]T, int, int) *types.DisabledReason) func() *types.DisabledReason {
|
||||||
|
return func() *types.DisabledReason {
|
||||||
|
items, startIdx, endIdx := self.getSelectedItems()
|
||||||
|
if len(items) == 0 {
|
||||||
|
return &types.DisabledReason{Text: self.c.Tr.NoItemSelected}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, callback := range callbacks {
|
||||||
|
if reason := callback(items, startIdx, endIdx); reason != nil {
|
||||||
|
return reason
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *ListControllerTrait[T]) itemsSelected(callbacks ...func([]T) *types.DisabledReason) func() *types.DisabledReason { //nolint:unused
|
||||||
|
return func() *types.DisabledReason {
|
||||||
|
items, _, _ := self.getSelectedItems()
|
||||||
|
if len(items) == 0 {
|
||||||
|
return &types.DisabledReason{Text: self.c.Tr.NoItemSelected}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, callback := range callbacks {
|
||||||
|
if reason := callback(items); reason != nil {
|
||||||
|
return reason
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Passes the selected item to the callback. Used for handler functions.
|
// Passes the selected item to the callback. Used for handler functions.
|
||||||
func (self *ListControllerTrait[T]) withItem(callback func(T) error) func() error {
|
func (self *ListControllerTrait[T]) withItem(callback func(T) error) func() error {
|
||||||
return func() error {
|
return func() error {
|
||||||
var zeroValue T
|
var zeroValue T
|
||||||
commit := self.getSelected()
|
commit := self.getSelectedItem()
|
||||||
if commit == zeroValue {
|
if commit == zeroValue {
|
||||||
return self.c.ErrorMsg(self.c.Tr.NoItemSelected)
|
return self.c.ErrorMsg(self.c.Tr.NoItemSelected)
|
||||||
}
|
}
|
||||||
@ -75,12 +113,35 @@ func (self *ListControllerTrait[T]) withItem(callback func(T) error) func() erro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *ListControllerTrait[T]) withItems(callback func([]T) error) func() error {
|
||||||
|
return func() error {
|
||||||
|
items, _, _ := self.getSelectedItems()
|
||||||
|
if len(items) == 0 {
|
||||||
|
return self.c.ErrorMsg(self.c.Tr.NoItemSelected)
|
||||||
|
}
|
||||||
|
|
||||||
|
return callback(items)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// like withItems but also passes the start and end index of the selection
|
||||||
|
func (self *ListControllerTrait[T]) withItemsRange(callback func([]T, int, int) error) func() error {
|
||||||
|
return func() error {
|
||||||
|
items, startIdx, endIdx := self.getSelectedItems()
|
||||||
|
if len(items) == 0 {
|
||||||
|
return self.c.ErrorMsg(self.c.Tr.NoItemSelected)
|
||||||
|
}
|
||||||
|
|
||||||
|
return callback(items, startIdx, endIdx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Like withItem, but doesn't show an error message if no item is selected.
|
// Like withItem, but doesn't show an error message if no item is selected.
|
||||||
// Use this for click actions (it's a no-op to click empty space)
|
// Use this for click actions (it's a no-op to click empty space)
|
||||||
func (self *ListControllerTrait[T]) withItemGraceful(callback func(T) error) func() error {
|
func (self *ListControllerTrait[T]) withItemGraceful(callback func(T) error) func() error {
|
||||||
return func() error {
|
return func() error {
|
||||||
var zeroValue T
|
var zeroValue T
|
||||||
commit := self.getSelected()
|
commit := self.getSelectedItem()
|
||||||
if commit == zeroValue {
|
if commit == zeroValue {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ func NewMenuController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().Menu,
|
c.Contexts().Menu,
|
||||||
c.Contexts().Menu.GetSelected,
|
c.Contexts().Menu.GetSelected,
|
||||||
|
c.Contexts().Menu.GetSelectedItems,
|
||||||
),
|
),
|
||||||
c: c,
|
c: c,
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ func NewReflogCommitsController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().ReflogCommits,
|
c.Contexts().ReflogCommits,
|
||||||
c.Contexts().ReflogCommits.GetSelected,
|
c.Contexts().ReflogCommits.GetSelected,
|
||||||
|
c.Contexts().ReflogCommits.GetSelectedItems,
|
||||||
),
|
),
|
||||||
c: c,
|
c: c,
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ func NewRemoteBranchesController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().RemoteBranches,
|
c.Contexts().RemoteBranches,
|
||||||
c.Contexts().RemoteBranches.GetSelected,
|
c.Contexts().RemoteBranches.GetSelected,
|
||||||
|
c.Contexts().RemoteBranches.GetSelectedItems,
|
||||||
),
|
),
|
||||||
c: c,
|
c: c,
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ func NewRemotesController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().Remotes,
|
c.Contexts().Remotes,
|
||||||
c.Contexts().Remotes.GetSelected,
|
c.Contexts().Remotes.GetSelected,
|
||||||
|
c.Contexts().Remotes.GetSelectedItems,
|
||||||
),
|
),
|
||||||
c: c,
|
c: c,
|
||||||
setRemoteBranches: setRemoteBranches,
|
setRemoteBranches: setRemoteBranches,
|
||||||
|
@ -24,6 +24,7 @@ func NewStashController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().Stash,
|
c.Contexts().Stash,
|
||||||
c.Contexts().Stash.GetSelected,
|
c.Contexts().Stash.GetSelected,
|
||||||
|
c.Contexts().Stash.GetSelectedItems,
|
||||||
),
|
),
|
||||||
c: c,
|
c: c,
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ func NewSubCommitsController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().SubCommits,
|
c.Contexts().SubCommits,
|
||||||
c.Contexts().SubCommits.GetSelected,
|
c.Contexts().SubCommits.GetSelected,
|
||||||
|
c.Contexts().SubCommits.GetSelectedItems,
|
||||||
),
|
),
|
||||||
c: c,
|
c: c,
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ func NewSubmodulesController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().Submodules,
|
c.Contexts().Submodules,
|
||||||
c.Contexts().Submodules.GetSelected,
|
c.Contexts().Submodules.GetSelected,
|
||||||
|
c.Contexts().Submodules.GetSelectedItems,
|
||||||
),
|
),
|
||||||
c: c,
|
c: c,
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ func NewSuggestionsController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().Suggestions,
|
c.Contexts().Suggestions,
|
||||||
c.Contexts().Suggestions.GetSelected,
|
c.Contexts().Suggestions.GetSelected,
|
||||||
|
c.Contexts().Suggestions.GetSelectedItems,
|
||||||
),
|
),
|
||||||
c: c,
|
c: c,
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,9 @@ func NewSwitchToDiffFilesController(
|
|||||||
c,
|
c,
|
||||||
context,
|
context,
|
||||||
context.GetSelectedRef,
|
context.GetSelectedRef,
|
||||||
|
func() ([]types.Ref, int, int) {
|
||||||
|
panic("Not implemented")
|
||||||
|
},
|
||||||
),
|
),
|
||||||
c: c,
|
c: c,
|
||||||
context: context,
|
context: context,
|
||||||
|
@ -32,6 +32,9 @@ func NewSwitchToSubCommitsController(
|
|||||||
c,
|
c,
|
||||||
context,
|
context,
|
||||||
context.GetSelectedRef,
|
context.GetSelectedRef,
|
||||||
|
func() ([]types.Ref, int, int) {
|
||||||
|
panic("Not implemented")
|
||||||
|
},
|
||||||
),
|
),
|
||||||
c: c,
|
c: c,
|
||||||
context: context,
|
context: context,
|
||||||
|
@ -25,6 +25,7 @@ func NewTagsController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().Tags,
|
c.Contexts().Tags,
|
||||||
c.Contexts().Tags.GetSelected,
|
c.Contexts().Tags.GetSelected,
|
||||||
|
c.Contexts().Tags.GetSelectedItems,
|
||||||
),
|
),
|
||||||
c: c,
|
c: c,
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ func NewWorktreeOptionsController(c *ControllerCommon, context CanViewWorktreeOp
|
|||||||
c,
|
c,
|
||||||
context,
|
context,
|
||||||
context.GetSelectedItemId,
|
context.GetSelectedItemId,
|
||||||
|
context.GetSelectedItemIds,
|
||||||
),
|
),
|
||||||
c: c,
|
c: c,
|
||||||
context: context,
|
context: context,
|
||||||
|
@ -28,6 +28,7 @@ func NewWorktreesController(
|
|||||||
c,
|
c,
|
||||||
c.Contexts().Worktrees,
|
c.Contexts().Worktrees,
|
||||||
c.Contexts().Worktrees.GetSelected,
|
c.Contexts().Worktrees.GetSelected,
|
||||||
|
c.Contexts().Worktrees.GetSelectedItems,
|
||||||
),
|
),
|
||||||
c: c,
|
c: c,
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
|
"github.com/samber/lo"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -69,6 +70,29 @@ func (self *CommitFileTreeViewModel) GetSelected() *CommitFileNode {
|
|||||||
return self.Get(self.GetSelectedLineIdx())
|
return self.Get(self.GetSelectedLineIdx())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *CommitFileTreeViewModel) GetSelectedItemId() string {
|
||||||
|
item := self.GetSelected()
|
||||||
|
if item == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return item.ID()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitFileTreeViewModel) GetSelectedItems() ([]*CommitFileNode, int, int) {
|
||||||
|
panic("Not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *CommitFileTreeViewModel) GetSelectedItemIds() ([]string, int, int) {
|
||||||
|
selectedItems, startIdx, endIdx := self.GetSelectedItems()
|
||||||
|
|
||||||
|
ids := lo.Map(selectedItems, func(item *CommitFileNode, _ int) string {
|
||||||
|
return item.ID()
|
||||||
|
})
|
||||||
|
|
||||||
|
return ids, startIdx, endIdx
|
||||||
|
}
|
||||||
|
|
||||||
func (self *CommitFileTreeViewModel) GetSelectedFile() *models.CommitFile {
|
func (self *CommitFileTreeViewModel) GetSelectedFile() *models.CommitFile {
|
||||||
node := self.GetSelected()
|
node := self.GetSelected()
|
||||||
if node == nil {
|
if node == nil {
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
"github.com/jesseduffield/lazygit/pkg/gui/context/traits"
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
|
"github.com/samber/lo"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -43,6 +44,36 @@ func (self *FileTreeViewModel) GetSelected() *FileNode {
|
|||||||
return self.Get(self.GetSelectedLineIdx())
|
return self.Get(self.GetSelectedLineIdx())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *FileTreeViewModel) GetSelectedItemId() string {
|
||||||
|
item := self.GetSelected()
|
||||||
|
if item == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return item.ID()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *FileTreeViewModel) GetSelectedItems() ([]*FileNode, int, int) {
|
||||||
|
startIdx, endIdx := self.GetSelectionRange()
|
||||||
|
|
||||||
|
nodes := []*FileNode{}
|
||||||
|
for i := startIdx; i <= endIdx; i++ {
|
||||||
|
nodes = append(nodes, self.Get(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes, startIdx, endIdx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *FileTreeViewModel) GetSelectedItemIds() ([]string, int, int) {
|
||||||
|
selectedItems, startIdx, endIdx := self.GetSelectedItems()
|
||||||
|
|
||||||
|
ids := lo.Map(selectedItems, func(item *FileNode, _ int) string {
|
||||||
|
return item.ID()
|
||||||
|
})
|
||||||
|
|
||||||
|
return ids, startIdx, endIdx
|
||||||
|
}
|
||||||
|
|
||||||
func (self *FileTreeViewModel) GetSelectedFile() *models.File {
|
func (self *FileTreeViewModel) GetSelectedFile() *models.File {
|
||||||
node := self.GetSelected()
|
node := self.GetSelected()
|
||||||
if node == nil {
|
if node == nil {
|
||||||
|
@ -242,6 +242,12 @@ type MenuItem struct {
|
|||||||
Section *MenuSection
|
Section *MenuSection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Defining this for the sake of conforming to the HasID interface, which is used
|
||||||
|
// in list contexts.
|
||||||
|
func (self *MenuItem) ID() string {
|
||||||
|
return self.Label
|
||||||
|
}
|
||||||
|
|
||||||
type Model struct {
|
type Model struct {
|
||||||
CommitFiles []*models.CommitFile
|
CommitFiles []*models.CommitFile
|
||||||
Files []*models.File
|
Files []*models.File
|
||||||
|
@ -136,6 +136,7 @@ type IListContext interface {
|
|||||||
Context
|
Context
|
||||||
|
|
||||||
GetSelectedItemId() string
|
GetSelectedItemId() string
|
||||||
|
GetSelectedItemIds() ([]string, int, int)
|
||||||
IsItemVisible(item HasUrn) bool
|
IsItemVisible(item HasUrn) bool
|
||||||
|
|
||||||
GetList() IList
|
GetList() IList
|
||||||
|
@ -6,3 +6,8 @@ type Suggestion struct {
|
|||||||
// label is what is actually displayed so it can e.g. contain color
|
// label is what is actually displayed so it can e.g. contain color
|
||||||
Label string
|
Label string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Conforming to the HasID interface, which is needed for list contexts
|
||||||
|
func (self *Suggestion) ID() string {
|
||||||
|
return self.Value
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user