Skill: adicionar-svgbob-rust
As referências a arquivos (@caminho) nesta skill são relativas a este diretório.
O que eu faço
Eu adiciono diagramas ASCII aos comentários de documentação /// do Rust usando a macro transform!() da crate svgbobdoc. O ASCII art dentro de blocos de código ```svgbob é convertido em SVG inline em tempo de compilação e incorporado como URIs data:image/svg+xml — sem necessidade de arquivos externos, funciona tanto no cargo doc local quanto no docs.rs.
O diagrama vive no próprio código-fonte — qualquer pessoa que ler o arquivo Rust verá o ASCII art diretamente.
Quando me usar
Use esta skill quando:
- Você tem uma biblioteca Rust com conceitos estruturais/arquiteturais melhor explicados com um diagrama
- Você deseja fluxogramas rápidos, diagramas de processo ou visuais de fluxo de dados sem arquivos de imagem externos
- O diagrama é simples o suficiente para ser representado com caracteres ASCII de desenho de caixas
- Você quer diagramas que sejam visíveis no código-fonte (não ocultos em PNGs externos)
- Você mantém uma crate onde o peso da dependência
svgbobdocé aceitável
Não adequado para:
- Visualizações de dados reais (gráficos de dispersão, gráficos de linha) — use
embed-doc-imageem vez disso - Diagramas complexos com caminhos curvos ou detalhes finos — o ASCII art tem limitações
- Projetos em compiladores Rust muito antigos (< 1.54)
Pré-requisitos
| Requisito | Propósito |
|---|---|
| Rust ≥ 1.54 ou nightly | Para suporte a atributo interno + macro proc |
svgbobdoc nas dependências | A crate de macro proc |
feature enable no svgbobdoc | Ativa o renderizador SVG svgbob |
Flag de feature doc-images (ou personalizada) | Gate de feature para compatibilidade |
| Metadados do docs.rs configurados | Garante que os SVGs renderizem no docs.rs |
Como eu trabalho
Passo 1: Verificar o estado atual
Leia Cargo.toml para verificar se svgbobdoc já está configurado:
svgbobdocestá em[dependencies]comfeatures = ["enable"]?- É opcional (recomendado)?
- Existe uma feature
doc-imagesou similar para ativá-lo? [package.metadata.docs.rs]incluifeatures = ["doc-images"]?
Verifique os arquivos fonte para uso existente de ```svgbob ou chamadas svgbobdoc::transform!().
Passo 2: Configurar infraestrutura (se ausente)
Se svgbobdoc não estiver configurado, adicione:
Adições ao Cargo.toml:
[dependencies]
svgbobdoc = { version = "0.3", optional = true, features = ["enable"] }
[features]
doc-images = ["dep:svgbobdoc"]
[package.metadata.docs.rs]
features = ["doc-images"]
Se embed-doc-image também for usado, combine sob a mesma feature:
[features]
doc-images = ["dep:embed-doc-image", "dep:svgbobdoc"]
Passo 3: Escanear o projeto
Procure recursivamente em <projeto>/src/ por arquivos *.rs. Identifique candidatos a diagrama — tipos e funções onde um diagrama ASCII esclareceria o conceito.
Passo 4: Identificar candidatos a diagrama
Uma função/tipo/módulo é um "candidato a diagrama" quando:
| Sinal | Exemplo |
|---|---|
| Fluxo de dados | Entrada → Processamento → Saída |
| Etapas de processo | Algoritmo com estágios claros |
| Mapeamento de coordenadas | (x, y) → coordenadas transformadas |
| Transformação geométrica | Rotação, projeção, escala |
| Estrutura de árvore/grafo | Árvore binária, netlist, grafo de dependência |
| Arquitetura | Hierarquia de módulos, estágios de pipeline |
| Máquina de estados | Estados e transições |
| Comparação | Antes vs Depois, duas alternativas |
| Layout | Planta baixa, layout de memória, empacotamento |
Passo 5: Projetar o diagrama ASCII
Capacidades de renderização do svgbob:
| Elemento ASCII | Renderização svgbob |
|---|---|
.─. / '─' | Bordas de retângulo arredondado |
│ / ─ | Linhas |
/ / \ | Linhas diagonais |
► / ▼ / ▲ / ◄ | Pontas de seta (Unicode) |
-> / <- | Conectores de seta |
=== / ~~~ | Linhas duplas/onduladas |
( ) / [ ] | Colchetes curvos/angulares |
○ / ● | Marcadores de círculo |
... | Conectores tracejados |
Dicas de design para diagramas claros:
- Mantenha compacto — máximo de 15-25 linhas por diagrama
- Use bordas de caixa —
.───.para o topo,'───'para o fundo - Rotule setas — Adicione texto ao lado dos conectores
──► - Alinhe com desenho de caixas Unicode —
─ │ ┌ ┐ └ ┘ ├ ┤ ┬ ┴ ┼ - Teste o diagrama — Use o editor svgbob para pré-visualizar
Exemplo — um fluxo de dados simples:
.───────────. .───────────. .───────────.
│ Entrada │────►│ Processo │────►│ Saída │
'───────────' '───────────' '───────────'
Passo 6: Adicionar o diagrama
Para documentação de struct:
/// Descrição existente.
///
/// O fluxo de transformação:
#[cfg_attr(feature = "doc-images", doc = svgbobdoc::transform!(
/// ```svgbob
/// .───────────. .───────────.
/// │ Passo 1 │────►│ Passo 2 │
/// '───────────' '───────────'
/// ```
))]
pub struct MeuTipo { ... }
Para documentação de função:
/// Descrição.
#[cfg_attr(feature = "doc-images", doc = svgbobdoc::transform!(
/// ```svgbob
/// .───────────. .───────────.
/// │ Input x │────►│ Output f(x)│
/// '───────────' '───────────'
/// ```
))]
pub fn minha_funcao(x: f64) -> f64 { ... }
IMPORTANTE: As linhas /// dentro de transform!() devem ser preservadas exatamente. A macro analisa /// como linhas de comentário de documentação e processa blocos ```svgbob dentro delas.
Passo 7: Compilar e verificar
# Compilar com diagramas
cargo doc --features doc-images --no-deps --open
Lista de verificação:
-
cargo build(sem features) passa — sem vazamento de dependência do svgbobdoc -
cargo build --features doc-imagespassa — a macrotransform!()é executada -
cargo doc --features doc-images --no-depscompleta com zero avisos - O HTML gerado contém URIs
data:image/svg+xml;base64,... - Os SVGs renderizam corretamente no navegador (setas, caixas, texto adequados)
# Verificar URIs de dados SVG em cada página de struct
grep -c "data:image/svg" target/doc/minha_crate/struct.MeuTipo.html
Passo 8: Verificar ambos os estados de feature
cargo build # Deve passar (svgbobdoc não vinculado)
cargo build --features doc-images # Deve passar (transform! executa)
cargo test --all-features # Todos os testes devem passar
Referência de Configuração
Cargo.toml básico (apenas svgbobdoc)
Configuração mínima para um projeto usando apenas svgbobdoc:
[package]
name = "minha-crate"
version = "0.1.0"
edition = "2024"
[dependencies]
svgbobdoc = { version = "0.3", optional = true, features = ["enable"] }
[features]
doc-images = ["dep:svgbobdoc"]
[package.metadata.docs.rs]
features = ["doc-images"]
Combinado com embed-doc-image
Ao usar tanto svgbobdoc (diagramas ASCII) quanto embed-doc-image (figuras PNG/SVG):
[dependencies]
embed-doc-image = { version = "0.1", optional = true }
svgbobdoc = { version = "0.3", optional = true, features = ["enable"] }
[features]
doc-images = ["dep:embed-doc-image", "dep:svgbobdoc"]
[package.metadata.docs.rs]
features = ["doc-images"]
Ambos compartilham a mesma feature doc-images — um cargo doc --features doc-images ativa ambos.
Nomes de feature personalizados
Se seu projeto já tem uma feature doc-images para outros propósitos, use um nome diferente:
[features]
default = []
svg-docs = ["dep:svgbobdoc"] # Nome personalizado
doc-images = ["dep:embed-doc-image"] # Nome existente
Então no código-fonte:
#[cfg_attr(feature = "svg-docs", doc = svgbobdoc::transform!(
/// ```svgbob
/// diagrama
/// ```
))]
pub struct MeuTipo;
Resolução de features com a sintaxe dep:
O prefixo dep: em definições de features foi estabilizado no Rust 1.60. Ele referencia explicitamente uma dependência opcional:
# Sintaxe moderna (Rust ≥ 1.60) — recomendada:
doc-images = ["dep:svgbobdoc"]
# Sintaxe legada — funciona, mas menos explícita:
doc-images = ["svgbobdoc"]
A forma dep: é preferida — ela previne ambiguidade entre nomes de dependência e feature.
Opções de metadados do docs.rs
| Configuração | Propósito |
|---|---|
features = ["doc-images"] | Ativa svgbobdoc durante a compilação da documentação |
rustdoc-args = ["--html-in-header", "src/doc-header.html"] | Injeta cabeçalhos KaTeX/JS |
all-features = true | Compila documentação com TODAS as features (use com cuidado) |
[package.metadata.docs.rs]
features = ["doc-images"]
rustdoc-args = ["--html-in-header", "src/doc-header.html"]
Compilação condicional com cfg_attr
O padrão central:
#[cfg_attr(
feature = "doc-images", // condição
doc = svgbobdoc::transform!( // atributo a emitir
/// ```svgbob
/// diagrama
/// ```
)
)]
Como funciona em cada compilação:
| Comando de compilação | cfg_attr avalia como | Resultado |
|---|---|---|
cargo build | feature = "doc-images" é falso | Atributo suprimido — sem macro, sem dependência svgbob |
cargo build --features doc-images | feature = "doc-images" é verdadeiro | #[doc = svgbobdoc::transform!(...)] é emitido — SVG gerado |
cargo doc --features doc-images | Igual ao acima | URIs de dados SVG incorporados no HTML |
| docs.rs (metadados definem features) | Igual ao acima | SVG renderiza no docs.rs |
Verificando a resolução de features
Verifique se a feature está corretamente conectada:
# Verifique se svgbobdoc NÃO está vinculado na compilação padrão
cargo build --verbose 2>&1 | grep svgbobdoc
# (não deve produzir saída)
# Verifique se svgbobdoc ESTÁ vinculado com a feature
cargo build --features doc-images --verbose 2>&1 | grep svgbobdoc
# Saída: "Compiling svgbobdoc v0.3.0"
Guia de Sintaxe de ASCII Art do svgbob
Caracteres de desenho de caixas
O renderizador svgbob reconhece estes caracteres Unicode de desenho de caixas e os converte em caminhos SVG:
| Caractere | Code point | Renderiza como |
|---|---|---|
─ | U+2500 | Linha horizontal |
│ | U+2502 | Linha vertical |
┌ | U+250C | Canto superior esquerdo |
┐ | U+2510 | Canto superior direito |
└ | U+2514 | Canto inferior esquerdo |
┘ | U+2518 | Canto inferior direito |
├ | U+251C | Junção T esquerda |
┤ | U+2524 | Junção T direita |
┬ | U+252C | Junção T superior |
┴ | U+2534 | Junção T inferior |
┼ | U+253C | Junção cruzada |
╱ | U+2571 | Diagonal para cima e direita |
╲ | U+2572 | Diagonal para cima e esquerda |
◄ | U+25C4 | Ponta de seta esquerda |
► | U+25BA | Ponta de seta direita |
▲ | U+25B2 | Ponta de seta para cima |
▼ | U+25BC | Ponta de seta para baixo |
● | U+25CF | Círculo preenchido |
○ | U+25CB | Círculo vazio |
═ | U+2550 | Horizontal dupla |
║ | U+2551 | Vertical dupla |
≈ | U+2248 | Linha ondulada |
→ | U+2192 | Seta para a direita |
Criando caixas
Retângulo arredondado (mais comum para nós de diagrama):
.───────────.
│ conteúdo │
'───────────'
- Use
.para o canto superior esquerdo,'para o canto superior direito - Use
'para o canto inferior esquerdo,.para o canto inferior direito - Preencha as bordas superior/inferior com
─ - Preencha as bordas laterais com
│
Retângulo reto:
┌───────────┐
│ conteúdo │
└───────────┘
Conectando caixas com setas
Seta horizontal:
.───. .───.
│ A │────────►│ B │
'───' '───'
Seta vertical:
.───.
│ A │
'───'
│
▼
.───.
│ B │
'───'
Seta a partir de um lado específico:
.───.
│ B │
'───'
▲
│
.───. │
│ A │──────┘
'───'
Adicionando rótulos às setas
Coloque o texto ao lado da linha da seta. O svgbob posiciona automaticamente:
.───. condição .───.
│ A │══════════════════►│ B │
'───' '───'
.───. falso .───.
│ A │──────────────►│ B │
'───' '───'
Texto multilinha em caixas
O svgbob quebra o texto naturalmente com base na largura da caixa:
.──────────────────────.
│ Este texto será │
│ quebrado dentro dos │
│ limites da caixa │
'──────────────────────'
Linhas diagonais
.───. .───.
│ A │╲ │ C │
'───' ╲ '───'
╲
╲ .───.
╲│ B │
╲'───'
Árvores e hierarquias
Árvore binária:
.───.
│ R │
'───'
╱ ╲
.───. .───.
│ L │ │ R │
'───' '───'
╱ ╲ ╲
.───. .───. .───.
│LL │ │LR │ │RR │
'───' '───' '───'
Hierarquia indentada (sem linhas):
.───────────────.
│ Raiz │
│ ├── Filho A │
│ ├── Filho B │
│ └── Filho C │
'───────────────'
Grades e matrizes
.──────┬──────┬──────.
│ a │ b │ c │
├──────┼──────┼──────┤
│ d │ e │ f │
├──────┼──────┼──────┤
│ g │ h │ i │
'──────┴──────┴──────'
Layouts de comparação
Lado a lado:
.─────────────. .─────────────.
│ Antes │ │ Depois │
│ .───────. │ │ .───────. │
│ │ Velho │ │ │ │ Novo │ │
│ '───────' │ │ '───────' │
'─────────────' '─────────────'
Antes → Depois (sequencial):
.───────────────. .───────────────.
│ Caminho lento│────►│ Caminho rápido│
│ O(n²) │ │ O(n log n) │
'───────────────' '───────────────'
Esquemas de banco de dados / tabelas
.──────────────────────────.
│ Tabela: usuarios │
├──────────────────────────┤
│ id INTEGER │──► PK
│ nome TEXT │
│ email TEXT │──► ÚNICO
│ criado_em DATETIME │
'──────────────────────────'
Fluxograma com decisão
.───────────.
│ Início │
'─────┬─────'
│
▼
.───────────.
│ Processo │
'─────┬─────'
│
▼
.───────────. sim .───────────.
│ Verificar?│─────────►│ Opção A │
'─────┬─────' '───────────'
│
│ não
▼
.───────────.
│ Opção B │
'───────────'
Arquitetura em camadas
.───────────────────────────────.
│ Camada de Aplicação │
├───────────────────────────────┤
│ Camada de Lógica de Negócios │
├───────────────────────────────┤
│ Camada de Acesso a Dados │
├───────────────────────────────┤
│ Banco de Dados │
'───────────────────────────────'
Diagrama de sequência / tempo (simples)
Cliente───┬────────────────────┐
│ Requisição │
│───────────────────►│
│ │
│◄───────────────────│
│ Resposta │
│ │
Cliente │ Servidor │
Diagrama de estado
.───────────.
┌─────────►│ Estado A │◄──────────┐
│ '─────┬─────' │
│ │ evento 1 │
│ ▼ │
│ .───────────. │
│ │ Estado B │──────────┼──► evento 2
│ '───────────' │
│ │ │
│ │ evento 3 │
│ ▼ │
│ .───────────. │
└──────────│ Estado C │──────────┘
'───────────'
Layout de memória / empacotamento
.──────────┬──────────┬──────────. ← 16 bytes
│ offset 0│ offset 4│ offset 8│
├──────────┼──────────┼──────────┤
│ campo A │ campo B │ campo C │
│ (u32) │ (f32) │ (u64) │
'──────────┴──────────┴──────────'
Mapa de conceitos / mapa mental
.───────────.
│ Conceito │
│ Central │
'───────────'
╱ │ ╲
╱ │ ╲
╱ │ ╲
.──────╱ │ ╲──────.
│ ╱ │ ╲ │
▼ ▼ ▼ ▼ ▼
.──────.──────.──────.──────.──────.
│ Sub 1│ Sub 2│ Sub 3│ Sub 4│ Sub 5│
'──────'──────'──────'──────'──────'
Exemplos de diagramas comuns e seus usos
Filtro passa-baixa (processamento de sinal)
.───────────────. .───────────────. .───────────────.
│ Sinal │────►│ Filtro │────►│ Sinal │
│ Original │ │ Passa-Baixa │ │ Filtrado │
'───────────────' '───────────────' '───────────────'
Pipeline de transformação de dados
.──────────. .──────────. .──────────. .──────────.
│ Dados │──►│ Parse │──►│ Validar│──►│ Salvar │
│ Brutos │ │ │ │ │ │ │
'──────────' '──────────' '──────────' '──────────'
Rede neural (simples)
.───. .───. .───.
│ i1│────►│ h1│────►│ o1│
'───' '───' '───'
│ │ │
│ .───. │ │
├───│ h2│─┼─────────┤
│ '───' │ │
│ │ │
.───. .───. .───.
│ i2│────►│ h3│────►│ o2│
'───' '───' '───'
Solução de problemas
Erro: "proc macro not found"
Causa: A feature doc-images não está ativada ou a dependência está faltando.
Solução: Verifique Cargo.toml e execute:
cargo build --features doc-images --verbose
Erro: "data:image URLs não aparecem"
Causa: A macro transform!() pode não estar sendo executada ou o svgbobdoc não está processando.
Solução:
- Verifique se a feature está ativada
- Verifique se os blocos de código usam ```svgbob`` (com três acentos graves)
- Verifique as URIs de dados no HTML gerado:
grep "data:image/svg" target/doc/sua_crate/*.html
Erro: "aviso de documentação gerada"
Causa: svgbobdoc pode produzir avisos para diagramas ambíguos.
Solução:
- Verifique a sintaxe do diagrama no editor svgbob
- Certifique-se de que as linhas de borda estejam corretamente alinhadas
- Use espaços consistentes para formatação
Referência rápida da API
Macro svgbobdoc::transform!
svgbobdoc::transform!(
/// ```svgbob
/// .───.
/// │ A │
/// '───'
/// ```
)
- Deve ser usada dentro de
#[doc = ...] - Deve ser combinada com
#[cfg_attr]para compilação condicional - A entrada são linhas de comentário de documentação (
///) - A saída é uma string contendo uma URI de dados SVG
Crate svgbobdoc
- Versão: 0.3.x (estável)
- Feature:
enablepara ativar o renderizador SVG - Uso: Criação de documentação inline SVG a partir de ASCII art
- Alternativas:
embed-doc-imagepara figuras PNG/SVG externas