org-lint
Linter para regras de formatação de prosa em arquivos org/md, documentadas em
~/.claude/rules/org-babel.md. O objetivo é
não depender sempre da memória manual para cada regra (e do risco: corrigir a recém-mencionada
e esquecer as demais), mas sim processar o texto através de uma lista explícita.
Quando aplicar
- Imediatamente após editar ou escrever um novo parágrafo de prosa em um arquivo
.org/.md(em vez de verificar manualmente cada regra de memória) — antes de mostrar o resultado ao usuário. - Mediante solicitação explícita do usuário ("verifique regras org", "execute lint", comparação com
clippy, etc.). - Não se aplica ao conteúdo de blocos
#+begin_src/#+begin_example(código) — apenas a parágrafos de prosa e títulos.
Passo 1 — verificação mecânica
Execute o script no(s) arquivo(s) que foram editados:
python3 ~/.claude/skills/org-lint/scripts/lint.py CAMINHO/DO/ARQUIVO.org
O script captura via regex:
/sem espaços ao redor de~...~/=...=(~a~/~b~em vez de~a~ / ~b~) — VIOLAÇÃO DEFINITIVA.[[file:../— link relativo ao diretório atual em vez da abreviaturaroot:— VIOLAÇÃO DEFINITIVA.- ausência de newline final no arquivo — VIOLAÇÃO DEFINITIVA.
- acrônimo em maiúsculas dentro de
=...=(ex.:=CSS=) — requer confirmação (exceções raras são permitidas). - itálico
/Palavra/— requer verificação: é realmente um termo do glossário do projeto (existe seção emspcfctn/glossary.org? há link para ele na primeira menção neste arquivo?), ou é um link para seção/arquivo INCORRETAMENTE NÃO convertido (deveria ser[[*Seção][...]]). - menção de arquivo como
=caminho/arquivo.org=— requer verificação: não deveria ser um link real[[file:...]]. - palavra "parâmetro"/"parâmetros"/... — requer verificação: se refere a propriedades de componente Rust/Yew
(
struct ...Props), a tradução correta é "propriedades"/"propriedade", não "parâmetros"/"parâmetro" (termo obsoleto). Fora de componentes Yew (parâmetros de função, CLI, procedimentos REST, etc.) "parâmetro" — OK, não altere. - bloco
:noweb-ref Definiçãoestá em uma seção antes do bloco:noweb-ref Declarações— requer verificação: a declaração deve vir primeiro, na ordem de leitura do arquivo de cima para baixo (veja org-babel.md). - vários blocos
#+begin_srccom o MESMO:tangle CAMINHOe sem nenhum:noweb yes/<<...>>no arquivo — VIOLAÇÃO DEFINITIVA (concatenação obsoleta, como no antigogitignore.org— veja org-babel.md). Refatore para um único bloco container:tangle+:noweb yescom placeholder(s)<<Nome>>e seções com:noweb-ref Nome. - o arquivo é tangado em VÁRIOS arquivos de destino diferentes, dos quais PELO MENOS DOIS consomem noweb
(têm
:noweb yesem um#+begin_srcesqueleto, ex.:config.org→.env.example+parameters.php), mas pelo menos um bloco:noweb-ref/<<...>>é nomeado sem prefixo de destino (Nomeem vez deenv:Nome) — VIOLAÇÃO DEFINITIVA (veja org-babel.md, regra sobre prefixos em arquivos org multi-alvo). Para arquivos com UM único arquivo de destino, e também para arquivos onde apenas UM destino consome noweb e os demais são destinos:tangleautossuficientes de bloco único sem<<...>>(ex.:gitignore.org: 5 destinos:tangle, mas apenas o.gitignoreraiz — via esqueleto noweb) — prefixo não é necessário, pois não há ambiguidade real. - parâmetros no cabeçalho
#+begin_srcestão em ordem incorreta — VIOLAÇÃO DEFINITIVA. Ordem correta: tipo do bloco →:noweb yes→:noweb-sep "..."→ demais parâmetros →:tangle CAMINHOou:noweb-ref Nome(no final, veja org-babel.md). - o arquivo se chama
cargo.org— VIOLAÇÃO DEFINITIVA (nome obsoleto para projetos Rust; renomeie paraconfig.org, veja org-babel.md). :tangleusa caminho absoluto (/...,~/...) ou ascendente..— VIOLAÇÃO DEFINITIVA (veja org-babel.md); o destino deve ser estritamente um caminho relativo descendente a partir do arquivo org. Se o destino estiver realmente fora da árvore de origem — é necessário um symlink ou outra estrutura de diretórios, não../caminho absoluto (episódio:farba-override→farba-themevia../farba-theme/..., tarefaFS-1085).- maiúsculas fora de
=...=(ex.:NÃO,APENAS) — requer verificação: se for destaque de palavra, e não acrônimo/abreviatura, substitua por negrito org (*não*), não por CAIXA ALTA. - palavra "hook"/"gancho" (tradução de "hook", React/Yew) — obsoleto; a tradução correta é "gancho"
(aplica-se apenas à prosa, não a identificadores de código como
use_effect_with). - linhas de prosa com mais de 105 caracteres — requer
fill-paragraphviaemacsclient(veja abaixo).
"VIOLAÇÕES DEFINITIVAS" sempre devem ser corrigidas. "Requer verificação manual" — revise cada uma, mas nem todas são
erros (ex.: =rest=/=forge-yew= — legítimas abreviaturas/nomes de crate, não violação).
Passo 2 — checklist manual (o que o script não captura)
- Identificadores de código/tipos/funções/variáveis/módulos — e quaisquer fragmentos ou expressões de código (ex.:
id=1,value == 0,items()) — til~...~. Abreviaturas/acrônimos e a forma "pública" do nome de crate/biblioteca (com hífen) — sinal de igual=...=. Caminho qualificadocrate::Tipo— é um nome de tipo do código, portanto inteiramente em til, mesmo com prefixo de crate. - Abreviaturas/acrônimos — em minúsculas dentro da frase, apenas a primeira letra maiúscula no início da frase (sem CAIXA ALTA completa), exceto para raras exceções consolidadas.
- Link para seção no mesmo arquivo —
[[*Nome do título][Nome]], não itálico e nem texto simples. Link para arquivo no mesmo diretório — simplesmente[[file:arquivo-vizinho.org][descrição]]; para arquivo em outro diretório (especialmente em outro repositório git dentro do diretório de trabalho comum) — via abreviaturaroot:([[root:code/ads-back/arquivo.org::N][descrição]]), não../../../relativo ao diretório atual. A abreviatura é declarada em.dir-locals.elna raiz do diretório de trabalho (formaevalcomlocate-dominating-file) — se ainda não existir no projeto, crie. - Itálico
/.../— apenas para termos do glossário do projeto (com tradução(/translation/)imediatamente após); na primeira menção do termo em cada arquivo —[[file:.../spcfctn/glossary.org::*Termo][...]]para a seção correspondente, e não repetição da definição.
Passo 3 — alinhamento
Para cada parágrafo editado, chame o fill-paragraph real via emacsclient --eval, em vez de
alinhar manualmente (veja a regra correspondente em org-babel.md). Escreva o texto do parágrafo em new_string/ao criar
o arquivo em uma única linha, sem tentar adivinhar quebras de linha, — pois isso será integralmente determinado pelo fill-paragraph.
É OBRIGATÓRIO chamar (font-lock-ensure) ANTES de org-fill-paragraph: o buffer aberto headless via
find-file-noselect não passa por fontificação, portanto links org [[caminho][descrição]] ainda não estão "dobrados" para
o texto visível curto descrição — sem font-lock-ensure o fill-paragraph contará a quebra de linha pelo longo
texto bruto do link, e não pela sua largura visível, e o resultado divergirá do que M-q fornece em um
Emacs interativo. Exemplo:
emacsclient --eval '
(let ((buf (find-file-noselect "CAMINHO/DO/ARQUIVO.org")))
(with-current-buffer buf
(org-mode)
(font-lock-ensure)
(goto-char (point-min))
(search-forward "fragmento único do parágrafo")
(org-fill-paragraph)
(save-buffer)))
'