diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2020-03-03 22:41:35 +1100 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2020-03-04 00:12:23 +1100 |
commit | b3522c48d9377fec9397581cf2ab439c92590c20 (patch) | |
tree | b6d6be1d6eee091cc4cb6c7a4dc3cc96699a04fb /pkg | |
parent | 0fc58a79867ae91ce8c0374ecfe95407b621ce55 (diff) |
refactor
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/gui/pty.go | 53 | ||||
-rw-r--r-- | pkg/gui/pty_windows.go | 13 | ||||
-rw-r--r-- | pkg/gui/tasks_adapter.go | 39 | ||||
-rw-r--r-- | pkg/tasks/tasks.go | 115 |
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 } |