Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: make sure the interactive printers can cleanup after Ctrl+C #383

Merged
merged 2 commits into from Jul 26, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 8 additions & 2 deletions interactive_multiselect_printer.go
Expand Up @@ -2,13 +2,13 @@ package pterm

import (
"fmt"
"os"
"sort"

"atomicgo.dev/cursor"
"atomicgo.dev/keyboard"
"atomicgo.dev/keyboard/keys"
"github.com/lithammer/fuzzysearch/fuzzy"
"github.com/pterm/pterm/internal"
)

var (
Expand Down Expand Up @@ -72,6 +72,11 @@ func (p InteractiveMultiselectPrinter) WithMaxHeight(maxHeight int) *Interactive

// Show shows the interactive multiselect menu and returns the selected entry.
func (p *InteractiveMultiselectPrinter) Show(text ...string) ([]string, error) {
// should be the first defer statement to make sure it is executed last
// and all the needed cleanup can be done before
cancel, exit := internal.NewCancelationSignal()
defer exit()

if len(text) == 0 || Sprint(text[0]) == "" {
text = []string{p.DefaultText}
}
Expand Down Expand Up @@ -219,7 +224,8 @@ func (p *InteractiveMultiselectPrinter) Show(text ...string) ([]string, error) {

area.Update(p.renderSelectMenu())
case keys.CtrlC:
os.Exit(1)
cancel()
return true, nil
case keys.Enter:
// Select option if not already selected
p.selectOption(p.fuzzySearchMatches[p.selectedOption])
Expand Down
11 changes: 9 additions & 2 deletions interactive_select_printer.go
Expand Up @@ -2,13 +2,13 @@ package pterm

import (
"fmt"
"os"
"sort"

"atomicgo.dev/cursor"
"atomicgo.dev/keyboard"
"atomicgo.dev/keyboard/keys"
"github.com/lithammer/fuzzysearch/fuzzy"
"github.com/pterm/pterm/internal"
)

var (
Expand Down Expand Up @@ -72,6 +72,11 @@ func (p InteractiveSelectPrinter) WithMaxHeight(maxHeight int) *InteractiveSelec

// Show shows the interactive select menu and returns the selected entry.
func (p *InteractiveSelectPrinter) Show(text ...string) (string, error) {
// should be the first defer statement to make sure it is executed last
// and all the needed cleanup can be done before
cancel, exit := internal.NewCancelationSignal()
defer exit()

if len(text) == 0 || Sprint(text[0]) == "" {
text = []string{p.DefaultText}
}
Expand Down Expand Up @@ -124,6 +129,7 @@ func (p *InteractiveSelectPrinter) Show(text ...string) (string, error) {

cursor.Hide()
defer cursor.Show()

err = keyboard.Listen(func(keyInfo keys.Key) (stop bool, err error) {
key := keyInfo.Code

Expand Down Expand Up @@ -216,7 +222,8 @@ func (p *InteractiveSelectPrinter) Show(text ...string) (string, error) {

area.Update(p.renderSelectMenu())
case keys.CtrlC:
os.Exit(1)
cancel()
return true, nil
case keys.Enter:
if len(p.fuzzySearchMatches) == 0 {
return false, nil
Expand Down
9 changes: 7 additions & 2 deletions interactive_textinput_printer.go
@@ -1,7 +1,6 @@
package pterm

import (
"os"
"strings"

"atomicgo.dev/cursor"
Expand Down Expand Up @@ -51,6 +50,11 @@ func (p *InteractiveTextInputPrinter) WithMultiLine(multiLine ...bool) *Interact

// Show shows the interactive select menu and returns the selected entry.
func (p *InteractiveTextInputPrinter) Show(text ...string) (string, error) {
// should be the first defer statement to make sure it is executed last
// and all the needed cleanup can be done before
cancel, exit := internal.NewCancelationSignal()
defer exit()

var areaText string

if len(text) == 0 || Sprint(text[0]) == "" {
Expand Down Expand Up @@ -130,7 +134,8 @@ func (p *InteractiveTextInputPrinter) Show(text ...string) (string, error) {
p.cursorXPos = 0
}
case keys.CtrlC:
os.Exit(0)
cancel()
return true, nil
case keys.Down:
if p.cursorYPos+1 < len(p.input) {
p.cursorXPos = (internal.GetStringMaxWidth(p.input[p.cursorYPos]) + p.cursorXPos) - internal.GetStringMaxWidth(p.input[p.cursorYPos+1])
Expand Down
21 changes: 21 additions & 0 deletions internal/cancelation_signal.go
@@ -0,0 +1,21 @@
package internal

import (
"os"
)

// NewCancelationSignal for keeping track of a cancelation
func NewCancelationSignal() (func(), func()) {
canceled := false

cancel := func() {
canceled = true
}
exit := func() {
if canceled {
os.Exit(1)
}
}

return cancel, exit
}