mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-08-07 22:02:56 +03:00
refactor
This commit is contained in:
@@ -1,6 +1,10 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
package gui
|
package gui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
"github.com/jesseduffield/pty"
|
"github.com/jesseduffield/pty"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -19,3 +23,52 @@ func (gui *Gui) onResize() error {
|
|||||||
|
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
13
pkg/gui/pty_windows.go
Normal file
13
pkg/gui/pty_windows.go
Normal file
@@ -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)
|
||||||
|
}
|
@@ -5,7 +5,6 @@ import (
|
|||||||
|
|
||||||
"github.com/jesseduffield/gocui"
|
"github.com/jesseduffield/gocui"
|
||||||
"github.com/jesseduffield/lazygit/pkg/tasks"
|
"github.com/jesseduffield/lazygit/pkg/tasks"
|
||||||
"github.com/jesseduffield/pty"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (gui *Gui) newCmdTask(viewName string, cmd *exec.Cmd) error {
|
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)
|
manager := gui.getManager(view)
|
||||||
|
|
||||||
if err := manager.NewTask(manager.NewCmdTask(cmd, height+oy+10)); err != nil {
|
r, err := cmd.StdoutPipe()
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
cmd.Stderr = cmd.Stdout
|
||||||
|
|
||||||
gui.State.Ptmx = ptmx
|
if err := cmd.Start(); err != nil {
|
||||||
onClose := func() { gui.State.Ptmx = nil }
|
|
||||||
|
|
||||||
if err := gui.onResize(); err != nil {
|
|
||||||
return err
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,7 +4,6 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"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 {
|
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() {
|
go func() {
|
||||||
<-stop
|
<-stop
|
||||||
if cmd.ProcessState == nil {
|
if err := commands.Kill(cmd); err != 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 {
|
|
||||||
m.Log.Warn(err)
|
m.Log.Warn(err)
|
||||||
}
|
}
|
||||||
|
if onDone != nil {
|
||||||
close(done)
|
onDone()
|
||||||
}()
|
}
|
||||||
|
|
||||||
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()
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
loadingMutex := sync.Mutex{}
|
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
|
// not sure if it's the right move to redefine this or not
|
||||||
m.readLines = make(chan int, 1024)
|
m.readLines = make(chan int, 1024)
|
||||||
|
|
||||||
|
done := make(chan struct{})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
scanner := bufio.NewScanner(r)
|
scanner := bufio.NewScanner(r)
|
||||||
scanner.Split(bufio.ScanLines)
|
scanner.Split(bufio.ScanLines)
|
||||||
@@ -196,6 +103,7 @@ func (m *ViewBufferManager) NewPtyTask(ptmx *os.File, cmd *exec.Cmd, linesToRead
|
|||||||
|
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-stop:
|
||||||
|
m.refreshView()
|
||||||
break outer
|
break outer
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
@@ -207,6 +115,7 @@ func (m *ViewBufferManager) NewPtyTask(ptmx *os.File, cmd *exec.Cmd, linesToRead
|
|||||||
}
|
}
|
||||||
m.refreshView()
|
m.refreshView()
|
||||||
case <-stop:
|
case <-stop:
|
||||||
|
m.refreshView()
|
||||||
break outer
|
break outer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,16 +126,16 @@ func (m *ViewBufferManager) NewPtyTask(ptmx *os.File, cmd *exec.Cmd, linesToRead
|
|||||||
|
|
||||||
m.refreshView()
|
m.refreshView()
|
||||||
|
|
||||||
onClose()
|
if onDone != nil {
|
||||||
|
onDone()
|
||||||
|
}
|
||||||
|
|
||||||
close(done)
|
close(done)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
m.readLines <- linesToRead
|
m.readLines <- linesToRead
|
||||||
|
|
||||||
m.Log.Warn("waiting for done channel")
|
|
||||||
<-done
|
<-done
|
||||||
m.Log.Warn("done channel returned")
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user