summaryrefslogtreecommitdiffstats
path: root/pkg/gui
diff options
context:
space:
mode:
authorKarim Khaleel <code.karim@gmail.com>2023-08-04 14:01:30 +0300
committerKarim Khaleel <code.karim@gmail.com>2023-09-20 08:35:41 +0300
commitedec116cebe6dde1f8e7ce375fabc407c84d92b5 (patch)
treebbc27be98cc27ad51fe8d55df23bf9d66a2698ab /pkg/gui
parentab5875c78fcd7fc2f0cdbc867dc84ef4331a5de3 (diff)
Add search history
Add search history for filterable and searchable views.
Diffstat (limited to 'pkg/gui')
-rw-r--r--pkg/gui/context/filtered_list_view_model.go4
-rw-r--r--pkg/gui/context/history_trait.go20
-rw-r--r--pkg/gui/context/remotes_context.go1
-rw-r--r--pkg/gui/context/search_trait.go6
-rw-r--r--pkg/gui/controllers/helpers/search_helper.go35
-rw-r--r--pkg/gui/controllers/search_prompt_controller.go20
-rw-r--r--pkg/gui/types/context.go9
-rw-r--r--pkg/gui/types/search_state.go5
8 files changed, 92 insertions, 8 deletions
diff --git a/pkg/gui/context/filtered_list_view_model.go b/pkg/gui/context/filtered_list_view_model.go
index 77f6e1174..1e649550a 100644
--- a/pkg/gui/context/filtered_list_view_model.go
+++ b/pkg/gui/context/filtered_list_view_model.go
@@ -3,13 +3,15 @@ package context
type FilteredListViewModel[T any] struct {
*FilteredList[T]
*ListViewModel[T]
+ *SearchHistory
}
func NewFilteredListViewModel[T any](getList func() []T, getFilterFields func(T) []string) *FilteredListViewModel[T] {
filteredList := NewFilteredList(getList, getFilterFields)
self := &FilteredListViewModel[T]{
- FilteredList: filteredList,
+ FilteredList: filteredList,
+ SearchHistory: NewSearchHistory(),
}
listViewModel := NewListViewModel(filteredList.GetFilteredList)
diff --git a/pkg/gui/context/history_trait.go b/pkg/gui/context/history_trait.go
new file mode 100644
index 000000000..f850a3b77
--- /dev/null
+++ b/pkg/gui/context/history_trait.go
@@ -0,0 +1,20 @@
+package context
+
+import (
+ "github.com/jesseduffield/lazygit/pkg/utils"
+)
+
+// Maintains a list of strings that have previously been searched/filtered for
+type SearchHistory struct {
+ history *utils.HistoryBuffer[string]
+}
+
+func NewSearchHistory() *SearchHistory {
+ return &SearchHistory{
+ history: utils.NewHistoryBuffer[string](1000),
+ }
+}
+
+func (self *SearchHistory) GetSearchHistory() *utils.HistoryBuffer[string] {
+ return self.history
+}
diff --git a/pkg/gui/context/remotes_context.go b/pkg/gui/context/remotes_context.go
index f5e2a97ab..43da46576 100644
--- a/pkg/gui/context/remotes_context.go
+++ b/pkg/gui/context/remotes_context.go
@@ -9,6 +9,7 @@ import (
type RemotesContext struct {
*FilteredListViewModel[*models.Remote]
*ListContextTrait
+ *SearchHistory
}
var (
diff --git a/pkg/gui/context/search_trait.go b/pkg/gui/context/search_trait.go
index fad68d794..264c8217d 100644
--- a/pkg/gui/context/search_trait.go
+++ b/pkg/gui/context/search_trait.go
@@ -9,12 +9,16 @@ import (
type SearchTrait struct {
c *ContextCommon
+ *SearchHistory
searchString string
}
func NewSearchTrait(c *ContextCommon) *SearchTrait {
- return &SearchTrait{c: c}
+ return &SearchTrait{
+ c: c,
+ SearchHistory: NewSearchHistory(),
+ }
}
func (self *SearchTrait) GetSearchString() string {
diff --git a/pkg/gui/controllers/helpers/search_helper.go b/pkg/gui/controllers/helpers/search_helper.go
index b244f20e4..8764337b1 100644
--- a/pkg/gui/controllers/helpers/search_helper.go
+++ b/pkg/gui/controllers/helpers/search_helper.go
@@ -36,7 +36,7 @@ func (self *SearchHelper) OpenFilterPrompt(context types.IFilterableContext) err
self.searchPrefixView().SetContent(self.c.Tr.FilterPrefix)
promptView := self.promptView()
promptView.ClearTextArea()
- promptView.TextArea.TypeString(context.GetFilter())
+ self.OnPromptContentChanged("")
promptView.RenderTextArea()
if err := self.c.PushContext(self.c.Contexts().Search); err != nil {
@@ -49,13 +49,13 @@ func (self *SearchHelper) OpenFilterPrompt(context types.IFilterableContext) err
func (self *SearchHelper) OpenSearchPrompt(context types.ISearchableContext) error {
state := self.searchState()
+ state.PrevSearchIndex = -1
+
state.Context = context
- searchString := context.GetSearchString()
self.searchPrefixView().SetContent(self.c.Tr.SearchPrefix)
promptView := self.promptView()
promptView.ClearTextArea()
- promptView.TextArea.TypeString(searchString)
promptView.RenderTextArea()
if err := self.c.PushContext(self.c.Contexts().Search); err != nil {
@@ -125,13 +125,17 @@ func (self *SearchHelper) ConfirmFilter() error {
// We also do this on each keypress but we do it here again just in case
state := self.searchState()
- _, ok := state.Context.(types.IFilterableContext)
+ context, ok := state.Context.(types.IFilterableContext)
if !ok {
self.c.Log.Warnf("Context %s is not filterable", state.Context.GetKey())
return nil
}
self.OnPromptContentChanged(self.promptContent())
+ filterString := self.promptContent()
+ if filterString != "" {
+ context.GetSearchHistory().Push(filterString)
+ }
return self.c.PopContext()
}
@@ -147,6 +151,9 @@ func (self *SearchHelper) ConfirmSearch() error {
searchString := self.promptContent()
context.SetSearchString(searchString)
+ if searchString != "" {
+ context.GetSearchHistory().Push(searchString)
+ }
view := context.GetView()
@@ -167,6 +174,26 @@ func (self *SearchHelper) CancelPrompt() error {
return self.c.PopContext()
}
+func (self *SearchHelper) ScrollHistory(scrollIncrement int) {
+ state := self.searchState()
+
+ context, ok := state.Context.(types.ISearchHistoryContext)
+ if !ok {
+ return
+ }
+
+ states := context.GetSearchHistory()
+
+ if val, err := states.PeekAt(state.PrevSearchIndex + scrollIncrement); err == nil {
+ state.PrevSearchIndex += scrollIncrement
+ promptView := self.promptView()
+ promptView.ClearTextArea()
+ promptView.TextArea.TypeString(val)
+ promptView.RenderTextArea()
+ self.OnPromptContentChanged(val)
+ }
+}
+
func (self *SearchHelper) Cancel() {
state := self.searchState()
diff --git a/pkg/gui/controllers/search_prompt_controller.go b/pkg/gui/controllers/search_prompt_controller.go
index 2326ed1c1..014edd094 100644
--- a/pkg/gui/controllers/search_prompt_controller.go
+++ b/pkg/gui/controllers/search_prompt_controller.go
@@ -33,6 +33,16 @@ func (self *SearchPromptController) GetKeybindings(opts types.KeybindingsOpts) [
Modifier: gocui.ModNone,
Handler: self.cancel,
},
+ {
+ Key: opts.GetKey(opts.Config.Universal.PrevItem),
+ Modifier: gocui.ModNone,
+ Handler: self.prevHistory,
+ },
+ {
+ Key: opts.GetKey(opts.Config.Universal.NextItem),
+ Modifier: gocui.ModNone,
+ Handler: self.nextHistory,
+ },
}
}
@@ -51,3 +61,13 @@ func (self *SearchPromptController) confirm() error {
func (self *SearchPromptController) cancel() error {
return self.c.Helpers().Search.CancelPrompt()
}
+
+func (self *SearchPromptController) prevHistory() error {
+ self.c.Helpers().Search.ScrollHistory(1)
+ return nil
+}
+
+func (self *SearchPromptController) nextHistory() error {
+ self.c.Helpers().Search.ScrollHistory(-1)
+ return nil
+}
diff --git a/pkg/gui/types/context.go b/pkg/gui/types/context.go
index dca5b042c..e06138a99 100644
--- a/pkg/gui/types/context.go
+++ b/pkg/gui/types/context.go
@@ -4,6 +4,7 @@ import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gui/patch_exploring"
+ "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/sasha-s/go-deadlock"
)
@@ -87,9 +88,16 @@ type Context interface {
HandleRenderToMain() error
}
+type ISearchHistoryContext interface {
+ Context
+
+ GetSearchHistory() *utils.HistoryBuffer[string]
+}
+
type IFilterableContext interface {
Context
IListPanelState
+ ISearchHistoryContext
SetFilter(string)
GetFilter() string
@@ -100,6 +108,7 @@ type IFilterableContext interface {
type ISearchableContext interface {
Context
+ ISearchHistoryContext
SetSearchString(string)
GetSearchString() string
diff --git a/pkg/gui/types/search_state.go b/pkg/gui/types/search_state.go
index 9b24af095..af806f2c3 100644
--- a/pkg/gui/types/search_state.go
+++ b/pkg/gui/types/search_state.go
@@ -12,11 +12,12 @@ const (
// TODO: could we remove this entirely?
type SearchState struct {
- Context Context
+ Context Context
+ PrevSearchIndex int
}
func NewSearchState() *SearchState {
- return &SearchState{}
+ return &SearchState{PrevSearchIndex: -1}
}
func (self *SearchState) SearchType() SearchType {