quinta-feira, 25 de novembro de 2004

Live bookmark's no melhor browser do mundo

Cheguei a mencionar sobre feeds rss no post Inovações no software livre.
A novidade agora fica com os live bookmark's do Mozilla Firefox.

Alguns conhecem bookmarks como "favoritos". Live bookmark's são favoritos "vivos", ou seja, se modificam de acordo com o conteúdo de algum site que publique feeds rss/atom.
Em suma, você adiciona o bookmark vivo no browser e fica sabendo os nomes dos artigos/textos quando o site tiver alguma publicação.

Frequento mais ou menos uns 20 blog's e admito que seria impraticável visitar um a um pra verificar se houve alteração. Os recursos do firefox vieram pra facilitam minha navegação, e muito. Existem muitos outros além dos bookmarks vivos pois é um browser extensível. Veja aqui todas as extensões disponíveis.

Das extensões que utilizo:
GMail Notifier: Notifica quando recebo um email na caixa de entrada do GMail e me avisa a quantidade de emails não lidos.
Bookmark sincronizer: Permite enviar meus bookmark's (inclusive os vivos) para um ftp e baixar em casa. Assim, mantenho meus favoritos atualizados em casa e no serviço.
HTML Validator: Valida páginas html de acordo com as normas da w3c.
Optimoz Tweaks: Esconde/Mostra a Side Bar automaticamente quando o mouse entra/sai nela.

Cada dia me surpreendo mais com o browser da mozilla!
Instale-o e se surpreenda também!

Um dos únicos argumentos que podem surgir é que nem todas páginas são exibidas, então vou rebater logo com a verdade pois todos deviam saber:

Primeiro: se você só utiliza Internet Explorer não conhece um browser de verdade, e te garanto que você só o conhece porque a Microsoft fez o favor de incluir ele no Windows para sua comodidade. Se tivesse que baixar da internet e instalar no seu windows, você não o faria. E mais: sua dona não tem interesse em aperfeiçoá-lo. Porquê? Veja aqui.

Segundo: O estrago na internet que ela fez com o monopólio que veio advindo desta "distribuição" disfarçada é incalculável. Muita gente sabe que a Microsoft nunca foi a que mais seguiu padrões e nem será. É bastante simples entender: padrões não possuem importância quando se é a maioria. Você faz e quase todo mundo automaticamente usa, isso importa. Comparo a dar remédio pra menino "guela abaixo": você tem muito mais força e se ele reagir você o domina.

A falta destes padrões dificultam que outros browser's exibam as mesmas páginas que o navegador dela exibe. Então, se você usa o Firefox/outro e ele não mostra a página que você deseja corretamente, a partir de agora já sabe que a culpa não é do browser: é do dono do site que não o fez seguindo padrões.

Esta não é somente a minha opnião. Bastante pessoas pensam como eu (ou eu penso como elas :D), duas:
Bruno Torres
Joel on Software

segunda-feira, 22 de novembro de 2004

Você adora ser um hardware man?

Pra quem é ou deseja ser um "hardware man" ou "suport man", que tal este cartum aparentemente feito pela IBM?

Ele descreve bastante bem o que você é/será!
É um cartum "flashiano" em chinês, mas não é difícil de enteder.
É um pouquinho grande, mas já aviso: vale cada bit do download.
A música de fundo é chique pra caramba!

Veja aqui o Cartum

quinta-feira, 18 de novembro de 2004

Um jogo de xadrez interessante

A fim de descobrir quem joga xadrez da turma:
Que tal ver o que o computador está calculando para fazer a jogada?

Achei super interessante este jogo de inteligência articial (sim, ele aprende jogando).
Não é necessário nem instalar! Basta clicar no link.

Link do jogo

Se não sabe jogar, vai querer pelo menos ver as imagens. (Cada linha correponde a uma jogada possível)

Imagens interessantes

Para os não curiosos que deixaram de olhar o código da página: é um jogo feito em java... mais precisamente um Applet. E muito bem feito!

sexta-feira, 5 de novembro de 2004

Btree for all

Não pude deixar de notar esta beleza de aula que vai do começo ao aparente final do assunto btree.

Aula btree USP

Huffman

Pra quem está boiando em código de huffman...

Leia esta apostila que explica muitíssimo bem!
É um arquivo em formato pdf.

Apostila da USP

quinta-feira, 4 de novembro de 2004

Build em somente um passo com Want

Want é uma ferramenta para automatizar a compilação de projetos delphi criada por Juancarlo Anez como podemos constatar no sourceforge. Sua criação foi inspirada na ferramenta Apache Ant e com isso acabou suportando a grande maioria de tarefas que esta tem a disposição. Não encontrei muita documentação a respeito do want mas a documentação do Apache Ant foi suficiente para minhas dúvidas e inclusive o próprio autor a indica.

De onde vem o nome? Conforme cita o autor a primeira idéia foi representar "Windows Ant" só que ele queria algo que também incluísse o Kylix/FreePascal. Porém como era fácil pensar: want compile, want install, ou seja, desejo compilar, desejo instalar, o nome acabou sendo mantido. :D

2.0 Por que utilizar?
Diria que automatizar o processo de compilação, principalmente quando se tem vários programas ou mesmo vários módulos, algumas diretivas de compilação e outras coisinhas mais, te leva a deixar de se preocupar com vários detalhes que geralmente são esquecidos no momento da distribuição dos binários para o Cliente e como diz a experiência, uma falha neste processo sempre causa alguns problemas e alguma insatisfação.
Além disso, uma das etapas que o Joel defende em seu blog no artigo 12 passos para um código melhor é exatamente o build em somente um passo. Admirando suas idéias e pensamentos (o cara é realmente bom no que escreve e pensa) não poderia deixar de perceber que realmente é um passo de grande importancia! E acredito que temos um bom motivo pra fazê-lo ao somar todo o processo que vai do Ctrl+F9 até a disponibilização em um ftp ou website.

3.0 Copiando e instalando
Do sourceforge você irá baixar este arquivo compactado que contém o binário, o código fonte do want e do dunit (do mesmo autor) além de alguns exemplos de script em xml.
Pra facilitar, coloque o arquivo want.exe em um diretório que esteja no path de seu sistema operacional (ou direcione o path até ele).
Copie também este programa ftp, feito em Delphi com os componentes Indy que será utilizado como exemplo de compilação.

A versão do Indy necessária é a 9.00.10 que vem por padrão no Delphi 7 mas não no 6. Pensando na frustação de quem usa o Delphi 6 e quer seguir o artigo deixo a dica: Remova o Indy que vem em seu Delphi através de "Adicionar/Remover programas - Borland Delphi 6/Alterar" desmarcando apenas o Indy. Depois baixe este arquivo, extraia e compile a package. Se ainda restar dúvida, veja as notas específicas para a sua versão de delphi direto do site do Indy.

4.0 Criando um script de compilação (want.xml)
Acompanhe a criação das tags observando o arquivo want.xml da pasta do programa ftp.

4.1 O cabeçalho do arquivo
O script possui seção geral (como todo xml) onde se é definido o nome do projeto, o diretório base que será utilizado na definição dos caminhos e o alvo padrão que será chamado quando não for fornecido parâmetro algum ao want.exe. Facilita bastante utilizar . ou .. para indicar o diretório atual e o anterior, principalmente quando resolver mudar o caminho dos fontes.



<project name="ftpth" basedir="." default="all">
</project>



4.2 Definindo propriedades

Considere propriedade como sendo uma varíavel do tipo string. Ela tem um nome e um conteúdo. Para definí-la você utiliza a sintaxe:

<property name="nomevar" value="valor"/>


Para definir o valor, além do texto, pode-se utilizar alguma outra propriedade já definida, variáveis vindas da linha de comando e chaves de arquivos ini.


<property name="nomevar" value="${propertyJaDefinida}textoadicional"/>



4.3 Lendo chaves de um arquivo ini
Antes um detalhe: Os caminhos de arquivos/diretórios no want, mesmo em ambiente windows são definidos utilizando barra normal.

Se sua empresa/projeto possui vários programadores, suspeito que cada um deles prefira instalar aquela suite de componentes ou até mesmo o próprio Delphi em um caminho diferente. Diria que cada um bagunça como pode, então iremos isolar os caminhos destes componentes em um arquivo ini com seções e chaves pré-definidas pra facilitar uma posterior manutenção no script. Nesta mesma "bagunça" cada programador há de querer que os binários resultantes da compilação fiquem em um diretório específico, então, mais uma chave no arquivo ini. Outro para os arquivos zipados, outro para isto, aquilo, aquilo...

Teoria: Para ler uma chave de um arquivo ini utilizamos o operador ?{}. A linha a seguir lê a chave "key1" da seção "seção1" do arquivo "th.ini" atribuindo seu valor a propriedade "nomeprop":


<property name="nomeprop" value="?{th.ini:seção1:key1}"/>


Embora o programa a ser compilado (ftpth) não necessite de componentes que não tenham dcu's fora da pasta lib, e o want também disponibilize uma chave para incluir o LibraryPath do delphi, vou ilustrar a inclusão. Ela está comentada utilizando <!-- --> e dentro da seção project:


<!--
<property name="delphibase" value="?{want.ini:paths:delphibase}"/>
<property name="tponguard" value="${delphibase}/?{want.ini:path:tponguard}"/>
<property name="jvcl" value="${delphibase}/?{want.ini:path:jvcl}"/>
<property name="jcl" value="${delphibase}/?{want.ini:path:jcl}"/>
-->
<property name="bin" value="?{want.ini:paths:bin}"/>
<property name="src" value="?{want.ini:paths:src}"/>
<property name="doc" value="?{want.ini:paths:doc}"/>



4.4 Variáveis vindas da linha de comando

Para as vezes em que for necessário definir algo somente no momento da chamada, existe a possibilidade de passar variáveis para o want através da flag -D.
Exemplo: Definindo que a propriedade nomeprop receberá o valor da variável nomevar
Na chamada do want: want acao -Dnomevar=conteudo
A variável no script:

<property name="nomeprop" value="%{var_linha_cmd}"/>



4.5 Conjunto de propriedades
Para facilitar a posterior inclusão dos caminhos todos de uma só vez na chamada do compilador, um agrupamento dos caminhos acima é o ideal. Até porque existem sistemas que utilizam vários componentes de terceiros e ninguém costuma colocar tudo numa mesma pasta :D. Para isso, utiliza-se a tag patternset:



<patternset id="sources">
<!--
<include name="${tponguard}"/>
<include name="${jvcl}"/>
<include name="${jcl}"/>
-->
</patternset>



4.6 Versionamento
Utilizando um arquivo ini e o auxílio de expressões regulares vamos definir algumas propriedades com as versões que serão utilizadas nos alvos daqui alguns minutos ;D. Ficarão posicionadas na seção project visando a visibilidade para todos alvos.



<!-- buscando a versão do último build em um arquivo ini -->
<property name="old.version" value="?{want.ini:ftpth:versao}" />
<!-- build anterior - note a utilização de expressões regulares -->
<regexp property="old.build" text="${old.version}"
pattern="^.*.([0-9]+)$" subst="1" />
<!-- incrementa o build number e prepara string com as versões -->
<property name="build" value="={1 + ${old.build}}" />
<regexp property="version" text="${old.version}"
pattern=".[0-9]*$" subst=".${build}" />
<regexp property="comma.version" pattern="." subst=","
text="${version}"/>
<property name="zipfile" value="${bin}/ftpth-${version}.zip"/>



4.7 Definindo alvos pré compilação

Como em makefile's, muito utilizados em c, c++, e outras, é possível definir alvos que realizam alguma tarefa especifica e também alvos que possuem alguma dependência. Um alvo (target) sempre será especificado na linha de comando indicando para o executável o que fazer. O alvo pode estar definido em "default" na tag "project" e ser omitido na chamada.

Fazendo do alvo "clean" o responsável em limpar o diretório definido no arquivo ini por sua vez mapeado na propriedade bin:


<target name="clean">
<delete dir="${bin}" basedir=".">
<include name="*.exe"/>
<include name="*.map"/>
</delete>
<delete dir="${src}" basedir=".">
<include name="*.dcu"/>
<include name="*.drc"/>
</delete>
<delete dir="${doc}" basedir=".">
<include name="*.*"/>
</delete>
</target>



Este alvo prepare cria o diretório onde ficarão os binários, pre-processa o arquivo de resources (com o ícone e informações da versão do arquivo) e gera o arquivo .res. Ele utiliza as propriedades de incremento de versão, este alvo será dependencia de outro, que chamaremos de "build".



<target name="prepare">
<mkdir dir="${bin}"/>
<!-- exibindo mensagem com a versão -->
<echo message="version=${version}" />
<echo message="build=${build}" />
<!-- note que as marcações do arquivo ftpth.template.rc são substituídas automaticamente -->
<echo input="${src}/ftpth.template.rc" file="${src}/ftpth.rc" />
<!-- gerando o arquivo de resources -->
<brcc file="${src}/ftpth.rc" output="${src}/ftpth.res" />
</target>



4.8 Defindo os alvos de compilação
Nos alvos abaixo não é utilizado nem a metade das opções possíveis para a tag dcc. Porém acredito que a grande maioria (senão todos) os parâmetros do dcc32.exe estão disponíveis. Fica a dica de uma exploração no código fonte do want, mais precisamente no arquivo DelphiTasks.pas da linha 254 em diante.


<target name="compile">
<!-- Invoca o compilador dcc para o arquivo ftpth.dpr no diretório src -->
<dcc basedir="${src}" source="ftpth.dpr">
<!-- Os executáveis vão para o diretório bin -->
<exeoutput path="../${bin}"/>
<console value="true"/>
<!-- Definindo uma diretiva de compilação -->
<define name="DEBUG"/>
<uselibrarypath value="true"/>
<!-- Onde encontrar os sources (comentado pela utilização do library path)
<unitpath refid="sources"/>
<includepath refid="sources"/>
-->
<resourcepath>
<include name="${src}"/>
</resourcepath>
</dcc>
</target>



Sendo o alvo anterior a compilação com informações de debug, vamos criar um novo a partir dele só que retirando as informações de debug e inserindo otimização no compilador. Se chamará "build" e depende dos alvos clean e prepare, ou seja, a sequencia de execução ao chamar "want build" será: clean, prepare, build.


<target name="build" depends="clean,prepare">
<dcc basedir="${src}" source="ftpth.dpr">
<exeoutput path="../${bin}"/>
<build value="true"/>
<optimize value="true"/>
<console value="true"/>
<uselibrarypath value="true"/>
<resourcepath>
<include name="${src}"/>
</resourcepath>
</dcc>
</target>



4.9 Gerando a documentação do fonte
Um exemplo de alvo que gera a documentação utilizando a ferramenta PasDoc. Pode notar que é invocado o executável propriamente dito com alguns parâmetros e em seu lugar poderia estar qualquer outra ferramenta que você conhece/utiliza que aceite parâmetros na chamada.
Uma coisinha nova que aparece é o operador @{} que faz com que o caminho relativo passado seja expandido e adaptado ao formato do sistema operacional.




<target name="doc">
<mkdir dir="${doc}"/>
<exec executable="pasdoc">
<arg value="--write-uses-list"/>
<arg value="-T FtpTh"/>
<arg value="-L br"/>
<arg value="-v 2"/>
<arg value="-M private,protected,published,public"/>
<arg value="-E"/>
<arg value="@{${doc}}"/>
<arg value="@{${src}/*.pas}"/>
</exec>
</target>



4.10 ZIP
Não será necessário compactador externo já que a want tem uma tag nativa para tal. Não a conhecia, mas é a PasZLib.
No arquivo zip será incluído o binário da compilação, os fontes e sua documentação.



<target name="zip">
<zip zipfile="${zipfile}">
<include name="${bin}/*.exe"/>
<include name="${src}/*.*"/>
<exclude name="${src}/*.dcu"/>
<exclude name="${src}/*.exe"/>
<include name="${doc}/*.*"/>
<include name="want.xml"/>
<include name="want.ini"/>
<include name="want.css"/>
<include name="want.html"/>
<include name="ftpsend.template"/>
</zip>
</target>



4.11 FTP
Está se perguntando pra que este programa de ftp já que o windows tem um desde o início da leitura, certo?
Bom, o ftp padrão do windows funciona extremamente bem até você estar atrás de um proxy. Fizeram o favor de não implementar o modo passivo (command pasv) e isso me impossibilita de utilizá-lo.

Assim como no arquivo dos resources, teremos um arquivo de template com os comandos para envio pelo ftp com algumas variáveis. A idéia é pre-processar este arquivo e enviar o resultado como parâmetro para o programa que vai despachar o build.

Arquivo template: ftpsend.template

Arquivo resultante: ftpsend.ftp



<target name="ftpsend" depends="zip">
<property name="ftphost" value="?{want.ini:ftp:host}"/>
<property name="ftpuser" value="?{want.ini:ftp:user}"/>
<property name="ftpkey" value="?{want.ini:ftp:key}"/>
<property name="binfile" value="@{${zipfile}}"/>
<property name="dirdoc" value="@{${doc}/*.*}"/>
<echo input="ftpsend.template" file="ftpsend.ftp" />
<exec executable="binary/ftpth">
<arg value="ftpsend.ftp"/>
</exec>
<delete dir="." file="ftpsend.ftp"/>
</target>



4.12 CVS
Só fazendo uma "xerox" do alvo tag do script de build do próprio want:


<target name="tag">
<regexp property="cvs.tag" text="build_${version}" pattern="." subst="_" />
<cvs command="rtag -R -F ${cvs.tag} ." />
</target>



4.13 Alvo default - O faz tudo!

Lembra-se que na seção project ficou definido que o alvo "all" deve ser o default?
Ele também fica responsável em gravar a versão no arquivo ini já que enquanto não chegar tudo no ftp podem acontecer erros e a versão não deveria ser incrementada por isso.



<target name="all" depends="build,doc,tag,ftpsend">
<!-- Gravando a versao no arquivo ini (só é executado se todo o processo tiver sucesso)-->
<ini file="want.ini">
<write section="ftpth" key="versao" value="${version}" />
</ini>
</target>



Conclusão
Foi ótimo digitar want e puf! está lá no site tudo correto, o número de versão, ícone, cvs etc :D
Se chegou até aqui acredito que vai achar ruim que não foi colocado pelo menos três ótimos alvos:
1) compilação de sistemas modularizados em packages

2) DUnit (já existe a tag)
3) InnoSetup (também já tem tag)