goncin@wordpress.com:~$ _

Linux, programação e toda sorte de nerdices

Arquivos Mensais: maio 2010

Aventuras em Python (parte 1)

Estou há cinco meses usando quase que exclusivamente o Ubuntu tanto em casa quanto no trabalho. Acho que já está na hora de tomar vergonha na cara 😛 e aprender a programar para Linux.

Tenho percebido que muitos dos programas disponíveis no Ubuntu foram escritos em Python. Não acredita? Experimente digitar isso no seu terminal:

locate *.py

Por ora, meu conhecimento sobre esta linguagem limita-se a saber que ela é interpretada, de alto nível, e com a curiosa característica de ter seus blocos de código definidos pela indentação.

Malgrado já haver tantos programas em Python numa instalação padrão do Ubuntu, preferi descarregar um novo aplicativo para dar uma olhada nos fontes, para ver se entendo alguma coisa. Pode parecer uma técnica esquisita para se aprender uma nova linguagem de programação, mas acredite, comigo funciona. O aplicativo em questão é o Turpial, um promissor cliente para o Twitter. Sua aparência lembra um pouco o TweetDeck, com a vantagem de rodar nativamente em Linux, apesar de (ainda) não ter tantas funcionalidades quanto aquele.

Para instalar o programa no Ubuntu (de modo a utilizá-lo), bastam as seguintes linhas de comando:

sudo add-apt-repository ppa:effie-jayx/turpial
sudo aptitude update
sudo aptitude install turpial

Para estudar o código fonte, porém, o melhor é baixar os fontes do Turpial a partir do GitHub, com o seguinte comando no terminal:

git clone git://github.com/satanas/Turpial.git turpial

Caso você queira me acompanhar, e ainda não tenha o cliente git instalado, execute isso antes:

sudo aptitude install git-core

Os fontes estarão na pasta turpial (cd turpial), com a seguinte estrutura:

Estrutura dos arquivos do código fonte do Turpial

Estrutura dos arquivos do código fonte do Turpial

Para ser direto, meu interesse é sobre como são construídas as interfaces gráficas no ambiente Linux. Seguindo meus instintos, fui procurar alguma coisa sob a pasta gtk (pra quem não sabe, GTK+ é o nome da biblioteca de interface gráfica utilizado pelo ambiente GNOME e pelos respectivos programas). Dentre os arquivos que lá estavam, abri o denominado about.py para dar uma olhada.

Interface do Turpial exibindo o <em>About Box</em>

Interface do Turpial exibindo o About Box

# -*- coding: utf-8 -*-

# Ventana para subir el ego de los desarrolladores de Turpial xD
#
# Author: Wil Alvarez (aka Satanas)
# Dic 21, 2009

import os
import gtk

class About:
    def __init__(self, parent=None):
        about = gtk.AboutDialog()
        about.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
        about.set_logo(parent.load_image('turpial_icon.png', True))
        about.set_name('Turpial')
        about.set_version(parent.version)
        about.set_copyright('Copyright (C) 2009 - 2010 Wil Alvarez')
        about.set_comments(_('Twitter client multi-interface written in Python'))
        about.set_transient_for(parent)
        about.set_position(gtk.WIN_POS_CENTER_ON_PARENT)

        try:
            path = os.path.realpath(os.path.join(os.path.dirname(__file__),
                '..', '..', '..', 'COPYING'))
            lic = file(path, 'r')
            license = lic.read()
            lic.close()
        except Exception, msg:
            license = 'This script is free software; you can redistribute it'
            'and\/or modify it under the\n\terms of the GNU General Public '
            'License as published by the Free Software\n\Foundation; either '
            'version 3 of the License, or (at your option) any later version.'
            '\n\n\You should have received a copy of the GNU General Public '
            'License along with\n\this script (see license); if not, write to '
            'the Free Software\n\Foundation, Inc., 59 Temple Place, Suite 330, '
            'Boston, MA  02111-1307  USA'
        about.set_license(license)
        authors = []
        try:
            path = os.path.realpath(os.path.join(os.path.dirname(__file__),
                '..', '..', '..', 'AUTHORS'))
            f = file(path, 'r')
            for line in f:
                authors.append(line.strip('\n'))
            f.close()
        except Exception, msg:
            pass

        about.set_authors(authors)

        about.connect("response", self.__response)
        about.connect("close", self.__close)
        about.connect("delete_event", self.__close)

        about.run()

    def __response(self, dialog, response, *args):
        if response < 0:
            dialog.destroy()
            dialog.emit_stop_by_name('response')

    def __close(self, widget, event=None):
        widget.destroy()
        return True

Consegui entender bem o que o código faz, mesmo porque é apenas um about box. Começa importando bibliotecas (linhas 8 e 9), antes de começar a definir a classe. Nesta, há um método construtor (__init__), no qual são definidos, primeiramente, o tipo e as propriedades da janela (linhas 13 a 21).

Entre as linhas 23 e 37, o código procura por um arquivo chamado COPYING, para dele extrair as informações de licença a serem exibidas na caixa de diálogo. Faz isso dentro de um bloco try...except, provendo uma saída sem erros para o caso de o arquivo não ser encontrado ou ocorrerem erros de leitura. Procedimento semelhante é feito entre as linhas 40 e 48, desta feita para ler o arquivo que contém a lista de autores.

Parece-me que a funcionalidade dos botões Créditos e Licença são providos pela classe AboutDialog do GTK+, tendo bastado ao autor apenas prover o conteúdo dos diálogos que abrem. A conexão é feita nas linhas 38 e 50, respectivamente.

Há um manipulador de respostas (__response), certamente para lidar com coisas do tipo “Sim/Não/Cancelar” ou “OK/Cancelar”, mas que, no contexto, serve apenas para fechar a janela, o que pode ser feito também pelo botão do decorador de janelas (__close).

Agora sinto-me um pouco menos analfabeto em Python. Acho que já aprendi as vogais. 😉

Anúncios

Netbeans: linewrap postergado para a próxima versão

Acabou-se o que era doce. Assim que eu atualizei meu Netbeans para a versão 6.9 beta, notei que os controles de configurações de quebra de linha (linewrap, ou ainda wordwrap) vieram desabilitados. Pesquisando sobre o assunto, cheguei a este tópico do fórum de desenvolvimento do Netbeans. Nele, os desenvolvedores anunciam que desabilitaram a nova funcionalidade como padão até a próxima versão do IDE (7.0?), para poder cumprir com o calendário de lançamento da 6.9. Pelo que pude inferir, não seria possível corrigir todos os bugs (e olha que são muitos) a tempo.

É uma má notícia, indubitavelmente. Em minha opinião, era uma dos poucos itens que faltava para o Netbeans se tornar o IDE perfeito, tanto que eu o agardava com ansiedade. Quando escrevi minha resenha sobre a versão de desenvolvimento, o snapshot do dia ainda funcionava, mas isso não continuou nos dias seguintes, o que me fez, inclusive, instalar a versão beta, para ver se as coisas iam melhores.

Sem embargo, é possível habilitar o linewrap de volta apondo a opção -J-Dorg.netbeans.editor.linewrap=true à linha de comando de inicialização do IDE. Pero no hay garantías. Use por sua conta e risco. 😉

PHP: métodos encadeados e __toString()

Para começar, considere esta classe PHP:

<?php

  class Calculadora {

    private $_resultado = 0;

    public function __construct($valorInicial) {
      $this->_resultado = $valorInicial;
    }

    public function mais($n) {
      if(is_numeric($n)) $this->_resultado += $n;
      return $this;
    }

    public function menos($n) {
      if(is_numeric($n)) $this->_resultado -= $n;
      return $this;
    }

    public function vezes($n) {
      if(is_numeric($n)) $this->_resultado *= $n;
      return $this;
    }

    public function divididoPor($n) {
      if(is_numeric($n)) $this->_resultado /= $n;
      return $this;
    }

    public function limpar() {
      $this->_resultado = 0;
      return $this;
    }

    public function igual() {
      return $this->_resultado;
    }

  }

?>

Sim, é uma classezinha boba. E sim, não tem documentação nenhuma 😛 , mas o que ela faz deve ficar bastante óbvio para quem programa em PHP. Meu objetivo aqui é ser didático com algo minimamente útil – em suma, não suporto aquelas classes Foo com métodos Bar que não fazem nada.

Pois bem. O primeiro ponto que desejo abordar nesse artigo é uma tendência em técnica de programação orientada a objetos chamada encadeamento de métodos (em inglês, method chaining ou ainda fluent interfaces). Esse assunto já foi tratado pelo companheiro Jonnas Fonini, mas não custa retomá-lo.

Vamos comparar a utilização da classe listada acima pela técnica tradicional com a utilização de métodos encadeados. Um sobrinho programando o arroz-com-feijão faria provavelmente assim:

<?php

  $calc = new Calculadora(10);
  $calc->vezes(7);
  $calc->menos(5);
  $calc->divididoPor(13);
  $resultado = $calc->igual();

  echo "O resultado de ((10 * 7) - 5) / 13 é $resultado";

?>

Utilizando métodos encadeados, tudo fica mais simples e direto. É o que um profissional faria.

<?php

  $calc = new Calculadora(10);
  echo 'O resultado de ((10 * 7) - 5) / 13 é ' .
    $calc->vezes(7)->menos(5)->divididoPor(13)->igual();

?>

Métodos encadeados tornam o código mais simples e legível. E, para que possam ser utilizados, basta que todos os métodos encadeáveis tenham como valor de retorno a própria instância da classe ($this), como demonstrado pelas linhas em destaque na listagem inicial.

Reparem que o método igual() não é encadeável, pois ele indica que a série de operações matemáticas está encerrada, e que, portanto, o objeto deve retornar o resultado. Todavia, não seria nada difícil “esquecê-lo” ao final de uma longa sequência de encadeamento, e não veríamos resultado algum.

Uma das possíveis soluções para este problema é o método mágico __toString() provido pela linguagem PHP. Em poucas palavras, este método define o que fazer quando se tenta converter um objeto em string (como, por exemplo, utilizando os construtores de linguagem echo ou print). Ao esquecermos o método igual() ao fim do encadeamento, é exatamente um objeto (o valor de retorno de divididoPor()) que passamos ao echo – e ele, por óbvio, não saberá como imprimir o objeto, já que só sabe lidar com strings (implícita ou explicitamente).

<?php

  class Calculadora {

    private $_resultado = 0;

    public function __construct($valorInicial) {
      $this->_resultado = $valorInicial;
    }

    public function mais($n) {
      if(is_numeric($n)) $this->_resultado += $n;
      return $this;
    }

    public function menos($n) {
      if(is_numeric($n)) $this->_resultado -= $n;
      return $this;
    }

    public function vezes($n) {
      if(is_numeric($n)) $this->_resultado *= $n;
      return $this;
    }

    public function divididoPor($n) {
      if(is_numeric($n)) $this->_resultado /= $n;
      return $this;
    }

    public function limpar() {
      $this->_resultado = 0;
      return $this;
    }

    public function __toString() {
      return "{$this->_resultado}";
    }

  }

?>

E isso é tudo. Ao sobrecarregarmos o método __toString(), estamos provendo, para todos os efeitos, uma representação do objeto em string, com a qual echo e print conseguem lidar. Note, contudo, que o valor de retorno do método deve ser explicitamente uma string (razão por que expandi o  resultado do cálculo, numérico, dentro de uma string) – não é possível, neste contexto, contar com a conversão implícita de tipos do PHP.

De quebra, __toString() resolve o problema do esquecimento de igual() para finalizar as operações. A bem da verdade, igual() sequer é mais necessário, tanto que foi retirado da listagem anterior. 😀

Até mais!

Fazendo o VirtualBox OSE reconhecer pendrives USB no Ubuntu

Quem usa o VirtualBox já deve saber que existem duas versões desse ótimo virtualizador: uma versão open source (OSE) e outra de código fechado. A principal diferença entre elas é que a OSE não suporta dispositivos USB. Em outras palavras, ela não vai reconhecer nenhum pendrive que você espete na máquina hospedeira.

O Ubuntu, como muitas distribuições, traz em seus repositórios apenas a versão OSE. Para quem precisa utilizar pendrives com máquinas virtuais, e não quer instalar a versão de código fechado, isso é um sério transtorno. Mas nada que um “jeitinho brasileiro” não resolva.

Vamos ao caminho das pedras, aplicável para quando o Ubuntu é o sistema hospedeiro:

  1. Na configuração da sua máquina virtual, vá em Pastas Compartilhadas. Ali, compartilhe a pasta /media. O nome da pasta (que é como o sistema convidado irá enxergá-la) fica a seu critério; eu costumo deixar como media mesmo;
  2. Inicialize sua máquina virtual. Caso já tenha instalado os adicionais para convidado, poderá acessar seu pendrive sob \\vboxsvr\media (caso o sistema convidado for windows) ou sob //vboxsvr/media (sistemas Linux).

O Ubuntu monta os pendrives sob /media, com o nome do rótulo do volume. Portanto, se o rótulo do seu pendrive for FOOBAR, você poderá acessar seus arquivos no sistema convidado em \\vboxsvr\media\FOOBAR.

Simples, não? 😀

Ubuntu: menus para todos os gostos

Uma das coisas que não me agrada na configuração padrão da área de trabalho do Ubuntu é o menu principal. Com três itens – Aplicativos, Locais e Sistemas, mais um ícone e uma fonte laaaaarga (Sans 10), em minha opinião esse menu ocupa espaço demais no painel superior. Até porque eu sou tão radical nessa questão de coisas ocupando espaço na tela, que acabo sempre me livrando de um dos painéis.

Menu padrão: folgado e espaçoso

Menu padrão: folgado e espaçoso

Felizmente, o Ubuntu oferece alternativas. Vamos a elas.

Menu principal compacto

Essa solução não exige a instalação de novos pacotes. Basta clicar com o botão secundário do mouse sobre o painel desejado e selecionar Adicionar ao painel… No diálogo que se abre, procure pelo item Menu principal, que traz à esquerda uma versão monocromática do ícone da distribuição.

Adicionando o menu principal compacto

Adicionando o menu principal compacto

Adicionado o menu compacto, removida a barra de menus padrão e reposicionando os itens do painel, chegamos a um resultado parecido com isso:

Menu principal compacto: problema de (falta de) espaço resolvido

Menu principal compacto: problema de (falta de) espaço resolvido

Menu principal do GNOME

Para quem quer uma nova experiência em termos de usabilidade, há um projeto chamado “Menu principal do GNOME“. O nome ajuda pouco, pois leva a confusões com os dois menus (padrão e compacto) anteriormente citados. Não se iluda, porém: o bichinho é mesmo bom, e, na minha opinião, deveria ser o default do GNOME.

Para utilizá-lo no Ubuntu, é necessário antes instalar um pacotinho. Abra seu terminal e:

sudo aptitude install gnome-main-menu

Após isso, clique com o botão secundário do mouse, Adicionar ao painel… e

Como assim dois "menu principal"?

Como assim dois "menu principal"?

Pois é, caros leitores. Eu havia dito que o nome do projeto (ou a tradução, vai saber), não ajudava. Agora temos dois itens “menu principal”. Não se confunda! Aquele que nos interessa no momento é o que traz o ícone de um monitor e a descrição “Navegador de aplicativos e menu padrão”.

Adicionado ao painel e feitos os ajustes necessários, temos:

Em frente, tente, utilize um menu diferente

Em frente, tente, utilize um menu diferente

Para quem está acostumado com o menu tradicional do GNOME, isso é bem diferente (já a turma do KDE vai notar uma vaga semelhança). Ao primeiro relance, percebe-se uma seção de “aplicativos favoritos”: é possível colocar quaisquer aplicativos ali, para tê-los ao alcance de um clique. Do lado direito, o mais notável é a opção Centro de Controle, que dá acesso às configurações do sistema, em um único local (à la KDE).

Os demais aplicativos ficam acessíveis por intermédio do botão Mais aplicativos… Isso pode ser um inconveniente para alguns, mas o clique a mais reserva uma grata surpresa: um navegador de aplicativos, com layout idêntico ao já mencionado Centro de Controle. Nele, é possível obter uma visão geral dos aplicativos instalados, por categoria. Alguns caracteres digitados na caixa Filtro à esquerda são suficientes para se encontrar rapidamente um aplicativo “perdido”.

O Navegador de Aplicativos mostrando os "edit"ores instalados

O Navegador de Aplicativos mostrando os "edit"ores instalados

GnoMenu

O Menu Principal do GNOME é muito bom, sem dúvida (ainda que ele ocupe espaço no painel com a palavra “Computador”…), mas, se você gosta de personalizar seu sistema até nos detalhes mais diminutos, então, sem dúvida, você precisa do GnoMenu. A instalação deste no Ubuntu requer não apenas a instalação de um pacote, como também a configuração de um repositório próprio, já que o aplicativo não está nos repositórios da distribuição. Nada que uma sequência simples de comandos no terminal não resolva.

sudo add-apt-repository ppa:gnomenu-team/ppa
sudo aptitude update
sudo aptitude install gnomenu

O GnoMenu aparece nos itens do Adicionar ao painel… com seu próprio e inconfundível nome. Instalado ao painel, e com o tema padrão, sua aparência é a seguinte:

O GnoMenu em sua roupagem padrão

O GnoMenu em sua roupagem padrão

Se a aparência dele – uma mistura de KDE com Windows Vista – não lhe parece muito atrativa, experimente clicar com o botão secundário do mouse sobre o ícone do GnoMenu no painel e escolher Propriedades. No diálogo que se abre, torna-se possível personalizar praticamente cada aspecto do menu, desde o ícone do painel até as cores do próprio menu, mediante a aplicação de diferentes temas. E, se não ficar satisfeito com os temas que vêm instalados por padrão, procure por outros no Gnome Look.

A propósito: a capacidade de customização do GnoMenu vive sendo aproveitada por aquelas distros que tentam mimetizar a aparência do sistema operacional de Redmond. 😉

E não é só apenas isso

Claro, as opções de menu do Ubuntu não param aqui. Há, por exemplo, o Global Menu, que deixa o ambiente de trabalho semelhante ao do Mac. Mas isso já é assunto para um outro post… 😀

apt-get vs. aptitude

Você, usuário do Ubuntu, Linux Mint e outras distros baseadas no Debian, já deu seu sudo apt-get update hoje? Ou prefere sudo aptitude update? Tanto faz? O apt-get e o aptitude são bastante parecidos, mas é bom saber que há diferenças importantes entre as ferramentas.

Ambos são frontends para o dpkg, o sistema de gerenciamento de pacotes do Debian, e como tal herdado pelas distros filhas. O aptitude nasceu como uma interface orientada a menus em modo terminal, mas também pode (e deve) ser utilizado na linha de comando. O apt-get, por seu turno, faz parte de um conjunto (o qual inclui ainda o apt-cache, o apt-file e o apt-cdrom) de comandos de terminal, e portanto não tem nada parecido com “menuzinhos”.

Se ambos podem ser utilizados praticamente da mesma forma, então qual a diferença entre eles? Vamos aos fatos.

Atualização do cache de pacotes (apt-get update vs. aptitude update)

Para essa tarefa, prefiro o aptitude, pelo simples fato de que, após atualizar o cache de pacotes, ele mostra a contagem de pacotes novos e atualizáveis. Com isso, é possível saber se será necessário dar um aptitude safe-upgrade (ou aptitude dist-upgrade) na sequência para manter o sistema atualizado, sem emitir esse comando.

Gerenciamento de dependências quebradas

Outro ponto em que o aptitude é melhor que o apt-get. Ao tentar instalar um pacote (com aptitude install <nome-do-pacote>), e caso haja pacotes quebrados (ou seja, com dependências não satisfeitas), o aptitude se prontifica a consertá-los, enquanto o apt-get se limita a dizer que é necessário executar o comando apt-get install -f antes de tentar instalar qualquer pacote. Se as sugestões de conserto do aptitude funcionam 100% das vezes, isso já é outra história. Mas pelo menos ele tenta.

Expressões regulares nos nomes dos pacotes

Para isso o apt-get é rei. Vira e mexe, lá estou eu desinstalando e instalando o X Server e todos os drivers de vídeo. O nome do pacote do X Server é xserver-xorg, e os drivers de vídeo seguem o padrão xserver-xorg-<nome-do-driver>. Com o apt-get, é possível executar apt-get remove (ou install) xserver-xorg*, mas com o aptitude, não :(. Com aquele, consigo (des)instalar todos os pacotes citados com uma única linha de comando.

Limpeza automática de pacotes não mais necessários

Se algum pacote se tornar desnecessário ou obsoleto, o aptitude o removerá automaticamente em sua próxima execução, sem sequer questionar o usuário. O apt-get se adstringe a informar que é preciso executar apt-get autoremove (?!) para se livrar do lixo.

Procurando por pacotes (apt-cache search vs. aptitude search)

Nisso a diferença é puramente cosmética. O aptitude search devolve as informações em colunas alinhadas, mais fáceis de ler.

Poderes de Super Vaca

Ah, sim, por último e não menos importante: o apt-get muge (apt-get moo), o aptitude não.  Mas este reserva uma surpresinha aos insistentes. Experimente esta sequência de comandos no terminal:

aptitude -v moo
aptitude -vv moo
aptitude -vvv moo
aptitude -vvvv moo
aptitude -vvvvv moo
aptitude -vvvvvv moo

Divirtam-se! 🙂

%d blogueiros gostam disto: