mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-07-31 14:24:25 +03:00
Support deleting items from the custom commands history
In the custom commands panel you can now tab to the suggestions and hit 'd' to delete items from there. Useful if you mistyped a command and don't want it to appear in your history any more.
This commit is contained in:
@ -14,10 +14,11 @@ type SuggestionsContext struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SuggestionsContextState struct {
|
type SuggestionsContextState struct {
|
||||||
Suggestions []*types.Suggestion
|
Suggestions []*types.Suggestion
|
||||||
OnConfirm func() error
|
OnConfirm func() error
|
||||||
OnClose func() error
|
OnClose func() error
|
||||||
AsyncHandler *tasks.AsyncHandler
|
OnDeleteSuggestion func() error
|
||||||
|
AsyncHandler *tasks.AsyncHandler
|
||||||
|
|
||||||
// FindSuggestions will take a string that the user has typed into a prompt
|
// FindSuggestions will take a string that the user has typed into a prompt
|
||||||
// and return a slice of suggestions which match that string.
|
// and return a slice of suggestions which match that string.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
||||||
@ -32,13 +33,34 @@ func (self *CustomCommandAction) Call() error {
|
|||||||
self.c.OS().Cmd.NewShell(command),
|
self.c.OS().Cmd.NewShell(command),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
HandleDeleteSuggestion: func(index int) error {
|
||||||
|
// index is the index in the _filtered_ list of suggestions, so we
|
||||||
|
// need to map it back to the full list. There's no really good way
|
||||||
|
// to do this, but fortunately we keep the items in the
|
||||||
|
// CustomCommandsHistory unique, which allows us to simply search
|
||||||
|
// for it by string.
|
||||||
|
item := self.c.Contexts().Suggestions.GetItems()[index].Value
|
||||||
|
fullIndex := lo.IndexOf(self.c.GetAppState().CustomCommandsHistory, item)
|
||||||
|
if fullIndex == -1 {
|
||||||
|
// Should never happen, but better be safe
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
self.c.GetAppState().CustomCommandsHistory = slices.Delete(
|
||||||
|
self.c.GetAppState().CustomCommandsHistory, fullIndex, fullIndex+1)
|
||||||
|
self.c.SaveAppStateAndLogError()
|
||||||
|
self.c.Contexts().Suggestions.RefreshSuggestions()
|
||||||
|
return nil
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *CustomCommandAction) GetCustomCommandsHistorySuggestionsFunc() func(string) []*types.Suggestion {
|
func (self *CustomCommandAction) GetCustomCommandsHistorySuggestionsFunc() func(string) []*types.Suggestion {
|
||||||
history := self.c.GetAppState().CustomCommandsHistory
|
return func(input string) []*types.Suggestion {
|
||||||
|
history := self.c.GetAppState().CustomCommandsHistory
|
||||||
|
|
||||||
return helpers.FilterFunc(history, self.c.UserConfig.Gui.UseFuzzySearch())
|
return helpers.FilterFunc(history, self.c.UserConfig.Gui.UseFuzzySearch())(input)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this mimics the shell functionality `ignorespace`
|
// this mimics the shell functionality `ignorespace`
|
||||||
|
@ -270,10 +270,20 @@ func (self *ConfirmationHelper) setKeyBindings(cancel goContext.CancelFunc, opts
|
|||||||
|
|
||||||
onClose := self.wrappedConfirmationFunction(cancel, opts.HandleClose)
|
onClose := self.wrappedConfirmationFunction(cancel, opts.HandleClose)
|
||||||
|
|
||||||
|
onDeleteSuggestion := func() error {
|
||||||
|
if opts.HandleDeleteSuggestion == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
idx := self.c.Contexts().Suggestions.GetSelectedLineIdx()
|
||||||
|
return opts.HandleDeleteSuggestion(idx)
|
||||||
|
}
|
||||||
|
|
||||||
self.c.Contexts().Confirmation.State.OnConfirm = onConfirm
|
self.c.Contexts().Confirmation.State.OnConfirm = onConfirm
|
||||||
self.c.Contexts().Confirmation.State.OnClose = onClose
|
self.c.Contexts().Confirmation.State.OnClose = onClose
|
||||||
self.c.Contexts().Suggestions.State.OnConfirm = onSuggestionConfirm
|
self.c.Contexts().Suggestions.State.OnConfirm = onSuggestionConfirm
|
||||||
self.c.Contexts().Suggestions.State.OnClose = onClose
|
self.c.Contexts().Suggestions.State.OnClose = onClose
|
||||||
|
self.c.Contexts().Suggestions.State.OnDeleteSuggestion = onDeleteSuggestion
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -284,6 +294,7 @@ func (self *ConfirmationHelper) clearConfirmationViewKeyBindings() {
|
|||||||
self.c.Contexts().Confirmation.State.OnClose = noop
|
self.c.Contexts().Confirmation.State.OnClose = noop
|
||||||
self.c.Contexts().Suggestions.State.OnConfirm = noop
|
self.c.Contexts().Suggestions.State.OnConfirm = noop
|
||||||
self.c.Contexts().Suggestions.State.OnClose = noop
|
self.c.Contexts().Suggestions.State.OnClose = noop
|
||||||
|
self.c.Contexts().Suggestions.State.OnDeleteSuggestion = noop
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *ConfirmationHelper) getSelectedSuggestionValue() string {
|
func (self *ConfirmationHelper) getSelectedSuggestionValue() string {
|
||||||
|
@ -43,6 +43,12 @@ func (self *SuggestionsController) GetKeybindings(opts types.KeybindingsOpts) []
|
|||||||
Key: opts.GetKey(opts.Config.Universal.TogglePanel),
|
Key: opts.GetKey(opts.Config.Universal.TogglePanel),
|
||||||
Handler: func() error { return self.c.ReplaceContext(self.c.Contexts().Confirmation) },
|
Handler: func() error { return self.c.ReplaceContext(self.c.Contexts().Confirmation) },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||||
|
Handler: func() error {
|
||||||
|
return self.context().State.OnDeleteSuggestion()
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return bindings
|
return bindings
|
||||||
|
@ -104,13 +104,14 @@ func (self *PopupHandler) Confirm(opts types.ConfirmOpts) error {
|
|||||||
|
|
||||||
func (self *PopupHandler) Prompt(opts types.PromptOpts) error {
|
func (self *PopupHandler) Prompt(opts types.PromptOpts) error {
|
||||||
return self.createPopupPanelFn(context.Background(), types.CreatePopupPanelOpts{
|
return self.createPopupPanelFn(context.Background(), types.CreatePopupPanelOpts{
|
||||||
Title: opts.Title,
|
Title: opts.Title,
|
||||||
Prompt: opts.InitialContent,
|
Prompt: opts.InitialContent,
|
||||||
Editable: true,
|
Editable: true,
|
||||||
HandleConfirmPrompt: opts.HandleConfirm,
|
HandleConfirmPrompt: opts.HandleConfirm,
|
||||||
HandleClose: opts.HandleClose,
|
HandleClose: opts.HandleClose,
|
||||||
FindSuggestionsFunc: opts.FindSuggestionsFunc,
|
HandleDeleteSuggestion: opts.HandleDeleteSuggestion,
|
||||||
Mask: opts.Mask,
|
FindSuggestionsFunc: opts.FindSuggestionsFunc,
|
||||||
|
Mask: opts.Mask,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,13 +165,14 @@ type CreateMenuOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type CreatePopupPanelOpts struct {
|
type CreatePopupPanelOpts struct {
|
||||||
HasLoader bool
|
HasLoader bool
|
||||||
Editable bool
|
Editable bool
|
||||||
Title string
|
Title string
|
||||||
Prompt string
|
Prompt string
|
||||||
HandleConfirm func() error
|
HandleConfirm func() error
|
||||||
HandleConfirmPrompt func(string) error
|
HandleConfirmPrompt func(string) error
|
||||||
HandleClose func() error
|
HandleClose func() error
|
||||||
|
HandleDeleteSuggestion func(int) error
|
||||||
|
|
||||||
FindSuggestionsFunc func(string) []*Suggestion
|
FindSuggestionsFunc func(string) []*Suggestion
|
||||||
Mask bool
|
Mask bool
|
||||||
@ -193,8 +194,9 @@ type PromptOpts struct {
|
|||||||
FindSuggestionsFunc func(string) []*Suggestion
|
FindSuggestionsFunc func(string) []*Suggestion
|
||||||
HandleConfirm func(string) error
|
HandleConfirm func(string) error
|
||||||
// CAPTURE THIS
|
// CAPTURE THIS
|
||||||
HandleClose func() error
|
HandleClose func() error
|
||||||
Mask bool
|
HandleDeleteSuggestion func(int) error
|
||||||
|
Mask bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type MenuSection struct {
|
type MenuSection struct {
|
||||||
|
@ -82,3 +82,12 @@ func (self *PromptDriver) ConfirmSuggestion(matcher *TextMatcher) {
|
|||||||
NavigateToLine(matcher).
|
NavigateToLine(matcher).
|
||||||
PressEnter()
|
PressEnter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *PromptDriver) DeleteSuggestion(matcher *TextMatcher) *PromptDriver {
|
||||||
|
self.t.press(self.t.keys.Universal.TogglePanel)
|
||||||
|
self.t.Views().Suggestions().
|
||||||
|
IsFocused().
|
||||||
|
NavigateToLine(matcher)
|
||||||
|
self.t.press(self.t.keys.Universal.Remove)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
41
pkg/integration/tests/custom_commands/delete_from_history.go
Normal file
41
pkg/integration/tests/custom_commands/delete_from_history.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package custom_commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
|
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||||
|
)
|
||||||
|
|
||||||
|
var DeleteFromHistory = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
|
Description: "Delete an entry from the custom commands history",
|
||||||
|
ExtraCmdArgs: []string{},
|
||||||
|
Skip: false,
|
||||||
|
SetupRepo: func(shell *Shell) {},
|
||||||
|
SetupConfig: func(cfg *config.AppConfig) {},
|
||||||
|
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||||
|
createCustomCommand := func(command string) {
|
||||||
|
t.GlobalPress(keys.Universal.ExecuteCustomCommand)
|
||||||
|
t.ExpectPopup().Prompt().
|
||||||
|
Title(Equals("Custom command:")).
|
||||||
|
Type(command).
|
||||||
|
Confirm()
|
||||||
|
}
|
||||||
|
|
||||||
|
createCustomCommand("echo 1")
|
||||||
|
createCustomCommand("echo 2")
|
||||||
|
createCustomCommand("echo 3")
|
||||||
|
|
||||||
|
t.GlobalPress(keys.Universal.ExecuteCustomCommand)
|
||||||
|
t.ExpectPopup().Prompt().
|
||||||
|
Title(Equals("Custom command:")).
|
||||||
|
SuggestionLines(
|
||||||
|
Contains("3"),
|
||||||
|
Contains("2"),
|
||||||
|
Contains("1"),
|
||||||
|
).
|
||||||
|
DeleteSuggestion(Contains("2")).
|
||||||
|
SuggestionLines(
|
||||||
|
Contains("3"),
|
||||||
|
Contains("1"),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
@ -105,6 +105,7 @@ var tests = []*components.IntegrationTest{
|
|||||||
custom_commands.BasicCmdFromConfig,
|
custom_commands.BasicCmdFromConfig,
|
||||||
custom_commands.CheckForConflicts,
|
custom_commands.CheckForConflicts,
|
||||||
custom_commands.ComplexCmdAtRuntime,
|
custom_commands.ComplexCmdAtRuntime,
|
||||||
|
custom_commands.DeleteFromHistory,
|
||||||
custom_commands.FormPrompts,
|
custom_commands.FormPrompts,
|
||||||
custom_commands.History,
|
custom_commands.History,
|
||||||
custom_commands.MenuFromCommand,
|
custom_commands.MenuFromCommand,
|
||||||
|
Reference in New Issue
Block a user