| 641 | } |
| 642 | |
| 643 | func (p *Program) handleSignals() chan struct{} { |
| 644 | ch := make(chan struct{}) |
| 645 | |
| 646 | // Listen for SIGINT and SIGTERM. |
| 647 | // |
| 648 | // In most cases ^C will not send an interrupt because the terminal will be |
| 649 | // in raw mode and ^C will be captured as a keystroke and sent along to |
| 650 | // Program.Update as a KeyMsg. When input is not a TTY, however, ^C will be |
| 651 | // caught here. |
| 652 | // |
| 653 | // SIGTERM is sent by unix utilities (like kill) to terminate a process. |
| 654 | go func() { |
| 655 | sig := make(chan os.Signal, 1) |
| 656 | signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM) |
| 657 | defer func() { |
| 658 | signal.Stop(sig) |
| 659 | close(ch) |
| 660 | }() |
| 661 | |
| 662 | for { |
| 663 | select { |
| 664 | case <-p.ctx.Done(): |
| 665 | return |
| 666 | |
| 667 | case s := <-sig: |
| 668 | if atomic.LoadUint32(&p.ignoreSignals) == 0 { |
| 669 | switch s { |
| 670 | case syscall.SIGINT: |
| 671 | p.msgs <- InterruptMsg{} |
| 672 | default: |
| 673 | p.msgs <- QuitMsg{} |
| 674 | } |
| 675 | return |
| 676 | } |
| 677 | } |
| 678 | } |
| 679 | }() |
| 680 | |
| 681 | return ch |
| 682 | } |
| 683 | |
| 684 | // handleResize handles terminal resize events. |
| 685 | func (p *Program) handleResize() chan struct{} { |