///|
/// `text` cut into lines no wider than `columns` terminal cells, breaking where
/// UAX #14 allows and always where it requires. A piece wider than `columns`
/// on its own stays whole.
fn wrap(text : String, columns : Int32) -> Array[String] {
  let lines = []
  let mut start = 0
  let mut fit = 0
  let line = fn(a, b) { text.exact_view(start=a, end=b).trim_end() }
  for brk in [..@linebreak.breaks(text), (text.length(), true)] {
    let (at, must) = brk
    if fit > start && @width.text_width(line(start, at)) > columns {
      lines.push(line(start, fit).to_owned())
      start = fit
    }
    fit = at
    if must {
      lines.push(line(start, at).to_owned())
      start = at
    }
  }
  lines
}

///|
/// `text` cut down to `columns` cells with a trailing ellipsis, never splitting
/// a user-perceived character.
fn truncate(text : String, columns : Int32) -> String {
  if @width.text_width(text) <= columns {
    return text
  }
  let out = StringBuilder()
  let mut used = 1
  for g in @segment.grapheme_clusters(text) {
    used += @width.text_width(g)
    if used > columns {
      break
    }
    out.write_string(g)
  }
  out.write_string("…")
  out.to_string()
}

///|
/// `text` padded with spaces to `columns` cells.
fn pad(text : String, columns : Int32) -> String {
  text + " ".repeat(columns - @width.text_width(text))
}

///|
fn main {
  let text = "MoonBit 把 Unicode 的断行规则用在终端里:English words wrap at spaces, 中文在字与字之间断开。"
  println("wrap at 24 cells")
  println("+" + "-".repeat(24) + "+")
  for l in wrap(text, 24) {
    println("|" + pad(l, 24) + "|")
  }
  println("+" + "-".repeat(24) + "+")
  println("")
  println("truncate to 12 cells")
  for
    s in [
      "Hello, world!", "你好,世界!欢迎光临", "🇨🇳🇬🇧🇫🇷🇩🇪🇯🇵🇺🇸🇮🇳",
      "e\u{301}e\u{301}e\u{301}e\u{301}e\u{301}e\u{301}e\u{301}e\u{301}e\u{301}e\u{301}e\u{301}e\u{301}e\u{301}",
    ] {
    println("  [" + pad(truncate(s, 12), 12) + "]")
  }
}