2018-08-14 11:05:26 +02:00
|
|
|
package gui
|
2018-05-26 05:23:39 +02:00
|
|
|
|
|
|
|
import (
|
2018-07-21 07:51:18 +02:00
|
|
|
"fmt"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
2018-05-26 05:23:39 +02:00
|
|
|
|
2018-07-21 07:51:18 +02:00
|
|
|
"github.com/jesseduffield/gocui"
|
2018-08-19 13:20:50 +02:00
|
|
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
2018-08-16 07:53:53 +02:00
|
|
|
"github.com/spkg/bom"
|
2018-05-26 05:23:39 +02:00
|
|
|
)
|
|
|
|
|
2018-08-18 06:52:01 +02:00
|
|
|
var cyclableViews = []string{"status", "files", "branches", "commits", "stash"}
|
2018-06-06 04:17:49 +02:00
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) refreshSidePanels(g *gocui.Gui) error {
|
2018-12-07 09:52:31 +02:00
|
|
|
if err := gui.refreshBranches(g); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-12-08 07:54:54 +02:00
|
|
|
if err := gui.refreshFiles(); err != nil {
|
2018-12-07 09:52:31 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := gui.refreshCommits(g); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-03-11 04:04:08 +02:00
|
|
|
|
2018-12-07 09:52:31 +02:00
|
|
|
return gui.refreshStashEntries(g)
|
2018-06-06 04:17:49 +02:00
|
|
|
}
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) nextView(g *gocui.Gui, v *gocui.View) error {
|
2018-07-21 07:51:18 +02:00
|
|
|
var focusedViewName string
|
|
|
|
if v == nil || v.Name() == cyclableViews[len(cyclableViews)-1] {
|
|
|
|
focusedViewName = cyclableViews[0]
|
|
|
|
} else {
|
2019-03-11 04:04:08 +02:00
|
|
|
// if we're in the commitFiles view we'll act like we're in the commits view
|
|
|
|
viewName := v.Name()
|
|
|
|
if viewName == "commitFiles" {
|
|
|
|
viewName = "commits"
|
|
|
|
}
|
2018-07-21 07:51:18 +02:00
|
|
|
for i := range cyclableViews {
|
2019-03-11 04:04:08 +02:00
|
|
|
if viewName == cyclableViews[i] {
|
2018-07-21 07:51:18 +02:00
|
|
|
focusedViewName = cyclableViews[i+1]
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if i == len(cyclableViews)-1 {
|
2018-08-15 11:49:43 +02:00
|
|
|
message := gui.Tr.TemplateLocalize(
|
|
|
|
"IssntListOfViews",
|
2018-08-16 11:31:50 +02:00
|
|
|
Teml{
|
2019-03-11 04:04:08 +02:00
|
|
|
"name": viewName,
|
2018-08-15 11:49:43 +02:00
|
|
|
},
|
|
|
|
)
|
|
|
|
gui.Log.Info(message)
|
2018-07-21 07:51:18 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
focusedView, err := g.View(focusedViewName)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2018-08-14 11:05:26 +02:00
|
|
|
return gui.switchFocus(g, v, focusedView)
|
2018-06-06 04:17:49 +02:00
|
|
|
}
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) previousView(g *gocui.Gui, v *gocui.View) error {
|
2018-07-22 04:07:36 +02:00
|
|
|
var focusedViewName string
|
2018-07-22 04:58:39 +02:00
|
|
|
if v == nil || v.Name() == cyclableViews[0] {
|
|
|
|
focusedViewName = cyclableViews[len(cyclableViews)-1]
|
2018-07-22 04:07:36 +02:00
|
|
|
} else {
|
2019-03-11 04:04:08 +02:00
|
|
|
// if we're in the commitFiles view we'll act like we're in the commits view
|
|
|
|
viewName := v.Name()
|
|
|
|
if viewName == "commitFiles" {
|
|
|
|
viewName = "commits"
|
|
|
|
}
|
2018-07-22 04:07:36 +02:00
|
|
|
for i := range cyclableViews {
|
2019-03-11 04:04:08 +02:00
|
|
|
if viewName == cyclableViews[i] {
|
2018-07-22 04:07:36 +02:00
|
|
|
focusedViewName = cyclableViews[i-1] // TODO: make this work properly
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if i == len(cyclableViews)-1 {
|
2018-08-15 11:49:43 +02:00
|
|
|
message := gui.Tr.TemplateLocalize(
|
|
|
|
"IssntListOfViews",
|
2018-08-16 11:31:50 +02:00
|
|
|
Teml{
|
2019-03-11 04:04:08 +02:00
|
|
|
"name": viewName,
|
2018-08-15 11:49:43 +02:00
|
|
|
},
|
|
|
|
)
|
|
|
|
gui.Log.Info(message)
|
2018-07-22 04:07:36 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
focusedView, err := g.View(focusedViewName)
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
2018-08-14 11:05:26 +02:00
|
|
|
return gui.switchFocus(g, v, focusedView)
|
2018-07-22 04:07:36 +02:00
|
|
|
}
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) newLineFocused(g *gocui.Gui, v *gocui.View) error {
|
2018-07-21 07:51:18 +02:00
|
|
|
switch v.Name() {
|
2018-09-05 11:12:11 +02:00
|
|
|
case "menu":
|
2018-12-07 09:52:31 +02:00
|
|
|
return gui.handleMenuSelect(g, v)
|
2018-08-18 06:52:01 +02:00
|
|
|
case "status":
|
|
|
|
return gui.handleStatusSelect(g, v)
|
2018-07-21 07:51:18 +02:00
|
|
|
case "files":
|
2019-01-15 11:12:31 +02:00
|
|
|
return gui.handleFileSelect(g, v, false)
|
2018-07-21 07:51:18 +02:00
|
|
|
case "branches":
|
2018-08-14 11:05:26 +02:00
|
|
|
return gui.handleBranchSelect(g, v)
|
2018-12-06 13:18:17 +02:00
|
|
|
case "commits":
|
|
|
|
return gui.handleCommitSelect(g, v)
|
2019-03-11 00:28:47 +02:00
|
|
|
case "commitFiles":
|
2019-03-09 16:42:10 +02:00
|
|
|
return gui.handleCommitFileSelect(g, v)
|
2018-12-06 13:18:17 +02:00
|
|
|
case "stash":
|
|
|
|
return gui.handleStashEntrySelect(g, v)
|
2018-07-21 07:51:18 +02:00
|
|
|
case "confirmation":
|
|
|
|
return nil
|
2018-08-11 07:09:37 +02:00
|
|
|
case "commitMessage":
|
2018-08-14 11:05:26 +02:00
|
|
|
return gui.handleCommitFocused(g, v)
|
2018-12-10 08:51:06 +02:00
|
|
|
case "credentials":
|
2018-12-16 08:05:34 +02:00
|
|
|
return gui.handleCredentialsViewFocused(g, v)
|
2018-07-21 07:51:18 +02:00
|
|
|
case "main":
|
2019-02-16 03:07:27 +02:00
|
|
|
if gui.State.Contexts["main"] == "merging" {
|
|
|
|
return gui.refreshMergePanel()
|
|
|
|
}
|
2018-07-21 07:51:18 +02:00
|
|
|
v.Highlight = false
|
|
|
|
return nil
|
|
|
|
default:
|
2018-08-16 07:16:32 +02:00
|
|
|
panic(gui.Tr.SLocalize("NoViewMachingNewLineFocusedSwitchStatement"))
|
2018-07-21 07:51:18 +02:00
|
|
|
}
|
2018-06-06 04:17:49 +02:00
|
|
|
}
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) returnFocus(g *gocui.Gui, v *gocui.View) error {
|
|
|
|
previousView, err := g.View(gui.State.PreviousView)
|
2018-07-21 07:51:18 +02:00
|
|
|
if err != nil {
|
2018-08-23 10:43:16 +02:00
|
|
|
// always fall back to files view if there's no 'previous' view stored
|
|
|
|
previousView, err = g.View("files")
|
|
|
|
if err != nil {
|
|
|
|
gui.Log.Error(err)
|
|
|
|
}
|
2018-07-21 07:51:18 +02:00
|
|
|
}
|
2018-08-14 11:05:26 +02:00
|
|
|
return gui.switchFocus(g, v, previousView)
|
2018-05-26 05:23:39 +02:00
|
|
|
}
|
|
|
|
|
2019-07-27 13:16:26 +02:00
|
|
|
func (gui *Gui) goToSideView(sideViewName string) func(g *gocui.Gui, v *gocui.View) error {
|
|
|
|
return func(g *gocui.Gui, v *gocui.View) error {
|
|
|
|
view, err := g.View(sideViewName)
|
|
|
|
if err != nil {
|
|
|
|
gui.Log.Error(err)
|
|
|
|
return nil
|
|
|
|
}
|
2019-10-26 23:45:44 +02:00
|
|
|
err = gui.closePopupPanels()
|
|
|
|
if err != nil {
|
|
|
|
gui.Log.Error(err)
|
|
|
|
return nil
|
|
|
|
}
|
2019-07-27 13:16:26 +02:00
|
|
|
return gui.switchFocus(g, nil, view)
|
2019-07-14 15:39:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-26 23:45:44 +02:00
|
|
|
func (gui *Gui) closePopupPanels() error {
|
|
|
|
gui.onNewPopupPanel()
|
2019-11-05 06:19:43 +02:00
|
|
|
err := gui.closeConfirmationPrompt(gui.g, true)
|
2019-10-26 23:45:44 +02:00
|
|
|
if err != nil {
|
|
|
|
gui.Log.Error(err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-06-09 11:06:33 +02:00
|
|
|
// pass in oldView = nil if you don't want to be able to return to your old view
|
2019-02-16 12:01:17 +02:00
|
|
|
// TODO: move some of this logic into our onFocusLost and onFocus hooks
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) switchFocus(g *gocui.Gui, oldView, newView *gocui.View) error {
|
2019-03-11 04:04:08 +02:00
|
|
|
// we assume we'll never want to return focus to a popup panel i.e.
|
|
|
|
// we should never stack popup panels
|
|
|
|
if oldView != nil && !gui.isPopupPanel(oldView.Name()) {
|
|
|
|
gui.State.PreviousView = oldView.Name()
|
2018-07-21 07:51:18 +02:00
|
|
|
}
|
2018-09-19 12:36:40 +02:00
|
|
|
|
2019-02-16 12:01:17 +02:00
|
|
|
gui.Log.Info("setting highlight to true for view" + newView.Name())
|
2018-08-15 11:49:43 +02:00
|
|
|
message := gui.Tr.TemplateLocalize(
|
|
|
|
"newFocusedViewIs",
|
2018-08-16 11:31:50 +02:00
|
|
|
Teml{
|
2018-08-15 11:49:43 +02:00
|
|
|
"newFocusedView": newView.Name(),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
gui.Log.Info(message)
|
2018-07-21 07:51:18 +02:00
|
|
|
if _, err := g.SetCurrentView(newView.Name()); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2018-12-02 10:57:01 +02:00
|
|
|
if _, err := g.SetViewOnTop(newView.Name()); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-07-21 07:51:18 +02:00
|
|
|
g.Cursor = newView.Editable
|
2018-08-28 20:13:01 +02:00
|
|
|
|
2018-12-07 09:52:31 +02:00
|
|
|
if err := gui.renderPanelOptions(); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-08-29 13:43:59 +02:00
|
|
|
return gui.newLineFocused(g, newView)
|
2018-05-26 05:23:39 +02:00
|
|
|
}
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) resetOrigin(v *gocui.View) error {
|
2019-04-25 21:37:19 +02:00
|
|
|
_ = v.SetCursor(0, 0)
|
2018-07-21 07:51:18 +02:00
|
|
|
return v.SetOrigin(0, 0)
|
2018-06-09 11:06:33 +02:00
|
|
|
}
|
|
|
|
|
2018-12-04 10:50:11 +02:00
|
|
|
// if the cursor down past the last item, move it to the last line
|
2019-03-23 02:42:19 +02:00
|
|
|
func (gui *Gui) focusPoint(cx int, cy int, lineCount int, v *gocui.View) error {
|
|
|
|
if cy < 0 || cy > lineCount {
|
2018-09-10 12:17:39 +02:00
|
|
|
return nil
|
|
|
|
}
|
2018-12-04 10:50:11 +02:00
|
|
|
ox, oy := v.Origin()
|
|
|
|
_, height := v.Size()
|
2019-04-25 21:37:19 +02:00
|
|
|
|
2018-12-04 10:50:11 +02:00
|
|
|
ly := height - 1
|
2019-04-25 21:37:19 +02:00
|
|
|
if ly == -1 {
|
|
|
|
ly = 0
|
|
|
|
}
|
2018-12-04 10:50:11 +02:00
|
|
|
|
|
|
|
// if line is above origin, move origin and set cursor to zero
|
|
|
|
// if line is below origin + height, move origin and set cursor to max
|
|
|
|
// otherwise set cursor to value - origin
|
2019-03-23 02:42:19 +02:00
|
|
|
if ly > lineCount {
|
2019-04-25 21:37:19 +02:00
|
|
|
_ = v.SetCursor(cx, cy)
|
|
|
|
_ = v.SetOrigin(ox, 0)
|
2018-12-04 10:50:11 +02:00
|
|
|
} else if cy < oy {
|
2019-04-25 21:37:19 +02:00
|
|
|
_ = v.SetCursor(cx, 0)
|
|
|
|
_ = v.SetOrigin(ox, cy)
|
2018-12-04 10:50:11 +02:00
|
|
|
} else if cy > oy+ly {
|
2019-04-25 21:37:19 +02:00
|
|
|
_ = v.SetCursor(cx, ly)
|
|
|
|
_ = v.SetOrigin(ox, cy-ly)
|
2018-12-04 10:50:11 +02:00
|
|
|
} else {
|
2019-04-25 21:37:19 +02:00
|
|
|
_ = v.SetCursor(cx, cy-oy)
|
2018-07-21 07:51:18 +02:00
|
|
|
}
|
|
|
|
return nil
|
2018-05-26 05:23:39 +02:00
|
|
|
}
|
|
|
|
|
2019-01-15 11:12:31 +02:00
|
|
|
func (gui *Gui) cleanString(s string) string {
|
2018-12-12 13:34:20 +02:00
|
|
|
output := string(bom.Clean([]byte(s)))
|
2019-01-15 11:12:31 +02:00
|
|
|
return utils.NormalizeLinefeeds(output)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (gui *Gui) setViewContent(g *gocui.Gui, v *gocui.View, s string) error {
|
|
|
|
v.Clear()
|
|
|
|
fmt.Fprint(v, gui.cleanString(s))
|
2018-12-12 13:34:20 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-01-15 11:12:31 +02:00
|
|
|
// renderString resets the origin of a view and sets its content
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) renderString(g *gocui.Gui, viewName, s string) error {
|
2018-07-21 07:51:18 +02:00
|
|
|
g.Update(func(*gocui.Gui) error {
|
|
|
|
v, err := g.View(viewName)
|
|
|
|
if err != nil {
|
2019-01-15 11:12:31 +02:00
|
|
|
return nil // return gracefully if view has been deleted
|
2018-07-21 07:51:18 +02:00
|
|
|
}
|
2019-01-15 11:12:31 +02:00
|
|
|
if err := v.SetOrigin(0, 0); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return gui.setViewContent(gui.g, v, s)
|
2018-07-21 07:51:18 +02:00
|
|
|
})
|
|
|
|
return nil
|
2018-05-26 05:23:39 +02:00
|
|
|
}
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) optionsMapToString(optionsMap map[string]string) string {
|
2018-07-21 07:51:18 +02:00
|
|
|
optionsArray := make([]string, 0)
|
|
|
|
for key, description := range optionsMap {
|
|
|
|
optionsArray = append(optionsArray, key+": "+description)
|
|
|
|
}
|
|
|
|
sort.Strings(optionsArray)
|
|
|
|
return strings.Join(optionsArray, ", ")
|
2018-06-09 11:06:33 +02:00
|
|
|
}
|
|
|
|
|
2018-12-07 09:52:31 +02:00
|
|
|
func (gui *Gui) renderOptionsMap(optionsMap map[string]string) error {
|
|
|
|
return gui.renderString(gui.g, "options", gui.optionsMapToString(optionsMap))
|
2018-06-09 11:06:33 +02:00
|
|
|
}
|
2018-07-22 04:07:36 +02:00
|
|
|
|
2018-08-11 07:09:37 +02:00
|
|
|
// TODO: refactor properly
|
2018-09-03 18:45:52 +02:00
|
|
|
// i'm so sorry but had to add this getBranchesView
|
2018-12-08 07:54:54 +02:00
|
|
|
func (gui *Gui) getFilesView() *gocui.View {
|
|
|
|
v, _ := gui.g.View("files")
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
func (gui *Gui) getCommitsView() *gocui.View {
|
|
|
|
v, _ := gui.g.View("commits")
|
2018-08-11 07:09:37 +02:00
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
2018-12-08 07:54:54 +02:00
|
|
|
func (gui *Gui) getCommitMessageView() *gocui.View {
|
|
|
|
v, _ := gui.g.View("commitMessage")
|
2018-08-11 07:09:37 +02:00
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
2018-12-08 07:54:54 +02:00
|
|
|
func (gui *Gui) getBranchesView() *gocui.View {
|
|
|
|
v, _ := gui.g.View("branches")
|
2018-08-11 07:09:37 +02:00
|
|
|
return v
|
|
|
|
}
|
2018-08-14 11:05:26 +02:00
|
|
|
|
2018-12-08 07:54:54 +02:00
|
|
|
func (gui *Gui) getMainView() *gocui.View {
|
|
|
|
v, _ := gui.g.View("main")
|
2018-12-02 10:57:01 +02:00
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
2019-10-30 11:23:25 +02:00
|
|
|
func (gui *Gui) getSecondaryView() *gocui.View {
|
|
|
|
v, _ := gui.g.View("secondary")
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
2018-12-08 07:54:54 +02:00
|
|
|
func (gui *Gui) getStashView() *gocui.View {
|
|
|
|
v, _ := gui.g.View("stash")
|
2018-12-06 13:18:17 +02:00
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
2019-03-11 00:28:47 +02:00
|
|
|
func (gui *Gui) getCommitFilesView() *gocui.View {
|
|
|
|
v, _ := gui.g.View("commitFiles")
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
2018-08-14 11:05:26 +02:00
|
|
|
func (gui *Gui) trimmedContent(v *gocui.View) string {
|
|
|
|
return strings.TrimSpace(v.Buffer())
|
|
|
|
}
|
|
|
|
|
2019-02-25 13:11:35 +02:00
|
|
|
func (gui *Gui) currentViewName() string {
|
|
|
|
currentView := gui.g.CurrentView()
|
2018-08-14 11:05:26 +02:00
|
|
|
return currentView.Name()
|
|
|
|
}
|
2018-09-05 11:07:46 +02:00
|
|
|
|
|
|
|
func (gui *Gui) resizeCurrentPopupPanel(g *gocui.Gui) error {
|
|
|
|
v := g.CurrentView()
|
2019-03-11 04:04:08 +02:00
|
|
|
if gui.isPopupPanel(v.Name()) {
|
2018-09-05 11:07:46 +02:00
|
|
|
return gui.resizePopupPanel(g, v)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (gui *Gui) resizePopupPanel(g *gocui.Gui, v *gocui.View) error {
|
|
|
|
// If the confirmation panel is already displayed, just resize the width,
|
|
|
|
// otherwise continue
|
|
|
|
content := v.Buffer()
|
2019-01-15 10:33:42 +02:00
|
|
|
x0, y0, x1, y1 := gui.getConfirmationPanelDimensions(g, v.Wrap, content)
|
2018-09-05 11:07:46 +02:00
|
|
|
vx0, vy0, vx1, vy1 := v.Dimensions()
|
|
|
|
if vx0 == x0 && vy0 == y0 && vx1 == x1 && vy1 == y1 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
gui.Log.Info(gui.Tr.SLocalize("resizingPopupPanel"))
|
|
|
|
_, err := g.SetView(v.Name(), x0, y0, x1, y1, 0)
|
|
|
|
return err
|
|
|
|
}
|
2018-12-04 10:50:11 +02:00
|
|
|
|
|
|
|
// generalFocusLine takes a lineNumber to focus, and a bottomLine to ensure we can see
|
|
|
|
func (gui *Gui) generalFocusLine(lineNumber int, bottomLine int, v *gocui.View) error {
|
|
|
|
_, height := v.Size()
|
|
|
|
overScroll := bottomLine - height + 1
|
|
|
|
if overScroll < 0 {
|
|
|
|
overScroll = 0
|
|
|
|
}
|
|
|
|
if err := v.SetOrigin(0, overScroll); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := v.SetCursor(0, lineNumber-overScroll); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (gui *Gui) changeSelectedLine(line *int, total int, up bool) {
|
|
|
|
if up {
|
|
|
|
if *line == -1 || *line == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-11-04 10:47:25 +02:00
|
|
|
*line--
|
2018-12-04 10:50:11 +02:00
|
|
|
} else {
|
|
|
|
if *line == -1 || *line == total-1 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-11-04 10:47:25 +02:00
|
|
|
*line++
|
2018-12-04 10:50:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (gui *Gui) refreshSelectedLine(line *int, total int) {
|
|
|
|
if *line == -1 && total > 0 {
|
|
|
|
*line = 0
|
|
|
|
} else if total-1 < *line {
|
|
|
|
*line = total - 1
|
|
|
|
}
|
|
|
|
}
|
2018-12-07 09:52:31 +02:00
|
|
|
|
|
|
|
func (gui *Gui) renderListPanel(v *gocui.View, items interface{}) error {
|
|
|
|
gui.g.Update(func(g *gocui.Gui) error {
|
2019-02-16 06:17:44 +02:00
|
|
|
isFocused := gui.g.CurrentView().Name() == v.Name()
|
|
|
|
list, err := utils.RenderList(items, isFocused)
|
2018-12-07 09:52:31 +02:00
|
|
|
if err != nil {
|
|
|
|
return gui.createErrorPanel(gui.g, err.Error())
|
|
|
|
}
|
|
|
|
v.Clear()
|
|
|
|
fmt.Fprint(v, list)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (gui *Gui) renderPanelOptions() error {
|
|
|
|
currentView := gui.g.CurrentView()
|
|
|
|
switch currentView.Name() {
|
|
|
|
case "menu":
|
|
|
|
return gui.renderMenuOptions()
|
|
|
|
case "main":
|
2019-02-16 03:07:27 +02:00
|
|
|
if gui.State.Contexts["main"] == "merging" {
|
|
|
|
return gui.renderMergeOptions()
|
|
|
|
}
|
2018-12-07 09:52:31 +02:00
|
|
|
}
|
2019-02-16 03:07:27 +02:00
|
|
|
return gui.renderGlobalOptions()
|
2018-12-07 09:52:31 +02:00
|
|
|
}
|
2019-02-25 13:11:35 +02:00
|
|
|
|
|
|
|
func (gui *Gui) handleFocusView(g *gocui.Gui, v *gocui.View) error {
|
|
|
|
_, err := gui.g.SetCurrentView(v.Name())
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-03-11 04:04:08 +02:00
|
|
|
func (gui *Gui) isPopupPanel(viewName string) bool {
|
|
|
|
return viewName == "commitMessage" || viewName == "credentials" || viewName == "confirmation" || viewName == "menu"
|
|
|
|
}
|
|
|
|
|
2019-02-25 13:11:35 +02:00
|
|
|
func (gui *Gui) popupPanelFocused() bool {
|
2019-03-11 04:04:08 +02:00
|
|
|
return gui.isPopupPanel(gui.currentViewName())
|
2019-02-25 13:11:35 +02:00
|
|
|
}
|