twwidth

package
v1.1.4 Latest Latest
Warning

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

Go to latest
Published: Mar 4, 2026 License: MIT Imports: 12 Imported by: 1

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 .

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 added in v1.1.3

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 added in v1.1.3

func EastAsianDetect() bool

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

func EastAsianForceLegacy added in v1.1.3

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 added in v1.1.3

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 added in v1.1.2

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

GetCacheStats returns current cache statistics

func IsEastAsian added in v1.1.1

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 IsTab added in v1.1.4

func IsTab(r rune) bool

IsTab returns true if r is a tab rune.

func SetCacheCapacity added in v1.1.2

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 added in v1.1.3

func SetForceNarrow(enable bool)

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

func SetOptions added in v1.1.2

func SetOptions(opts Options)

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

func SetTabWidth added in v1.1.4

func SetTabWidth(w int)

SetTabWidth sets the global tab width.

func TabWidth added in v1.1.4

func TabWidth() int

TabWidth returns the detected global tab width.

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 added in v1.1.2

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 added in v1.1.3

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 added in v1.1.3

func Debugging() Detection

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

type Enviroment added in v1.1.3

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 added in v1.1.2

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 added in v1.1.3

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.

type Tab added in v1.1.4

type Tab rune
const (
	TabWidthDefault     = 8
	TabString       Tab = '\t'
)

func (Tab) Byte added in v1.1.4

func (t Tab) Byte() byte

func (Tab) IsTab added in v1.1.4

func (t Tab) IsTab() bool

IsTab returns true if t equals the default tab.

func (Tab) Rune added in v1.1.4

func (t Tab) Rune() rune

func (Tab) String added in v1.1.4

func (t Tab) String() string

type Tabinal added in v1.1.4

type Tabinal struct {
	// contains filtered or unexported fields
}

func TabInstance added in v1.1.4

func TabInstance() *Tabinal

TabInstance returns the singleton Tabinal.

func (*Tabinal) SetWidth added in v1.1.4

func (t *Tabinal) SetWidth(w int)

SetWidth sets the tab width if valid (1–32).

func (*Tabinal) Size added in v1.1.4

func (t *Tabinal) Size() int

Size returns the current tab width, default if unset.

func (*Tabinal) String added in v1.1.4

func (t *Tabinal) String() string

Jump to

Keyboard shortcuts

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