1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2024-11-30 09:16:47 +02:00
lazygit/view_helpers.go

234 lines
5.4 KiB
Go
Raw Normal View History

2018-05-26 05:23:39 +02:00
package main
import (
"fmt"
"sort"
"strings"
"time"
2018-05-26 05:23:39 +02:00
"github.com/jesseduffield/gocui"
2018-05-26 05:23:39 +02:00
)
2018-06-06 04:17:49 +02:00
var cyclableViews = []string{"files", "branches", "commits", "stash"}
2018-06-09 11:06:33 +02:00
func refreshSidePanels(g *gocui.Gui) error {
refreshBranches(g)
refreshFiles(g)
refreshCommits(g)
return nil
2018-06-06 04:17:49 +02:00
}
func nextView(g *gocui.Gui, v *gocui.View) error {
var focusedViewName string
if v == nil || v.Name() == cyclableViews[len(cyclableViews)-1] {
focusedViewName = cyclableViews[0]
} else {
for i := range cyclableViews {
if v.Name() == cyclableViews[i] {
focusedViewName = cyclableViews[i+1]
break
}
if i == len(cyclableViews)-1 {
devLog(v.Name() + " is not in the list of views")
return nil
}
}
}
focusedView, err := g.View(focusedViewName)
if err != nil {
panic(err)
}
return switchFocus(g, v, focusedView)
2018-06-06 04:17:49 +02:00
}
func previousView(g *gocui.Gui, v *gocui.View) error {
var focusedViewName string
2018-07-22 04:58:39 +02:00
if v == nil || v.Name() == cyclableViews[0] {
focusedViewName = cyclableViews[len(cyclableViews)-1]
} else {
for i := range cyclableViews {
if v.Name() == cyclableViews[i] {
focusedViewName = cyclableViews[i-1] // TODO: make this work properly
break
}
if i == len(cyclableViews)-1 {
devLog(v.Name() + " is not in the list of views")
return nil
}
}
}
focusedView, err := g.View(focusedViewName)
if err != nil {
panic(err)
}
return switchFocus(g, v, focusedView)
}
2018-06-06 04:17:49 +02:00
func newLineFocused(g *gocui.Gui, v *gocui.View) error {
mainView, _ := g.View("main")
mainView.SetOrigin(0, 0)
switch v.Name() {
case "files":
return handleFileSelect(g, v)
case "branches":
return handleBranchSelect(g, v)
case "confirmation":
return nil
case "main":
// TODO: pull this out into a 'view focused' function
refreshMergePanel(g)
v.Highlight = false
return nil
case "commits":
return handleCommitSelect(g, v)
case "stash":
return handleStashEntrySelect(g, v)
default:
panic("No view matching newLineFocused switch statement")
}
2018-06-06 04:17:49 +02:00
}
2018-05-26 05:23:39 +02:00
func returnFocus(g *gocui.Gui, v *gocui.View) error {
previousView, err := g.View(state.PreviousView)
if err != nil {
panic(err)
}
return switchFocus(g, v, previousView)
2018-05-26 05:23:39 +02:00
}
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
2018-05-26 05:23:39 +02:00
func switchFocus(g *gocui.Gui, oldView, newView *gocui.View) error {
// we assume we'll never want to return focus to a confirmation panel i.e.
// we should never stack confirmation panels
if oldView != nil && oldView.Name() != "confirmation" {
oldView.Highlight = false
devLog("setting previous view to:", oldView.Name())
state.PreviousView = oldView.Name()
}
newView.Highlight = true
devLog(newView.Name())
if _, err := g.SetCurrentView(newView.Name()); err != nil {
return err
}
g.Cursor = newView.Editable
return newLineFocused(g, newView)
2018-05-26 05:23:39 +02:00
}
func getItemPosition(v *gocui.View) int {
_, cy := v.Cursor()
_, oy := v.Origin()
return oy + cy
2018-05-26 05:23:39 +02:00
}
2018-06-05 10:48:46 +02:00
func trimmedContent(v *gocui.View) string {
return strings.TrimSpace(v.Buffer())
2018-06-05 10:48:46 +02:00
}
2018-05-26 05:23:39 +02:00
func cursorUp(g *gocui.Gui, v *gocui.View) error {
// swallowing cursor movements in main
// TODO: pull this out
if v == nil || v.Name() == "main" {
return nil
}
ox, oy := v.Origin()
cx, cy := v.Cursor()
if err := v.SetCursor(cx, cy-1); err != nil && oy > 0 {
if err := v.SetOrigin(ox, oy-1); err != nil {
return err
}
}
newLineFocused(g, v)
return nil
2018-05-26 05:23:39 +02:00
}
func cursorDown(g *gocui.Gui, v *gocui.View) error {
// swallowing cursor movements in main
// TODO: pull this out
if v == nil || v.Name() == "main" {
return nil
}
cx, cy := v.Cursor()
ox, oy := v.Origin()
if cy+oy >= len(v.BufferLines())-2 {
return nil
}
if err := v.SetCursor(cx, cy+1); err != nil {
if err := v.SetOrigin(ox, oy+1); err != nil {
return err
}
}
newLineFocused(g, v)
return nil
2018-05-26 05:23:39 +02:00
}
2018-06-09 11:06:33 +02:00
func resetOrigin(v *gocui.View) error {
if err := v.SetCursor(0, 0); err != nil {
return err
}
return v.SetOrigin(0, 0)
2018-06-09 11:06:33 +02:00
}
2018-05-26 05:23:39 +02:00
// if the cursor down past the last item, move it up one
func correctCursor(v *gocui.View) error {
cx, cy := v.Cursor()
_, oy := v.Origin()
lineCount := len(v.BufferLines()) - 2
if cy >= lineCount-oy {
return v.SetCursor(cx, lineCount-oy)
}
return nil
2018-05-26 05:23:39 +02:00
}
func renderString(g *gocui.Gui, viewName, s string) error {
g.Update(func(*gocui.Gui) error {
v, err := g.View(viewName)
// just in case the view disappeared as this function was called, we'll
// silently return if it's not found
if err != nil {
return nil
}
v.Clear()
fmt.Fprint(v, s)
v.Wrap = true
return nil
})
return nil
2018-05-26 05:23:39 +02:00
}
func splitLines(multilineString string) []string {
multilineString = strings.Replace(multilineString, "\r", "", -1)
if multilineString == "" || multilineString == "\n" {
return make([]string, 0)
}
lines := strings.Split(multilineString, "\n")
if lines[len(lines)-1] == "" {
return lines[:len(lines)-1]
}
return lines
2018-05-26 05:23:39 +02:00
}
2018-06-09 11:06:33 +02:00
func optionsMapToString(optionsMap map[string]string) string {
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
}
func renderOptionsMap(g *gocui.Gui, optionsMap map[string]string) error {
return renderString(g, "options", optionsMapToString(optionsMap))
2018-06-09 11:06:33 +02:00
}
func loader() string {
characters := "|/-\\"
now := time.Now()
nanos := now.UnixNano()
index := nanos / 50000000 % int64(len(characters))
return characters[index : index+1]
}