Usando a linguagem PIC no Rmarkdown

A linguagem pic fornece uma maneira fácil de escrever diagramas procedurais a serem incluídos em documentação técnica.

A linguagem pic fornece uma maneira fácil de escrever diagramas procedurais a serem incluídos em documentação técnica. A linguagem é suficientemente flexível para ser bastante útil para gráficos de estado, diagramas de rede de Petri, fluxogramas, esquemas de circuitos elétricos, layouts e outros tipos de ilustração envolvendo usos de formas geométricas simples e splines.

Como essas descrições são processuais e baseadas em objetos, eles são compactos e fáceis de modificar. A implementação gpic (gnu pic) de pic é distribuída pela Free Software Foundation. Como ambas as implementações estão amplamente disponíveis na forma de fonte para gratuitos, eles são boas apostas para escrever documentação muito portátil.

A versão original de 1984 de pic está obsoleta há muito tempo. A versão reescrita de 1991 ainda é disponível como parte do módulo Documenter’s Work Bench do System V.

Em 2020 D. Richard Hipp criou uma nova versão chamada Pikchr (pronuncia-se “picture”), com uma linguagem semelhante à pic. O Pikchr foi projetado para ser incorporado em blocos de código protegidos de Markdown ou mecanismos semelhantes de outras linguagens de documentação.

Instalação do Fossil

Fazer o download no endereço abaixo, colocar como executável e deixar em um lugar acessível no caminho (path) do sistema

chmod +x fossil
sudo mv fossil /usr/local/bin

Link para download.

Instalação do Pikchr

Procedimento para instalação do pikchr pode ser encontrato no endereço pikchr.org.

Apos compilar colocar o executável em uma pasta acessível pelo path.

Filtro Lua

Para identificar os códigos em pikchr e converter para <svg> vamos usar um filtro em Lua Script. Copie o código abaixo e crie um arquivo chamado pikchr.lua no diretório de trabalho.

-- Pandoc filter to process code blocks with class "pikchr" containing
-- pikchr markup into SVG images.
--
-- * Assumes Fossil is present on the path.
-- * For HTML formats, you may alternatively use --self-contained
--
-- https://pandoc.org/lua-filters.html#converting-abc-code-to-music-notation

local function pikchr(markup)
    local svg = pandoc.pipe("fossil", {"pikchr"}, markup)
    return svg
end

function CodeBlock(block)
    if block.classes[1] == "pikchr" then
        local img = pikchr(block.text)
        if block.attributes["echo"] == "true" then
          pandoc.CodeBlock(block.text, {class='html'})
          return {pandoc.CodeBlock(block.text), pandoc.RawInline('html', img)}
        else 
          return pandoc.RawInline('html', img)
        end
    end
end

Com isto vamos substituir os scripts em pikchr para <svg> e colocá-los diretamento no html, permitindo assim ajustas usando css e js. Para usar o filtro basta passar o seguinte argumento para o pandoc:

pandoc_args: ["--lua-filter=pikchr.lua"]

Exemplo

Segue um primeiro exemplo retirado da página do pikchr.

arrow right 200% "Markdown" "Source"
box rad 10px "Markdown" "Formatter" "(markdown.c)" fit
arrow right 200% "HTML+SVG" "Output"
arrow <-> down from last box.s
box same "Pikchr" "Formatter" "(pikchr.c)" fit
Markdown Source Markdown Formatter (markdown.c) HTML+SVG Output Pikchr Formatter (pikchr.c)

Um exemplo um pouco mais complexo:

$bwd = 4cm
$bht = 1cm
$dist = 2cm
$E1 = 0x96ceb4;
$E2 = 0xffeead;
$E3 = 0xffcc5c;
$E4 = 0xff6f69;
$Q1 = 0xF0F0F0;
$Q2 = 0xF0F0F0;
$Q3 = 0xF0F0F0;
$Q4 = 0xF0F0F0;
$Q5 = 0xF0F0F0;
$P1 = 0xb7d7e8;
$P2 = 0xdaebe8;
$T1 = 0xff7b25;
E1: oval dotted width 2.5cm  height 1cm "Economia"  with .c at (0,0) fill $E1;
E2: oval dotted width 2.5cm  height 1cm  "Eficiência"  with .c at (0, -$dist) fill $E2;
E3: oval dotted width 2.5cm  height 1cm  "Eficácia"  with .c at (0, -2*$dist) fill $E3;
E4: oval dotted width 2.5cm  height 1cm  "Efetividade"  with .c at (0, -3*$dist) fill $E4;
Q1: box rad .1 height 1cm "Custo" with .c at (2*$dist, .5*$dist) fill $Q1;
Q2: box rad .1 height 1cm "Recursos" with .c at (2*$dist, -.5*$dist) fill $Q2;
Q3: box rad .1 height 1cm "Produtos" "Serviços" with .c at (2*$dist, -1.5*$dist) fill $Q3;
Q4: box rad .1 height 1cm "Resultados" with .c at (2*$dist, -2.5*$dist) fill $Q4;
Q5: box rad .1 height 1cm "Impacto" with .c at (2*$dist, -3.5*$dist) fill $Q5;
P1: oval dotted rad .05 width 3cm height 1cm \
          "Nível de Serviço" \
          "e Qualidade" with .c at (4*$dist, -1*$dist) fill $P1;
P2: oval dotted rad .05 width 3cm height 1cm "Satisfação" with .c at (4*$dist, -2*$dist) fill $P2;
T1: box thick rad .05 width 3cm height 1cm "População" with .c at (6.25*$dist, -1.5*$dist) fill $T1;
L1: arrow from E1.e to Q1.w color $E1;
L2: arrow from E1.e to Q2.w color $E1;
L3: arrow from E2.e to Q2.w color $E2;
L4: arrow from E2.e to Q3.w color $E2; 
L5: arrow from E3.e to Q3.w color $E3;
L6: arrow from E3.e to Q4.w color $E3;
L7: arrow from E4.e to Q4.w color $E4;
L8: arrow from E4.e to Q5.w color $E4;  
L9: arrow from Q3.e to P1.w color $P1;  
L10: arrow from Q3.e to P2.w color $P1;  
L11: arrow from Q4.e to P2.w color $P2; 
L12: arrow from P1.e to T1.w color $T1;  
L13: arrow from P2.e to T1.w color $T1;  
Economia Eficiência Eficácia Efetividade Custo Recursos Produtos Serviços Resultados Impacto Nível de Serviço e Qualidade Satisfação População