Contents

ainame/swift-displaywidth

wcwidth implementation with the latest Unicode spec

Why use this?

Instead of this library, there's wcwidth imported with import Darwin, import Musl, or import Glibc.

  • https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/wcwidth.3.html
  • https://www.gnu.org/software/gnulib/manual/html_node/wcwidth.html
  • https://git.musl-libc.org/cgit/musl/tree/src/ctype/wcwidth.c

If that meets your requirements, you should just use it. However, this project has following superior points.

  • Portable/Cross-platform implementation that doesn't require a C library nor even Foundation
  • Up-to-date Unicode spec
  • Better support of Unicode grapheme clusters
  • Swift-friendly API

Usage

Add to your Package.swift:

dependencies: [
    .package(url: "https://github.com/ainame/swift-displaywidth", from: "0.1.0")
]

Then:

import DisplayWidth

// call as function
let baseDisplayWidth = DisplayWidth()
baseDisplayWidth("A")        // 1
baseDisplayWidth("あ")       // 2
baseDisplayWidth("👩‍💻")       // 2
baseDisplayWidth("e\u{0301}") // 1 (e + combining acute)

// If your environment treat ambiguous chars as full-width,
// you can set this option.
let ambiguousWidth = DisplayWidth(treatAmbiguousAsFullWidth: true)
import DisplayWidth

// ANSI escape sequences can be ignored during string measurement.
let ansiAwareDisplayWidth = DisplayWidth(stripsANSI: true)
ansiAwareDisplayWidth("\u{001B}[31mhello\u{001B}[0m") // 5

// Tabs can advance to the next tab stop every 4 columns.
let tabStopsDisplayWidth = DisplayWidth(tab: .tabStops(4))
tabStopsDisplayWidth("a\tb") // 5

// Or each tab can count as a fixed number of spaces.
let fixedTabsDisplayWidth = DisplayWidth(tab: .fixedSpaces(3))
fixedTabsDisplayWidth("a\tb") // 5

stripsANSI and tab affect string measurement only. Character and scalar measurement keep their existing behavior. DisplayWidth.Tab.tabStops(n) uses terminal-style tab stops, while .fixedSpaces(n) counts each tab as exactly n columns. For example, with 3, "a\tb" is width 4 with .tabStops(3) and width 5 with .fixedSpaces(3).

Diagram with 4:

.tabStops(4)
tab stops: 4, 8, 12, ...

"a\tb"    = 1 + 3 + 1 = 5
"ab\tb"   = 2 + 2 + 1 = 5
"abcd\tb" = 4 + 4 + 1 = 9

.fixedSpaces(4)
every tab = 4

"a\tb"    = 1 + 4 + 1 = 6
"ab\tb"   = 2 + 4 + 1 = 7
"abcd\tb" = 4 + 4 + 1 = 9

Reference: Tab stop

Package Metadata

Repository: ainame/swift-displaywidth

Stars: 4

Forks: 0

Open issues: 0

Default branch: main

Primary language: swift

License: MIT

Topics: swift, tui, unicode

README: README.md