Application 2025-07-16

Developing TUI Applications with x/term

Develop TUI applications with Go's x/term package—master terminal state management, ANSI escape sequences, and interactive interfaces.

Read in: ja
Developing TUI Applications with x/term

Introduction

Recently, I tried creating a terminal-based typing game using Go's x/term package. In this article, I will share the features of the x/term package and insights I gained during TUI application development.

As a practical TUI application using x/term, I am developing a git client tool called ggc, so please give it a star if you like it.

What is the x/term Package

x/term is one of Go's experimental packages that provides low-level functionalities for terminal operations. It was previously golang.org/x/crypto/ssh/terminal, but now it is an independent package as golang.org/x/term.

Main Features

  1. Getting terminal size
width, height, err := term.GetSize(int(os.Stdout.Fd()))
  1. Capturing low-level key inputs
oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
if err != nil {
    log.Fatal(err)
}
defer term.Restore(int(os.Stdin.Fd()), oldState)
  1. Controlling echo
  2. Controlling terminal modes

Using these features, you can create interactive TUI applications with cursor position control and immediate key input detection.

Implementing the Typing Game

1. Basic Design

The core features of the typing game are as follows:

2. Managing Terminal State

The most important aspect when using x/term is managing the terminal state:

// Set terminal to raw mode
oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
if err != nil {
    log.Fatal(err)
}

// Restore original state upon program exit
defer term.Restore(int(os.Stdin.Fd()), oldState)

// Signal handling
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
go func() {
    <-sigCh
    term.Restore(int(os.Stdin.Fd()), oldState)
    os.Exit(0)
}()

3. Controlling Screen Display

Using ANSI escape sequences to control screen display:

// Hide cursor
fmt.Print("\033[?25l")
defer fmt.Print("\033[?25h") // Restore display on exit

// Clear screen
fmt.Print("\033[2J")

// Move cursor position (to x=10, y=5)
fmt.Printf("\033[%d;%dH", 5, 10)

4. Performance Optimization

Here are some points to ensure display stability:

Implementation Points

1. Error Handling and Recovery

// Recovery process during panic
defer func() {
    if r := recover(); r != nil {
        term.Restore(int(os.Stdin.Fd()), oldState)
        fmt.Printf("Recovered from panic: %v\n", r)
    }
}()

2. Cross-Platform Support

var clear string
if runtime.GOOS == "windows" {
    clear = "cls"
} else {
    clear = "clear"
}
cmd := exec.Command(clear)
cmd.Stdout = os.Stdout
cmd.Run()

Conclusion

Developing TUI applications with x/term requires low-level control, but it offers a high degree of freedom. The typing game implementation example I created demonstrates basic patterns, but you can apply these to create various TUI applications.

Reference Links

Tags: TUI CLI Game
Share: 𝕏 Post Facebook Hatena
✏️ View source / Discuss on GitHub
☕ Support

If you enjoy this blog, consider supporting it. Every bit helps keep it running!


Related Articles