summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2020-03-03 22:41:35 +1100
committerJesse Duffield <jessedduffield@gmail.com>2020-03-04 00:12:23 +1100
commitb3522c48d9377fec9397581cf2ab439c92590c20 (patch)
treeb6d6be1d6eee091cc4cb6c7a4dc3cc96699a04fb
parent0fc58a79867ae91ce8c0374ecfe95407b621ce55 (diff)
refactor
-rw-r--r--pkg/gui/pty.go53
-rw-r--r--pkg/gui/pty_windows.go13
-rw-r--r--pkg/gui/tasks_adapter.go39
-rw-r--r--pkg/tasks/tasks.go115
4 files changed, 82 insertions, 138 deletions
diff --git a/pkg/gui/pty.go b/pkg/gui/pty.go
index 18fb98fda..39642b7f0 100644
--- a/pkg/gui/pty.go
+++ b/pkg/gui/pty.go
@@ -1,6 +1,10 @@
+// +build !windows
+
package gui
import (
+ "os/exec"
+
"github.com/jesseduffield/pty"
)
@@ -19,3 +23,52 @@ func (gui *Gui) onResize() error {
return nil
}
+
+// Some commands need to output for a terminal to active certain behaviour.
+// For example, git won't invoke the GIT_PAGER env var unless it thinks it's
+// talking to a terminal. We typically write cmd outputs straight to a view,
+// which is just an io.Reader. the pty package lets us wrap a command in a
+// pseudo-terminal meaning we'll get the behaviour we want from the underlying
+// command.
+func (gui *Gui) newPtyTask(viewName string, cmd *exec.Cmd) error {
+ width, _ := gui.getMainView().Size()
+ pager := gui.GitCommand.GetPager(width)
+
+ if pager == "" {
+ // if we're not using a custom pager we don't need to use a pty
+ return gui.newCmdTask(viewName, cmd)
+ }
+
+ cmd.Env = append(cmd.Env, "GIT_PAGER="+pager)
+
+ view, err := gui.g.View(viewName)
+ if err != nil {
+ return nil // swallowing for now
+ }
+
+ _, height := view.Size()
+ _, oy := view.Origin()
+
+ manager := gui.getManager(view)
+
+ ptmx, err := pty.Start(cmd)
+ if err != nil {
+ return err
+ }
+
+ gui.State.Ptmx = ptmx
+ onClose := func() {
+ ptmx.Close()
+ gui.State.Ptmx = nil
+ }
+
+ if err := gui.onResize(); err != nil {
+ return err
+ }
+
+ if err := manager.NewTask(manager.NewCmdTask(ptmx, cmd, height+oy+10, onClose)); err != nil {
+ return err
+ }
+
+ return nil
+}
diff --git a/pkg/gui/pty_windows.go b/pkg/gui/pty_windows.go
new file mode 100644
index 000000000..f5f6110f4
--- /dev/null
+++ b/pkg/gui/pty_windows.go
@@ -0,0 +1,13 @@
+// +build windows
+
+package gui
+
+import "os/exec"
+
+func (gui *Gui) onResize() error {
+ return nil
+}
+
+func (gui *Gui) newPtyTask(viewName string, cmd *exec.Cmd) error {
+ return gui.newCmdTask(viewName, cmd)
+}
diff --git a/pkg/gui/tasks_adapter.go b/pkg/gui/tasks_adapter.go
index fc2b0a3bf..198c11e34 100644
--- a/pkg/gui/tasks_adapter.go
+++ b/pkg/gui/tasks_adapter.go
@@ -5,7 +5,6 @@ import (
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/tasks"
- "github.com/jesseduffield/pty"
)
func (gui *Gui) newCmdTask(viewName string, cmd *exec.Cmd) error {
@@ -19,47 +18,17 @@ func (gui *Gui) newCmdTask(viewName string, cmd *exec.Cmd) error {
manager := gui.getManager(view)
- if err := manager.NewTask(manager.NewCmdTask(cmd, height+oy+10)); err != nil {
- return err
- }
-
- return nil
-}
-
-func (gui *Gui) newPtyTask(viewName string, cmd *exec.Cmd) error {
- width, _ := gui.getMainView().Size()
- pager := gui.GitCommand.GetPager(width)
-
- if pager == "" {
- // if we're not using a custom pager we don't need to use a pty
- return gui.newCmdTask(viewName, cmd)
- }
-
- cmd.Env = append(cmd.Env, "GIT_PAGER="+pager)
-
- view, err := gui.g.View(viewName)
- if err != nil {
- return nil // swallowing for now
- }
-
- _, height := view.Size()
- _, oy := view.Origin()
-
- manager := gui.getManager(view)
-
- ptmx, err := pty.Start(cmd)
+ r, err := cmd.StdoutPipe()
if err != nil {
return err
}
+ cmd.Stderr = cmd.Stdout
- gui.State.Ptmx = ptmx
- onClose := func() { gui.State.Ptmx = nil }
-
- if err := gui.onResize(); err != nil {
+ if err := cmd.Start(); err != nil {
return err
}
- if err := manager.NewTask(manager.NewPtyTask(ptmx, cmd, height+oy+10, onClose)); err != nil {
+ if err := manager.NewTask(manager.NewCmdTask(r, cmd, height+oy+10, nil)); err != nil {
return err
}
diff --git a/pkg/tasks/tasks.go b/pkg/tasks/tasks.go
index 716de488e..853c45fe9 100644
--- a/pkg/tasks/tasks.go
+++ b/pkg/tasks/tasks.go
@@ -4,7 +4,6 @@ import (
"bufio"
"fmt"
"io"
- "os"
"os/exec"
"sync"
"time"
@@ -47,110 +46,16 @@ func (m *ViewBufferManager) ReadLines(n int) {
}()
}
-func (m *ViewBufferManager) NewCmdTask(cmd *exec.Cmd, linesToRead int) func(chan struct{}) error {
+func (m *ViewBufferManager) NewCmdTask(r io.Reader, cmd *exec.Cmd, linesToRead int, onDone func()) func(chan struct{}) error {
return func(stop chan struct{}) error {
- r, err := cmd.StdoutPipe()
- if err != nil {
- return err
- }
- cmd.Stderr = cmd.Stdout
-
- if err := cmd.Start(); err != nil {
- return err
- }
-
go func() {
<-stop
- if cmd.ProcessState == nil {
- if err := commands.Kill(cmd); err != nil {
- m.Log.Warn(err)
- }
- }
- }()
-
- // not sure if it's the right move to redefine this or not
- m.readLines = make(chan int, 1024)
-
- done := make(chan struct{})
-
- go func() {
- scanner := bufio.NewScanner(r)
- scanner.Split(bufio.ScanLines)
-
- loaded := false
-
- go func() {
- ticker := time.NewTicker(time.Millisecond * 100)
- defer ticker.Stop()
- select {
- case <-ticker.C:
- if !loaded {
- m.beforeStart()
- m.writer.Write([]byte("loading..."))
- m.refreshView()
- }
- case <-stop:
- return
- }
- }()
-
- outer:
- for {
- select {
- case linesToRead := <-m.readLines:
- for i := 0; i < linesToRead; i++ {
- ok := scanner.Scan()
- if !loaded {
- m.beforeStart()
- loaded = true
- }
-
- select {
- case <-stop:
- m.refreshView()
- break outer
- default:
- }
- if !ok {
- m.refreshView()
- break outer
- }
- m.writer.Write(append(scanner.Bytes(), []byte("\n")...))
- }
- m.refreshView()
- case <-stop:
- m.refreshView()
- break outer
- }
- }
- m.refreshView()
-
- if err := cmd.Wait(); err != nil {
+ if err := commands.Kill(cmd); err != nil {
m.Log.Warn(err)
}
-
- close(done)
- }()
-
- m.readLines <- linesToRead
-
- <-done
-
- return nil
- }
-}
-
-func (m *ViewBufferManager) NewPtyTask(ptmx *os.File, cmd *exec.Cmd, linesToRead int, onClose func()) func(chan struct{}) error {
- return func(stop chan struct{}) error {
- r := ptmx
-
- defer ptmx.Close()
-
- done := make(chan struct{})
- go func() {
- <-stop
- commands.Kill(cmd)
- ptmx.Close()
+ if onDone != nil {
+ onDone()
+ }
}()
loadingMutex := sync.Mutex{}
@@ -158,6 +63,8 @@ func (m *ViewBufferManager) NewPtyTask(ptmx *os.File, cmd *exec.Cmd, linesToRead
// not sure if it's the right move to redefine this or not
m.readLines = make(chan int, 1024)
+ done := make(chan struct{})
+
go func() {
scanner := bufio.NewScanner(r)
scanner.Split(bufio.ScanLines)
@@ -196,6 +103,7 @@ func (m *ViewBufferManager) NewPtyTask(ptmx *os.File, cmd *exec.Cmd, linesToRead
select {
case <-stop:
+ m.refreshView()
break outer
default:
}
@@ -207,6 +115,7 @@ func (m *ViewBufferManager) NewPtyTask(ptmx *os.File, cmd *exec.Cmd, linesToRead
}
m.refreshView()
case <-stop:
+ m.refreshView()
break outer
}
}
@@ -217,16 +126,16 @@ func (m *ViewBufferManager) NewPtyTask(ptmx *os.File, cmd *exec.Cmd, linesToRead
m.refreshView()
- onClose()
+ if onDone != nil {
+ onDone()
+ }
close(done)
}()
m.readLines <- linesToRead
- m.Log.Warn("waiting for done channel")
<-done
- m.Log.Warn("done channel returned")
return nil
}