Handle more signals #61
21
cui/cui.go
|
@ -56,16 +56,29 @@ func moveCursorToward(dir string, amount int) {
|
|||
}
|
||||
}
|
||||
|
||||
// Exit performs cleanup operations before exiting the application
|
||||
func Exit() {
|
||||
CleanupTerm()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// InitTerm sets the terminal modes appropriate for Bombadillo
|
||||
func InitTerm() {
|
||||
SetCharMode()
|
||||
Tput("rmam") // turn off line wrapping
|
||||
Tput("smcup") // use alternate screen
|
||||
}
|
||||
|
||||
// CleanupTerm reverts changs to terminal mode made by InitTerm
|
||||
func CleanupTerm() {
|
||||
moveCursorToward("down", 500)
|
||||
moveCursorToward("right", 500)
|
||||
SetLineMode()
|
||||
|
||||
fmt.Print("\n")
|
||||
fmt.Print("\033[?25h")
|
||||
Tput("smam") // turn off line wrap
|
||||
Tput("rmcup") // use alternate screen
|
||||
os.Exit(0)
|
||||
fmt.Print("\033[?25h") // reenables cursor blinking
|
||||
Tput("smam") // turn on line wrap
|
||||
Tput("rmcup") // stop using alternate screen
|
||||
}
|
||||
|
||||
func Clear(dir string) {
|
||||
|
|
36
main.go
|
@ -112,7 +112,7 @@ func loadConfig() error {
|
|||
if lowerkey == "configlocation" {
|
||||
// The config defaults to the home folder.
|
||||
// Users cannot really edit this value. But
|
||||
// a compile time override is available.
|
||||
// a compile time override is available.
|
||||
// It is still stored in the ini and as a part
|
||||
// of the options map.
|
||||
continue
|
||||
|
@ -140,7 +140,6 @@ func loadConfig() error {
|
|||
|
||||
func initClient() error {
|
||||
bombadillo = MakeClient(" ((( Bombadillo ))) ")
|
||||
cui.SetCharMode()
|
||||
|
||||
err := loadConfig()
|
||||
if bombadillo.Options["tlscertificate"] != "" && bombadillo.Options["tlskey"] != "" {
|
||||
bombadillo.Certs.LoadCertificate(bombadillo.Options["tlscertificate"], bombadillo.Options["tlskey"])
|
||||
|
@ -148,16 +147,22 @@ func initClient() error {
|
|||
return err
|
||||
}
|
||||
|
||||
// In the event of SIGCONT, ensure the display is shown correctly. Accepts a
|
||||
// signal, blocking until it is received. Once not blocked, corrects terminal
|
||||
// display settings. Loops indefinitely, does not return.
|
||||
func handleSIGCONT(c <-chan os.Signal) {
|
||||
// In the event of specific signals, ensure the display is shown correctly.
|
||||
// Accepts a signal, blocking until it is received. Once not blocked, corrects
|
||||
// terminal display settings as appropriate for that signal. Loops
|
||||
// indefinitely, does not return.
|
||||
func handleSignals(c <-chan os.Signal) {
|
||||
for {
|
||||
<-c
|
||||
cui.Tput("rmam") // turn off line wrapping
|
||||
cui.Tput("smcup") // use alternate screen
|
||||
cui.SetCharMode()
|
||||
bombadillo.Draw()
|
||||
switch <-c {
|
||||
sloum
commented
I have not used channels a lot (though did recently for a game I made...plummet, available on my tildegit). We are in a goroutine so it wont matter, but just for my own knowledge: this line will block until a signal is received, yeah? I have not used channels a lot (though did recently for a game I made...plummet, available on my tildegit). We are in a goroutine so it wont matter, but just for my own knowledge: this line will block until a signal is received, yeah?
asdf
commented
That's correct. It's a buffered channel, and blocks until a value is received. This is the first time I've used channels, but they are interesting and work well. The general logic here is that You can assign the value from a channel using The way it is being used here, you could also write it as: This is also the first time I'm seeing the select statement, so thanks for the prompt on that. btw plummet is pretty cool! A nice little game. That's correct. It's a buffered channel, and blocks until a value is received.
This is the first time I've used channels, but they are interesting and work well.
The general logic here is that `signal.Notify` listens for the specified signals, then sends them to the channel when they are received. In this goroutine, the channel is blocked until it gets a signal, and then it does the appropriate thing.
You can assign the value from a channel using `x := <- c` like you have done in plummet. You can also just do `<- c` if you just want to wait until it receives a value, but don't actually want to do anything with that value.
The way it is being used here, you could also write it as:
x := <-c
switch x {
case ...
This is also the first time I'm seeing the [select](https://tour.golang.org/concurrency/5) statement, so thanks for the prompt on that.
btw plummet is pretty cool! A nice little game.
|
||||
case syscall.SIGTSTP:
|
||||
cui.CleanupTerm()
|
||||
syscall.Kill(syscall.Getpid(), syscall.SIGSTOP)
|
||||
sloum
commented
I would have never found this :( The documentation for the syscall lib is the one really swampy place in golang. I would have never found this :( The documentation for the syscall lib is the one really swampy place in golang.
asdf
commented
Yeah, documentation is a bit light, and it seems like a lot of the code is automatically generated. I actually found this by searching around. This is the same way that other languages perform this task. Also, in the shell, the command is very similar: kill -s SIGNAL pid Also - syscall is also apparently deprecated, but I'm not sure when it is going to be replaced. I guess eventually this will have to be rewritten slightly. Yeah, documentation is a bit light, and it seems like a lot of the code is automatically generated.
I actually found this by searching around. This is the same way that other languages perform this task. Also, in the shell, the command is very similar:
kill -s SIGNAL pid
Also - syscall is also apparently deprecated, but I'm not sure when it is going to be replaced. I guess eventually this will have to be rewritten slightly.
|
||||
case syscall.SIGCONT:
|
||||
cui.InitTerm()
|
||||
bombadillo.Draw()
|
||||
case syscall.SIGINT:
|
||||
cui.Exit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,8 +179,7 @@ func main() {
|
|||
// So that we can open files from gemini
|
||||
mc = mailcap.NewMailcap()
|
||||
|
||||
cui.Tput("rmam") // turn off line wrapping
|
||||
cui.Tput("smcup") // use alternate screen
|
||||
cui.InitTerm()
|
||||
defer cui.Exit()
|
||||
err := initClient()
|
||||
if err != nil {
|
||||
|
@ -183,10 +187,10 @@ func main() {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
// watch for SIGCONT, send it to be handled
|
||||
// watch for signals, send them to be handled
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGCONT)
|
||||
go handleSIGCONT(c)
|
||||
signal.Notify(c, syscall.SIGTSTP, syscall.SIGCONT, syscall.SIGINT)
|
||||
go handleSignals(c)
|
||||
|
||||
// Start polling for terminal size changes
|
||||
go bombadillo.GetSize()
|
||||
|
|
This was moved to cui.InitTerm() which is now executed directly in main(). I'm not sure on the full impact of this move.
I see no reason that should be a problem.
Yeah upon further investigation it looks ok to me too, I was just a bit worried about error handling.