Comments (7)
This could be fixed by re-raising the signal in the init
function after handling it:
diff --git a/pterm.go b/pterm.go
index 09557157..82397ed0 100644
--- a/pterm.go
+++ b/pterm.go
@@ -7,11 +7,13 @@
package pterm
import (
"atomicgo.dev/cursor"
"github.com/gookit/color"
+ "fmt"
"os"
"os/signal"
"syscall"
)
var (
@@ -36,8 +38,21 @@ func init() {
signal.Notify(c, os.Interrupt)
signal.Notify(c, syscall.SIGTERM)
go func() {
- for range c {
+ for s := range c {
cursor.Show()
+
+ // Re-raise the signal to trigger the default behavior
+ signal.Stop(c)
+ p, err := os.FindProcess(os.Getpid())
+ if err != nil {
+ _, _ = fmt.Fprintf(os.Stderr, "pterm: Failed to re-raise %s: %v\n", s, err)
+ continue
+ }
+ err = p.Signal(s)
+ if err != nil {
+ _, _ = fmt.Fprintf(os.Stderr, "pterm: Failed to re-raise %s: %v\n", s, err)
+ continue
+ }
}
}()
}
}
However, this could lead to other unexpected behavior: Any other handlers registered by the program via signal.Notify
would receive the same signal twice, because the Go runtime sends each signal to all handlers registered for that signal.
The only clean solution I see is to not register any signal handler in pterm and instead provide methods which the consumer can call themself to ensure that the cursor is restored. The ProgressbarPrinter
already provides a Stop()
method which can be used for that, for example like this:
func DownloadWithProgressbar() {
p := pterm.DefaultProgressbar.WithTotal(len(fakeInstallList)).WithTitle("Downloading stuff")
// Ensure that the progressbar printer is stopped when receiving a
// terminating signal
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
go func() {
<-sigs
p.Stop()
os.Exit(1)
}()
defer signal.Stop(sigs)
p.Start()
for i := 0; i < p.Total; i++ {
if i == 6 {
time.Sleep(time.Second * 3) // Simulate a slow download.
}
p.UpdateTitle("Downloading " + fakeInstallList[i]) // Update the title of the progressbar.
pterm.Success.Println("Downloading " + fakeInstallList[i]) // If a progressbar is running, each print will be printed above the progressbar.
p.Increment() // Increment the progressbar by one. Use Add(x int) to increment by a custom amount.
time.Sleep(time.Millisecond * 350) // Sleep 350 milliseconds.
}
}
The other cases where cursor.Hide
is currently called in pterm are InteractiveSelectPrinter.Show
and InteractiveMultiselectPrinter.Show
. Those do not yet provide methods to clean up the terminal.
from pterm.
Hi @adombeck, I think this was closed by accident (as a side-effect of closing another issue, that referenced this one). If the issue still persists, you can re-open this one :)
from pterm.
Thanks, this was indeed closed by accident.
from pterm.
Hi, I will definitely look into this.
The only clean solution I see is to not register any signal handler in pterm and instead provide methods which the consumer can call themself to ensure that the cursor is restored. The ProgressbarPrinter already provides a Stop() method which can be used for that, for example like this:
The problem with this is that if a user kills the process in the middle of a progressbar (or similar printer), then the Stop()
method is not executed. This causes the cursor to remain hidden until the terminal is restarted.
Your example shows, how a user would have to implement the signal handling by himself, but I think this is not in favor of PTerms simplicity philosophy. Every PTerm printer should be usable without any extra setup.
from pterm.
How about registering the signal handler in ProgressbarPrinter.Start
(and InteractiveSelectPrinter.Show
/ InteractiveMultiselectPrinter.Show
) instead of init
and making that optional via ProgressbarPrinter.WithoutSignalHandling
or something like that.
from pterm.
I removed the whole signal handling in #570. I think PTerm should not mess with signal handling. While this could cause that the cursor disappears, when crtl+c is pressed while the cursor is hidden, I still think it's the better option. There would be no optimal solution, if we handle signals inside PTerm. There would always be an edge-case, where a user wants to handle the signal by himself.
Appending to that, many terminals unhide the cursor, as soon as the user starts typing.
Thanks for pointing it out, and sorry for the long wait.
from pterm.
Released in v0.12.68
from pterm.
Related Issues (20)
- TreePrinter doesnโt use TextStyle for root text
- Proposal: Improve project homepage HOT 3
- If WithFilter is enabled and you try to set a custom key MultiSelect immediately exits. HOT 3
- Progressbar always writing control characters to stdout. HOT 2
- Add `reviewdog` with `golangci-lint`
- Add support for linux 'watch' command HOT 2
- wrong print of box with title including asian characters HOT 1
- Migrate to classic `golangci-lint` action
- Library check and uncheck all of duplicated option names HOT 1
- Request to add a timeout for InteractiveConfirm HOT 2
- Proposal: Add handler for log/slog
- `BasicTextInput` weird
- Fix `interactive_multiselect` examples
- Stopped spinner over writes the progressbar HOT 4
- Repeating Prompt Text when Default Text Goes Beyond Single Line
- Make `spinner.Stop` return itself
- Pasting in a string that is 1043 characters during interactive text input causes repeats in prompt HOT 8
- Multi-select components support horizontal display
- Default Value for InteractiveTextInput HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pterm.