Skip to content

Commit

Permalink
feat: kill the program and restore terminal state
Browse files Browse the repository at this point in the history
* Add Kill() to force kill the program from the outside
* Prevent renderer channel from being closed multiple times
  • Loading branch information
aymanbagabas committed Feb 7, 2022
1 parent 9a06319 commit 3b65b2c
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 6 deletions.
9 changes: 7 additions & 2 deletions standard_renderer.go
Expand Up @@ -32,6 +32,7 @@ type standardRenderer struct {
lastRender string
linesRendered int
useANSICompressor bool
once sync.Once

// essentially whether or not we're using the full size of the terminal
altScreenActive bool
Expand Down Expand Up @@ -72,7 +73,9 @@ func (r *standardRenderer) start() {
func (r *standardRenderer) stop() {
r.flush()
clearLine(r.out)
close(r.done)
r.once.Do(func() {
close(r.done)
})

if r.useANSICompressor {
if w, ok := r.out.(io.WriteCloser); ok {
Expand All @@ -84,7 +87,9 @@ func (r *standardRenderer) stop() {
// kill halts the renderer. The final frame will not be rendered.
func (r *standardRenderer) kill() {
clearLine(r.out)
close(r.done)
r.once.Do(func() {
close(r.done)
})
}

// listen waits for ticks on the ticker, or a signal to stop the renderer.
Expand Down
25 changes: 21 additions & 4 deletions tea.go
Expand Up @@ -97,6 +97,8 @@ type Program struct {
// is on by default.
CatchPanics bool

killc chan bool

console console.Console

// Stores the original reference to stdin for cases where input is not a
Expand Down Expand Up @@ -248,6 +250,7 @@ func NewProgram(model Model, opts ...ProgramOption) *Program {
input: os.Stdin,
msgs: make(chan Msg),
CatchPanics: true,
killc: make(chan bool, 1),
}

// Apply all options to the program.
Expand Down Expand Up @@ -486,6 +489,8 @@ func (p *Program) StartReturningModel() (Model, error) {
// Handle updates and draw.
for {
select {
case <-p.killc:
return nil, nil
case err := <-errs:
cancelContext()
waitForGoroutines(cancelReader.Cancel())
Expand Down Expand Up @@ -577,13 +582,25 @@ func (p *Program) Quit() {
p.Send(Quit())
}

// Kill stops the program immediately and restores the former terminal state.
// The final render that you would normally see when quitting will be skipped.
//
// This method is currently provisional. The method signature may alter
// slightly, or it may be removed in a future version of this package.
func (p *Program) Kill() {
p.killc <- true
p.shutdown(true)
}

// shutdown performs operations to free up resources and restore the terminal
// to its original state.
func (p *Program) shutdown(kill bool) {
if kill {
p.renderer.kill()
} else {
p.renderer.stop()
if p.renderer != nil {
if kill {
p.renderer.kill()
} else {
p.renderer.stop()
}
}
p.ExitAltScreen()
p.DisableMouseCellMotion()
Expand Down

0 comments on commit 3b65b2c

Please sign in to comment.