got this bad boy compiling again

This commit is contained in:
Jesse Duffield 2018-08-13 21:16:21 +10:00
parent 97cff65612
commit 9e725ae24e
13 changed files with 267 additions and 241 deletions

View file

@ -2,9 +2,9 @@ package app
import ( import (
"io" "io"
"os"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gui" "github.com/jesseduffield/lazygit/pkg/gui"
@ -18,7 +18,21 @@ type App struct {
Log *logrus.Logger Log *logrus.Logger
OSCommand *commands.OSCommand OSCommand *commands.OSCommand
GitCommand *commands.GitCommand GitCommand *commands.GitCommand
Gui *gocui.Gui Gui *gui.Gui
}
func newLogger(config config.AppConfigurer) *logrus.Logger {
log := logrus.New()
if !config.GetDebug() {
log.Out = nil
return log
}
file, err := os.OpenFile("development.log", os.O_CREATE|os.O_WRONLY, 0666)
if err != nil {
panic("unable to log to file") // TODO: don't panic (also, remove this call to the `panic` function)
}
log.Out = file
return log
} }
// NewApp retruns a new applications // NewApp retruns a new applications
@ -28,7 +42,7 @@ func NewApp(config config.AppConfigurer) (*App, error) {
Config: config, Config: config,
} }
var err error var err error
app.Log = logrus.New() app.Log = newLogger(config)
app.OSCommand, err = commands.NewOSCommand(app.Log) app.OSCommand, err = commands.NewOSCommand(app.Log)
if err != nil { if err != nil {
return nil, err return nil, err
@ -37,7 +51,7 @@ func NewApp(config config.AppConfigurer) (*App, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
app.Gui, err = gui.NewGui(app.Log, app.GitCommand, config.GetVersion()) app.Gui, err = gui.NewGui(app.Log, app.GitCommand, app.OSCommand, config.GetVersion())
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -30,7 +30,7 @@ type StashEntry struct {
// Conflict : A git conflict with a start middle and end corresponding to line // Conflict : A git conflict with a start middle and end corresponding to line
// numbers in the file where the conflict bars appear // numbers in the file where the conflict bars appear
type Conflict struct { type Conflict struct {
start int Start int
middle int Middle int
end int End int
} }

View file

@ -8,7 +8,6 @@ import (
"strings" "strings"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
"github.com/jesseduffield/gocui"
gitconfig "github.com/tcnksm/go-gitconfig" gitconfig "github.com/tcnksm/go-gitconfig"
) )
@ -105,28 +104,34 @@ func (c *OSCommand) GetOpenCommand() (string, string, error) {
// VsCodeOpenFile opens the file in code, with the -r flag to open in the // VsCodeOpenFile opens the file in code, with the -r flag to open in the
// current window // current window
func (c *OSCommand) VsCodeOpenFile(g *gocui.Gui, filename string) (string, error) { // each of these open files needs to have the same function signature because
return c.RunCommand("code -r " + filename) // they're being passed as arguments into another function,
// but only editFile actually returns a *exec.Cmd
func (c *OSCommand) VsCodeOpenFile(filename string) (*exec.Cmd, error) {
_, err := c.RunCommand("code -r " + filename)
return nil, err
} }
// SublimeOpenFile opens the filein sublime // SublimeOpenFile opens the filein sublime
// may be deprecated in the future // may be deprecated in the future
func (c *OSCommand) SublimeOpenFile(g *gocui.Gui, filename string) (string, error) { func (c *OSCommand) SublimeOpenFile(filename string) (*exec.Cmd, error) {
return c.RunCommand("subl " + filename) _, err := c.RunCommand("subl " + filename)
return nil, err
} }
// OpenFile opens a file with the given // OpenFile opens a file with the given
func (c *OSCommand) OpenFile(g *gocui.Gui, filename string) (string, error) { func (c *OSCommand) OpenFile(filename string) (*exec.Cmd, error) {
cmdName, cmdTrail, err := c.GetOpenCommand() cmdName, cmdTrail, err := c.GetOpenCommand()
if err != nil { if err != nil {
return "", err return nil, err
} }
return c.RunCommand(cmdName + " " + filename + cmdTrail) _, err = c.RunCommand(cmdName + " " + filename + cmdTrail)
return nil, err
} }
// EditFile opens a file in a subprocess using whatever editor is available, // EditFile opens a file in a subprocess using whatever editor is available,
// falling back to core.editor, VISUAL, EDITOR, then vi // falling back to core.editor, VISUAL, EDITOR, then vi
func (c *OSCommand) editFile(g *gocui.Gui, filename string) (string, error) { func (c *OSCommand) EditFile(filename string) (*exec.Cmd, error) {
editor, _ := gitconfig.Global("core.editor") editor, _ := gitconfig.Global("core.editor")
if editor == "" { if editor == "" {
editor = os.Getenv("VISUAL") editor = os.Getenv("VISUAL")
@ -140,10 +145,9 @@ func (c *OSCommand) editFile(g *gocui.Gui, filename string) (string, error) {
} }
} }
if editor == "" { if editor == "" {
return "", ErrNoEditorDefined return nil, ErrNoEditorDefined
} }
c.PrepareSubProcess(editor, filename) return c.PrepareSubProcess(editor, filename)
return "", nil
} }
// PrepareSubProcess iniPrepareSubProcessrocess then tells the Gui to switch to it // PrepareSubProcess iniPrepareSubProcessrocess then tells the Gui to switch to it

View file

@ -117,7 +117,7 @@ func (gui *Gui) handleBranchSelect(g *gocui.Gui, v *gocui.View) error {
return nil return nil
} }
// refreshStatus is called at the end of this because that's when we can // gui.refreshStatus is called at the end of this because that's when we can
// be sure there is a state.Branches array to pick the current branch from // be sure there is a state.Branches array to pick the current branch from
func (gui *Gui) refreshBranches(g *gocui.Gui) error { func (gui *Gui) refreshBranches(g *gocui.Gui) error {
g.Update(func(g *gocui.Gui) error { g.Update(func(g *gocui.Gui) error {
@ -135,7 +135,7 @@ func (gui *Gui) refreshBranches(g *gocui.Gui) error {
fmt.Fprintln(v, branch.GetDisplayString()) fmt.Fprintln(v, branch.GetDisplayString())
} }
gui.resetOrigin(v) gui.resetOrigin(v)
return refreshStatus(g) return gui.refreshStatus(g)
}) })
return nil return nil
} }

View file

@ -34,7 +34,7 @@ func (gui *Gui) refreshCommits(g *gocui.Gui) error {
shaColor.Fprint(v, commit.Sha+" ") shaColor.Fprint(v, commit.Sha+" ")
white.Fprintln(v, commit.Name) white.Fprintln(v, commit.Name)
} }
refreshStatus(g) gui.refreshStatus(g)
if g.CurrentView().Name() == "commits" { if g.CurrentView().Name() == "commits" {
gui.handleCommitSelect(g, v) gui.handleCommitSelect(g, v)
} }
@ -105,7 +105,7 @@ func (gui *Gui) handleCommitSquashDown(g *gocui.Gui, v *gocui.View) error {
if err := gui.refreshCommits(g); err != nil { if err := gui.refreshCommits(g); err != nil {
panic(err) panic(err)
} }
refreshStatus(g) gui.refreshStatus(g)
return gui.handleCommitSelect(g, v) return gui.handleCommitSelect(g, v)
} }
@ -138,7 +138,7 @@ func (gui *Gui) handleCommitFixup(g *gocui.Gui, v *gocui.View) error {
if err := gui.refreshCommits(g); err != nil { if err := gui.refreshCommits(g); err != nil {
panic(err) panic(err)
} }
return refreshStatus(g) return gui.refreshStatus(g)
}, nil) }, nil)
return nil return nil
} }

View file

@ -8,6 +8,7 @@ import (
// "strings" // "strings"
"errors" "errors"
"os/exec"
"strings" "strings"
"github.com/fatih/color" "github.com/fatih/color"
@ -171,7 +172,7 @@ func (gui *Gui) handleFileSelect(g *gocui.Gui, v *gocui.View) error {
gui.renderfilesOptions(g, &file) gui.renderfilesOptions(g, &file)
var content string var content string
if file.HasMergeConflicts { if file.HasMergeConflicts {
return refreshMergePanel(g) return gui.refreshMergePanel(g)
} }
content = gui.GitCommand.Diff(file) content = gui.GitCommand.Diff(file)
@ -191,9 +192,9 @@ func (gui *Gui) handleCommitPress(g *gocui.Gui, filesView *gocui.View) error {
return nil return nil
} }
// HandleCommitEditorPress - handle when the user wants to commit changes via // handleCommitEditorPress - handle when the user wants to commit changes via
// their editor rather than via the popup panel // their editor rather than via the popup panel
func (gui *Gui) HandleCommitEditorPress(g *gocui.Gui, filesView *gocui.View) error { func (gui *Gui) handleCommitEditorPress(g *gocui.Gui, filesView *gocui.View) error {
if len(gui.stagedFiles(gui.State.Files)) == 0 && !gui.State.HasMergeConflicts { if len(gui.stagedFiles(gui.State.Files)) == 0 && !gui.State.HasMergeConflicts {
return gui.createErrorPanel(g, "There are no staged files to commit") return gui.createErrorPanel(g, "There are no staged files to commit")
} }
@ -214,7 +215,7 @@ func (gui *Gui) PrepareSubProcess(g *gocui.Gui, commands ...string) error {
return nil return nil
} }
func (gui *Gui) genericFileOpen(g *gocui.Gui, v *gocui.View, open func(*gocui.Gui, string) (string, error)) error { func (gui *Gui) genericFileOpen(g *gocui.Gui, v *gocui.View, open func(string) (*exec.Cmd, error)) error {
file, err := gui.getSelectedFile(g) file, err := gui.getSelectedFile(g)
if err != nil { if err != nil {
if err != errNoFiles { if err != errNoFiles {
@ -222,26 +223,31 @@ func (gui *Gui) genericFileOpen(g *gocui.Gui, v *gocui.View, open func(*gocui.Gu
} }
return nil return nil
} }
if _, err := open(g, file.Name); err != nil { sub, err := open(file.Name)
if err != nil {
return gui.createErrorPanel(g, err.Error()) return gui.createErrorPanel(g, err.Error())
} }
if sub != nil {
gui.SubProcess = sub
return ErrSubProcess
}
return nil return nil
} }
func (gui *Gui) handleFileEdit(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleFileEdit(g *gocui.Gui, v *gocui.View) error {
return gui.genericFileOpen(g, v, gui.editFile) return gui.genericFileOpen(g, v, gui.OSCommand.EditFile)
} }
func (gui *Gui) handleFileOpen(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleFileOpen(g *gocui.Gui, v *gocui.View) error {
return gui.genericFileOpen(g, v, gui.openFile) return gui.genericFileOpen(g, v, gui.OSCommand.OpenFile)
} }
func (gui *Gui) handleSublimeFileOpen(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleSublimeFileOpen(g *gocui.Gui, v *gocui.View) error {
return gui.genericFileOpen(g, v, gui.sublimeOpenFile) return gui.genericFileOpen(g, v, gui.OSCommand.SublimeOpenFile)
} }
func (gui *Gui) handleVsCodeFileOpen(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleVsCodeFileOpen(g *gocui.Gui, v *gocui.View) error {
return gui.genericFileOpen(g, v, gui.vsCodeOpenFile) return gui.genericFileOpen(g, v, gui.OSCommand.VsCodeOpenFile)
} }
func (gui *Gui) handleRefreshFiles(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleRefreshFiles(g *gocui.Gui, v *gocui.View) error {
@ -250,13 +256,13 @@ func (gui *Gui) handleRefreshFiles(g *gocui.Gui, v *gocui.View) error {
func (gui *Gui) refreshStateFiles() { func (gui *Gui) refreshStateFiles() {
// get files to stage // get files to stage
files := getGitStatusFiles() files := gui.GitCommand.GetStatusFiles()
gui.State.Files = mergeGitStatusFiles(gui.State.Files, files) gui.State.Files = gui.GitCommand.MergeStatusFiles(gui.State.Files, files)
updateHasMergeConflictStatus() gui.updateHasMergeConflictStatus()
} }
func (gui *Gui) updateHasMergeConflictStatus() error { func (gui *Gui) updateHasMergeConflictStatus() error {
merging, err := isInMergeState() merging, err := gui.GitCommand.IsInMergeState()
if err != nil { if err != nil {
return err return err
} }
@ -290,7 +296,7 @@ func (gui *Gui) catSelectedFile(g *gocui.Gui) (string, error) {
} }
return "", gui.renderString(g, "main", "No file to display") return "", gui.renderString(g, "main", "No file to display")
} }
cat, err := catFile(item.Name) cat, err := gui.GitCommand.CatFile(item.Name)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -302,12 +308,12 @@ func (gui *Gui) refreshFiles(g *gocui.Gui) error {
if err != nil { if err != nil {
return err return err
} }
refreshStateFiles() gui.refreshStateFiles()
filesView.Clear() filesView.Clear()
for _, file := range gui.State.Files { for _, file := range gui.State.Files {
renderFile(file, filesView) gui.renderFile(file, filesView)
} }
correctCursor(filesView) gui.correctCursor(filesView)
if filesView == g.CurrentView() { if filesView == g.CurrentView() {
gui.handleFileSelect(g, filesView) gui.handleFileSelect(g, filesView)
} }
@ -315,14 +321,14 @@ func (gui *Gui) refreshFiles(g *gocui.Gui) error {
} }
func (gui *Gui) pullFiles(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) pullFiles(g *gocui.Gui, v *gocui.View) error {
createMessagePanel(g, v, "", "Pulling...") gui.createMessagePanel(g, v, "", "Pulling...")
go func() { go func() {
if output, err := gitPull(); err != nil { if output, err := gui.GitCommand.Pull(); err != nil {
gui.createErrorPanel(g, output) gui.createErrorPanel(g, output)
} else { } else {
gui.closeConfirmationPrompt(g) gui.closeConfirmationPrompt(g)
refreshCommits(g) gui.refreshCommits(g)
refreshStatus(g) gui.refreshStatus(g)
} }
gui.refreshFiles(g) gui.refreshFiles(g)
}() }()
@ -330,15 +336,15 @@ func (gui *Gui) pullFiles(g *gocui.Gui, v *gocui.View) error {
} }
func (gui *Gui) pushFiles(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) pushFiles(g *gocui.Gui, v *gocui.View) error {
createMessagePanel(g, v, "", "Pushing...") gui.createMessagePanel(g, v, "", "Pushing...")
go func() { go func() {
branchName = gui.State.Branches[0].Name branchName := gui.State.Branches[0].Name
if output, err := commands.Push(branchName); err != nil { if output, err := gui.GitCommand.Push(branchName); err != nil {
gui.createErrorPanel(g, output) gui.createErrorPanel(g, output)
} else { } else {
gui.closeConfirmationPrompt(g) gui.closeConfirmationPrompt(g)
refreshCommits(g) gui.refreshCommits(g)
refreshStatus(g) gui.refreshStatus(g)
} }
}() }()
return nil return nil
@ -360,22 +366,22 @@ func (gui *Gui) handleSwitchToMerge(g *gocui.Gui, v *gocui.View) error {
return gui.createErrorPanel(g, "This file has no merge conflicts") return gui.createErrorPanel(g, "This file has no merge conflicts")
} }
gui.switchFocus(g, v, mergeView) gui.switchFocus(g, v, mergeView)
return refreshMergePanel(g) return gui.refreshMergePanel(g)
} }
func (gui *Gui) handleAbortMerge(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleAbortMerge(g *gocui.Gui, v *gocui.View) error {
output, err := gitAbortMerge() output, err := gui.GitCommand.AbortMerge()
if err != nil { if err != nil {
return gui.createErrorPanel(g, output) return gui.createErrorPanel(g, output)
} }
createMessagePanel(g, v, "", "Merge aborted") gui.createMessagePanel(g, v, "", "Merge aborted")
refreshStatus(g) gui.refreshStatus(g)
return gui.refreshFiles(g) return gui.refreshFiles(g)
} }
func (gui *Gui) handleResetHard(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleResetHard(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(g, v, "Clear file panel", "Are you sure you want `reset --hard HEAD`? You may lose changes", func(g *gocui.Gui, v *gocui.View) error { return gui.createConfirmationPanel(g, v, "Clear file panel", "Are you sure you want `reset --hard HEAD`? You may lose changes", func(g *gocui.Gui, v *gocui.View) error {
if err := commands.ResetHard(); err != nil { if err := gui.GitCommand.ResetHard(); err != nil {
gui.createErrorPanel(g, err.Error()) gui.createErrorPanel(g, err.Error())
} }
return gui.refreshFiles(g) return gui.refreshFiles(g)

View file

@ -37,12 +37,27 @@ type Gui struct {
OSCommand *commands.OSCommand OSCommand *commands.OSCommand
Version string Version string
SubProcess *exec.Cmd SubProcess *exec.Cmd
State StateType State guiState
}
type guiState struct {
Files []commands.File
Branches []commands.Branch
Commits []commands.Commit
StashEntries []commands.StashEntry
PreviousView string
HasMergeConflicts bool
ConflictIndex int
ConflictTop bool
Conflicts []commands.Conflict
EditHistory *stack.Stack
Platform platform
Version string
} }
// NewGui builds a new gui handler // NewGui builds a new gui handler
func NewGui(log *logrus.Logger, gitCommand *commands.GitCommand, oSCommand *commands.OSCommand, version string) (*Gui, error) { func NewGui(log *logrus.Logger, gitCommand *commands.GitCommand, oSCommand *commands.OSCommand, version string) (*Gui, error) {
initialState := StateType{ initialState := guiState{
Files: make([]commands.File, 0), Files: make([]commands.File, 0),
PreviousView: "files", PreviousView: "files",
Commits: make([]commands.Commit, 0), Commits: make([]commands.Commit, 0),
@ -64,21 +79,6 @@ func NewGui(log *logrus.Logger, gitCommand *commands.GitCommand, oSCommand *comm
}, nil }, nil
} }
type StateType struct {
Files []commands.File
Branches []commands.Branch
Commits []commands.Commit
StashEntries []commands.StashEntry
PreviousView string
HasMergeConflicts bool
ConflictIndex int
ConflictTop bool
Conflicts []commands.Conflict
EditHistory *stack.Stack
Platform platform
Version string
}
type platform struct { type platform struct {
os string os string
shell string shell string
@ -105,7 +105,7 @@ func getPlatform() platform {
} }
} }
func scrollUpMain(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) scrollUpMain(g *gocui.Gui, v *gocui.View) error {
mainView, _ := g.View("main") mainView, _ := g.View("main")
ox, oy := mainView.Origin() ox, oy := mainView.Origin()
if oy >= 1 { if oy >= 1 {
@ -114,7 +114,7 @@ func scrollUpMain(g *gocui.Gui, v *gocui.View) error {
return nil return nil
} }
func scrollDownMain(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) scrollDownMain(g *gocui.Gui, v *gocui.View) error {
mainView, _ := g.View("main") mainView, _ := g.View("main")
ox, oy := mainView.Origin() ox, oy := mainView.Origin()
if oy < len(mainView.BufferLines()) { if oy < len(mainView.BufferLines()) {
@ -123,8 +123,8 @@ func scrollDownMain(g *gocui.Gui, v *gocui.View) error {
return nil return nil
} }
func handleRefresh(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleRefresh(g *gocui.Gui, v *gocui.View) error {
return refreshSidePanels(g) return gui.refreshSidePanels(g)
} }
func max(a, b int) int { func max(a, b int) int {
@ -257,35 +257,35 @@ func (gui *Gui) layout(g *gocui.Gui) error {
// these are only called once // these are only called once
gui.handleFileSelect(g, filesView) gui.handleFileSelect(g, filesView)
gui.refreshFiles(g) gui.refreshFiles(g)
refreshBranches(g) gui.refreshBranches(g)
refreshCommits(g) gui.refreshCommits(g)
refreshStashEntries(g) gui.refreshStashEntries(g)
nextView(g, nil) gui.nextView(g, nil)
} }
resizePopupPanels(g) gui.resizePopupPanels(g)
return nil return nil
} }
func fetch(g *gocui.Gui) error { func (gui *Gui) fetch(g *gocui.Gui) error {
gitFetch() gui.GitCommand.Fetch()
refreshStatus(g) gui.refreshStatus(g)
return nil return nil
} }
func updateLoader(g *gocui.Gui) error { func (gui *Gui) updateLoader(g *gocui.Gui) error {
if confirmationView, _ := g.View("confirmation"); confirmationView != nil { if confirmationView, _ := g.View("confirmation"); confirmationView != nil {
content := gui.trimmedContent(confirmationView) content := gui.trimmedContent(confirmationView)
if strings.Contains(content, "...") { if strings.Contains(content, "...") {
staticContent := strings.Split(content, "...")[0] + "..." staticContent := strings.Split(content, "...")[0] + "..."
gui.renderString(g, "confirmation", staticContent+" "+loader()) gui.renderString(g, "confirmation", staticContent+" "+gui.loader())
} }
} }
return nil return nil
} }
func goEvery(g *gocui.Gui, interval time.Duration, function func(*gocui.Gui) error) { func (gui *Gui) goEvery(g *gocui.Gui, interval time.Duration, function func(*gocui.Gui) error) {
go func() { go func() {
for range time.Tick(interval) { for range time.Tick(interval) {
function(g) function(g)
@ -293,36 +293,36 @@ func goEvery(g *gocui.Gui, interval time.Duration, function func(*gocui.Gui) err
}() }()
} }
func resizePopupPanels(g *gocui.Gui) error { func (gui *Gui) resizePopupPanels(g *gocui.Gui) error {
v := g.CurrentView() v := g.CurrentView()
if v.Name() == "commitMessage" || v.Name() == "confirmation" { if v.Name() == "commitMessage" || v.Name() == "confirmation" {
return resizePopupPanel(g, v) return gui.resizePopupPanel(g, v)
} }
return nil return nil
} }
// Run setup the gui with keybindings and start the mainloop // Run setup the gui with keybindings and start the mainloop
func (gui *Gui) Run() (*exec.Cmd, error) { func (gui *Gui) Run() error {
g, err := gocui.NewGui(gocui.OutputNormal, OverlappingEdges) g, err := gocui.NewGui(gocui.OutputNormal, OverlappingEdges)
if err != nil { if err != nil {
return nil, err return err
} }
defer g.Close() defer g.Close()
g.FgColor = gocui.ColorDefault g.FgColor = gocui.ColorDefault
goEvery(g, time.Second*60, fetch) gui.goEvery(g, time.Second*60, gui.fetch)
goEvery(g, time.Second*10, gui.refreshFiles) gui.goEvery(g, time.Second*10, gui.refreshFiles)
goEvery(g, time.Millisecond*10, updateLoader) gui.goEvery(g, time.Millisecond*10, gui.updateLoader)
g.SetManagerFunc(gui.layout) g.SetManagerFunc(gui.layout)
if err = gui.keybindings(g); err != nil { if err = gui.keybindings(g); err != nil {
return nil, err return err
} }
err = g.MainLoop() err = g.MainLoop()
return nil, err return err
} }
// RunWithSubprocesses loops, instantiating a new gocui.Gui with each iteration // RunWithSubprocesses loops, instantiating a new gocui.Gui with each iteration
@ -342,6 +342,6 @@ func (gui *Gui) RunWithSubprocesses() {
} }
} }
func quit(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) quit(g *gocui.Gui, v *gocui.View) error {
return gocui.ErrQuit return gocui.ErrQuit
} }

View file

@ -70,15 +70,15 @@ func (gui *Gui) keybindings(g *gocui.Gui) error {
// input in the confirmation panel // input in the confirmation panel
for _, viewName := range []string{"files", "branches", "commits", "stash"} { for _, viewName := range []string{"files", "branches", "commits", "stash"} {
bindings = append(bindings, []Binding{ bindings = append(bindings, []Binding{
{ViewName: viewName, Key: gocui.KeyTab, Modifier: gocui.ModNone, Handler: nextView}, {ViewName: viewName, Key: gocui.KeyTab, Modifier: gocui.ModNone, Handler: gui.nextView},
{ViewName: viewName, Key: gocui.KeyArrowLeft, Modifier: gocui.ModNone, Handler: previousView}, {ViewName: viewName, Key: gocui.KeyArrowLeft, Modifier: gocui.ModNone, Handler: gui.previousView},
{ViewName: viewName, Key: gocui.KeyArrowRight, Modifier: gocui.ModNone, Handler: nextView}, {ViewName: viewName, Key: gocui.KeyArrowRight, Modifier: gocui.ModNone, Handler: gui.nextView},
{ViewName: viewName, Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: cursorUp}, {ViewName: viewName, Key: gocui.KeyArrowUp, Modifier: gocui.ModNone, Handler: gui.cursorUp},
{ViewName: viewName, Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: cursorDown}, {ViewName: viewName, Key: gocui.KeyArrowDown, Modifier: gocui.ModNone, Handler: gui.cursorDown},
{ViewName: viewName, Key: 'h', Modifier: gocui.ModNone, Handler: previousView}, {ViewName: viewName, Key: 'h', Modifier: gocui.ModNone, Handler: gui.previousView},
{ViewName: viewName, Key: 'l', Modifier: gocui.ModNone, Handler: nextView}, {ViewName: viewName, Key: 'l', Modifier: gocui.ModNone, Handler: gui.nextView},
{ViewName: viewName, Key: 'k', Modifier: gocui.ModNone, Handler: cursorUp}, {ViewName: viewName, Key: 'k', Modifier: gocui.ModNone, Handler: gui.cursorUp},
{ViewName: viewName, Key: 'j', Modifier: gocui.ModNone, Handler: cursorDown}, {ViewName: viewName, Key: 'j', Modifier: gocui.ModNone, Handler: gui.cursorDown},
}...) }...)
} }

View file

@ -16,89 +16,89 @@ import (
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
) )
func findConflicts(content string) ([]commands.Conflict, error) { func (gui *Gui) findConflicts(content string) ([]commands.Conflict, error) {
conflicts := make([]commands.Conflict, 0) conflicts := make([]commands.Conflict, 0)
var newConflict conflict var newConflict commands.Conflict
for i, line := range utils.SplitLines(content) { for i, line := range utils.SplitLines(content) {
if line == "<<<<<<< HEAD" || line == "<<<<<<< MERGE_HEAD" || line == "<<<<<<< Updated upstream" { if line == "<<<<<<< HEAD" || line == "<<<<<<< MERGE_HEAD" || line == "<<<<<<< Updated upstream" {
newConflict = conflict{start: i} newConflict = commands.Conflict{Start: i}
} else if line == "=======" { } else if line == "=======" {
newConflict.middle = i newConflict.Middle = i
} else if strings.HasPrefix(line, ">>>>>>> ") { } else if strings.HasPrefix(line, ">>>>>>> ") {
newConflict.end = i newConflict.End = i
conflicts = append(conflicts, newConflict) conflicts = append(conflicts, newConflict)
} }
} }
return conflicts, nil return conflicts, nil
} }
func shiftConflict(conflicts []commands.Conflict) (commands.Conflict, []commands.Conflict) { func (gui *Gui) shiftConflict(conflicts []commands.Conflict) (commands.Conflict, []commands.Conflict) {
return conflicts[0], conflicts[1:] return conflicts[0], conflicts[1:]
} }
func shouldHighlightLine(index int, conflict commands.Conflict, top bool) bool { func (gui *Gui) shouldHighlightLine(index int, conflict commands.Conflict, top bool) bool {
return (index >= conflict.start && index <= conflict.middle && top) || (index >= conflict.middle && index <= conflict.end && !top) return (index >= conflict.Start && index <= conflict.Middle && top) || (index >= conflict.Middle && index <= conflict.End && !top)
} }
func coloredConflictFile(content string, conflicts []commands.Conflict, conflictIndex int, conflictTop, hasFocus bool) (string, error) { func (gui *Gui) coloredConflictFile(content string, conflicts []commands.Conflict, conflictIndex int, conflictTop, hasFocus bool) (string, error) {
if len(conflicts) == 0 { if len(conflicts) == 0 {
return content, nil return content, nil
} }
conflict, remainingConflicts := shiftConflict(conflicts) conflict, remainingConflicts := gui.shiftConflict(conflicts)
var outputBuffer bytes.Buffer var outputBuffer bytes.Buffer
for i, line := range splitLines(content) { for i, line := range utils.SplitLines(content) {
colourAttr := color.FgWhite colourAttr := color.FgWhite
if i == conflict.start || i == conflict.middle || i == conflict.end { if i == conflict.Start || i == conflict.Middle || i == conflict.End {
colourAttr = color.FgRed colourAttr = color.FgRed
} }
colour := color.New(colourAttr) colour := color.New(colourAttr)
if hasFocus && conflictIndex < len(conflicts) && conflicts[conflictIndex] == conflict && shouldHighlightLine(i, conflict, conflictTop) { if hasFocus && conflictIndex < len(conflicts) && conflicts[conflictIndex] == conflict && gui.shouldHighlightLine(i, conflict, conflictTop) {
colour.Add(color.Bold) colour.Add(color.Bold)
} }
if i == conflict.end && len(remainingConflicts) > 0 { if i == conflict.End && len(remainingConflicts) > 0 {
conflict, remainingConflicts = shiftConflict(remainingConflicts) conflict, remainingConflicts = gui.shiftConflict(remainingConflicts)
} }
outputBuffer.WriteString(coloredStringDirect(line, colour) + "\n") outputBuffer.WriteString(utils.ColoredStringDirect(line, colour) + "\n")
} }
return outputBuffer.String(), nil return outputBuffer.String(), nil
} }
func handleSelectTop(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleSelectTop(g *gocui.Gui, v *gocui.View) error {
state.ConflictTop = true gui.State.ConflictTop = true
return refreshMergePanel(g) return gui.refreshMergePanel(g)
} }
func handleSelectBottom(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleSelectBottom(g *gocui.Gui, v *gocui.View) error {
state.ConflictTop = false gui.State.ConflictTop = false
return refreshMergePanel(g) return gui.refreshMergePanel(g)
} }
func handleSelectNextConflict(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleSelectNextConflict(g *gocui.Gui, v *gocui.View) error {
if state.ConflictIndex >= len(state.Conflicts)-1 { if gui.State.ConflictIndex >= len(gui.State.Conflicts)-1 {
return nil return nil
} }
state.ConflictIndex++ gui.State.ConflictIndex++
return refreshMergePanel(g) return gui.refreshMergePanel(g)
} }
func handleSelectPrevConflict(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleSelectPrevConflict(g *gocui.Gui, v *gocui.View) error {
if state.ConflictIndex <= 0 { if gui.State.ConflictIndex <= 0 {
return nil return nil
} }
state.ConflictIndex-- gui.State.ConflictIndex--
return refreshMergePanel(g) return gui.refreshMergePanel(g)
} }
func isIndexToDelete(i int, conflict commands.Conflict, pick string) bool { func (gui *Gui) isIndexToDelete(i int, conflict commands.Conflict, pick string) bool {
return i == conflict.middle || return i == conflict.Middle ||
i == conflict.start || i == conflict.Start ||
i == conflict.end || i == conflict.End ||
pick != "both" && pick != "both" &&
(pick == "bottom" && i > conflict.start && i < conflict.middle) || (pick == "bottom" && i > conflict.Start && i < conflict.Middle) ||
(pick == "top" && i > conflict.middle && i < conflict.end) (pick == "top" && i > conflict.Middle && i < conflict.End)
} }
func resolveConflict(g *gocui.Gui, conflict commands.Conflict, pick string) error { func (gui *Gui) resolveConflict(g *gocui.Gui, conflict commands.Conflict, pick string) error {
gitFile, err := gui.getSelectedFile(g) gitFile, err := gui.getSelectedFile(g)
if err != nil { if err != nil {
return err return err
@ -116,126 +116,121 @@ func resolveConflict(g *gocui.Gui, conflict commands.Conflict, pick string) erro
if err != nil { if err != nil {
break break
} }
if !isIndexToDelete(i, conflict, pick) { if !gui.isIndexToDelete(i, conflict, pick) {
output += line output += line
} }
} }
devLog(output) gui.Log.Info(output)
return ioutil.WriteFile(gitFile.Name, []byte(output), 0644) return ioutil.WriteFile(gitFile.Name, []byte(output), 0644)
} }
func pushFileSnapshot(g *gocui.Gui) error { func (gui *Gui) pushFileSnapshot(g *gocui.Gui) error {
gitFile, err := gui.getSelectedFile(g) gitFile, err := gui.getSelectedFile(g)
if err != nil { if err != nil {
return err return err
} }
content, err := catFile(gitFile.Name) content, err := gui.GitCommand.CatFile(gitFile.Name)
if err != nil { if err != nil {
return err return err
} }
state.EditHistory.Push(content) gui.State.EditHistory.Push(content)
return nil return nil
} }
func handlePopFileSnapshot(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handlePopFileSnapshot(g *gocui.Gui, v *gocui.View) error {
if state.EditHistory.Len() == 0 { if gui.State.EditHistory.Len() == 0 {
return nil return nil
} }
prevContent := state.EditHistory.Pop().(string) prevContent := gui.State.EditHistory.Pop().(string)
gitFile, err := gui.getSelectedFile(g) gitFile, err := gui.getSelectedFile(g)
if err != nil { if err != nil {
return err return err
} }
ioutil.WriteFile(gitFile.Name, []byte(prevContent), 0644) ioutil.WriteFile(gitFile.Name, []byte(prevContent), 0644)
return refreshMergePanel(g) return gui.refreshMergePanel(g)
} }
func handlePickHunk(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handlePickHunk(g *gocui.Gui, v *gocui.View) error {
conflict := state.Conflicts[state.ConflictIndex] conflict := gui.State.Conflicts[gui.State.ConflictIndex]
pushFileSnapshot(g) gui.pushFileSnapshot(g)
pick := "bottom" pick := "bottom"
if state.ConflictTop { if gui.State.ConflictTop {
pick = "top" pick = "top"
} }
err := resolveConflict(g, conflict, pick) err := gui.resolveConflict(g, conflict, pick)
if err != nil { if err != nil {
panic(err) panic(err)
} }
refreshMergePanel(g) gui.refreshMergePanel(g)
return nil return nil
} }
func handlePickBothHunks(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handlePickBothHunks(g *gocui.Gui, v *gocui.View) error {
conflict := state.Conflicts[state.ConflictIndex] conflict := gui.State.Conflicts[gui.State.ConflictIndex]
pushFileSnapshot(g) gui.pushFileSnapshot(g)
err := resolveConflict(g, conflict, "both") err := gui.resolveConflict(g, conflict, "both")
if err != nil { if err != nil {
panic(err) panic(err)
} }
return refreshMergePanel(g) return gui.refreshMergePanel(g)
} }
func currentViewName(g *gocui.Gui) string { func (gui *Gui) refreshMergePanel(g *gocui.Gui) error {
currentView := g.CurrentView() cat, err := gui.catSelectedFile(g)
return currentView.Name()
}
func refreshMergePanel(g *gocui.Gui) error {
cat, err := catSelectedFile(g)
if err != nil { if err != nil {
return err return err
} }
state.Conflicts, err = findConflicts(cat) gui.State.Conflicts, err = gui.findConflicts(cat)
if err != nil { if err != nil {
return err return err
} }
if len(state.Conflicts) == 0 { if len(gui.State.Conflicts) == 0 {
return handleCompleteMerge(g) return gui.handleCompleteMerge(g)
} else if state.ConflictIndex > len(state.Conflicts)-1 { } else if gui.State.ConflictIndex > len(gui.State.Conflicts)-1 {
state.ConflictIndex = len(state.Conflicts) - 1 gui.State.ConflictIndex = len(gui.State.Conflicts) - 1
} }
hasFocus := currentViewName(g) == "main" hasFocus := gui.currentViewName(g) == "main"
if hasFocus { if hasFocus {
renderMergeOptions(g) gui.renderMergeOptions(g)
} }
content, err := coloredConflictFile(cat, state.Conflicts, state.ConflictIndex, state.ConflictTop, hasFocus) content, err := gui.coloredConflictFile(cat, gui.State.Conflicts, gui.State.ConflictIndex, gui.State.ConflictTop, hasFocus)
if err != nil { if err != nil {
return err return err
} }
if err := scrollToConflict(g); err != nil { if err := gui.scrollToConflict(g); err != nil {
return err return err
} }
return gui.renderString(g, "main", content) return gui.renderString(g, "main", content)
} }
func scrollToConflict(g *gocui.Gui) error { func (gui *Gui) scrollToConflict(g *gocui.Gui) error {
mainView, err := g.View("main") mainView, err := g.View("main")
if err != nil { if err != nil {
return err return err
} }
if len(state.Conflicts) == 0 { if len(gui.State.Conflicts) == 0 {
return nil return nil
} }
conflict := state.Conflicts[state.ConflictIndex] conflict := gui.State.Conflicts[gui.State.ConflictIndex]
ox, _ := mainView.Origin() ox, _ := mainView.Origin()
_, height := mainView.Size() _, height := mainView.Size()
conflictMiddle := (conflict.end + conflict.start) / 2 conflictMiddle := (conflict.End + conflict.Start) / 2
newOriginY := int(math.Max(0, float64(conflictMiddle-(height/2)))) newOriginY := int(math.Max(0, float64(conflictMiddle-(height/2))))
return mainView.SetOrigin(ox, newOriginY) return mainView.SetOrigin(ox, newOriginY)
} }
func switchToMerging(g *gocui.Gui) error { func (gui *Gui) switchToMerging(g *gocui.Gui) error {
state.ConflictIndex = 0 gui.State.ConflictIndex = 0
state.ConflictTop = true gui.State.ConflictTop = true
_, err := g.SetCurrentView("main") _, err := g.SetCurrentView("main")
if err != nil { if err != nil {
return err return err
} }
return refreshMergePanel(g) return gui.refreshMergePanel(g)
} }
func renderMergeOptions(g *gocui.Gui) error { func (gui *Gui) renderMergeOptions(g *gocui.Gui) error {
return gui.renderOptionsMap(g, map[string]string{ return gui.renderOptionsMap(g, map[string]string{
"↑ ↓": "select hunk", "↑ ↓": "select hunk",
"← →": "navigate conflicts", "← →": "navigate conflicts",
@ -245,7 +240,7 @@ func renderMergeOptions(g *gocui.Gui) error {
}) })
} }
func handleEscapeMerge(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleEscapeMerge(g *gocui.Gui, v *gocui.View) error {
filesView, err := g.View("files") filesView, err := g.View("files")
if err != nil { if err != nil {
return err return err
@ -254,12 +249,12 @@ func handleEscapeMerge(g *gocui.Gui, v *gocui.View) error {
return gui.switchFocus(g, v, filesView) return gui.switchFocus(g, v, filesView)
} }
func handleCompleteMerge(g *gocui.Gui) error { func (gui *Gui) handleCompleteMerge(g *gocui.Gui) error {
filesView, err := g.View("files") filesView, err := g.View("files")
if err != nil { if err != nil {
return err return err
} }
stageSelectedFile(g) gui.stageSelectedFile(g)
gui.refreshFiles(g) gui.refreshFiles(g)
return gui.switchFocus(g, nil, filesView) return gui.switchFocus(g, nil, filesView)
} }

View file

@ -4,17 +4,18 @@ import (
"fmt" "fmt"
"github.com/jesseduffield/gocui" "github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands"
) )
func refreshStashEntries(g *gocui.Gui) error { func (gui *Gui) refreshStashEntries(g *gocui.Gui) error {
g.Update(func(g *gocui.Gui) error { g.Update(func(g *gocui.Gui) error {
v, err := g.View("stash") v, err := g.View("stash")
if err != nil { if err != nil {
panic(err) panic(err)
} }
state.StashEntries = getGitStashEntries() gui.State.StashEntries = gui.GitCommand.GetStashEntries()
v.Clear() v.Clear()
for _, stashEntry := range state.StashEntries { for _, stashEntry := range gui.State.StashEntries {
fmt.Fprintln(v, stashEntry.DisplayString) fmt.Fprintln(v, stashEntry.DisplayString)
} }
return gui.resetOrigin(v) return gui.resetOrigin(v)
@ -22,15 +23,15 @@ func refreshStashEntries(g *gocui.Gui) error {
return nil return nil
} }
func getSelectedStashEntry(v *gocui.View) *StashEntry { func (gui *Gui) getSelectedStashEntry(v *gocui.View) *commands.StashEntry {
if len(state.StashEntries) == 0 { if len(gui.State.StashEntries) == 0 {
return nil return nil
} }
lineNumber := gui.getItemPosition(v) lineNumber := gui.getItemPosition(v)
return &state.StashEntries[lineNumber] return &gui.State.StashEntries[lineNumber]
} }
func renderStashOptions(g *gocui.Gui) error { func (gui *Gui) renderStashOptions(g *gocui.Gui) error {
return gui.renderOptionsMap(g, map[string]string{ return gui.renderOptionsMap(g, map[string]string{
"space": "apply", "space": "apply",
"g": "pop", "g": "pop",
@ -39,54 +40,54 @@ func renderStashOptions(g *gocui.Gui) error {
}) })
} }
func handleStashEntrySelect(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleStashEntrySelect(g *gocui.Gui, v *gocui.View) error {
if err := renderStashOptions(g); err != nil { if err := gui.renderStashOptions(g); err != nil {
return err return err
} }
go func() { go func() {
stashEntry := getSelectedStashEntry(v) stashEntry := gui.getSelectedStashEntry(v)
if stashEntry == nil { if stashEntry == nil {
gui.renderString(g, "main", "No stash entries") gui.renderString(g, "main", "No stash entries")
return return
} }
diff, _ := getStashEntryDiff(stashEntry.Index) diff, _ := gui.GitCommand.GetStashEntryDiff(stashEntry.Index)
gui.renderString(g, "main", diff) gui.renderString(g, "main", diff)
}() }()
return nil return nil
} }
func handleStashApply(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleStashApply(g *gocui.Gui, v *gocui.View) error {
return stashDo(g, v, "apply") return gui.stashDo(g, v, "apply")
} }
func handleStashPop(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleStashPop(g *gocui.Gui, v *gocui.View) error {
return stashDo(g, v, "pop") return gui.stashDo(g, v, "pop")
} }
func handleStashDrop(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) handleStashDrop(g *gocui.Gui, v *gocui.View) error {
return gui.createConfirmationPanel(g, v, "Stash drop", "Are you sure you want to drop this stash entry?", func(g *gocui.Gui, v *gocui.View) error { return gui.createConfirmationPanel(g, v, "Stash drop", "Are you sure you want to drop this stash entry?", func(g *gocui.Gui, v *gocui.View) error {
return stashDo(g, v, "drop") return gui.stashDo(g, v, "drop")
}, nil) }, nil)
} }
func stashDo(g *gocui.Gui, v *gocui.View, method string) error { func (gui *Gui) stashDo(g *gocui.Gui, v *gocui.View, method string) error {
stashEntry := getSelectedStashEntry(v) stashEntry := gui.getSelectedStashEntry(v)
if stashEntry == nil { if stashEntry == nil {
return gui.createErrorPanel(g, "No stash to "+method) return gui.createErrorPanel(g, "No stash to "+method)
} }
if output, err := gitStashDo(stashEntry.Index, method); err != nil { if output, err := gui.GitCommand.StashDo(stashEntry.Index, method); err != nil {
gui.createErrorPanel(g, output) gui.createErrorPanel(g, output)
} }
refreshStashEntries(g) gui.refreshStashEntries(g)
return gui.refreshFiles(g) return gui.refreshFiles(g)
} }
func handleStashSave(g *gocui.Gui, filesView *gocui.View) error { func (gui *Gui) handleStashSave(g *gocui.Gui, filesView *gocui.View) error {
gui.createPromptPanel(g, filesView, "Stash changes", func(g *gocui.Gui, v *gocui.View) error { gui.createPromptPanel(g, filesView, "Stash changes", func(g *gocui.Gui, v *gocui.View) error {
if output, err := gitStashSave(gui.trimmedContent(v)); err != nil { if output, err := gui.GitCommand.StashSave(gui.trimmedContent(v)); err != nil {
gui.createErrorPanel(g, output) gui.createErrorPanel(g, output)
} }
refreshStashEntries(g) gui.refreshStashEntries(g)
return gui.refreshFiles(g) return gui.refreshFiles(g)
}) })
return nil return nil

View file

@ -5,9 +5,10 @@ import (
"github.com/fatih/color" "github.com/fatih/color"
"github.com/jesseduffield/gocui" "github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/utils"
) )
func refreshStatus(g *gocui.Gui) error { func (gui *Gui) refreshStatus(g *gocui.Gui) error {
v, err := g.View("status") v, err := g.View("status")
if err != nil { if err != nil {
panic(err) panic(err)
@ -17,22 +18,22 @@ func refreshStatus(g *gocui.Gui) error {
// contents end up cleared // contents end up cleared
g.Update(func(*gocui.Gui) error { g.Update(func(*gocui.Gui) error {
v.Clear() v.Clear()
pushables, pullables := git.UpstreamDifferenceCount() pushables, pullables := gui.GitCommand.UpstreamDifferenceCount()
fmt.Fprint(v, "↑"+pushables+"↓"+pullables) fmt.Fprint(v, "↑"+pushables+"↓"+pullables)
branches := state.Branches branches := gui.State.Branches
if err := updateHasMergeConflictStatus(); err != nil { if err := gui.updateHasMergeConflictStatus(); err != nil {
return err return err
} }
if state.HasMergeConflicts { if gui.State.HasMergeConflicts {
fmt.Fprint(v, coloredString(" (merging)", color.FgYellow)) fmt.Fprint(v, utils.ColoredString(" (merging)", color.FgYellow))
} }
if len(branches) == 0 { if len(branches) == 0 {
return nil return nil
} }
branch := branches[0] branch := branches[0]
name := coloredString(branch.Name, branch.getColor()) name := utils.ColoredString(branch.Name, branch.GetColor())
repo := getCurrentProject() repo := utils.GetCurrentRepoName()
fmt.Fprint(v, " "+repo+" → "+name) fmt.Fprint(v, " "+repo+" → "+name)
return nil return nil
}) })

View file

@ -13,7 +13,7 @@ var cyclableViews = []string{"files", "branches", "commits", "stash"}
func (gui *Gui) refreshSidePanels(g *gocui.Gui) error { func (gui *Gui) refreshSidePanels(g *gocui.Gui) error {
gui.refreshBranches(g) gui.refreshBranches(g)
gui.gui.refreshFiles(g) gui.refreshFiles(g)
gui.refreshCommits(g) gui.refreshCommits(g)
return nil return nil
} }
@ -38,7 +38,7 @@ func (gui *Gui) nextView(g *gocui.Gui, v *gocui.View) error {
if err != nil { if err != nil {
panic(err) panic(err)
} }
return gui.gui.switchFocus(g, v, focusedView) return gui.switchFocus(g, v, focusedView)
} }
func (gui *Gui) previousView(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) previousView(g *gocui.Gui, v *gocui.View) error {
@ -52,7 +52,7 @@ func (gui *Gui) previousView(g *gocui.Gui, v *gocui.View) error {
break break
} }
if i == len(cyclableViews)-1 { if i == len(cyclableViews)-1 {
devLog(v.Name() + " is not in the list of views") gui.Log.Info(v.Name() + " is not in the list of views")
return nil return nil
} }
} }
@ -72,27 +72,27 @@ func (gui *Gui) newLineFocused(g *gocui.Gui, v *gocui.View) error {
case "files": case "files":
return gui.handleFileSelect(g, v) return gui.handleFileSelect(g, v)
case "branches": case "branches":
return handleBranchSelect(g, v) return gui.handleBranchSelect(g, v)
case "confirmation": case "confirmation":
return nil return nil
case "commitMessage": case "commitMessage":
return handleCommitFocused(g, v) return gui.handleCommitFocused(g, v)
case "main": case "main":
// TODO: pull this out into a 'view focused' function // TODO: pull this out into a 'view focused' function
refreshMergePanel(g) gui.refreshMergePanel(g)
v.Highlight = false v.Highlight = false
return nil return nil
case "commits": case "commits":
return handleCommitSelect(g, v) return gui.handleCommitSelect(g, v)
case "stash": case "stash":
return handleStashEntrySelect(g, v) return gui.handleStashEntrySelect(g, v)
default: default:
panic("No view matching newLineFocused switch statement") panic("No view matching newLineFocused switch statement")
} }
} }
func (gui *Gui) returnFocus(g *gocui.Gui, v *gocui.View) error { func (gui *Gui) returnFocus(g *gocui.Gui, v *gocui.View) error {
previousView, err := g.View(state.PreviousView) previousView, err := g.View(gui.State.PreviousView)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -105,16 +105,16 @@ func (gui *Gui) switchFocus(g *gocui.Gui, oldView, newView *gocui.View) error {
// we should never stack confirmation panels // we should never stack confirmation panels
if oldView != nil && oldView.Name() != "confirmation" { if oldView != nil && oldView.Name() != "confirmation" {
oldView.Highlight = false oldView.Highlight = false
devLog("setting previous view to:", oldView.Name()) gui.Log.Info("setting previous view to:", oldView.Name())
state.PreviousView = oldView.Name() gui.State.PreviousView = oldView.Name()
} }
newView.Highlight = true newView.Highlight = true
devLog("new focused view is " + newView.Name()) gui.Log.Info("new focused view is " + newView.Name())
if _, err := g.SetCurrentView(newView.Name()); err != nil { if _, err := g.SetCurrentView(newView.Name()); err != nil {
return err return err
} }
g.Cursor = newView.Editable g.Cursor = newView.Editable
return newLineFocused(g, newView) return gui.newLineFocused(g, newView)
} }
func (gui *Gui) getItemPosition(v *gocui.View) int { func (gui *Gui) getItemPosition(v *gocui.View) int {
@ -138,7 +138,7 @@ func (gui *Gui) cursorUp(g *gocui.Gui, v *gocui.View) error {
} }
} }
newLineFocused(g, v) gui.newLineFocused(g, v)
return nil return nil
} }
@ -159,7 +159,7 @@ func (gui *Gui) cursorDown(g *gocui.Gui, v *gocui.View) error {
} }
} }
newLineFocused(g, v) gui.newLineFocused(g, v)
return nil return nil
} }
@ -207,7 +207,7 @@ func (gui *Gui) optionsMapToString(optionsMap map[string]string) string {
} }
func (gui *Gui) renderOptionsMap(g *gocui.Gui, optionsMap map[string]string) error { func (gui *Gui) renderOptionsMap(g *gocui.Gui, optionsMap map[string]string) error {
return gui.renderString(g, "options", optionsMapToString(optionsMap)) return gui.renderString(g, "options", gui.optionsMapToString(optionsMap))
} }
func (gui *Gui) loader() string { func (gui *Gui) loader() string {
@ -237,3 +237,8 @@ func (gui *Gui) getCommitMessageView(g *gocui.Gui) *gocui.View {
func (gui *Gui) trimmedContent(v *gocui.View) string { func (gui *Gui) trimmedContent(v *gocui.View) string {
return strings.TrimSpace(v.Buffer()) return strings.TrimSpace(v.Buffer())
} }
func (gui *Gui) currentViewName(g *gocui.Gui) string {
currentView := g.CurrentView()
return currentView.Name()
}

View file

@ -46,8 +46,8 @@ func ColoredStringDirect(str string, colour *color.Color) string {
return colour.SprintFunc()(fmt.Sprint(str)) return colour.SprintFunc()(fmt.Sprint(str))
} }
// GetCurrentProject gets the repo's base name // GetCurrentRepoName gets the repo's base name
func GetCurrentProject() string { func GetCurrentRepoName() string {
pwd, err := os.Getwd() pwd, err := os.Getwd()
if err != nil { if err != nil {
log.Fatalln(err.Error()) log.Fatalln(err.Error())