zero also inserts a space, but after trying using text.tracking, it appears that any visual spacing is considered by a PDF viewer as a space. So the only thing that worked is using 0.14 em or less.
text.tracking
#let format-number(num, group-spacing: 0.2em) = {
let parts = num
.split("_")
.map(part => {
let clusters = part.clusters()
if clusters.len() == 1 {
(part, none, none)
} else if clusters.len() == 2 {
let (first, last) = clusters
(first, none, last)
} else {
let (first, ..middle, last) = clusters
(first, middle.join(), last)
}
})
let previous-last
let with-spacing(a, b) = text(tracking: group-spacing, a + b)
for (i, (first, middle, last)) in parts.enumerate() {
if last == none and middle == none {
if i + 1 == parts.len() {
with-spacing(previous-last, first)
}
previous-last = first
} else if last == none and middle != none {
with-spacing(previous-last, first)
if i + 1 == parts.len() { middle }
previous-last = middle
} else {
with-spacing(previous-last, first)
middle
if i + 1 == parts.len() { last }
previous-last = last
}
}
}
#format-number("1_234_567_890")
#let format-number(num, group-spacing: 0.2em) = {
let parts = num
.text
.split()
.map(part => {
let clusters = part.clusters()
if clusters.len() == 1 {
(part, none, none)
} else if clusters.len() == 2 {
let (first, last) = clusters
(first, none, last)
} else {
let (first, ..middle, last) = clusters
(first, middle.join(), last)
}
})
let previous-last
for (i, (first, middle, last)) in parts.enumerate() {
if last == none and middle == none {
if i + 1 == parts.len() {
text(tracking: group-spacing, previous-last + first)
}
previous-last = first
} else if last == none and middle != none {
text(tracking: group-spacing, previous-last + first)
if i + 1 == parts.len() { middle }
previous-last = middle
} else {
text(tracking: group-spacing, previous-last + first)
middle
if i + 1 == parts.len() { last }
previous-last = last
}
}
}
#format-number[1 234 567 890]
#let format-number(num, group-spacing: 0.2em) = {
let parts = num
.text
.clusters()
.rev()
.chunks(3)
.map(array.rev)
.rev()
.map(clusters => {
if clusters.len() == 1 {
(..clusters, none, none)
} else if clusters.len() == 2 {
let (first, last) = clusters
(first, none, last)
} else {
let (first, ..middle, last) = clusters
(first, middle.join(), last)
}
})
let previous-last
for (i, (first, middle, last)) in parts.enumerate() {
if last == none and middle == none {
if i + 1 == parts.len() {
text(tracking: group-spacing, previous-last + first)
}
previous-last = first
} else if last == none and middle != none {
text(tracking: group-spacing, previous-last + first)
if i + 1 == parts.len() { middle }
previous-last = middle
} else {
text(tracking: group-spacing, previous-last + first)
middle
if i + 1 == parts.len() { last }
previous-last = last
}
}
}
#format-number[1234567890]