Example #1
0
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
}
Example #2
0
//listen starts a providing events over the return InputEvent channel.
func (t *Terminal) forwardEvents() chan Event {
	onInput := make(chan Event, 1000)

	go func() {
		buf := make([]byte, 128)
		for {
			select {
			case <-t.onSignalEvent:
				for {
					n, err := syscall.Read(t.termIn, buf)
					if term_sys.HasInput(err) {
						b := buf[:n]
						event, err := t.inputParsing.extractEvent(b)
						if err != nil {
							log.Println("onSignalEvent", err)
						} else {
							onInput <- event
						}
					}
					if len(t.onSignalEvent) == 0 {
						break
					}
				}

			case <-t.onWindowSizeChange:
				w, h, err := term_sys.GetTerminalDims(t.termOut.Fd())
				if err != nil {
					log.Println(err)
					continue
				}
				ev := Event{Type: EventResize, Width: w, Height: h}
				onInput <- ev

			case wg := <-t.quitSignals:
				log.Println("Quiting Terminal : listen return")
				wg.Done()
				return
			}
		}
	}()

	return onInput
}