Add Application.HandlePanic

Resolves #74.
This commit is contained in:
Trevor Slocum 2021-08-03 13:20:44 -07:00
parent 6758d2a787
commit 492ab21896
26 changed files with 75 additions and 10 deletions

View file

@ -1,4 +1,5 @@
v1.5.7 (WIP)
- Add Application.HandlePanic
- Add Modal.SetButtonsAlign and Modal.SetTextAlign
- Fix TextView.GetRegionText error when text contains color tags
- Fix TextView region tags when placed at the end of a line

View file

@ -125,6 +125,23 @@ func NewApplication() *Application {
}
}
// HandlePanic (when deferred at the start of a goroutine) handles panics
// gracefully. The terminal is returned to its original state before the panic
// message is printed.
//
// Panics may only be handled by the panicking goroutine. Because of this,
// HandlePanic must be deferred at the start of each goroutine (including main).
func (a *Application) HandlePanic() {
p := recover()
if p == nil {
return
}
a.finalizeScreen()
panic(p)
}
// SetInputCapture sets a function which captures all key events before they are
// forwarded to the key event handler of the primitive which currently has
// focus. This function can then choose to forward that key event (or a
@ -290,15 +307,7 @@ func (a *Application) Run() error {
return err
}
// We catch panics to clean up because they mess up the terminal.
defer func() {
if p := recover(); p != nil {
if a.screen != nil {
a.screen.Fini()
}
panic(p)
}
}()
defer a.HandlePanic()
// Draw the screen for the first time.
a.Unlock()
@ -308,6 +317,8 @@ func (a *Application) Run() error {
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer a.HandlePanic()
defer wg.Done()
for {
a.RLock()
@ -431,6 +442,8 @@ func (a *Application) Run() error {
semaphore := &sync.Mutex{}
go func() {
defer a.HandlePanic()
for update := range a.updates {
semaphore.Lock()
update()
@ -570,13 +583,18 @@ func (a *Application) Stop() {
a.Lock()
defer a.Unlock()
a.finalizeScreen()
a.screenReplacement <- nil
}
func (a *Application) finalizeScreen() {
screen := a.screen
if screen == nil {
return
}
a.screen = nil
screen.Fini()
a.screenReplacement <- nil
}
// Suspend temporarily suspends the application by exiting terminal UI mode and

View file

@ -8,6 +8,7 @@ import (
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
box := cview.NewBox()
box.SetBorder(true)

View file

@ -5,6 +5,8 @@ import "code.rocketnine.space/tslocum/cview"
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
button := cview.NewButton("Hit Enter to close")

View file

@ -7,6 +7,8 @@ import (
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
checkbox := cview.NewCheckBox()

View file

@ -5,6 +5,8 @@ import "code.rocketnine.space/tslocum/cview"
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
dropdown := cview.NewDropDown()

View file

@ -14,6 +14,8 @@ func demoBox(title string) *cview.Box {
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
subFlex := cview.NewFlex()

View file

@ -18,6 +18,8 @@ func wrap(f func()) func(ev *tcell.EventKey) *tcell.EventKey {
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
input1 := cview.NewInputField()

View file

@ -7,6 +7,8 @@ import (
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
form := cview.NewForm()

View file

@ -8,6 +8,8 @@ import (
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
box := cview.NewBox()

View file

@ -7,6 +7,8 @@ import (
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
newPrimitive := func(text string) cview.Primitive {

View file

@ -12,6 +12,7 @@ const wordList = "ability,able,about,above,accept,according,account,across,act,a
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
words := strings.Split(wordList, ",")

View file

@ -17,6 +17,8 @@ type company struct {
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
inputField := cview.NewInputField()
inputField.SetLabel("Enter a company name: ")
inputField.SetFieldWidth(30)

View file

@ -8,6 +8,8 @@ import (
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
inputField := cview.NewInputField()

View file

@ -9,6 +9,8 @@ import (
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
list := cview.NewList()

View file

@ -7,6 +7,8 @@ import (
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
modal := cview.NewModal()

View file

@ -11,6 +11,8 @@ const panelCount = 5
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
panels := cview.NewPanels()

View file

@ -43,6 +43,8 @@ var app = cview.NewApplication()
// Starting point for the presentation.
func main() {
defer app.HandlePanic()
var debugPort int
flag.IntVar(&debugPort, "debug", 0, "port to serve debug info")
flag.Parse()

View file

@ -61,6 +61,7 @@ func (r *RadioButtons) InputHandler() func(event *tcell.EventKey, setFocus func(
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
radioButtons := NewRadioButtons([]string{"Lions", "Elephants", "Giraffes"})
radioButtons.SetBorder(true)

View file

@ -9,6 +9,7 @@ import (
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
grid := cview.NewGrid()
grid.SetColumns(-1, 6, 4, 30, -1)

View file

@ -11,6 +11,8 @@ const panelCount = 5
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
panels := cview.NewTabbedPanels()

View file

@ -12,6 +12,8 @@ const loremIpsumText = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr,
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
table := cview.NewTable()

View file

@ -21,6 +21,8 @@ Capitalize on low hanging fruit to identify a ballpark value added activity to b
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
textView := cview.NewTextView()

View file

@ -12,6 +12,8 @@ import (
// Show a navigable tree view of the current directory.
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
app.EnableMouse(true)
rootDir := "."

View file

@ -9,6 +9,8 @@ import (
func main() {
app := cview.NewApplication()
defer app.HandlePanic()
panels := cview.NewPanels()
form := cview.NewForm()

View file

@ -10,6 +10,8 @@ import (
func ExampleNewApplication() {
// Initialize application.
app := NewApplication()
// Handle panics gracefully.
defer app.HandlePanic()
// Create shared TextView.
sharedTextView := NewTextView()
@ -71,6 +73,8 @@ func ExampleNewApplication() {
func ExampleApplication_EnableMouse() {
// Initialize application.
app := NewApplication()
// Handle panics gracefully.
defer app.HandlePanic()
// Enable mouse support.
app.EnableMouse(true)