1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-12-16 11:37:01 +02:00
lazygit/pkg/gui/global_handlers.go

228 lines
5.6 KiB
Go
Raw Normal View History

2020-03-29 01:31:34 +02:00
package gui
import (
"fmt"
2020-03-29 01:31:34 +02:00
"math"
"strings"
2021-04-04 15:51:59 +02:00
"github.com/jesseduffield/gocui"
2020-08-11 13:18:38 +02:00
"github.com/jesseduffield/lazygit/pkg/commands"
2020-03-29 01:31:34 +02:00
"github.com/jesseduffield/lazygit/pkg/utils"
)
2020-08-19 11:07:14 +02:00
// these views need to be re-rendered when the screen mode changes. The commits view,
// for example, will show authorship information in half and full screen mode.
2020-08-19 11:26:05 +02:00
func (gui *Gui) rerenderViewsWithScreenModeDependentContent() error {
2021-04-04 16:44:13 +02:00
for _, view := range []*gocui.View{gui.Views.Branches, gui.Views.Commits} {
if err := gui.rerenderView(view); err != nil {
2020-08-19 11:07:14 +02:00
return err
}
2020-03-29 01:31:34 +02:00
}
return nil
}
// TODO: GENERICS
func nextIntInCycle(sl []WindowMaximisation, current WindowMaximisation) WindowMaximisation {
for i, val := range sl {
if val == current {
if i == len(sl)-1 {
return sl[0]
}
return sl[i+1]
}
}
return sl[0]
}
// TODO: GENERICS
func prevIntInCycle(sl []WindowMaximisation, current WindowMaximisation) WindowMaximisation {
for i, val := range sl {
if val == current {
if i > 0 {
return sl[i-1]
}
return sl[len(sl)-1]
}
}
return sl[len(sl)-1]
}
func (gui *Gui) nextScreenMode() error {
gui.State.ScreenMode = nextIntInCycle([]WindowMaximisation{SCREEN_NORMAL, SCREEN_HALF, SCREEN_FULL}, gui.State.ScreenMode)
2020-08-19 11:26:05 +02:00
return gui.rerenderViewsWithScreenModeDependentContent()
}
func (gui *Gui) prevScreenMode() error {
gui.State.ScreenMode = prevIntInCycle([]WindowMaximisation{SCREEN_NORMAL, SCREEN_HALF, SCREEN_FULL}, gui.State.ScreenMode)
2020-08-19 11:07:14 +02:00
2020-08-19 11:26:05 +02:00
return gui.rerenderViewsWithScreenModeDependentContent()
2020-03-29 01:31:34 +02:00
}
2021-04-04 15:51:59 +02:00
func (gui *Gui) scrollUpView(view *gocui.View) error {
ox, oy := view.Origin()
2020-10-03 06:54:55 +02:00
newOy := int(math.Max(0, float64(oy-gui.Config.GetUserConfig().Gui.ScrollHeight)))
2021-04-04 15:51:59 +02:00
return view.SetOrigin(ox, newOy)
2020-03-29 01:31:34 +02:00
}
2021-04-04 15:51:59 +02:00
func (gui *Gui) scrollDownView(view *gocui.View) error {
ox, oy := view.Origin()
2021-04-11 03:43:07 +02:00
scrollHeight := gui.linesToScrollDown(view)
if scrollHeight > 0 {
if err := view.SetOrigin(ox, oy+scrollHeight); err != nil {
return err
}
}
if manager, ok := gui.viewBufferManagerMap[view.Name()]; ok {
manager.ReadLines(scrollHeight)
}
return nil
}
func (gui *Gui) linesToScrollDown(view *gocui.View) int {
_, oy := view.Origin()
2020-03-29 01:31:34 +02:00
y := oy
2021-04-02 06:25:27 +02:00
canScrollPastBottom := gui.Config.GetUserConfig().Gui.ScrollPastBottom
if !canScrollPastBottom {
2021-04-04 15:51:59 +02:00
_, sy := view.Size()
2020-03-29 01:31:34 +02:00
y += sy
}
2020-10-03 06:54:55 +02:00
scrollHeight := gui.Config.GetUserConfig().Gui.ScrollHeight
2021-04-04 15:51:59 +02:00
scrollableLines := view.ViewLinesHeight() - y
2021-04-11 03:43:07 +02:00
if scrollableLines < 0 {
return 0
2020-03-29 01:31:34 +02:00
}
2021-04-11 03:43:07 +02:00
// margin is about how many lines must still appear if you scroll
// all the way down. In practice every file ends in a newline so it will really
// just show a single line
margin := 1
if canScrollPastBottom {
margin = 2
}
if scrollableLines-margin < scrollHeight {
scrollHeight = scrollableLines - margin
}
if oy+scrollHeight < 0 {
return 0
} else {
return scrollHeight
2020-03-29 01:31:34 +02:00
}
2021-04-11 03:43:07 +02:00
}
func (gui *Gui) scrollUpMain() error {
if gui.canScrollMergePanel() {
gui.State.Panels.Merging.UserScrolling = true
}
2021-04-04 15:51:59 +02:00
return gui.scrollUpView(gui.Views.Main)
2020-03-29 01:31:34 +02:00
}
func (gui *Gui) scrollDownMain() error {
if gui.canScrollMergePanel() {
gui.State.Panels.Merging.UserScrolling = true
}
2021-04-04 15:51:59 +02:00
return gui.scrollDownView(gui.Views.Main)
2020-03-29 01:31:34 +02:00
}
func (gui *Gui) scrollUpSecondary() error {
2021-04-04 15:51:59 +02:00
return gui.scrollUpView(gui.Views.Secondary)
2020-03-29 01:31:34 +02:00
}
func (gui *Gui) scrollDownSecondary() error {
2021-04-04 15:51:59 +02:00
return gui.scrollDownView(gui.Views.Secondary)
2020-03-29 01:31:34 +02:00
}
func (gui *Gui) scrollUpConfirmationPanel() error {
2021-04-04 15:51:59 +02:00
if gui.Views.Confirmation.Editable {
2020-03-29 01:31:34 +02:00
return nil
}
2021-04-04 15:51:59 +02:00
return gui.scrollUpView(gui.Views.Confirmation)
2020-03-29 01:31:34 +02:00
}
func (gui *Gui) scrollDownConfirmationPanel() error {
2021-04-04 15:51:59 +02:00
if gui.Views.Confirmation.Editable {
2020-03-29 01:31:34 +02:00
return nil
}
2021-04-04 15:51:59 +02:00
return gui.scrollDownView(gui.Views.Confirmation)
2020-03-29 01:31:34 +02:00
}
func (gui *Gui) handleRefresh() error {
2020-03-29 01:31:34 +02:00
return gui.refreshSidePanels(refreshOptions{mode: ASYNC})
}
func (gui *Gui) handleMouseDownMain() error {
2020-03-29 01:31:34 +02:00
if gui.popupPanelFocused() {
return nil
}
2021-04-11 07:01:49 +02:00
switch gui.currentSideContext() {
case gui.State.Contexts.Files:
2020-08-16 10:22:55 +02:00
// set filename, set primary/secondary selected, set line number, then switch context
// I'll need to know it was changed though.
// Could I pass something along to the context change?
2021-04-04 15:51:59 +02:00
return gui.enterFile(false, gui.Views.Main.SelectedLineIdx())
2021-04-11 07:01:49 +02:00
case gui.State.Contexts.CommitFiles:
2021-04-04 15:51:59 +02:00
return gui.enterCommitFile(gui.Views.Main.SelectedLineIdx())
2020-03-29 01:31:34 +02:00
}
return nil
}
func (gui *Gui) handleMouseDownSecondary() error {
2020-03-29 01:31:34 +02:00
if gui.popupPanelFocused() {
return nil
}
2021-04-04 17:10:23 +02:00
switch gui.g.CurrentView() {
case gui.Views.Files:
2021-04-04 15:51:59 +02:00
return gui.enterFile(true, gui.Views.Secondary.SelectedLineIdx())
2020-03-29 01:31:34 +02:00
}
return nil
}
2021-04-10 09:31:23 +02:00
func (gui *Gui) fetch(canPromptForCredentials bool, span string) (err error) {
gui.Mutexes.FetchMutex.Lock()
defer gui.Mutexes.FetchMutex.Unlock()
2020-08-23 13:25:39 +02:00
2020-08-11 13:18:38 +02:00
fetchOpts := commands.FetchOptions{}
if canPromptForCredentials {
fetchOpts.PromptUserForCredential = gui.promptUserForCredential
}
2021-04-10 09:31:23 +02:00
err = gui.GitCommand.WithSpan(span).Fetch(fetchOpts)
2020-03-29 01:31:34 +02:00
2020-08-11 13:18:38 +02:00
if canPromptForCredentials && err != nil && strings.Contains(err.Error(), "exit status 128") {
2020-11-16 11:38:26 +02:00
_ = gui.createErrorPanel(gui.Tr.PassUnameWrong)
2020-03-29 01:31:34 +02:00
}
_ = gui.refreshSidePanels(refreshOptions{scope: []RefreshableView{BRANCHES, COMMITS, REMOTES, TAGS}, mode: ASYNC})
2020-03-29 01:31:34 +02:00
2020-08-11 12:18:50 +02:00
return err
2020-03-29 01:31:34 +02:00
}
func (gui *Gui) handleCopySelectedSideContextItemToClipboard() error {
// important to note that this assumes we've selected an item in a side context
itemId := gui.getSideContextSelectedItemId()
if itemId == "" {
return nil
}
2021-04-11 11:35:42 +02:00
if err := gui.OSCommand.WithSpan(gui.Tr.Spans.CopyToClipboard).CopyToClipboard(itemId); err != nil {
return gui.surfaceError(err)
}
2020-12-24 11:21:54 +02:00
truncatedItemId := utils.TruncateWithEllipsis(strings.Replace(itemId, "\n", " ", -1), 50)
gui.raiseToast(fmt.Sprintf("'%s' %s", truncatedItemId, gui.Tr.LcCopiedToClipboard))
return nil
}