mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-12 12:55:47 +02:00
Bump gocui
This includes new gocui logic for tracking busy/idle program state
This commit is contained in:
parent
585ea361f6
commit
631cf1e873
29 changed files with 273 additions and 59 deletions
130
vendor/github.com/jesseduffield/gocui/gui.go
generated
vendored
130
vendor/github.com/jesseduffield/gocui/gui.go
generated
vendored
|
@ -173,6 +173,13 @@ type Gui struct {
|
|||
screen tcell.Screen
|
||||
suspendedMutex sync.Mutex
|
||||
suspended bool
|
||||
|
||||
// Tracks whether the program is busy (i.e. either something is happening on
|
||||
// the main goroutine or a worker goroutine). Used by integration tests
|
||||
// to wait until the program is idle before progressing.
|
||||
busyCount int
|
||||
busyCountMutex sync.Mutex
|
||||
idleListeners []chan struct{}
|
||||
}
|
||||
|
||||
// NewGui returns a new Gui object with a given output mode.
|
||||
|
@ -230,6 +237,13 @@ func NewGui(mode OutputMode, supportOverlaps bool, playRecording bool, headless
|
|||
return g, nil
|
||||
}
|
||||
|
||||
// An idle listener listens for when the program is idle. This is useful for
|
||||
// integration tests which can wait for the program to be idle before taking
|
||||
// the next step in the test.
|
||||
func (g *Gui) AddIdleListener(c chan struct{}) {
|
||||
g.idleListeners = append(g.idleListeners, c)
|
||||
}
|
||||
|
||||
// Close finalizes the library. It should be called after a successful
|
||||
// initialization and when gocui is not needed anymore.
|
||||
func (g *Gui) Close() {
|
||||
|
@ -602,16 +616,51 @@ type userEvent struct {
|
|||
// the user events queue. Given that Update spawns a goroutine, the order in
|
||||
// which the user events will be handled is not guaranteed.
|
||||
func (g *Gui) Update(f func(*Gui) error) {
|
||||
go g.UpdateAsync(f)
|
||||
g.IncrementBusyCount()
|
||||
|
||||
go g.updateAsyncAux(f)
|
||||
}
|
||||
|
||||
// UpdateAsync is a version of Update that does not spawn a go routine, it can
|
||||
// be a bit more efficient in cases where Update is called many times like when
|
||||
// tailing a file. In general you should use Update()
|
||||
func (g *Gui) UpdateAsync(f func(*Gui) error) {
|
||||
g.IncrementBusyCount()
|
||||
|
||||
g.updateAsyncAux(f)
|
||||
}
|
||||
|
||||
func (g *Gui) updateAsyncAux(f func(*Gui) error) {
|
||||
g.userEvents <- userEvent{f: f}
|
||||
}
|
||||
|
||||
// Calls a function in a goroutine. Handles panics gracefully and tracks
|
||||
// number of background tasks.
|
||||
// Always use this when you want to spawn a goroutine and you want lazygit to
|
||||
// consider itself 'busy` as it runs the code. Don't use for long-running
|
||||
// background goroutines where you wouldn't want lazygit to be considered busy
|
||||
// (i.e. when you wouldn't want a loader to be shown to the user)
|
||||
func (g *Gui) OnWorker(f func()) {
|
||||
g.IncrementBusyCount()
|
||||
go func() {
|
||||
g.onWorkerAux(f)
|
||||
g.DecrementBusyCount()
|
||||
}()
|
||||
}
|
||||
|
||||
func (g *Gui) onWorkerAux(f func()) {
|
||||
panicking := true
|
||||
defer func() {
|
||||
if panicking && Screen != nil {
|
||||
Screen.Fini()
|
||||
}
|
||||
}()
|
||||
|
||||
f()
|
||||
|
||||
panicking = false
|
||||
}
|
||||
|
||||
// A Manager is in charge of GUI's layout and can be used to build widgets.
|
||||
type Manager interface {
|
||||
// Layout is called every time the GUI is redrawn, it must contain the
|
||||
|
@ -666,27 +715,68 @@ func (g *Gui) MainLoop() error {
|
|||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case ev := <-g.gEvents:
|
||||
if err := g.handleEvent(&ev); err != nil {
|
||||
return err
|
||||
}
|
||||
case ev := <-g.userEvents:
|
||||
if err := ev.f(g); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := g.consumeevents(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.flush(); err != nil {
|
||||
err := g.processEvent()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// consumeevents handles the remaining events in the events pool.
|
||||
func (g *Gui) consumeevents() error {
|
||||
func (g *Gui) IncrementBusyCount() {
|
||||
g.busyCountMutex.Lock()
|
||||
defer g.busyCountMutex.Unlock()
|
||||
|
||||
g.busyCount++
|
||||
}
|
||||
|
||||
func (g *Gui) DecrementBusyCount() {
|
||||
g.busyCountMutex.Lock()
|
||||
defer g.busyCountMutex.Unlock()
|
||||
|
||||
if g.busyCount == 0 {
|
||||
panic("busyCount is already 0")
|
||||
}
|
||||
|
||||
if g.busyCount == 1 {
|
||||
// notify listeners that the program is idle
|
||||
for _, listener := range g.idleListeners {
|
||||
listener <- struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
g.busyCount--
|
||||
}
|
||||
|
||||
func (g *Gui) processEvent() error {
|
||||
select {
|
||||
case ev := <-g.gEvents:
|
||||
g.IncrementBusyCount()
|
||||
defer func() { g.DecrementBusyCount() }()
|
||||
|
||||
if err := g.handleEvent(&ev); err != nil {
|
||||
return err
|
||||
}
|
||||
case ev := <-g.userEvents:
|
||||
// user events increment busyCount ahead of time
|
||||
defer func() { g.DecrementBusyCount() }()
|
||||
|
||||
if err := ev.f(g); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := g.processRemainingEvents(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := g.flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// processRemainingEvents handles the remaining events in the events pool.
|
||||
func (g *Gui) processRemainingEvents() error {
|
||||
for {
|
||||
select {
|
||||
case ev := <-g.gEvents:
|
||||
|
@ -694,7 +784,9 @@ func (g *Gui) consumeevents() error {
|
|||
return err
|
||||
}
|
||||
case ev := <-g.userEvents:
|
||||
if err := ev.f(g); err != nil {
|
||||
err := ev.f(g)
|
||||
g.DecrementBusyCount()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
|
@ -1355,7 +1447,7 @@ func (g *Gui) StartTicking(ctx context.Context) {
|
|||
|
||||
for _, view := range g.Views() {
|
||||
if view.HasLoader {
|
||||
g.userEvents <- userEvent{func(g *Gui) error { return nil }}
|
||||
g.UpdateAsync(func(g *Gui) error { return nil })
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue