twwidth

package
v0.0.0-...-709355e Latest Latest
Warning

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

Go to latest
Published: Jun 21, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package twwidth provides intelligent East Asian width detection.

In 2025/2026, most modern terminal emulators (VSCode, Windows Terminal, iTerm2, Alacritty) and modern monospace fonts (Hack, Fira Code, Cascadia Code) treat box-drawing characters as Single Width, regardless of the underlying OS Locale.

Detection Logic (in order of priority): - RUNEWIDTH_EASTASIAN environment variable (explicit user override) - Force Legacy Mode (programmatic override for backward compatibility) - Modern environment detection (VSCode, Windows Terminal, etc. -> Narrow) - Locale-based detection (CJK locales in traditional terminals -> Wide)

This prioritization ensures that: - Users can always override behavior using RUNEWIDTH_EASTASIAN - Modern development environments work correctly by default - Traditional CJK terminals maintain compatibility via locale checks

Examples:

// Force narrow borders (for Hack font in zh_CN)
RUNEWIDTH_EASTASIAN=0 go run .

// Force wide borders (for legacy CJK terminals)
RUNEWIDTH_EASTASIAN=1 go run .

width.go

Index

Constants

View Source
const (
	EnvLCAll              = "LC_ALL"
	EnvLCCtype            = "LC_CTYPE"
	EnvLang               = "LANG"
	EnvRuneWidthEastAsian = "RUNEWIDTH_EASTASIAN"
	EnvTerm               = "TERM"
	EnvTermProgram        = "TERM_PROGRAM"
	EnvTermProgramWsl     = "TERM_PROGRAM_WSL"
	EnvWTProfile          = "WT_PROFILE_ID" // Windows Terminal
	EnvConEmuANSI         = "ConEmuANSI"    // ConEmu
	EnvAlacritty          = "ALACRITTY_LOG" // Alacritty
	EnvVTEVersion         = "VTE_VERSION"   // GNOME/VTE
)

Environment Variable Constants

Variables

This section is empty.

Functions

func Display

func Display(cond *runewidth.Condition, str string) int

Display calculates the visual width of a string using a specific runewidth.Condition. Deprecated: use WidthWithOptions with the new twwidth.Options struct instead. This function is kept for backward compatibility.

func EastAsianConservative

func EastAsianConservative() bool

EastAsianConservative is a stricter version that only defaults to Narrow if the terminal is definitely known to be modern (e.g. VSCode, iTerm2). It avoids heuristics like checking "xterm" in the TERM variable.

func EastAsianDetect

func EastAsianDetect() bool

EastAsianDetect checks the environment variables to determine if East Asian width calculations should be enabled.

func EastAsianForceLegacy

func EastAsianForceLegacy(force bool)

EastAsianForceLegacy forces the detection logic to ignore modern environment checks. It relies solely on Locale detection. This is useful for applications that need strict backward compatibility.

Note: This does NOT override RUNEWIDTH_EASTASIAN. User environment variables take precedence. This should be called before the first table render.

func EastAsianMode

func EastAsianMode() string

EastAsianMode returns the decision path used for the current environment. Useful for debugging why a specific width was chosen.

func Filter

func Filter() *regexp.Regexp

Filter compiles and returns a regular expression for matching ANSI escape sequences, including CSI (Control Sequence Introducer) and OSC (Operating System Command) sequences. The returned regex can be used to strip ANSI codes from strings.

func GetCacheStats

func GetCacheStats() (size, capacity int, hitRate float64)

GetCacheStats returns current cache statistics

func IsEastAsian

func IsEastAsian() bool

IsEastAsian returns the current East Asian width setting. This function is thread-safe.

Example:

if twdw.IsEastAsian() {
	// Handle East Asian width characters
}

func SetCacheCapacity

func SetCacheCapacity(capacity int)

SetCacheCapacity changes the cache size dynamically If capacity <= 0, disables caching entirely

func SetCondition

func SetCondition(cond *runewidth.Condition)

SetCondition sets the global East Asian width setting based on a runewidth.Condition. Deprecated: use SetOptions with the new twwidth.Options struct instead. This function is kept for backward compatibility.

func SetEastAsian

func SetEastAsian(enable bool)

SetEastAsian enables or disables East Asian width handling globally. This function is thread-safe.

Example:

twdw.SetEastAsian(true) // Enable East Asian width handling

func SetForceNarrow

func SetForceNarrow(enable bool)

SetForceNarrow to preserve the new flag, or create a new setter

func SetOptions

func SetOptions(opts Options)

SetOptions sets the global options for width calculation. This function is thread-safe.

func Truncate

func Truncate(s string, maxWidth int, suffix ...string) string

Truncate shortens a string to fit within a specified visual width, optionally appending a suffix (e.g., "..."). It preserves ANSI escape sequences and adds a reset sequence (\x1b[0m) if needed to prevent formatting bleed. The function respects the global East Asian width setting and is thread-safe.

If maxWidth is negative, an empty string is returned. If maxWidth is zero and a suffix is provided, the suffix is returned. If the string's visual width is less than or equal to maxWidth, the string (and suffix, if provided and fits) is returned unchanged.

Example:

s := twdw.Truncate("Hello\x1b[31mWorld", 5, "...") // Returns "Hello..."
s = twdw.Truncate("Hello", 10) // Returns "Hello"

func Width

func Width(str string) int

Width calculates the visual width of a string using the global cache for performance. It excludes ANSI escape sequences and accounts for the global East Asian width setting. This function is thread-safe.

Example:

width := twdw.Width("Hello\x1b[31mWorld") // Returns 10

func WidthNoCache

func WidthNoCache(str string) int

WidthNoCache calculates the visual width of a string without using the global cache.

Example:

width := twdw.WidthNoCache("Hello\x1b[31mWorld") // Returns 10

func WidthWithOptions

func WidthWithOptions(str string, opts Options) int

WidthWithOptions calculates the visual width of a string with specific options, bypassing the global settings and cache. This is useful for one-shot calculations where global state is not desired.

Types

type Detection

type Detection struct {
	AutoUseEastAsian bool       `json:"auto_use_east_asian"`
	DetectionMode    string     `json:"detection_mode"`
	Raw              Enviroment `json:"raw"`
	Derived          State      `json:"derived"`
}

Detection aggregates all debug information regarding East Asian width detection.

func Debugging

func Debugging() Detection

Debugging returns detailed information about the detection decision. Useful for users to include in Github issues.

type Enviroment

type Enviroment struct {
	GOOS                string `json:"goos"`
	LC_ALL              string `json:"lc_all"`
	LC_CTYPE            string `json:"lc_ctype"`
	LANG                string `json:"lang"`
	RUNEWIDTH_EASTASIAN string `json:"runewidth_eastasian"`
	TERM                string `json:"term"`
	TERM_PROGRAM        string `json:"term_program"`
}

type Options

type Options struct {
	EastAsianWidth bool

	// Explicitly force box drawing chars to be narrow
	// regardless of EastAsianWidth setting.
	ForceNarrowBorders bool
}

Options allows for configuring width calculation on a per-call basis.

type State

type State struct {
	NormalizedLocale   string `json:"normalized_locale"`
	IsCJKLocale        bool   `json:"is_cjk_locale"`
	IsModernEnv        bool   `json:"is_modern_env"`
	LegacyOverrideMode bool   `json:"legacy_override_mode"`
}

State captures the calculated internal state.

Jump to

Keyboard shortcuts

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