term

package
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 23, 2025 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package term provides terminal utilities for width detection, string handling, and flexible layout systems. It includes ANSI-aware string processing, multi-column layouts, and responsive design utilities used by progress bars, frames, and other UI components.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsTTY

func IsTTY() bool

IsTTY returns true if the current environment supports TTY operations and ANSI escape sequences. This is used to determine whether cursor positioning and other terminal control sequences will work.

Example:

if term.IsTTY() {
	// Use ANSI escape sequences for cursor control
	fmt.Print("\033[1A\033[K")
} else {
	// Fall back to simpler output without cursor control
	fmt.Println("Updated content")
}

func PrintableWidth

func PrintableWidth(s string) int

PrintableWidth returns the width of printable characters in a string, excluding ANSI escape sequences. This function correctly handles Unicode characters, emojis, and wide characters.

Examples:

PrintableWidth("hello")                    // Returns: 5
PrintableWidth("\033[31mhello\033[0m")     // Returns: 5 (ignores ANSI codes)
PrintableWidth("你好")                      // Returns: 4 (wide characters)
PrintableWidth("hello 👋")                 // Returns: 8 (emoji counts as 2)

func StripCodes

func StripCodes(s string) string

StripCodes returns the printable characters in a string, excluding ANSI escape sequences. This function correctly handles Unicode characters, emojis, and wide characters.

Examples:

StripCodes("hello")                    // Returns: "hello"
StripCodes("\033[31mhello\033[0m")     // Returns: "hello"
StripCodes("你好")                      // Returns: "你好"
StripCodes("hello 👋")                 // Returns: "hello 👋"

func TruncateAndPad

func TruncateAndPad(text string, maxWidth int) string

TruncateAndPad truncates text to fit within maxWidth and pads it to exactly that width. If the text is longer than maxWidth, it's truncated with "..." suffix. If shorter, it's padded with spaces to reach exactly maxWidth.

func TruncateString

func TruncateString(s string, maxWidth int) string

TruncateString truncates a string to the specified printable width while preserving ANSI escape sequences. The function correctly handles Unicode characters, emojis, and ANSI color codes. If maxWidth is 0 or negative, it returns an empty string.

Examples:

TruncateString("hello world", 5)                      // Returns: "hello"
TruncateString("\033[31mhello world\033[0m", 5)       // Returns: "\033[31mhello"
TruncateString("你好世界", 6)                          // Returns: "你好世" (wide chars)
TruncateString("hello 👋 world", 8)                   // Returns: "hello 👋"

func Width

func Width() int

Width returns the current terminal width in columns. If the terminal width cannot be detected (e.g., when not running in a TTY), it returns a default width of 120 columns.

Example:

width := term.Width()
if width < 80 {
	fmt.Println("Terminal is too narrow for optimal display")
}

Types

type SectionLayout

type SectionLayout struct {
	TotalWidth int       // Total available width
	Widths     []float64 // Relative widths for each section (e.g., [0.2, 0.6, 0.2] or [1, 3, 1])
	MinWidths  []int     // Minimum widths for each section (optional, can be nil)
}

SectionLayout represents a flexible layout with variable number of columns and their relative widths. The Widths slice contains relative proportions (they don't need to sum to 1.0 or 100%). MinWidths contains the minimum width for each section (optional, can be nil).

func NewSectionLayout

func NewSectionLayout(totalWidth int, weights ...float64) SectionLayout

NewSectionLayout creates a new SectionLayout with the given total width and relative proportions. The weights represent relative proportions and don't need to sum to 1.0 or 100%.

Examples:

// 3-column layout with 20%, 60%, 20% proportions
layout := term.NewSectionLayout(100, 1, 3, 1)
widths := layout.SectionWidths() // Returns [20, 60, 20]

// 2-column layout with equal proportions
layout := term.NewSectionLayout(80, 0.5, 0.5)
widths := layout.SectionWidths() // Returns [40, 40]

// Layout with minimum widths to prevent column collapse
layout := term.NewSectionLayout(50, 2, 1, 1)
layout = layout.WithMinWidths(15, 10, 10)
widths := layout.SectionWidths() // Ensures minimums are respected

This is commonly used by progress bars for title/bar/message layout.

func (SectionLayout) SectionWidths

func (l SectionLayout) SectionWidths() []int

SectionWidths calculates the actual widths for each section, applying minimums and proportional reduction if the total exceeds available width.

func (SectionLayout) WithMinWidths

func (l SectionLayout) WithMinWidths(minWidths ...int) SectionLayout

WithMinWidths sets minimum widths for each section and returns the updated layout. This method ensures that no section will be smaller than its minimum width, even when proportional scaling would make it smaller.

Example:

// Create layout with minimum constraints
layout := term.NewSectionLayout(100, 1, 3, 1).WithMinWidths(15, 20, 10)
widths := layout.SectionWidths() // Ensures sections are at least 15, 20, 10 wide

// Without minimums: might get [20, 60, 20]
// With minimums: might get [20, 60, 20] or [15, 65, 20] depending on constraints

If the sum of minimum widths exceeds the total width, the layout will still attempt to fit all sections by proportionally reducing non-minimum space.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL