From plugadvpl
Sets encoding policy for ADVPL/TLPP source files: cp1252 for .prw/.prx, UTF-8 for .tlpp, preserve-by-default. Use before editing/writing sources or when seeing mojibake characters.
How this skill is triggered — by the user, by Claude, or both
Slash command
/plugadvpl:advpl-encodingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Fontes ADVPL/TLPP em projetos Protheus reais misturam dois encodings:
Fontes ADVPL/TLPP em projetos Protheus reais misturam dois encodings:
.prw / .prx clássicos → cp1252 (Windows-1252) — padrão histórico, herdado do Clipper..tlpp moderno → UTF-8 é suportado e recomendado pela TOTVS para código novo.Em clientes grandes essas duas extensões coexistem no mesmo repositório. Algumas codebases legadas chegam a ter .prw em UTF-8 (raro, mas existe). A regra é: preserve o encoding detectado, nunca normalize por conta própria.
Edit ou Write em .prw, .prx, .tlpp.Read e ver ç ou ã no output (sinal de cp1252 lido como utf-8)./plugadvpl:ingest em base nova (verifique a política)..ps1, .sh) que vão ser lidos por terminal cp1252.Ao salvar cp1252 como UTF-8 (ou vice-versa) sem decodificar corretamente, estes caracteres viram lixo:
| Char cp1252 | Byte cp1252 | Lido como UTF-8 (mojibake) |
|---|---|---|
ç | 0xE7 | ç |
ã | 0xE3 | ã |
á | 0xE1 | á |
é | 0xE9 | é |
ó | 0xF3 | ó |
Á | 0xC1 | Ã |
° | 0xB0 | ° |
— (em-dash) | 0x97 | â |
↔ (arrow) | (não existe cp1252) | crash UnicodeEncodeError |
Comentários // Atualizacao viram // Atualização quando lidos errado. Pior: o compilador AppServer rejeita o arquivo, ou compila e quebra strings em runtime.
Char fora do cp1252 = crash:
↔(U+2194),→(U+2192), box-drawing (─,│), emojis. Não existem em cp1252 → quando Python/AppServer tenta encodarcp1252, dáUnicodeEncodeError: 'charmap' codec can't encode character. Foi exatamente o bug da v0.3.0 do plugadvpl no--helpem Windows PS 5.1.
Algoritmo real (parser.py, validado em ampla base de fontes ADVPL):
"cp1252" (default Protheus; ASCII é subset)."utf-8"."cp1252".chardet[:4096] (sample do início do arquivo) → heurística, último fallback.latin-1 se chardet falhar.Detalhe técnico: a ordem UTF-8 strict antes de cp1252 é proposital. cp1252 só tem 5 bytes indefinidos (0x81/8D/8F/90/9D); todos os outros valores 0x00-0xFF são "válidos" em cp1252. Então tentar cp1252 primeiro misdecodaria silenciosamente bytes UTF-8 multi-byte como sequência de chars latinos. UTF-8 strict rejeita bytes cp1252 típicos (
ã= 0xE3 sozinho não forma sequência UTF-8 válida).
A extensão não influencia a ordem —
.tlppsegue o mesmo algoritmo. Mas como.tlppna prática tem mais chars multi-byte, o passo 2 acerta primeiro.
A coluna encoding da tabela fontes (não "sources") registra o resultado. Consulte antes de editar:
SELECT arquivo, encoding FROM fontes WHERE arquivo = 'XXX.prw';
Ou via CLI: /plugadvpl:doctor mostra distribuição de encoding na base.
--encoding-policy no ingest/plugadvpl:ingest aceita uma das três políticas:
preserve (default) — armazena o encoding detectado por fonte, não impõe regra global. Recomendado.cp1252 — assume cp1252 para .prw/.prx; emite warning para .tlpp UTF-8 detectado.utf8-warn — emite warning para qualquer fonte que NÃO seja UTF-8 (útil em migração ativa).Para edição feita por Claude, preserve sempre.
Quando o código precisa misturar encodings em runtime (ex: REST que recebe JSON UTF-8 num fonte cp1252):
| Função | Direção | Quando usar |
|---|---|---|
EncodeUTF8(cStr) | cp1252 → UTF-8 | Antes de enviar string ADVPL pra REST/JSON |
DecodeUTF8(cStr) | UTF-8 → cp1252 | Após receber body UTF-8 de REST/JSON |
STRICONV(cStr, nCodepage) | cp1252 ↔ outras | Conversões cross-codepage (sistemas externos) |
// Recebendo body REST UTF-8 e gravando em fonte cp1252
WSMETHOD POST cadastraCliente WSRECEIVE cBody WSSERVICE zClientes
Local oJson := Nil
Local cBody := DecodeUTF8(Self:GetContent()) // converte UTF-8 → cp1252
FwJsonDeserialize(cBody, @oJson)
RecLock("SA1", .T.)
SA1->A1_NOME := AllTrim(oJson:nome) // string cp1252, OK pra gravar
MsUnlock()
Return .T.
// Enviando resposta JSON UTF-8 a partir de dados cp1252
WSMETHOD GET listaClientes WSSERVICE zClientes
Local cResp := '{"nome":"' + AllTrim(SA1->A1_NOME) + '"}'
Self:SetResponse(EncodeUTF8(cResp)) // converte cp1252 → UTF-8
Return .T.
Quirk:
EncodeUTF8()com char inválido retorna NIL e loga warning noconsole.logdo AppServer. Sempre verifique retorno em rotinas críticas.
XML é exceção: o parser XML do ADVPL internamente já faz UTF-8 ↔ cp1252 — você lê chars como á, ç direto no XmlElem:Text sem conversão manual.
ConOut/FwLogMsg no console.log aparece com mojibake se o terminal estiver em codepage diferente:
:: appserver.bat — antes de subir
chcp 1252
TotvsAppServer.exe -console
Pra Linux/WSL: locale pt_BR.iso-8859-1 ou converter o log com iconv na hora de ler.
🚨 PERIGO: o Read tool do Claude Code lê
.prwcp1252 como UTF-8. Bytes acentuados (0x80-0xFF) viram�(U+FFFD). Se você fizerEditnessa visão, oEditregrava o arquivo inteiro em UTF-8, com�no lugar dos acentos não-editados. Acentos não-editados ficam corrompidos. Bug clássico do reporter, v0.8.8 doc.
.prw cp1252 com Claude (Caminho A)# 1. ANTES de Read/Edit: converte cp1252 -> utf-8 (preserva acentos)
plugadvpl edit-prw stage <fonte.prw>
# Atalho de: plugadvpl edit-prw save <fonte> --from cp1252 --to utf-8
# Cria .bak automático com bytes cp1252 originais
# 2. Agora Read mostra "Função" certinho. Edit/Write podem operar sem perda.
# O ARQUIVO está temporariamente em UTF-8 — não compila assim, mas
# o Claude vê tudo correto.
# 3. DEPOIS das edições: volta pra cp1252 (acentos novos viram bytes 0xE7 etc.)
plugadvpl edit-prw commit <fonte.prw>
# Atalho de: plugadvpl edit-prw save <fonte> --from utf-8 --to cp1252
# Detecta automático que o arquivo está em utf-8 agora
Caminho B — edição cirúrgica via PowerShell em cp1252 nativo (zero conversão):
$path = "Customizados\FOO.PRW"
$enc = [System.Text.Encoding]::GetEncoding(1252)
$txt = $enc.GetString([System.IO.File]::ReadAllBytes($path))
$txt = $txt -replace 'PADRAO_VELHO', 'PADRAO_NOVO'
[System.IO.File]::WriteAllBytes($path, $enc.GetBytes($txt))
Bom quando a mudança é mecânica (find/replace). Verboso pra refactor complexo.
Caminho C — restringir Edit a trechos ASCII puro (frágil):
Só edita linhas sem � no Read output. Mas o Edit regrava arquivo inteiro
e os � ficam → bug. NÃO RECOMENDADO.
plugadvpl --format json doctor (ou SELECT encoding FROM fontes WHERE arquivo='X.prw').Read (Funç..., ç, �), não é o arquivo que está corrompido — é a tool lendo errado. Confirme com plugadvpl edit-prw check <fonte>.Edit se o Read mostrou �..prw novo → cp1252; .tlpp novo → UTF-8..ps1, .sh, .bat) que rodam em terminal cp1252 → ASCII-only é mais portável. UTF-8 BOM nesses scripts atrapalha mais que ajuda (causa parse errors em PS 5.1)..prw (cp1252, byte 0xE7 para ç):
// Funcao de validacao do codigo do cliente
User Function ValCli()
Local cMsg := "Operacao concluida com sucesso"
Return .T.
Como exibição em markdown, vou usar comentário sem acentos pra clareza. No fonte real,
ç,ã,éestão lá literalmente como bytes cp1252 — Claude/IDE precisa decodar como cp1252 pra ler corretamente.
Os bytes do source: // Fun\xe7\xe3o de valida\xe7\xe3o. Se Claude leu como UTF-8, vai ver // Função. Não "conserte" isso editando — o arquivo está correto, o problema é o decoder.
#include "TOTVS.CH", dispara EncodeUTF8() falhas em runtime..prw com BOM UTF-8 (EF BB BF) → AppServer rejeita..ps1/.sh/.bat com BOM UTF-8 → terminal PS 5.1 não reconhece, parser quebra (bug real do install.ps1 v0.3.1)..tlpp em cp1252 só porque o resto do projeto é cp1252 → perde recurso natural do TLPP (chars Unicode, emoji em strings, etc.).file -i (Linux/WSL) ou /plugadvpl:doctor para encoding real.DecodeUTF8 → byte sequences inválidos no SQL.cNomeCliênte) — compilador aceita mas quebra deserialização cross-encoding (CSV, REST). Veja [[advpl-fundamentals]].↔/→, emojis, box-drawing) em string de fonte .prw → UnicodeEncodeError em runtime quando AppServer tenta exibir.| Extensão | Encoding esperado | Alternativa aceita | Política Claude |
|---|---|---|---|
.prw | cp1252 | (raro) utf-8 | preserve |
.prx | cp1252 | — | preserve |
.tlpp | utf-8 | cp1252 (legado) | preserve |
.ch | cp1252 | utf-8 | preserve |
.th | utf-8 | — | preserve |
.ps1/.sh (instaladores) | ASCII-only OU UTF-8 sem BOM | — | preserve, ASCII se possível |
| Body REST/JSON | utf-8 | — | EncodeUTF8/DecodeUTF8 |
[[advpl-fundamentals]] — char ASCII-only em identificadores; .prw (cp1252, 10 chars) vs .tlpp (utf-8, 250 chars).[[advpl-webservice]] — REST/JSON precisa EncodeUTF8/DecodeUTF8 ao entrar/sair do fonte cp1252.[[advpl-web]] — Webex/HTML serve em UTF-8; conversão é obrigatória.[[advpl-debugging]] — mojibake é sintoma frequente; primeiro passo é /plugadvpl:doctor.[[advpl-code-review]] — não há regra de lint específica de encoding ainda (gap conhecido).[[plugadvpl-index-usage]] — /plugadvpl:doctor checa encoding real de cada fonte ingesto./plugadvpl:doctor — checa encoding real de cada fonte ingesto./plugadvpl:ingest --encoding-policy {cp1252|preserve|utf8-warn} — controla detecção./plugadvpl:status — mostra distribuição de encodings na base.SELECT encoding, COUNT(*) FROM fontes GROUP BY encoding.npx claudepluginhub jonipraia/plugadvpl --plugin plugadvplSafely edit .prw files with cp1252 encoding in Claude Code by converting between UTF-8 and cp1252 to avoid corruption.
Ensures Delphi source files (.pas, .dfm, etc.) use UTF-8 with BOM encoding. Detects and fixes mojibake, missing BOM, and encoding problems.