1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-01-24 05:36:19 +02:00

247 lines
6.6 KiB
Go
Raw Normal View History

2022-08-12 09:19:39 +10:00
package components
2022-08-09 20:27:44 +10:00
import (
"fmt"
"strings"
"time"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gui/types"
integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types"
)
type Input struct {
gui integrationTypes.GuiDriver
2022-08-09 20:27:44 +10:00
keys config.KeybindingConfig
assert *Assert
2022-08-09 20:27:44 +10:00
pushKeyDelay int
}
func NewInput(gui integrationTypes.GuiDriver, keys config.KeybindingConfig, assert *Assert, pushKeyDelay int) *Input {
return &Input{
2022-08-09 20:27:44 +10:00
gui: gui,
keys: keys,
assert: assert,
pushKeyDelay: pushKeyDelay,
}
}
// key is something like 'w' or '<space>'. It's best not to pass a direct value,
// but instead to go through the default user config to get a more meaningful key name
func (self *Input) Press(keyStrs ...string) {
2022-08-09 20:27:44 +10:00
for _, keyStr := range keyStrs {
self.press(keyStr)
2022-08-09 20:27:44 +10:00
}
}
func (self *Input) press(keyStr string) {
2022-08-09 20:27:44 +10:00
self.Wait(self.pushKeyDelay)
self.gui.PressKey(keyStr)
}
func (self *Input) SwitchToStatusWindow() {
self.press(self.keys.Universal.JumpToBlock[0])
self.assert.CurrentWindowName("status")
2022-08-09 20:27:44 +10:00
}
2022-12-26 16:49:54 +11:00
// switch to status window and assert that the status view is on top
func (self *Input) SwitchToStatusView() {
self.SwitchToStatusWindow()
2022-12-27 15:07:11 +11:00
self.assert.Views().Current().Name("status")
2022-12-26 16:49:54 +11:00
}
func (self *Input) SwitchToFilesWindow() {
self.press(self.keys.Universal.JumpToBlock[1])
self.assert.CurrentWindowName("files")
2022-08-09 20:27:44 +10:00
}
2022-12-26 16:49:54 +11:00
// switch to files window and assert that the files view is on top
func (self *Input) SwitchToFilesView() {
self.SwitchToFilesWindow()
2022-12-27 15:07:11 +11:00
self.assert.Views().Current().Name("files")
2022-12-26 16:49:54 +11:00
}
func (self *Input) SwitchToBranchesWindow() {
self.press(self.keys.Universal.JumpToBlock[2])
self.assert.CurrentWindowName("localBranches")
2022-08-09 20:27:44 +10:00
}
2022-12-26 16:49:54 +11:00
// switch to branches window and assert that the branches view is on top
func (self *Input) SwitchToBranchesView() {
self.SwitchToBranchesWindow()
2022-12-27 15:07:11 +11:00
self.assert.Views().Current().Name("localBranches")
2022-12-26 16:49:54 +11:00
}
func (self *Input) SwitchToCommitsWindow() {
self.press(self.keys.Universal.JumpToBlock[3])
self.assert.CurrentWindowName("commits")
2022-08-09 20:27:44 +10:00
}
2022-12-26 16:49:54 +11:00
// switch to commits window and assert that the commits view is on top
func (self *Input) SwitchToCommitsView() {
self.SwitchToCommitsWindow()
2022-12-27 15:07:11 +11:00
self.assert.Views().Current().Name("commits")
2022-12-26 16:49:54 +11:00
}
func (self *Input) SwitchToStashWindow() {
self.press(self.keys.Universal.JumpToBlock[4])
self.assert.CurrentWindowName("stash")
2022-08-09 20:27:44 +10:00
}
2022-12-26 16:49:54 +11:00
// switch to stash window and assert that the stash view is on top
func (self *Input) SwitchToStashView() {
self.SwitchToStashWindow()
2022-12-27 15:07:11 +11:00
self.assert.Views().Current().Name("stash")
2022-12-26 16:49:54 +11:00
}
func (self *Input) Type(content string) {
2022-08-09 20:27:44 +10:00
for _, char := range content {
self.press(string(char))
2022-08-09 20:27:44 +10:00
}
}
// i.e. pressing enter
func (self *Input) Confirm() {
self.press(self.keys.Universal.Confirm)
2022-09-17 11:58:24 -07:00
}
// i.e. same as Confirm
func (self *Input) Enter() {
self.press(self.keys.Universal.Confirm)
}
// i.e. pressing escape
func (self *Input) Cancel() {
self.press(self.keys.Universal.Return)
2022-08-09 20:27:44 +10:00
}
// i.e. pressing space
2022-08-14 20:47:09 +10:00
func (self *Input) PrimaryAction() {
self.press(self.keys.Universal.Select)
2022-08-09 20:27:44 +10:00
}
// i.e. pressing down arrow
func (self *Input) NextItem() {
self.press(self.keys.Universal.NextItem)
2022-08-09 20:27:44 +10:00
}
// i.e. pressing up arrow
func (self *Input) PreviousItem() {
self.press(self.keys.Universal.PrevItem)
2022-08-09 20:27:44 +10:00
}
func (self *Input) ContinueMerge() {
self.Press(self.keys.Universal.CreateRebaseOptionsMenu)
2022-12-27 15:07:11 +11:00
self.assert.Views().Current().SelectedLine(Contains("continue"))
2022-08-09 20:27:44 +10:00
self.Confirm()
}
func (self *Input) ContinueRebase() {
2022-08-09 20:27:44 +10:00
self.ContinueMerge()
}
// for when you want to allow lazygit to process something before continuing
func (self *Input) Wait(milliseconds int) {
2022-08-09 20:27:44 +10:00
time.Sleep(time.Duration(milliseconds) * time.Millisecond)
}
func (self *Input) LogUI(message string) {
2022-08-09 20:27:44 +10:00
self.gui.LogUI(message)
}
func (self *Input) Log(message string) {
2022-08-09 20:27:44 +10:00
self.gui.LogUI(message)
}
// this will look for a list item in the current panel and if it finds it, it will
// enter the keypresses required to navigate to it.
// The test will fail if:
2022-08-12 09:24:39 +10:00
// - the user is not in a list item
// - no list item is found containing the given text
// - multiple list items are found containing the given text in the initial page of items
//
2022-08-09 20:27:44 +10:00
// NOTE: this currently assumes that ViewBufferLines returns all the lines that can be accessed.
// If this changes in future, we'll need to update this code to first attempt to find the item
// in the current page and failing that, jump to the top of the view and iterate through all of it,
// looking for the item.
func (self *Input) NavigateToListItem(matcher *matcher) {
2022-08-09 20:27:44 +10:00
self.assert.InListContext()
currentContext := self.gui.CurrentContext().(types.IListContext)
view := currentContext.GetView()
var matchIndex int
self.assert.assertWithRetries(func() (bool, string) {
matchIndex = -1
var matches []string
2022-12-26 17:15:33 +11:00
lines := view.ViewBufferLines()
// first we look for a duplicate on the current screen. We won't bother looking beyond that though.
2022-12-26 17:15:33 +11:00
for i, line := range lines {
ok, _ := matcher.test(line)
if ok {
matches = append(matches, line)
matchIndex = i
}
2022-08-09 20:27:44 +10:00
}
if len(matches) > 1 {
2022-12-26 17:15:33 +11:00
return false, fmt.Sprintf("Found %d matches for `%s`, expected only a single match. Matching lines:\n%s", len(matches), matcher.name(), strings.Join(matches, "\n"))
} else if len(matches) == 0 {
2022-12-26 17:15:33 +11:00
return false, fmt.Sprintf("Could not find item matching: %s. Lines:\n%s", matcher.name(), strings.Join(lines, "\n"))
} else {
return true, ""
}
})
selectedLineIdx := view.SelectedLineIdx()
if selectedLineIdx == matchIndex {
2022-12-27 15:07:11 +11:00
self.assert.Views().Current().SelectedLine(matcher)
return
2022-08-09 20:27:44 +10:00
}
if selectedLineIdx < matchIndex {
for i := selectedLineIdx; i < matchIndex; i++ {
self.NextItem()
2022-08-09 20:27:44 +10:00
}
2022-12-27 15:07:11 +11:00
self.assert.Views().Current().SelectedLine(matcher)
return
} else {
for i := selectedLineIdx; i > matchIndex; i-- {
self.PreviousItem()
2022-08-09 20:27:44 +10:00
}
2022-12-27 15:07:11 +11:00
self.assert.Views().Current().SelectedLine(matcher)
return
2022-08-09 20:27:44 +10:00
}
}
2022-12-27 11:21:44 +11:00
func (self *Input) Confirmation() *ConfirmationAsserter {
self.assert.InConfirm()
return &ConfirmationAsserter{assert: self.assert, input: self}
}
2022-12-27 11:21:44 +11:00
func (self *Input) Prompt() *PromptAsserter {
self.assert.InPrompt()
2022-12-27 11:21:44 +11:00
return &PromptAsserter{assert: self.assert, input: self}
}
2022-12-27 11:34:41 +11:00
func (self *Input) Alert() *AlertAsserter {
self.assert.InAlert()
return &AlertAsserter{assert: self.assert, input: self}
}
2022-12-27 11:34:41 +11:00
func (self *Input) Menu() *MenuAsserter {
self.assert.InMenu()
2022-12-27 11:34:41 +11:00
return &MenuAsserter{assert: self.assert, input: self}
}
func (self *Input) CommitMessagePanel() *CommitMessagePanelAsserter {
self.assert.InCommitMessagePanel()
return &CommitMessagePanelAsserter{assert: self.assert, input: self}
}