/
githubmirror
/
lazygit
Обзор
Документация
Войти
/
githubmirror
/
lazygit
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
pkg/gui/context/suggestions_context.go
108 строк
3 KB
Stefan Haller
Capture suggestions inputs on the UI thread
17 июл 2026, 13:35
17 июл 2026, 13:35
d36ce51
Код
Авторство
О чём код?
package context import ( "github.com/jesseduffield/lazygit/pkg/gui/presentation" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/tasks" ) type SuggestionsContext struct { *ListViewModel[*types.Suggestion] *ListContextTrait State *SuggestionsContextState } type SuggestionsContextState struct { Suggestions []*types.Suggestion OnConfirm func() error OnClose func() error OnDeleteSuggestion func() error AsyncHandler *tasks.AsyncHandler AllowEditSuggestion bool // FindSuggestions will take a string that the user has typed into a prompt // and return a slice of suggestions which match that string. FindSuggestions func(string) []*types.Suggestion } var _ types.IListContext = (*SuggestionsContext)(nil) func NewSuggestionsContext( c *ContextCommon, ) *SuggestionsContext { state := &SuggestionsContextState{ AsyncHandler: tasks.NewAsyncHandler(c.OnWorker), } getModel := func() []*types.Suggestion { return state.Suggestions } getDisplayStrings := func(_ int, _ int) [][]string { return presentation.GetSuggestionListDisplayStrings(state.Suggestions) } viewModel := NewListViewModel(getModel) return &SuggestionsContext{ State: state, ListViewModel: viewModel, ListContextTrait: &ListContextTrait{ Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{ View: c.Views().Suggestions, WindowName: "suggestions", Key: SUGGESTIONS_CONTEXT_KEY, Kind: types.PERSISTENT_POPUP, Focusable: true, HasUncontrolledBounds: true, })), ListRenderer: ListRenderer{ list: viewModel, getDisplayStrings: getDisplayStrings, }, c: c, }, } } func (self *SuggestionsContext) SetSuggestions(suggestions []*types.Suggestion) { // SetSuggestions is invoked from AsyncHandler (a worker goroutine) when // the prompt input changes, as well as from prepareConfirmationPanel on // the UI thread. Bounce to the UI thread either way so the worker path // keeps flushing once HandleRender stops calling Render() itself. self.c.OnUIThread(func() error { self.State.Suggestions = suggestions self.SetSelection(0) self.c.ResetViewOrigin(self.GetView()) self.HandleRender() return nil }) } func (self *SuggestionsContext) RefreshSuggestions() { // Capture the suggestions function and the prompt input here, on the UI // thread, rather than inside the worker below: the main thread rewrites both // (State.FindSuggestions and the prompt's TextArea) when it (re)creates a // prompt panel, so reading them from the worker races those writes. It's // also more correct -- we search for the input as it was when dispatched, // which is what this request's AsyncHandler id corresponds to. findSuggestionsFn := self.State.FindSuggestions promptInput := self.c.GetPromptInput() self.State.AsyncHandler.Do(func() func() { if findSuggestionsFn != nil { suggestions := findSuggestionsFn(promptInput) return func() { self.SetSuggestions(suggestions) } } return func() {} }) } // There is currently no need to use range-select in the suggestions view so we're disabling it. func (self *SuggestionsContext) RangeSelectEnabled() bool { return false } func (self *SuggestionsContext) GetOnDoubleClick() func() error { return self.State.OnConfirm }