Pages

Sunday, June 14, 2009

Apresentando um Makefile em detalhes

Não tem muito tem e fiz uma introdução ao comando make. Como mencionado, a forma mais simples quanto possível de apresentar essa questão é utilizando um exemplo que seja tão simples quanto possível e que não seja simples demais para não ficar algo muito superficial. Por isso, escolhi o meu próprio Makefile, criado para gerar um dvi/pdf de um código LaTeX. Portanto, eu vou colocar esse código aqui conforme eu for citando, mas se quiser, baixe o mesmo para acompanhar localmente e fazer suas próprias anotações nele. Eu não vou modificar o Makefile hoje, mas eu posso vir a atualizar/modificar ele no futuro (até irei comentar sobre pontos falhos do mesmo durante a exposição).

Primeiro passo

O primeiro passo é definir o objetivo.

No nosso exemplo: Compilar um código LaTeX, considerando a possibilidade de existir uma bibliografia, um índice remissivo, nomenclatura e glossário. Isso é o mais completo que eu conheço. Além disso, o Makefile deve sempre gerar um PDF e gerar um DVI quando possível. Para gerar o PDF, eu quero que o usuário possa escolher entre gerar primeiro um DVI e depois converter para o PDF ou gerar direto o PDF. Eu também quero que o Makefile facilite o meu trabalho para visualizar o documento e que seja possível eliminar o resultado e o lixo intermediário gerado facilmente.

Esse era o meu objetivo nesse caso. E entenda que eu sei como fazer essas coisas no terminal (o make não faz mágica)...

Em outros casos, pode ser: gerar o programa helloworld a partir do código fonte main.c, incluindo uma forma de eliminar o resultado final e os arquivos intermediários.

Lembrando regras básicas de programação.

Recomendações que não são utilizadas por quem recomenda não são, necessariamente, recomendações ruins....

Comente sempre que achar necessidade e quando não achar também, seja sucinto, mas não omita informações. Entretanto, não se culpe se depois alguém disser que não entendeu o que você queria ter dito. Como senhores do programa, naquele momento parece muito claro o que estamos escrevendo. Depois de um certo tempo, isso tornar menos claro. Então, se possível, reveja suas anotações depois de um certo tempo.

O alinhamento do código é muito importante, mas não precisa ser de 8 espaços, pode ser 1 ou 2. Eu gosto de 2, mas nesse caso do meu Makefile eu utilizei apenas 1 espaço. Dizem por aí que o recomendado é 3.

Sempre que possível, faça a tarefa automaticamente. Não peça ao usuário informações que não sejam necessárias, automatize sempre que possível, sem perder a generalidade.

Por fim, porém não menos importante... escreva como usar o seu código. Isso é para você mesmo se lembrar depois...

O Makefile.

O Makefile começa com um cabeçalho.
Informe o que achar necessário.

# File: Makefile
# Author: J. F. Mitre <http://jfmitre.com>
# Created: Sex 29 Mai 2009 10:14:33 BRT
# Last Update: Qui 04 Jun 2009 21:30:21 BRT
# Notes: Arquivo Makefile para compilar códigos em LaTeX
# Execute "make help" para ajuda
###############################################################################


É educado guardar um CHANGELOG. Eu escrevi o programa em uma tacada só na quinta do dia 04. Na sexta anterior tinha sido o dia que eu decidi fazer o arquivo e escrever as idéias. Então meu CHANGELOG é pequeno. Ainda assim, eu não o divulguei...

Teria sido legal colocar uma nota sobre licença. Eu esqueci desse detalhe...

Definições de variáveis

A primeira parte do Makefile é composta por definições de variáveis.

# Programas Selecionados {{{
########################## PROGRAMAS SELECIONADOS #############################

# Comando que gera compila o código LaTeX. Escolha entre: latex ou pdflatex
TEX = latex
# Comando que visualiza o arquivo .dvi
DVIVIEW = kdvi
# Comando que visualiza o arquivo .pdf
PDFVIEW = evince
# Comando que converte o arquivo .dvi em .ps
DVIPS = dvips

# }}}


Esse bloco acima define quais são os valores das variáveis TEX, DVIVIEW, PDFVIEW e DVIPS. São aplicativos do sistema que fazem aquilo o comentário indica. Esse são os comandos que serão utilizados pelo make ao executar um certa tarefa. Esses comandos foram colocados no primeiro bloco, porque podem ser modificados pelo usuário.

Veja como exemplo a variável TEX. Eu posso usar latex ou pdflatex. O primeiro comando gera um arquivo .dvi enquanto o segundo gera diretamente um arquivo .pdf. Eu também posso usar o visualizador que eu quiser para ver um certo formato de arquivo. Ao invés de kdvi, eu poderia especificar okular ou mesmo o evince (embora ele não inclua as imagens na visualização). E assim por diante. São variáveis para o usuário definir...

Que fique claro que um Makefile mais sofisticado teria colocar essas opções como argumentos, mas como eu disse, esse Makefile que eu escolhi é mais complexo que o básico e mais simples que o completo.

O bloco seguinte são as opções do programas

# Opções dos comandos {{{
############################ OPÇÕES DOS COMANDOS ##############################

# Opções do comando TEX especificado acima
OPTDVI = -halt-on-error
# Opções do comando dvips, que converte o arquivo .dvi para o .ps
OPTPS = -Z
# Opções do comando comando "pdflatex"
OPTPDF =
# Formato de conversão utilizado pelo ps2pdf (necessário especificar)
FORMATO = a4
# Estilos dos glossários, nomenclaturas, etc.
STYLENLS = nomencl.ist
STYLEGLS = nomencl.ist
# Opções do comando make
OPTMAKE = -s

# }}}

Se o usuário não conhece o comando, fica muito difícil dar palpites aqui. É necessário olhar o man de cada aplicativo para saber porque coloquei certas opções e para escolher outras. Afirmo que essas opções são agradáveis para 99 % dos usuários. Dois únicos cuidados são: definir o tamanho do papel para o ps2pdf e definir o estilo para o glossário e nomenclaturas. Note que eu usei o mesmo, mas há casos onde existe um estilo pré-definido e casos onde são diferentes os estilos.

Novamente, as opções padrões ficam no interior do Makefile, as alternativas deviam ser passadas por linha de comando, algo que eu não fiz intencionalmente... (quem sabe em uma versão futura)

Seguindo, encontramos mais variáveis.

# Outros programas {{{
############################# OUTROS PROGRAMAS ################################

# Comando que gera o índice, a nomenclatura, etc. Não existe outro atualmente
MAKEINDEX = makeindex
# Comando que gera a bibliografia, não existe outro atualmente
BIB = bibtex
# Conversão entre arquivo .ps e arquivo .pdf, existem outros, mas esse é o
# melhor para o GNU/Linux.
PSPDF = ps2pdf
# Eliminar arquivo. Não é razoável fazer de outra forma.
RM = rm -fv
# Comando make (até existem outros, mas não para esse Makefile).
MAKE = make

# }}}

Essas variáveis, são os outros comandos. Comandos no sistema que eu NÃO quero que sejam modificados. Quem gera o índice, e o makeindex, não existe outro. Quem gera a bibliografia é o bibtex, não existe outro.
Quem deleta arquivos é o rm. Bom, até existem outras formas de usá-lo, mas você quer mesmo modificar isso?

Da mesma forma, o make é o make. Até existem outros, como o colormake, mas fracamente, se é para usar um comando, use o mesmo que foi digitado, ou seja, se eu digito cmake, ele compilaria com o cmake, se eu digito make, ele compila com o make. Se entendeu a minha lógica, é melhor não modificar nesse comando até que consiga fazer o sincronismo entre o digitado pelo usuário e essa variável sem que o usuário deva especificar no interior.

Embora o autor (eu) não recomende modificá-las, essas variáveis são como quaisquer outras. Podem, sim, ser modificadas. O maior exemplo disso é o ps2pdf. Existem inúmeras formas de converter um arquivo .ps em um arquivo .pdf, mas apenas uma foi disponibilizada por mim, porque assim eu defini.

Execução
Passada a parte de configuração, vem a parte de execução.

Os primeiros comandos são preparações, eventualmente necessárias.

# Indentificação do nome do arquivo
DOC := $(shell egrep -l '^[^%]*\\begin\{document\}' *.tex |rev|cut -b5- |rev)

# Verificando se existe bibliografia

BIBFILE := $(shell egrep -l '^[^%]*\\bibliography\{' $(DOC).tex)

# Verifica se é uma apresentação do prosper
PROSPER := $(shell egrep -l '^[^%]*\\documentclass\[.*\]\{prosper\}' *.tex)


O primeiro comando define qual é o arquivo principal dentro do diretório em que ele é executado.
É um comando no shell. Ele gera a variável DOC, essa variável é utilizada como $(DOC) (se fosse um shellscript, seria $DOC, mas não é um shellscript, é um Makefile). De forma que $(DOC).tex é o arquivo principal da estrutra LaTeX (que pode conter vários documentos independentes).

Nesse ponto, vemos a primeira falha do autor. Ele não deixou claro, mas se existirem dois arquivo .tex com nomes diferentes contem um \begin{document} NÃO COMENTADO no mesmo diretório, haverá erro de compilação.

Porque o comando seguinte, verifica o arquivo $(DOC).tex procurando pela existência do comando que define se existe ou não uma bibliografia.

O terceiro comando é um daqueles casos de automação úteis. Oras, se o documento .tex for um código do prosper, então o DVI não faz sentido... logo, eu posso identificar esses casos e resolver o problema dele gerando sempre um PDF no final.

Relembrando as ações básicas

Gerar um $(DOC).dvi, gerar um $(DOC).pdf, limpar os arquivos intermediários, eliminar tudo que foi gerado pelo Makefile, inclusive o produto final e mostrar o resultado, tanto do dvi, quanto do pdf.

A ordem dos blocos não importa, exceto pelo primeiro bloco.

Bloco $(DOC).dvi, o primeiro bloco
# Gerando o "arquivo" DVI ...
$(DOC).dvi:
# mas ele é esperto o bastando para saber que não gera-se DVI com o pdflatex.
# E também gerará o PDF caso seja o proper seja utilizado.
@if [ ! -z $(PROSPER) ]; then \
$(MAKE) dvi; \
$(DVIPS) $(OPTPS) $(DOC).dvi; \
$(PSPDF) -sPAPERSIZE=$(FORMATO) $(DOC).ps $(DOC).pdf; \
elif [ $(TEX) == latex ]; then \
$(MAKE) dvi; \
elif [ $(TEX) == pdflatex ]; then \
$(MAKE) $(DOC).pdf; \
fi
Em teoria, esse bloco gera um arquivo DVI, mas ele DEVE ser esperto o bastante para saber que não se gera um DVI quando utiliza-se o pdflatex, e o serviço NUNCA para no DVI quando se está utilizando o prosper.

Mas o primeiro detalhe é o nome do bloco: $(DOC).dvi. O nome do bloco é o nome do suposto produto final. Isso é MUITO importante, porque evita que você compile novamente aquilo que já foi compilado, ou seja, se ao digitar "make $(DOC).dvi" no terminal o make encontrar o arquivo $(DOC).dvi, então ele para ali mesmo.

O segundo detalhe é posição do bloco dentro do código. Ele é o primeiro bloco, logo, ao digitar "make" sem argumentos, será ele que será executado.

Todos os comandos que compõem esse bloco estão afastados de um tab da margem esquerda.

O algorítimo é outro assunto, mas para melhor entendimento do Makefile, eu vou passar por esse bloco mais detalhadamente.

A primeira linha verifica se a variável $(PROSPER) não está vazia. Por que ela não está vazia, deve-se criar o DVI, converter esse DVI para o formato PS e depois converter o PS para o PDF. Porque não converter direto do DVI para o PDF ? Porque fica muito melhor assim de acordo com minha opinião. Um Makefile mais completo devia dar margem a outras opiniões. Caso $(TEX) seja igual a "latex" e não seja um arquivo prosper, então, eu quero gerar um dvi. Se $(TEX) for igual a pdflatex, então eu quero gerar um pdf diretamente. Por que isso foi feito ? Caso eu digite make no terminal, não é esse o bloco que será executado ? Então, se eu tiver selecionado pdflatex, eu certamente quero um pdf, eu não quero o DVI (porque o pdflatex não gera dvi :-0 ), logo crie o pdf. Melhor que uma mensagem de "erro" antipática (criada porquem escreveu o Makefile) que não lhe permita usar o make sem argumento diretamente no terminal.

O arroba na frente do if significa que eu não quero que o comando ecoe pelo terminal. Por padrão, o comando make funciona como se estivesse em permanente modo de debug. Mostrando quais são os comando que serão executados e executando-os. Eu não quero que ele escreva o comando na tela ? Então coloco o arroba na frente. O arroba na frente do if serve para todo o grupo de "uma única linha" do if.

Digo uma única linha, porque a barra invertida no final de cada linha significa que o comando continua na linha seguinte. O motivo pelo qual fiz isso no arquivo, é porque é mais fácil lidar com erros de formatos quando se utiliza a barra invertida (que deve ser o último caractere de uma certa linha).

Note os comandos no interior das condições.
    $(MAKE) dvi; \
ou então,
    $(MAKE) $(DOC).pdf; \
Esse comandos estão invocando o próprio make, que invoca um bloco dentro do Makefile. Um dos blocos chama-se "dvi" e o outro "$(DOC).pdf". Por similaridade com o "$(DOC).dvi", acredito que todos imagem o que seja o "$(DOC).pdf". Por sua vez, o bloco "dvi". É quem faz o serviço sujo. É ele quem de fato realiza o trabalho de compilar os código fonte gerando o resultado. Eu poderia dispensar esse bloco adicional, contudo, o código fica mais legível com ele, que faz um papel de subrotina ou função (como preferir).

Antes olhar o bloco que faz o serviço sujo. Vamos observar o bloco $(DOC).pdf

Bloco $(DOC).pdf
# Gera o arquivo PDF...
$(DOC).pdf:
# de um arquivo DVI, convertendo-o para PS e em seguida para PDF caso
# o comando padrão seja o latex ou diretamente, caso o comando padrão seja
# o pdflatex.
# Também diminuimos o esforço caso o prosper esteja sendo usado.
@if [ ! -z $(PROSPER) ]; then \
$(MAKE) $(DOC).dvi; \
elif [ $(TEX) = latex ]; then \
$(MAKE) $(DOC).dvi; \
$(DVIPS) $(OPTPS) $(DOC).dvi; \
$(PSPDF) -sPAPERSIZE=$(FORMATO) $(DOC).ps $(DOC).pdf; \
elif [ $(TEX) = pdflatex ]; then \
$(MAKE) pdflatex; \
fi
Primeiro, ele verifica se é um arquivo prosper e caso seja, passa ao bloco $(DOC).dvi o dever de cuidar desse caso. Se $(TEX) for igual a "latex", então primeiro deve-se gerar um DVI e sem seguida converter para ps e por fim, converter para pdf. Nesse ponto nota-se claramente a vantagem de ter o bloco com o nome $(DOC).dvi. Caso o DVI exista, ele não será recriado. Caso $(TEX) seja pdflatex, então chame o comando "$(MAKE) pdflatex", ou seja, o originalíssimo nome de bloco igual a "pdflatex" para a criar um pdf com o "pdflatex".

Bloco dvi

Aquele que faz o serviço sujo. Ele é idêntico ao bloco "pdflatex". O único motivo para os dois blocos existirem é porque assim eu defini. Até as opções, que são diferentes variáveis para cada comando, não justifica tal escolha. Primeiro porque eu poderia usar um if para gerar diferentes opções para cada comando, segundo porque as opções do comando latex são iguais as do comando pdflatex.

E porque defini dois blocos ? Porque eu estava com pressa para assistir uma defesa de tese nesse dia e não percebi o que tinha escrito até que era tarde demais. Aí tive pouco tempo para modificar.

Reconheço e reafirmo a utilidade de existir o bloco dvi e o bloco pdflatex, assim como devia existir o bloco pdf. porque a intuição humana fará o usuário digitar "make dvi" ou "make pdflatex" ou "make pdf" e assim é muito bom sincronizar o código a intuição humana. Mas definitivamente, não precisa ser dois blocos grandes e idênticos.

Bom, o bloco dvi é dado abaixo
# Gerando o arquivo DVI com o latex
dvi:
# Compliação inicial do arquivo tex
$(TEX) $(OPTDVI) $(DOC).tex
# Se existe bibliografia ...
@if [ ! -z $(BIBFILE) ]; then\
$(BIB) $(DOC).aux; \
$(TEX) $(OPTDVI) $(DOC).tex; \
$(BIB) $(DOC).aux; \
$(TEX) $(OPTDVI) $(DOC).tex; \
fi
# Se existe glossário, nomenclatura ou indice...
@if [ -f "$(DOC).nlo" ]; then \
$(MAKEINDEX) $(DOC).nlo $(STYLENLS) -o $(DOC).nls; \
$(TEX) $(OPTDVI) $(DOC).tex; \
fi
@if [ -f "$(DOC).glo" ]; then \
$(MAKEINDEX) $(DOC).glo -s $(STYLEGLS) -o $(DOC).gls; \
$(TEX) $(OPTDVI) $(DOC).tex; \
fi
@if [ -f "$(DOC).nlo" ]; then \
$(MAKEINDEX) $(DOC).nlo $(STYLENLS) -o $(DOC).nls; \
$(TEX) $(OPTDVI) $(DOC).tex; \
fi
@if [ -f "$(DOC).glo" ]; then \
$(MAKEINDEX) $(DOC).glo -s $(STYLEGLS) -o $(DOC).gls; \
$(TEX) $(OPTDVI) $(DOC).tex; \
fi
@if [ -f "$(DOC).idx" ]; then \
$(MAKEINDEX) $(DOC).idx; \
$(TEX) $(OPTDVI) $(DOC).tex; \
$(MAKEINDEX) $(DOC).idx; \
$(TEX) $(OPTDVI) $(DOC).tex; \
fi
# Uma última vez apenas para confirmar que tudo está ok...
$(TEX) $(OPTDVI) $(DOC).tex
Observe que ele não passa de um bloco de comandos em lista para os quais são efetuadas operações adicionais caso exista bibliografia, glossário, nomenclatura e índice. Nada diferente do que faria se estivesse escrevendo um shellscript, ou seja, nada diferente do que faria se estivesse digitando tudo no terminal. Todos os comandos são repetidos pelo menos duas vezes para assegurar o sucesso de qualquer projeto, não importa o tamanho. Mas esse tipo de dica é latex/terminal/linux não Makefile. Caso venha a compilar o código fonte em c, teriamos algo como "$(GCC) $(GCC_FLAGS) $(CODE)" e seria apenas uma vez.

Blocos clean e cleanall

... ou melhor dizendo limpando o diretório. Os dois blocos são reponsáveis por eliminar os arquivos não mais desejados. O bloco clean limpa os arquivos intermediários (e como tem arquivos intermediários nesse caso). o bloco cleanall, elimina todos os arquivos, inclusive os resultados, ou seja, o pdf e o dvi gerado.
# Limpando o básico dos arquivos gerados pelo compilador
clean:
@$(RM) *.aux *.log
@$(RM) *.toc *.lot *.lof
@$(RM) *.ttt *.fff *.blg *.out
@$(RM) *.ind *.ilg *.idx *.aux *.glo
@$(RM) *.gls *.abx *.nlo *.syx *.nls
@$(RM) *.ps
@$(RM) *.tex.backup
@$(RM) *.bib.backup *.bib.bak
@$(RM) *.tex.bak
@$(RM) *.bbl
@$(RM) *.*~
@$(RM) Makefile~

# Limpando tudo, inclusive os arquivos finais.
cleanall:
$(MAKE) clean
@$(RM) *.dvi *.pdf
Detalhe interessante fica por conta de como o cleanall foi criado. Ele usa o bloco clean e depois elimina o que sobrou, que são os resultados. Essa é a forma elegante de aproveitar os comandos de um bloco em outro bloco.

Blocos de visualização

Quatro blocos adicionais foram criados para permitir visualizar o resultado: show e shownew, showpdf e shownewpdf.
show:
@if [ ! -z $(PROSPER) ]; then \
$(MAKE) $(DOC).dvi; \
$(PDFVIEW) $(DOC).pdf; \
elif [ $(TEX) == latex ]; then \
$(MAKE) $(DOC).dvi; \
$(DVIVIEW) $(DOC).dvi; \
elif [ $(TEX) == pdflatex ]; then \
$(MAKE) $(DOC).pdf; \
$(PDFVIEW) $(DOC).pdf; \
fi

# Idem ao "show", a diferença é que aqui
# é feito uma nova compilação, de um jeito ou de outro
shownew:
$(MAKE) cleanall
@if [ ! -z $(PROSPER) ]; then \
$(MAKE) $(DOC).dvi; \
$(PDFVIEW) $(DOC).pdf; \
elif [ $(TEX) == latex ]; then \
$(MAKE) $(DOC).dvi; \
$(DVIVIEW) $(DOC).dvi; \
elif [ $(TEX) == pdflatex ]; then \
$(MAKE) $(DOC).pdf; \
$(PDFVIEW) $(DOC).pdf; \
fi

# Idem ao "show", mas para arquivos PDF apenas
showpdf:
$(MAKE) $(DOC).pdf
$(PDFVIEW) $(DOC).pdf

# Idem ao "shownew", mas para arquivos PDF apenas
shownewpdf:
$(MAKE) cleanall
$(MAKE) $(DOC).pdf
$(PDFVIEW) $(DOC).pdf

# }}}
Nesse ponto, espero que tenham compreendido o suficiente do código para compreender o que foi feito. Pois o objetivo é visualizar o arquivo. Se for um DVI abrir o visualizador de DVI, se for um PDF abrir um visualizador de pdf, caso não exista o arquivo, crie-o.

Os blocos com "new" no nome, são assim definidas porque eliminam o pdf/dvi que eventualmente exista, compila novamente e exibe o novo arquivo.

Os blocos com "pdf" no nome, força que seja visualizado o pdf, não importa qual o processo que o gera. Os demais vão exibir o DVI sempre que esse for válido/existir ou o PDF, em contrário.

Finalizando

O último bloco (que eu não vou transcrever para esse ponto) é o bloco help, que permite que o usuário digite "make help" para descobrir quais são os comandos diponíveis.

Conclusão
Esse texto ficou longo demais. Então vou ser breve.

Falta discutir alguns pontos e abordar um Makefile para programação em si (ou seja, para arquivo C/C++/Fortran). Assim como algumas normas de etiqueta para esses tipos de Makefile. Entenda: existem nomes de variáveis que são reconhecidos por qualquer programador no mundo, como GCC_FLAGS, porque usá-las ou não usá-las. E finalmente discutir porque usar o Makefile e não um shellscript. Existem fatores que induzem a usar o Makefile, mas se é apenas para você, porque usar o make ? Mas não prometo a terceira parte para logo...

Uma quarta parte agendada para daqui a muito (muito mesmo) tempo, seria como lidar de forma correta com as opções dentro do Makefile. Esse é o ponto mais delicado e complexo e daria um ar profissional ao Makefile (como os dos grandes programas). Mas é também o que dá mais trabalho, portanto, exige planejamento e detalhamento ... e tempo para escrever.

Thursday, June 11, 2009

Nemiver: Interface gráfica para o gdb

Uma das grandes dificuldades de utilizar o vim como uma IDE de programação é que este, apesar de vários esforços em contrário, não possui um interface amigável para realizar um debug em um programa. Diga-se de passagem, isso é ponto para emacs, que possui esse tipo de recurso.

Pode-se dizer que o gdb é "A Interface". Digo, muito provavelmente um profissional qualificado deve conhecer o suficiente do gdb para usá-lo no terminal. Eu ainda não cheguei nesse nível.

Na busca de uma interface gráfica, eu encontrei o Nemiver. Uma leve é muito competente interface gráfica do projeto GNOME para o gdb.

Possui o básico, breakpoints, next, step in e out, monitorar valores, etc e etc. Não me deixou na mão em nenhum ponto que eu considere crucial.

Dica rápida, abra o aplicativo executável compilado com a opção de debug e depois abra o código fonte através da opção "Selecionar do alvo executável". Lá estão todos os códigos que compõem aquele aplicativo. A ajuda é interessante. Realmente ajuda nos pontos chaves.

Seu concorrente mais próximo em objetivo é o KDbg, mas, seguindo a diferença básica entre GNOME e KDE, o Nemiver possui uma interface muito mais limpa e objetiva.

Sunday, June 07, 2009

Colorindo as "man pages"

Para colorir uma página de manual sem alterar o paginador padrão do comando man, defina as linhas abaixo no ~/.bashrc.
#  begin blinking
export LESS_TERMCAP_mb=$'\E[01;31m'
# begin bold
export LESS_TERMCAP_md=$'\E[01;33m'
# end mode
export LESS_TERMCAP_me=$'\E[0m'
# begin standout-mode - info box
export LESS_TERMCAP_so=$'\E[01;41;37m'
# end standout-mode
export LESS_TERMCAP_se=$'\E[0m'
# begin underline
export LESS_TERMCAP_us=$'\E[01;32m'
# end underline
export LESS_TERMCAP_ue=$'\E[0m'
Recarregue o ~/.bashrc (abra uma nova janela do terminal após salvar o arquivo) e digite "man man" (página de manual do comando man) para ver como ficou o resultado.

Traduzindo

Blinking é piscando ... você já viu alguma coisa piscando no man ? Eu não faço idéia de onde a configuração de "begin blinking" vai atual... eu não vi o vermelho (número 31) em negrito (01) em lugar algum das páginas que verifiquei.

A variável relativa a "begin bold" refere-se ao conteúdo que tradicionalmente está em negrito, ou seja, nomes dos programas e opções da maioria das páginas man. Bem como títulos de seções. O 01 refere-se ao negrito (sugiro fortemente que mantenha) e 33 é amarelo.

A variável relativa a "begin standout-mode" refere-se aquela caixa que fica na parte de baixo da janela e indica a a linha (posição relativa e absoluta no texto). Nessa configuração pessoal, eu usei 41, que refere-se ao background com cor vermelha e branco (37) como cor da fonte.

A variável relativa a "begin underline" refere-se ao conteúdo que tradicionalmente está em sublinhado. Aplica-se quase todos os valores das opções da página de uma manual. No meu exemplo, eu utilizo 01, que é referente a negrito, e 32, que é a cor verde.

Todos os "end alguma coisa" refere-se a restabelecer a coloração normal do texto após aplicar a modificação de cor. A menos que queira um carnaval de cores sem sentido na sua página de manual, é conveniente manter a configuração acima.

As cores

O código de cores e efeitos é simples. As Funções ZZ inclui uma função que lhe ajuda com essa tarefa, mas você não precisa instalar a mesma para usar as cores, basta visitar a página de testes para descobrir quais são as cores que lhe interessa.

Na prática, onde está 01 acima, pode variar entre 00, modo normal, 01, modo em negrito. O 04 forma escrita sublinhada (e eu não sei porque), pois o bom senso diz que o 02 e 03 deviam existir... Pois, ... acho que o bom senso não foi respeitado, pois não funciona comigo... ou que deve ter algum significado especial esse 04.

Onde lê-se 41 nas variáveis acima, pode-se alterar entre 40 e 47. Aí a figura da página das funções ZZ ajuda, pois essa configuração refere-se a cor de fundo.

Onde lê-se 37, ou melhor, números na casa de 30, pode-se usar números entre 30 e 37 e essas referem-se a cor da fonte. Novamente o link da página de testes da funções ZZ ajuda muito, porque você deve combinar os valores de fundo e fonte para que tudo fique visível. Note inclusive que seria muito ruim usar uma fonte azul com um fundo preto...

Nota: 30 é preto, mas preto com negrito fica cinza e torna-se visível sob o fundo preto. Observe que existe uma grosseira variação na tonalidade da cor conforme o status da fonte. É basicamente por isso que uso negrito em tudo acima. Torna o que é importante mais nítido...

Não funcionou ?

Infelizmente, a configuração acima não funciona em qualquer distribuição. Eu conheço essa dica a muito tempo, mas não funciona(va) no openSUSE... Há um tópico no fórum que tenta esclarecer alguma coisa (mas cuidado, porque lá tem alguma informações trocadas/erradas), tudo que consegui foi colocar a "info box" colorido... o que não adianta nada. Eu só pude confirmar que essa dica realmente funcionava hoje, no Arch Linux.... Nunca testei no Ubuntu

Alternativas ?
No Viva o Linux possui uma dica que ensina como usar o most como paginador do man e uma dica de como criar uma função para ler o resultado do man no vim nos comentários. A dica sobre o most e o man você também encontra em outros lugares, como aqui.

E falando do vim, no wiki existe uma dica mais completa (com várias dicas nos comentários adicionando outras informações) de como colocar o vim para ser o leitor das páginas de manual que eu ainda não testei, e não sei se testarei, mas inclui uma personalização da sintaxe, o que é necessário, pois o padrão não é muito bom.

No meu vim, essa dica também funciona.

Nem tudo fica colorido ?

Curiosamente, o vim é o único que permitiria você de adivinhar o que deve ou não colorir. Entenda que por padrão, não há como o paginador comum (seja ele qual for), adivinhar o que deve ser colorido sem a formatação da página informe isso a ele. Ou seja, o que não está em negrito e o que não está sublinhado, não será identificado como um ponto a ser colorido... e nem tudo que devia ter sofrido com essas modificações de formato de fato sofreram em algumas páginas de manual (veja "man find" ou "man vim" e compare com "man man" e "man cp").

E é aí que o vim pode levar vantagem, pois pode-se alterar a sintaxe para ele utilizar expressões regulares para identificar o que é uma opção, valor, etc, etc. Infelizmente, isso não é o padrão.

Saturday, June 06, 2009

Mudando radicalmente a distribuição

Imagine dirigindo um caminhão e mandando esse caminhão fazer uma curva para direita. Agora, imagine que ao fazer isso, o caminhão vire para a esquerda. Consegue ver um problema aqui ?

Pois é exatamente assim que eu estava me sentindo ao usar o openSUSE 11.1. Pela terceira vez em 2 meses ele "quebrou algum recurso". Dessa vez o locale foi corrompido, e assim como eu já havia visto em outro computador, ele "acreditou" que eu estava utilizando uma codificação exótica da qual eu nunca tinha ouvido falar...

Quem já usou o openSUSE sabe o quanto somos reféns do yast. Se o Yast diz que eu estou utilizando UTF-8, o que eu poderia fazer ? Editar o arquivo na mão ? Não no openSUSE. No openSUSE não se edita diretamente NENHUM arquivo de configuração. O máximo que eu poderia fazer é editar um arquivo que seria o responsável de editar o outro arquivo (é... arquivo que gerencia arquivo).

Por esses motivo é perdi definitivamente a minha paciência com o openSUSE e instalei o Arch Linux.

Por que o Arch Linux ?

Se eu escrever: vire a direita, ele vira a direita... se isso está certo ou errado é problema meu.
Possui um excelente gerenciador de pacotes.
São raras as perguntas sem respostas. Digo, é a maior taxa de solved/resolvido por unidade de tópicos que eu já vi em um fórum.

E a instabilidade ?

Mais instável do que andava a última versão do openSUSE ? Definitivamente, não. Além disso, como eu disse, para toda pergunta existe uma resposta, assim, quando há um problema, surge uma solução ... De qualquer forma, assim que eu terminar de configurar o sistema eu irei fazer um backup de partição para assegurar uma restauração rápida em caso de necessidade. Afinal, minha máquina principal é uma máquina produtiva e as vezes não pode parar. Embora, eu tenha uma máquina na universidade que sempre pode me servir em caso de necessidade (eu trato essa máquina de forma mais conservadora, limitando programas existentes, freqüência de atualizações, etc, assim, nela o openSUSE ainda está ok).

Ainda assim, existe um ponto a ser levado em consideração. A tal da instabilidade é teórica. Digo isso porque até agora, eu só vi estabilidade e soluções de problemas. Tudo que não funcionava no openSUSE está funcionando agora. Exemplo, o gerenciador de discos removíveis encriptados, que não funcionava no meu openSUSE corretamente.

Mais a melhor impressão que tive do sistema sobre essa questão foi quando eu abri o krename. O krename existente no openSUSE foi compilado com o KDE4 e não funciona. O disponível no Arch Linux foi compilado com o KDE3 e FUNCIONA. Qual dos dois foi menos responsável ?

Por tudo isso e mais alguma coisa, a tal instabilidade é teórica. Espero alguma turbulência em grandes upgrades que possam requerer alguma modificação grosseira no arquivo de configuração. Nada além disso.

Problemas ?

Claro que eu tive problemas !!! Mas como disse acima, todos os problemas tinham solução em algum lugar da internet.

É engraçado como o sistema, por exemplo, me lembrou que eu tenho duas placas de rede na máquina (eu só uso uma, a outra sempre fica desabilitada), mas eu demorei a correlacionar o fato de ter uma instabilidade em conseguir conectar ou não por conta da ordem de leitura dos módulos delas... Mas é a tal coisa, para instalar o Arch Linux deve conhecer sua máquina. A distribuição não perdoa quem esquece esses detalhes...

Alguns problemas, ou melhor, questões, estavam associados ao pouco uso do pacman e ao desconhecimento de nomes de pacotes e seu conteúdo. Um exemplo, como eu saberia a priori que o okular estava no pacote kdegraphics ? Mas todas essas perguntas são respondidas por alguém.

Todos os meus problemas foram solucionados em menos de 1 dia. Recorde histórico nesses mais de 10 anos de uso do GNU/Linux. Seria eu aprendendo alguma coisa ou o sistema não querendo mais informação do que a necessária ?

Uma curiosidade

Para um sistema que requer que eu configure o teclado com um arquivo de configuração escrito manualmente, foi muito curioso encontrar tantas linhas de configuração no /etc/vimrc e /etc/gvimrc. São vários detalhes que me obrigam a alertar sobre a necessidade de olhar esses dois arquivos antes de usar os programas. O problema está para quem já tem um .vimrc e não quer configurações conflitantes entre os arquivos. Por tudo isso, eu sugeriria uma remoção significativa do conteúdo desses dois arquivos...

E porque eu usava o openSUSE mesmo ?

Resposta fácil. Na época que comecei a usá-lo, era a única distribuição que compilava o openFOAM (programa livre para simulação CFD). E o sistema não foi ruim. Na verdade eu gostei muito da versão 10.3, apesar de me sentir um pouco incomodado com o excesso de camadas entre minhas edições de configuração e os arquivos de configuração propriamente dito e com a velocidade do Yast. A verdade é que tudo funcionou e eu não podia desejar menos. E a inércia faz com que continue-se utilizando a mesma distro quando tudo vai bem (especialmente com as melhorias do Yast). Mas os problemas atuais do openSUSE 11.1 foram fatais, sistema estava lento demais, demorava muito para abrir alguns módulos do Yast quando não o próprio GNOME (chegava ao ponto de ser possível fazer um lanche enquanto o sistema dava boot), alguns erros "sem lógica" apareciam do nada, etc. O último problema, que foi o de codificação, foi fatal. Se eu o usasse por mais tempo eu correria o risco de corromper todos os meus arquivos. Seria uma tragédia. Tradicionalmente, eu restauraria a partição de um backup estável, mas resolvi por um fim nisso. Pelo menos em casa. Na universidade eu vou esperar aparecer um "problema-desculpa" para usar o Debian.

g3data

Ainda não aprendi como fazer contribuições, mas o único programa que instalei que não estava nos repositórios oficiais é o g3data. Um simpático programa para interpolar gráficos que estão em formato de imagem (png, pelo menos, nunca tentei com outro). Ele está no AUR, mas desatualizado (ok, pouquinho desatualizado, mas sabe como é, não ?). Então eu criei o meu próprio PKGBUILD. Para ser bem honesto, eu apenas peguei o que estava no AUR e modifiquei os campos necessários.

Eu não vou contribuir oficialmente enquanto não ler toda aquela documentação que parece existir por aí. Afinal, se eu fizer algo errado não vai ser por omissão. E espero não cometer nenhum pecado ao fazer essa modificação e disponibilizá-la aqui...

Comentários finais

Espero ter tempo para aprender alguma coisa sobre o AUR.

É realmente maravilhoso utilizar o /etc/rc.conf para configurar o sistema.

Claro que eu instalei o tema padrão do Ubuntu no meu Arch Linux... (para quem não sabe, é o meu tema predileto). Até isso ficou melhor no Arch Linux do que no openSUSE, que adora reclamar do tema...

Tenho minhas dúvidas se eu vou escrever alguma dica para o Arch Linux nesse blog. Não sei se vou aprender algo que não tenha sido detalhadamente divulgado por outro em algum lugar e eu raramente repito assuntos que possam ser encontrados na internet, exceto quando é algo que considero muito raro ou importante. Acho que gastei todo meu conhecimento inédito nesse tópico... Mas provável é que eu escreva reviews sobre certos assuntos...

Eu agora tenho nautilus-actions. Não funcionava no openSUSE como devia (dava trabalho para instalar e funcionava a meia-boca)

E o nautilus mostra os modos de "visão de ícones/em lista/compacta" ao lado da barra de enderenços (o openSUSE não mostra ela, penso que era uma configuração, mas nunca achei como restaurar ao "normal")

Eu agora tenho gdmsetup. Estava com saudades dos bons e velhos aplicativos...

As fontes estão mais bonitas... e eu não fiz nada para isso...

E o OpenFOAM ? Bem, se por acaso de um dia ensolarado eu necessitar de ter a versão de desenvolvimento novamente na minha máquina pessoal. Com 100% de certeza não será para executar coisa alguma. Agora existe uma versão instalada em um cluster do lab. Logo, me basta saber o usar bem o editor de textos via terminal (entenda, vim ou emacs). Mas ainda que esse cenário mude, o OpenFOAM tem mostrado uma filosofia de empacotar sua própria versão de tudo. Portanto, tudo que eu teria é trabalho em ler os arquivos de configuração e a documentação e assim determinar exatamente quais são os componentes necessários (e suas respectivas versões) para uma compilação com sucesso. Aliás, hoje é mais fácil compilar o OpenFOAM no Ubuntu do que no openSUSE de forma que todos os argumentos que nos levaram a utilizar o openSUSE foram destruídos.

Sinceramente, espero nunca ter que abandonar o Arch Linux.
É muito agradável, leve, simples, etc.

Thursday, June 04, 2009

Uma introdução ao comando make

Eu peço uma licença poética a todos para facilitar aqui a explicação sobre o que é o comando make. Considere este um dos programas mais complexo e mais simples do universo *nix. Essa contradição somada a um rico e super-direto manual, tende a não fornecer uma das melhores famas a esse programa.

O programa.

O make é um programa como qualquer outro, normalmente instalado no GNU/Linux como um pacote independente. Sua função é muito simples. O make executa instruções contidas em um certo arquivo. Digitando apenas make no terminal, o comando busca pelo arquivo Makefile existente dentro do mesmo diretório onde foi executado. O arquivo com as instruções pode ser manualmente especificado com a opção -f. Nesse caso, ele pode estar em qualquer diretório e ter
qualquer nome.

O arquivo Makefile - Conceitos básicos.

Me permitam fazer o paralelo de associar a idéia de um Makefile, com um script para shell. Pois os dois possuem a mesma função prática.

O script executa instruções divididas de acordo com opções pré-estabelecidas no seu interior. O make executa instruções estabelecidas de acordo com cada uma dos blocos de instruções de um arquivo Makefile.

O Makefile, portanto, contém instruções em série de algo que deseja fazer. Exatamente da mesma forma que seria, caso estivesse escrevendo um script.

O Makefile é dividido em blocos de comandos. Cada bloco possui um nome, e esse nome tona-se um argumento para o comando make.

Veja um exemplo de bloco:
clean:
rm -vf *.backup
rm -vf *~
rm -vf *.o
O nome do bloco é "clean".
As instruções são para utilizar o comando rm com as opções -vf (verbose e force).
Eles estão uma linha abaixo do nome e separado de pelo menos uma tabulação da primeira coluna da lina.

O uso do make.

Tradicionalmente, o uso básico do make consiste em algumas poucas opções:
  • make
    Digitando apenas make no terminal, o programa procura pelo Makefile e executa o primeiro dos blocos de comandos existentes dentro desse arquivo.
  • make -f ARQUIVO
    Esse exemplo é igual ao anterior, mas o arquivo Makefile está em um lugar qualquer do disco, com um nome qualquer também... Não é um uso comum.
  • make dothat
    Nesse exemplo, dothat representa o nome de uma das instâncias existentes dentro do arquivo Makefile.
    No nosso simples exemplo, poderíamos escrever "make clean" e ele executaria as instruções daquele bloco naquele comando. Note que se "clean" for o primeiro bloco de comandos, digitar apenas "make" ou "make clean" produz o mesmo resutado.
No próximo texto sobre o assunto, estudaremos um Makefile detalhadamente. Será o Makefile que eu escrevi e disponibilizei para compilar o códigos em LaTeX. Não é um Makefile tão simples, nem tão complicado. Dará um interessante estudo de caso.

Nova forma de disponibilizar scripts e arquivos de configuração

Eu perdi a paciência com o Snipt mais rápido do que eu podia imaginar.

Assim, na busca de um lugar que pudesse aceitar os meus pequenos arquivos de configuração e scripts, eu me optei pelo Google Sites.

O Google Sites está muito melhor que o falecido Google Pages e conta com um número muito bom de recursos, inclusive, com formas específicas para compartilhar artigos que o tornam muito próximos de um "Google Drive" (vide template "File Cabinet"). A disponibilidade de 100 MB é muito mais do que eu preciso para compartilhar arquivos de configuração...

A escolha natural do Google Sites dá-se depois de pensar em como transferir os arquivos que eu compartilho via Google Pages (que com o fim deste, serão automaticamente transferidos para o Google Sites).

Bom, os três arquivos compartilhados recentemente nesse blog, o ~/.vimrc, o Makefile para LaTeX e o latexfilter, foram atualizados para a última versão e transferidos para o Google Sites. Note no fim de cada uma dessas páginas a existência do arquivo anexado.

Todos os arquivos de configuração e scripts disponibilizados aqui estão disponíveis na barra lateral do blog. E serão atualizados silenciosamente quando tiverem apenas algumas pequenas correções...

Não tenho certeza de que vou atualizar os links nos tópicos oficiais, o mais provável é que fique como está...

Nota: Para gerar essas páginas bonitinhas, abra o arquivo vim, selecione o esquema de cores de sua preferência e digite no modo de comando:
   :so $VIMRUNTIME/syntax/2html.vim 
No meu .vimrc, existe um mapeamento que correlaciona o \2html em modo normal com esse comando acima. O gvim exibe em "Editar" > "Esquema de cores" todos os esquemas de cores que possui instalado.

Wednesday, June 03, 2009

.vimrc atualizado

O meu .vimrc foi atualizado.

A nova versão possui tantas melhorias que nem seria possível listar tudo nesse blog.
Destaques, além das importantes pequenas correções, vão para:
  • Correção ortográfica. Com correção simultânea a digitação por duas formas diferentes. Destaque para palavras repetidas uma após a outra (tipo oi oi), entre outras. Nota para modificação do acesso ao dicionário que contorna um bug que eu encontrei...
  • Esquema visual aprimorado com função para identificar a resolução do monitor e ajustar a fonte no gvim (dependente de variável no .bashrc)
  • Ajustes para lidar com textos encriptados pelo GNU GPG.
  • Para LaTeX, temos a integração da bibliografia de um arquivo arquivo .bib com um dicionário para autocompletar.
  • e o ajuste da forma de realizar a verificação do log gerado pelo vim (sintaxe e integração de script).
Do mais, se alguém tiver uma dica de algo que seja muito melhor que Snipt, favor me informar. Ele não é ruim, mas me parece muito pesado...

Monday, June 01, 2009

Snippets

Snippets são trechos reutilizáveis de código ou texto. Normalmente escreve-se uma palavra chave e um TAB e o trecho é inserido no conteúdo atual. Existe para mais de um editor de textos (vim, gedit, etc).

O maior problema dessa idéia brilhante é que é necessário configurar seus snippets. Não seria legal se você pudesse usar o que outras pessoas já fizeram ?

Pois, olhe os links externos da referência sobre snippet na wikipédia.

Infelizmente, a forma de escrever um snippet varia um pouquinho entre editores, mas nada que comprometa o reaproveitamento, pois escrever um snippet é algo muito simples.

A premissa é que você gasta tempo agora (e não vai ser tão pouco assim, um dia, pelo menos) configurando o que será necessário várias vezes ao longo de sua produtividade (o que lhe fará ganhar muitos dias). O ganho de tempo é extraordinário.

Agora, falta apenas uma extensão para o Firefox. Na verdade a extensão até existe, mas é experimental e para versão 2.0, ou seja, não existe de fato...