x icon indicating copy to clipboard operation
x copied to clipboard

bug: x/ansi incorrect calculations of \t

Open lrstanley opened this issue 1 month ago • 3 comments

Description

Currently, ansi.StringWidth(), ansi.StringWidthWc(), etc, incorrectly calculate \t (tab) characters. I am not sure if this is intended behavior or not. If it is, documentation should probably be updated to make it clear that users should strip those values out of their input.

Example test:

package main

import (
    "fmt"

    "github.com/charmbracelet/x/ansi"
)

func main() {
    fmt.Println(ansi.StringWidth("\t"))
}

Returns 0. Using \ttest returns 4.

Version

master

Environment

Linux (Windows 11 & WSL2) / Windows Terminal / na

lrstanley avatar Nov 11 '25 02:11 lrstanley

Hey @lrstanley, thank you for flagging this one. This is indeed intentional. A tab character width depends on the context where it's being used. For example, on your favorite editor, you probably have a default setting for how wide a tab should be. Most set it to 4 by default. Some people prefer 8 etc. Thus, it has a width of zero the same as other C0 control characters.

aymanbagabas avatar Nov 18 '25 15:11 aymanbagabas

Hey @lrstanley, thank you for flagging this one. This is indeed intentional. A tab character width depends on the context where it's being used. For example, on your favorite editor, you probably have a default setting for how wide a tab should be. Most set it to 4 by default. Some people prefer 8 etc. Thus, it has a width of zero the same as other C0 control characters.

Would it make sense to have this be explicitly documented in the godoc for those methods? And any other common values which may have the same effect? I figure tab in particular is probably common to trip folks up. I suspect that since it's also not handled automatically by things like bubbles, maybe that should be accounted for as well. E.g. viewport v2 just accepts them as-is in input strings without replacing them, which breaks all sorts of things with layout, wrapping, etc.

lrstanley avatar Nov 18 '25 22:11 lrstanley

Would it make sense to have this be explicitly documented in the godoc for those methods? And any other common values which may have the same effect? I figure tab in particular is probably common to trip folks up. I suspect that since it's also not handled automatically by things like bubbles, maybe that should be accounted for as well. E.g. viewport v2 just accepts them as-is in input strings without replacing them, which breaks all sorts of things with layout, wrapping, etc.

Yes, that would be much appreciated. It might be helpful to put a comment on how to replace tabs using strings.ReplaceAll

aymanbagabas avatar Nov 19 '25 14:11 aymanbagabas