term.go 987 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. package termutil
  2. import (
  3. "errors"
  4. "os"
  5. "os/signal"
  6. "sync"
  7. )
  8. var echoLocked bool
  9. var echoLockMutex sync.Mutex
  10. var errLocked = errors.New("terminal locked")
  11. // RawModeOn switches terminal to raw mode
  12. func RawModeOn() (quit chan struct{}, err error) {
  13. echoLockMutex.Lock()
  14. defer echoLockMutex.Unlock()
  15. if echoLocked {
  16. err = errLocked
  17. return
  18. }
  19. if err = lockEcho(); err != nil {
  20. return
  21. }
  22. echoLocked = true
  23. quit = make(chan struct{}, 1)
  24. go catchTerminate(quit)
  25. return
  26. }
  27. // RawModeOff restore previous terminal state
  28. func RawModeOff() (err error) {
  29. echoLockMutex.Lock()
  30. defer echoLockMutex.Unlock()
  31. if !echoLocked {
  32. return
  33. }
  34. if err = unlockEcho(); err != nil {
  35. return
  36. }
  37. echoLocked = false
  38. return
  39. }
  40. // listen exit signals and restore terminal state
  41. func catchTerminate(quit chan struct{}) {
  42. sig := make(chan os.Signal, 1)
  43. signal.Notify(sig, unlockSignals...)
  44. defer signal.Stop(sig)
  45. select {
  46. case <-quit:
  47. RawModeOff()
  48. case <-sig:
  49. RawModeOff()
  50. }
  51. }