README.md

# string_width

[![Package Version](https://img.shields.io/hexpm/v/string_width)](https://hex.pm/packages/string_width)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/string_width/)

```sh
gleam add string_width@3
```

A small package estimating the required number of cells when printing a string on the terminal. It supports all Gleam targets, handles ANSI escape codes, includes useful layout functions, and passes the tests of the NPM [string-width](https://www.npmjs.com/package/string-width) package, among others.

It is also one of the fastest options available, even including target-specific ones, while still providing you full flexibility and correctness.

```gleam
import string_width

pub fn main() {
  string_width.dimensions("hello,\n안녕하세요")
  // --> string_width.Size(rows: 2, columns: 10)

  string_width.line_with(
    "👩‍👩‍👦‍👦",
    string_width.new() |> string_width.mode_2027,
  )
  // --> 2

  // word wrapping and truncation
  string_width.limit(
    "Lorem ipsum dolor sit amet\nIs a common placeholder string",
    to: Size(rows: 3, columns: 10),
    ellipsis: "..."
  )
  // --> "Lorem ipsum dolor\nsit amet\nIs a common place..."

  // position a string inside a box
  string_width.position(
    "XXX",
    in: Size(rows: 3, columns: 10),
    align: Center,
    place: Middle,
    with: "."
  )
  // --> "..........\n...XXX....\n.........."
}
```


### Limitations

- Many terminals don't support grapheme clusters properly, so by default, the
  values returned by this library try to match the behaviour of libc instead
  of modern text rendering pipelines.

  If you encounter a mismatch that is consistent across multiple environments,
  feel free to open an issue or ping me on Discord!

- The behaviour when encountering stray variant selectors does not match other similar libraries.


### Sources

The table lookup technique used by this library is heavily based on the musl libc `wcwidth` implementation. I built updated tables using the Unicode 16.0 data, and added support for ambiguous characters. It also uses the regex of the ansi-regex npm package, and the test cases of the string-width npm package.


- **UAX #11 East Asian Width:** [https://www.unicode.org/reports/tr11/](https://www.unicode.org/reports/tr11/)
- **Grapheme Clusters in Terminals:** [https://mitchellh.com/writing/grapheme-clusters-in-terminals](https://mitchellh.com/writing/grapheme-clusters-in-terminals)
- **get-east-asian-width:** [https://github.com/sindresorhus/get-east-asian-width](https://github.com/sindresorhus/get-east-asian-width)
- **string-width:** [https://github.com/sindresorhus/string-width](https://github.com/sindresorhus/string-width)
- **ansi-regex:** [https://github.com/chalk/ansi-regex](https://github.com/chalk/ansi-regex)
- **musl-libc wcwidth:** [https://git.musl-libc.org/cgit/musl/tree/src/ctype/wcwidth.c](https://git.musl-libc.org/cgit/musl/tree/src/ctype/wcwidth.c)
- **glibc wcwidth:** [https://sourceware.org/git/?p=glibc.git;a=blob;f=wcsmbs/wcwidth.h;hb=HEAD](https://sourceware.org/git/?p=glibc.git;a=blob;f=wcsmbs/wcwidth.h;hb=HEAD)