ADRIANOLAUREANO← Artigos
SÉRIE TRAÇO · 02/03LAYOUTFITS

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?

ARTIGO 34 · TRAÇO 0.2 · MOTOR DE LAYOUT

7operadores de documento

3larguras demonstradas

1decisão fits por grupo

TRAÇO · ESTRUTURA, ALTERNATIVAS E PROVA
ENTRADAse(condição){
mostre(valor)//nota
}
TRAÇO 0.2preservar · compor · provar
SAÍDAse (condição) {
··mostre(valor) // nota
}

VOCABULÁRIO VISUAL

As decisões que tornam o resultado confiável.

01Texttrecho que não quebra
02SoftLineespaço ou quebra possível
03Groupalternativa plana ou quebrada
04Indentrecuo após quebra
05IfBreakconteúdo dependente da escolha
06fitsteste limitado do espaço restante
O Traço não “arruma espaços”: ele preserva estrutura, constrói opções de layout e prova a estabilidade da escolha.
01
Imprimir da esquerda para a direita decide cedo demais.
Uma quebra não pode ser desimpressa
mostre(relatorio(usuario, periodo, incluir_detalhes))
                    ↑ só aqui descobrimos que não cabe
saída já emitida → voltar exige buffer e contexto
Primeiro descrevemos alternativas; depois o renderizador escolhe.
02
Código vira um documento ainda não renderizado.
Uma pequena álgebra de layout
OperadorEm linguagem comum
Texttexto indivisível
Linequebra obrigatória
SoftLineespaço se couber, quebra se não
Concatpeças em sequência
Grouptenta forma plana como conjunto
Indentrecuo aplicado após quebras
IfBreakconteúdo que aparece conforme escolha
03
Uma chamada guarda as duas formas ao mesmo tempo.
Group não é apenas um contêiner
Group
├─ Text "soma("
├─ Indent
│  ├─ SoftLine
│  └─ Join(Text "," + SoftLine, [primeiro, segundo])
├─ SoftLine
└─ Text ")"

plano: soma(primeiro, segundo)
quebrado:
soma(
  primeiro,
  segundo
)
As regras constroem a árvore; o renderizador escolhe o modo do grupo.
04
fits responde uma pergunta limitada.
A forma plana cabe no restante?
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.

05
A mesma estrutura em 40, 80 e 120 colunas.
A política permanece; somente fits muda
120: calcular_relatorio(usuario, periodo, detalhes)

80:  calcular_relatorio(
       usuario, periodo, detalhes
     )

40:  calcular_relatorio(
       usuario,
       periodo,
       detalhes
     )
Grupos aninhados permitem que lista interna quebre depois da chamada externa.

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.

06
Bytes não medem largura visual.
O modelo de coluna precisa ser declarado

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.

MedidaUso
bytesintervalos do parser
code pointsiteração Unicode
colunas visuaisdecisão de layout
07
Indentação é estável; alinhamento pode criar cascatas.
Escolhemos recuo relativo
alinhamento: resultado = função(argumento,
                                 outro)  ← depende da coluna inicial
indentação: resultado = função(
  argumento,
  outro
) ← depende somente da estrutura
O Traço prefere indentação para reduzir diffs quando o lado esquerdo muda.
08
Goldens tornam cada escolha observável.
Traço 0.2

Cada 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.

Resposta do capítulo

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.

Baixar Traço 0.2 (.zip)Rust · Pulso · fixtures isoladas

O que este artigo fez você pensar?

Dúvidas, experiências e contrapontos ajudam a próxima pessoa a enxergar o assunto por outro ângulo.

Todos passam por moderação. Ao enviar, você concorda com a política de privacidade.

Receba os próximos artigos.

Uma mensagem quando uma nova investigação estiver pronta. Só isso.