- Para usuários que querem ler posts da web diretamente no terminal, o James' Coffee Blog também oferece os artigos no formato de páginas de manual do Linux
- Mesmo com a mesma URL, se o cliente enviar
Accept: text/roff, recebe um documento roff em vez de HTML, usando negociação de conteúdo HTTP
- O arquivo
.man de cada post é gerado com um template que inclui as seções TITLE, AUTHOR, PUBLISHED, POST e URL
- No corpo, foi usado o Markdown original para torná-lo mais legível do que HTML, embora o espaçamento nem sempre fique perfeitamente alinhado na página de manual
- O NGINX detecta requisições
text/roff e reescreve a URL para um arquivo .man, permitindo salvar com curl e abrir com man ./post.page
Ler posts de blog com man
- As páginas de manual do Linux são a forma básica de consultar o uso de comandos no terminal, normalmente abertas com
man <command>
- Por exemplo, o manual do comando
tac pode ser visto assim
man tac
- O James' Coffee Blog montou um fluxo para que posts da web também possam ser lidos da mesma forma, baixando a versão
roff da URL do artigo e abrindo-a com man
- Um exemplo real de requisição é o seguinte
curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/ > post.page && man ./post.page
Escolhendo o formato com negociação de conteúdo HTTP
- O núcleo da implementação é a negociação de conteúdo HTTP, em que o cliente informa ao servidor qual formato de resposta deseja
- O cabeçalho
Accept é usado para transmitir o tipo de conteúdo desejado
- Por exemplo,
Accept: image/png significa “envie um arquivo PNG, se possível”
- Também é possível especificar vários tipos de conteúdo e prioridades, mas aqui é usado apenas o pedido de um formato específico
- Quando se quer receber um post de blog em formato de página de manual, envia-se o cabeçalho
Accept: text/roff
- Ao ver esse cabeçalho, o servidor retorna uma resposta text/roff que pode ser aberta no
man, em vez de HTML
Como os arquivos .man são gerados
- As páginas de manual do Linux são escritas na sintaxe roff
- O site foi modificado para gerar uma versão em página
man para cada post do blog
- A estrutura do template usado é a seguinte
.TH jamesg.blog 1 "" "jamesg.blog"
.SH TITLE
...
.SH AUTHOR
James' Coffee Blog (https://jamesg.blog)
.SH PUBLISHED
...
.SH POST
...
.SH URL
...
- O template usa o nome de domínio como cabeçalho e cria cinco seções
- TITLE
- AUTHOR
- PUBLISHED
- POST
- URL
- No corpo, é usado o Markdown original
- O espaçamento na página de manual nem sempre fica perfeito
- Ainda assim, ficou mais fácil de ler do que HTML e perdeu menos informação sobre títulos e parágrafos do que texto puro
Baixando com curl e abrindo com man
- A versão
roff de um post do blog pode ser requisitada com o seguinte comando
curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/ > post.page
- O resultado salvo pode ser aberto como uma página de manual local
man ./post.page
- Se um navegador comum requisitar a mesma URL do artigo, ele recebe a versão HTML
- Já o comando
curl acima solicita explicitamente a versão text/roff para a mesma URL
Reescrevendo para arquivos .man no NGINX
- O servidor trata separadamente as requisições
text/roff com algumas linhas de configuração do NGINX
- Em
/etc/nginx/nginx.conf, são declaradas variáveis que ativam uma flag quando um tipo de conteúdo específico é detectado
map $uri $redirect_suffix {
~^/(.*)/$ $1;
default "";
}
map $http_accept $redirect_location {
default "";
"~^text/roff" 1;
}
- No arquivo de configuração do site, em
/etc/nginx/sites-enabled, adiciona-se uma regra para tratar requisições de páginas roff
server {
...
location / {
if ($redirect_location = 1) {
rewrite ^/(.*)/$ /$1.man last;
}
...
}
}
- Essa configuração remove a barra final da URL e adiciona
.man quando existe o cabeçalho Accept: text/roff
- Como resultado, o NGINX lê o arquivo
.man correspondente em vez do index.html de cada post
- Com isso, o mesmo post do blog pode ser lido em HTML no navegador e como página de manual do Linux no terminal
1 comentários
Opiniões no Hacker News
Seria legal oferecer um repositório deb como forma de assinatura de blog
Algo como baixar todos os posts com
apt updatee poder ver o post mais recente e links para o índice de todos os posts comman your-blogAcho que eu teria medo de assinar
Eles podem ser vistos localmente com o pacote dwww: “Read all on-line documentation with a WWW browser”
https://packages.debian.org/bookworm/dwww
Joerg Jaspert foi o antigo mantenedor do pacote Linux Gazette: https://people.debian.org/~joerg/ (2002)
Foi um dos melhores casos que já vi de integração de entrega de informação e documentação ao sistema operacional, especialmente por tornar a documentação man/info mais útil do que as interfaces tradicionais baseadas em terminal
Também existe o Debian Planet, um blog relacionado ao Debian, mas acho que ele nunca foi oferecido como pacote do próprio Debian
Sinceramente, RSS provavelmente é uma opção melhor para assinar blogs
Em https://github.com/capjamesg/jamesg.blog.deb há conteúdo para criar, com os comandos abaixo, um arquivo deb que contém apenas a página man
git clone [https://github.com/capjamesg/jamesg.blog.deb](<https://github.com/capjamesg/jamesg.blog.deb>)cd jamesg.blog.debdpkg-deb --build --root-owner-group jamesg.blogsudo dpkg -i jamesg.blog.debEntão você deve ver uma saída como
Processing triggers for man-db (2.9.1-1) ..., o que significa que a página de manual paraman jamesg.blogestá disponívelPor enquanto há apenas um placeholder, e provavelmente vou finalizar amanhã
Pode virar um post do blog em breve
Dá para enviar direto por pipe para o
man, sem precisar fazer fork nem usar um arquivo intermediáriocurl -sL -H "Accept: text/roff" [https://jamesg.blog/2024/02/28/programming-projects/](<https://jamesg.blog/2024/02/28/programming-projects/>) | man -l -{curl,wget}por pipe para comandosAmigos não deixam amigos enviar streams diretamente por pipe para comandos
https://news.ycombinator.com/item?id=39554044
Para referência,
curl -sL -H "Accept: text/roff" [https://jamesg.blog/2024/02/28/programming-projects/](<https://jamesg.blog/2024/02/28/programming-projects/>) | man -l /dev/stdinfunciona no meu ambienteNão é preciso salvar o arquivo roff localmente
bashcostuma ser considerado uma má práticaPessoalmente, acho aceitável. Quem entende as implicações de segurança quase certamente também sabe fazer esse tipo de conversão, então não há necessidade de ensinar
Mas não é bom ensinar isso a iniciantes. Um dia eles podem acabar caindo em alguma armadilha. Conforme ganharem experiência, vão descobrir naturalmente esse recurso, e espero que até lá também tenham aprendido as implicações
O texto não é meu: https://www.seancassidy.me/dont-pipe-to-your-shell.html
/usr/bin/man: illegal option -- lTentei criar um comando de uma linha com pipe no Mac, mas ele continuou dando erro
A implementação de
mando macOS não tem a flag-l. Conferi a página de manualman -l <(curl -sL -H "Accept: text/roff" https://jamesg.blog/2024/02/28/programming-projects/)Se a conversa for sobre URLs que fazem coisas divertidas no terminal, lembro de algo que vi há tempos no textfiles.com
Era uma forma de exibir um curta de animação usando códigos de terminal VT100, tudo servido a partir de um único URI
Em sistemas modernos, dá para assistir aplicando um limite de velocidade
curl --limit-rate 1000 [http://textfiles.com/sf/STARTREK/trek.vt](<http://textfiles.com/sf/STARTREK/trek.vt>) && resetO
resetestá aí porque o terminal pode ficar bagunçadoOutros URIs baseados em terminal:
curl cheat.sh/tarbusca exemplos de uso do programa depois da/, ecurl wttr.in/berlintraz informações de clima formatadas para o terminalNa prática é bem simples; a parte mais difícil é gerar os frames
Dá para fazer isso com
ffmpeg+img2txt.py: https://github.com/bfontaine/RickASCIIRoll/tree/master/movie...Havia um mirror antigo de https://16colo.rs/, então dá para ver a maior parte da arte ANSI já publicada até hoje
Ex.:
curl ansi.hrtk.in/ungenannt_1453.anshttps://itsfoss.com/star-wars-linux/
tritty, dá para simular velocidades de transmissão de 1200/9600 BPSAgora só falta um conversor de Markdown para roff, e, ao procurar, vi que já existem alguns
https://github.com/postmodern/kramdown-man
https://rtomayko.github.io/ronn/ronn.1.html
https://kristaps.bsd.lv/lowdown/
[0]: https://pandoc.org/
md2groffjá existe há muito tempo nas comunidades da linhagem suckless/2f30/cat-vhttps://codeberg.org/nereusx/md2roff
Há um pacote do Emacs que instala o SICP de Abelson e Sussman no diretório Info
Basta digitar
M-x package-install sicp RETAo ver isso, pensei que também daria para instalar uma estante inteira de arquivos de blogs com um leitor de feeds modificado
Ao ler Info no Emacs, também dá para usar bookmarks
chicken-scheme. Depois execute como rootchicken-install srfi-203chicken-install srtfi216O
~/.csircpara o SICP fica assim(import scheme)(import (srfi 203))(import (srfi 216))(define (inc x) (+ x 1))(define (dec x) (- x 1))Depois, é só usar o Geiser de usuário e o Geiser para Chicken como de costume
Talvez eu consiga descobrir a resposta pesquisando na internet, mas quero perguntar no HN
No ensino médio, no HP-UX, lembro de alguém me mostrar como pular para uma palavra sublinhada, ou seja, uma referência de seção, usando alguma combinação de teclas, mas não consigo lembrar de jeito nenhum quais eram
Também verifiquei
man(1)eman(7), mas não encontrei. Pode ser uma falsa memóriaman ohmané, essencialmente,nroff -man /usr/share/man/man1/ohman.1 | $PAGEROu seja, você não está interagindo com o man nem com o nroff, mas com o pager
Hoje em dia,
lessé o mais comum, e é bem provável quemoretambém seja, na prática, less; mas antigamente havia outros, e o HPUX talvez usasse algo comopgpgera da linhagem AT&T,moreda linhagem BSD, elessda linhagem GNUTodos os três iniciam uma busca por regex com
/, então dá para encontrar independentemente de estar sublinhado ou nãolesstambém suporta arquivos de tags, então dá para pular para a próxima tag comtdthelpview, o visualizador de ajuda do CDE. Ele pode ter exibido páginas maninfoIronicamente, boa parte da documentação original do groff é escrita em texinfo: https://lists.gnu.org/archive/html/groff/2005-10/msg00107.ht...
Não sei por que esse detalhe tão pequeno ativou meu instinto de implicar. Talvez seja porque alguém na internet estava ligeiramente errado
Talvez porque desde o início fosse desnecessariamente centrado em Linux, ou porque eu esperava outra coisa e no fim era só uma breve demonstração de negociação de conteúdo do NGINX
De todo modo, há alguns pontos inúteis que faço questão de mencionar
Tecnicamente, ele não está retornando roff. Coisas como
.THnão são roff em si, mas parte de um pacote de macros para escrever páginas manFiquei decepcionado por não haver conversão de Markdown para roff. Achei que essa seria a parte interessante do artigo, e pelo menos uma ferramenta existente poderia ter sido usada
Da mesma forma, por causa disso, a formatação do texto na verdade também não fica correta. A entrada roff pressupõe uma linha por frase, para distinguir o
.no fim de uma frase de.com outros usosAlém disso, qualquer linha que comece com
.pode ser interpretada como um comando e causar problemasOu talvez eu seja apenas um velho ranzinza
Fiquei ainda mais confuso por existirem outras ferramentas como
groffenroffSó um texto explicando “o que são roff/páginas man/nroff/outras variantes e como usá-los” já daria um post de blog por si só
Eu teria gostado de uma explicação curta e clara, e acho que também ajudaria outras pessoas
Pensei em Markdown para roff como uma v2. Quando comecei a pensar em implementar um parser, alguém me indicou https://github.com/sunaku/md2man, e isso parece resolver o problema
Ainda preciso descobrir como integrar isso ao meu site em Python rodando sobre GitHub Pages, então vou ter que ajustar um pouco
O Pandoc consegue converter Markdown para roff de página man com muita facilidade
Se você colocar isso em um template apropriado, vai parecer bem mais uma página man de verdade
O tipo de mídia correto, segundo a RFC 4263, é text/troff: https://www.rfc-editor.org/rfc/rfc4263.html
Ideia bacana. Agora é só ligar o cronômetro até aparecer “oferecendo meus posts de blog como um DOOM WAD jogável”