mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-11 20:36:03 +02:00
got this bad boy compiling again
This commit is contained in:
parent
97cff65612
commit
9e725ae24e
13 changed files with 267 additions and 241 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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},
|
||||||
}...)
|
}...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
})
|
})
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
|
|
@ -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())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue