// Close returns the terminal to the original state. func (t *Terminal) Close() error { log.Println("Quiting Terminal") wg := &sync.WaitGroup{} wg.Add(2) t.quitSignals <- wg t.quitWriting <- wg wg.Wait() esc := t.escapes t.WriteAll( esc.ShowCursor(), esc.Sgr0(), esc.ClearScreen(), esc.Exit(), esc.ExitKeypad(), esc.MouseExit()) term_sys.SetTerminalAttributes(t.termOut.Fd(), t.originalTermAtts) err := syscall.Close(t.termIn) t.termIn = 0 // File descriptor if err != nil { return fmt.Errorf("Close error %d", err) //TODO: log instead of print } return nil }
func NewTerminal() (*Terminal, error) { termOut, err := os.OpenFile("/dev/tty", syscall.O_WRONLY, 0) if err != nil { panic(err) } termIn, err := syscall.Open("/dev/tty", syscall.O_RDONLY, 0) if err != nil { panic(err) } _, err = term_sys.ChangeFileDescriptor(termIn, syscall.F_SETFL, syscall.O_ASYNC|syscall.O_NONBLOCK) if err != nil { return nil, err } _, err = term_sys.ChangeFileDescriptor(termIn, syscall.F_SETOWN, syscall.Getpid()) if runtime.GOOS != "darwin" && err != nil { return nil, err } originalTermAtts, err := term_sys.SetupTerminalAttributes(termOut) if err != nil { panic(err) } setupTermAtts, err := term_sys.SetupTerminalAttributes(termOut) if err != nil { panic(err) } err = term_sys.SetTerminalAttributes(termOut.Fd(), setupTermAtts) if err != nil { panic(err) } w, h, err := term_sys.GetTerminalDims(termOut.Fd()) if err != nil { panic(err) } t := &Terminal{ termOut: termOut, termIn: termIn, setupTermAtts: setupTermAtts, originalTermAtts: originalTermAtts, width: w, height: h, escapes: NewEscapes(), onWindowSizeChange: term_sys.NewSignal(syscall.SIGWINCH), onSignalEvent: term_sys.NewSignal(syscall.SIGIO), quitSignals: make(chan *sync.WaitGroup, 0), quitWriting: make(chan *sync.WaitGroup, 0), inputParsing: NewInputParsing(), } return t, nil }