Cor, tabela e o terminal que não é terminal
Colorir sem estragar o | grep, e desenhar tabela, árvore e barra sem dependência.
A regra que quase todo programa de terminal erra: cor só quando a saída é um terminal. Canalizado para um arquivo ou para o grep, o código de escape vira lixo no meio do dado — e um grep "erro" deixa de casar porque há um \x1b[31m grudado na palavra.
dataforge
adopt Arcane.Color as Cor
adopt Arcane.OS as OS
// 'auto' decide pelo terminal; 'supports' responde o que ele aceita
assert Cor.supports() is yes or Cor.supports() is no
// E 'strip' tira a cor de um texto já colorido — é o que um teste faz.
pintado := Cor.red("falhou")
assert Cor.strip(pintado) is "falhou"
out Cor.strip(Cor.bold(Cor.green("ok")))Tabela#
dataforge
adopt Arcane.Color as Cor
linhas := [
["produto", "qtd", "preço"],
["café", "12", "R$ 32,90"],
["filtro", "3", "R$ 8,50"],
]
desenho := Cor.table(linhas)
assert "produto" in desenho
out desenhoÁrvore, régua e barra#
dataforge
adopt Arcane.Color as Cor
out Cor.rule("Relatório")
out Cor.tree({"projeto": {"src": ["main.df", "util.df"], "tests": ["main_test.df"]}})
out Cor.bar(0.72, 30)
out Cor.box("Concluído em 1,2 s")Progresso que não polui um log#
Uma barra que se reescreve com \r é ótima num terminal e é uma linha por quadro num arquivo de log. A saída é perguntar antes:
dataforge
adopt Arcane.Color as Cor
adopt Arcane.OS as OS
action progresso(feito, total):
given not OS.is_tty():
// canalizado: uma linha por marco, e só
given feito % 50 is 0:
out $" {feito}/{total}"
yield void
out $"\r {Cor.bar(feito / total, 24)} {feito}/{total}"
yield void
cycle i from 1 to 100:
given i % 50 is 0:
progresso(i, 100)
out ""A largura do terminal#
dataforge
adopt Arcane.Cli as Cli
adopt Arcane.Color as Cor
largura := Cli.largura()
assert largura > 0
// Sem terminal, ela devolve um padrão — e é por isso que ela nunca é
// zero: uma divisão por largura no meio do desenho estouraria.
out $"largura: {largura} colunas"