Como um formatador decide onde quebrar uma linha?
A mesma chamada cabe em 120 colunas, fica apertada em 80 e precisa virar várias linhas em 40. Como adiar a decisão até conhecer o espaço disponível?
se(condição){
mostre(valor)//nota
}se (condição) {
··mostre(valor) // nota
}VOCABULÁRIO VISUAL
As decisões que tornam o resultado confiável.
mostre(relatorio(usuario, periodo, incluir_detalhes))
↑ só aqui descobrimos que não cabe
saída já emitida → voltar exige buffer e contexto| Operador | Em linguagem comum |
|---|---|
| Text | texto indivisível |
| Line | quebra obrigatória |
| SoftLine | espaço se couber, quebra se não |
| Concat | peças em sequência |
| Group | tenta forma plana como conjunto |
| Indent | recuo aplicado após quebras |
| IfBreak | conteúdo que aparece conforme escolha |
Group
├─ Text "soma("
├─ Indent
│ ├─ SoftLine
│ └─ Join(Text "," + SoftLine, [primeiro, segundo])
├─ SoftLine
└─ Text ")"
plano: soma(primeiro, segundo)
quebrado:
soma(
primeiro,
segundo
)fn fits(mut remaining: usize, queue: &mut Queue) -> bool {
while remaining > 0 {
match next() {
Text(s) => remaining -= visual_width(s),
Line => return true,
Group(doc) => queue.push_flat(doc),
}
}
false
}O teste considera coluna atual, indentação e documentos já enfileirados. Ele para na primeira quebra obrigatória e nunca faz backtracking sem limite.
120: calcular_relatorio(usuario, periodo, detalhes)
80: calcular_relatorio(
usuario, periodo, detalhes
)
40: calcular_relatorio(
usuario,
periodo,
detalhes
)Comentários de fim de linha forçam quebra. Uma URL ou string longa pode ultrapassar o limite: largura máxima orienta alternativas, não corta tokens.
O Traço mede colunas Unicode aproximadas: caracteres largos contam dois, combinantes zero e tab é proibido na saída. Não tenta reproduzir toda fonte proporcional; formatadores trabalham com um modelo monoespaçado documentado.
| Medida | Uso |
|---|---|
| bytes | intervalos do parser |
| code points | iteração Unicode |
| colunas visuais | decisão de layout |
alinhamento: resultado = função(argumento,
outro) ← depende da coluna inicial
indentação: resultado = função(
argumento,
outro
) ← depende somente da estruturaCada fixture possui saídas esperadas em 40, 80 e 120 colunas. Testes cobrem grupos aninhados, comentários, listas vazias, tokens longos e medem nós visitados para impedir comportamento explosivo.
O formatador não quebra quando “chega no limite”. Ele constrói alternativas estruturais e escolhe, grupo por grupo, a forma que cabe no espaço restante.
PROJETO COMPLETO · ESTADO EXATO DESTE CAPÍTULO
Baixe o Traço 0.2.
Pacote exclusivo com código Rust, corpus Pulso, testes e limites documentados. O modo check nunca modifica arquivos.