How to center text around a character?

Say I have a string x = "FooBar | Baz". I essentially want to center align x around the character "|". What is the best way to do this? Simply doing align(center)[#x] does not quite work, since "FooBar" and "Baz" are not the same length.

1 Like

Hello. The easiest way would be to compare left and right parts and add the difference to the shorter one:

#context align(center, {
  line(angle: 90deg)
  let x = "FooBar | Baz"
  let center-char = "|"
  let (a, b) = x.split(center-char)
  let width = (a: measure(a).width, b: measure(b).width)
  if width.a < width.b {
    a += h(width.b - width.a)
  } else {
    b += h(width.a - width.b)
  }
  block(a + center-char + b)
  block(x)
})

Or with a function:

#let center-around-char(char, text) = context {
  let (a, b) = text.split(char)
  let width = (a: measure(a).width, b: measure(b).width)
  if width.a < width.b {
    a += h(width.b - width.a)
  } else {
    b += h(width.a - width.b)
  }
  a + char + b
}

#align(center, {
  line(angle: 90deg)
  let x = "FooBar | Baz"
  block(center-around-char("|", x))
  block(x)
})
2 Likes

Here’s an idea using grids:

#let center-around(s, mid) = {
  assert(type(s) == str and type(mid) == str, message: "string and mid must be strings")
  
  let split-res = s.split(mid)
  if split-res.len() < 2 {
    align(center, [#s])
  } else {
    let (before, ..after) = split-res
    // If it appears more than once, center around the first
    let after = after.join(mid)
    grid(
      columns: (1fr, auto, 1fr),
      align: (right, center, left),
      [#before], [#mid], [#after]
    )
  }
}

#center-around("typst | superdupercooldonuts", "|")

// For comparison
#center-around("typst | superdupercooldonuts", "absent")

2 Likes

@Andrew @PgBiel Awesome, thank you all for the solutions! In my simple case, these seem to behave about the same.