Showing posts with label geek. Show all posts
Showing posts with label geek. Show all posts

23 January 2009

Emacs

Já faz um tempo que eu estou ciente da guerra sagrada dos editores de texto. Como o primeiro deles que eu vi sendo usado foi o vi (trocadilho não intencional) foi ele o primeiro a ganhar minha atenção também. No entanto nunca me motivei o suficiente para me adaptar à interface. Como minha história de programador foi marcada por editores bem normais (para os padrões de hoje) eu acabava sempre caindo para uma alternativa simples e confortável quando eu realmente tinha que fazer algo sério, ou então para um ambiente especializado caso precisasse trabalhar com uma linguagem específica.

No entanto, eu sempre me senti atraído pelas lendas de poder infinito prometido àqueles que dominam um desses editores lendários. Um pouco frustrado pela falta de flexibilidade da minha opção atual, resolvi voltar a investir no aprendizado de uma dessas ferramentas. Baixei e instalei os dois, mas apesar da minha maior simpatia com o Vim, resolvi que deveria experimentar o GNU Emacs dessa vez.

Bom, os comentários sarcásticos sobre o Emacs dizendo que ele é “um grande sistema operacional, faltando apenas um editor decente” estão perto de ser verdade: o Emacs é um sistema bem complexo. Ele vem com diversos modos de edição diferente que são divididos em dois tipos: major-modes e minor-modes. Os major-modes governam o comportamento geral do editor para um determinado buffer (o que você chamaria de "arquivo" em um editor comum, mas que não necessariamente está associado a um arquivo no disco), enquanto os minor-modes adicionam comandos e comportamentos que podem complementar um major-mode. Para um determinado buffer apenas um major-mode pode estar ativo, mas minor-modes podem ser vários. Um exemplo: o major-mode Text serve para editar arquivos de texto normais e o minor-mode Autofill pode ser usado para que as linhas sejam quebradas automaticamente para formar parágrafos uniformes. Existem também major-modes para linguagens de programação e marcação como o c-mode, o python-mode e o html-mode. Além de comandos adicionais, aparecem menus para executar alguns dos comandos mais comuns.

Bom, até agora parece que tudo isso é só uma nomenclatura rebuscada pra coisas comuns que todos os editores tem, mas a diferença é o grau de customização que é possível no emacs. Cada um desses modos são implementados como programas em um dialeto específico de Lisp chamado Emacs Lisp ou ELisp. O que acontece é que cada tecla (ou combinação de teclas) pressionada pode estar associada com uma função ELisp, inclusive as teclas alfanuméricas, o que quer dizer que quando você digita a letra A no seu teclado, existe uma função Lisp que insere o caractere A na posição atual do cursor. Porém, não precisa ser assim! Nada impede você de associar qualquer tecla ou combinação com qualquer outro comando fazendo seu próprio programa Lisp. E é graças a essa flexibilidade que o Emacs vem com uma míriade de modos que não tem nada a ver com editar texto, por exemplo, um psicoterapeuta virtual, um jogo de tetris, um navegador de arquivos, leitor de notícias online e MUITOS outros, tanto já incluídos no GNU Emacs como disponíveis na internet. Fora minor-modes adicionais que acrescentam ferramentas muito legais como essa aqui:



Vale também mencionar que um dos major-modes chamado org-mode tem uma palestra de mais de 40 minutos do Google Tech Talks para explicar o seu funcionamento.

Apesar de todas essas maravilhas, existem razões pelas quais é difícil começar a usar o Emacs.
  • A pletora de funcionalidade pode ser um tanto desgastante. São tantos comandos e opções que é enlouquecedor no início.
  • Os atalhos de teclado costumam envolver malabarismos não tão comuns em outros editores. Existem atalhos como Ctrl+x, b significando que você precisa primeiro apertar Ctrl+x e depois apertar b, até porque Ctrl+x, Ctrl+b é outro atalho que ativa outro comando.
  • O programa foi criado bem antes de algumas convenções que muitos de nós estamos acostumados (Ctrl+C, Ctrl+V, Ctrl+Z, alguém?). Para se ter uma idéia, o comando padrão de desfazer é Ctrl+_ e como o caractere é um underscore, isso significa que você precisa apertar Shift junto em um teclado QWERTY convencional. Felizmente isso tem uma solução simples: existe o modo CUA que é fácil de ativar e que faz com que muitas coisas passem a funcionar do jeito que é convencional nos editores atuais.
  • O programa é um tanto feio para padrões estéticos atuais e tem cara de antigo.
  • Customizar o comportamento do programa significa editar um arquivo Lisp ou usar uma interface um tanto poluída chamada Custom (que, adivinhem, é implementada em Lisp dentro do próprio Emacs)
Apesar dessas desvantagens eu estou gostando de aprender a usá-lo. Já fiz minhas primeiras funções em Lisp para adicionar uns comandos que eu sentia falta de outros editores e foi bem fácil. A impressão que eu tenho é que é um tipo de ferramenta que tem uma interface nem um pouco convencional, mas que compensa aprender. É mais ou menos a impressão que eu tenho do Blender também.

Meu principal objetivo é usá-lo como a IDE perfeita para Python e ele tem umas features bastante impressionantes para isso:



O Rope é usado para uma parte da funcionalidade mostrada nesse vídeo. É uma biblioteca com recursos de refatoração e funções de introspecção úteis para IDE's. No Emacs ele é usado através do Ropemacs.

Uma dica para quem estiver iniciando: aprenda os comandos por nome. Todo comando tem um nome que está relacionado com a função que ele desempenha. Aperte Esc e depois x (ou segure a tecla Meta - Alt normalmente - e pressione x) que você irá para o minibuffer e poderá executar um comando digitando seu nome. Além disso, você não precisa saber todo o nome do comando, basta apertar tab para mostrar uma lista de opções de autocompletar. Se o comando que você executar tiver um atalho de teclado, uma mensagem aparecerá no minibuffer dizendo qual é o atalho, logo após a execução. Assim você pode ir memorizando os atalhos dos comandos que você usa com mais frequência, enquanto os comandos novos que você aprender dá pra memorizar pelo nome que é muito mais fácil.

14 October 2008

Uma dura verdade

Writer's Block: acontece na programação também.

26 September 2008

Lento

Eu sabia que não devia ter comprado esse HD que grava os dados como ranhuras em um pedaço de rocha...


Pra ser justo, um pouco depois o Vista se deu conta que era mesmo um meio magnético e conseguiu apagar em menos de um minuto.

15 July 2008

Nesse semestre

Eu...
  1. ... fiz um visualizador de transformações no plano projetivo usando Python + PyOpenGL;
  2. ... fiz um parser para uma linguagem com sintaxe parecida com C - mas com várias simplificações - usando o ANTLR;
  3. ... projetei um processador muito simples no Max+PLUS II;
  4. ... implementei um contador como uma máquina de Moore no Max+PLUS II e depois passei o programa para um FPGA e vi ele funcionando;
  5. ... implementei em software parte do que o OpenGL faz em hardware (transformações geométricas e projetivas), renderizei um modelo 3D usando a minha implementação e o OpenGL e comparei os dois lado a lado;
  6. ... fiz um jogo para Xbox 360 usando o XNA Game Studio 2.0, com a ajuda de um colega na programação e de minha namorada na arte, onde implementei a física do zero e fiz até alguns shaders;
  7. ... implementei alguns algoritmos de métodos numéricos;
Isso é o que eu lembro de prático que eu fiz. Pode parecer pouco para alguns, mas deu pra cansar bastante.

O importante é que terminou e eu passei em todas as cadeiras! \o/

05 June 2008

Python: pseudo-código executável

Depois de várias noites mal dormidas tentando fazer funcionar minha função de rasterizar triângulos, finalmente consegui! O jeito que eu encontrei foi escrever ela em Python, debugar até funcionar e só depois traduzir ela pra C++.

Mais uma vez Python me serviu como pseudo-código executável e testável. É a única linguagem em que eu consigo pensar e escrever código quase diretamente.

23 February 2008

Músicas de Super NES

Estava conversando com a minha colega Nadjia sobre Chrono Trigger no GTalk e ela comentou que queria baixar a trilha sonora. Foi então que eu me lembrei que em tempos remotos da minha adolescência, quando eu ouvia SÓ música de Video Game, eu tinha descoberto in The Internets um plugin mágico do Winamp que tocava o formato SPC. Além disso tinham sites inteiros dedicados a hospedar trilhas sonoras em SPC.

Agora, com uma rápida busca no Google achei esse site aqui: http://snesmusic.org/. Aí tem plugins, players e trilhas pra baixar. Ah, pra quem não sabe o que é SPC, segundo o próprio site:
SPC files are memory dumps from the SPC700, which again is a custom CPU in the SNES designed and manufactured by Sony controlling a separate DSP chip for producing sound.
Ou seja, SPC são arquivos de música gravados no formato original que vinha nos cartuchos de Super NES. Com um player de SPC dá pra ouvir as músicas dos seus jogos favoritos no formato e qualidade originais do video game. "Qual a vantagem?", você me pergunta. Daí eu digo que dá pra baixar a trilha COMPLETA do Chrono Trigger por 318KB.

Ah, antes que alguém pergunte, existem os equivalente para os outros consoles também, é só procurar por aí. Claro que só tem vantagem quando o console usa instrumentos sintetizados, pq em outros casos qualquer música seria tão grande quanto um MP3. No caso do PlayStation (o primeiro) alguns jogos usam músicas com instrumentos sintetizados (por exemplo: FF7) e existem plugins e players pra esses arquivos também. A implicação disso é ter todas a trilha do jogo em um tamanho muito compacto e com a mesma qualidade que tinha no videogame.

23 January 2008

gtk.EntryCompletion

Esse é um tutorial que exige algum conhecimento de programação, da linguagem Python e do módulo PyGTK. Programadores experientes em outras linguagens provavelmente conseguirão entender e adaptar às suas necessidades. Caso queira aprender, existem tutoriais introdutórios de Python e PyGTK.

Para quem programa interfaces em PyGTK (ou GTK+ em outra linguagem, eu uso Python) aí vai uma dica de usabilidade:

Caso você tenha um campo de texto no seu programa, considere se não existe uma lista de valores comuns de preenchimento e dê uma ajudinha ao usuário a lembrar desses valores usando um gtk.EntryCompletion. Usá-lo é muito simples:
# Aqui eu pego uma gtk.Entry. Nesse caso peguei ela do
# meu xml que eu criei no glade

entry = xml.get_widget('entry_verbo')

# Depois crio os dois objetos necessários: um gtk.EntryCompletion,
# que vai desenhar a lista de sugestões e um gtk.ListStore que
# vai armazenar os valores.

completion = gtk.EntryCompletion()
list_store = gtk.ListStore(gobject.TYPE_STRING)

# Inserir uns valores. Note que são tuplas de um elemento só
# (por isso a vírgula sem nada depois). As tuplas inseridas
# seguem o modelo inicializado no construtor do ListStore.
# Nesse caso eu usei apenas um gobject.TYPE_STRING para dizer
# que minha lista guarda apenas uma string por registro

list_store.append(('aqui',))
list_store.append(('botamos',))
list_store.append(('umas',))
list_store.append(('palavras',))
list_store.append(('para',))
list_store.append(('testar',))

# Aqui eu associo a list_store ao meu completion criado anteriormente

completion.set_model(list_store)
completion.set_match_func(match_func)

# O método abaixo escolhe qual coluna do modelo vai conter o texto a
# ser mostrado no completion. Como só tem uma coluna no gtk.ListStore,
# vai ser essa que vamos usar.

completion.set_text_column(0)

entry.set_completion(completion)
Bom, a única coisa que falta no código acima é definir match_func que é uma função para buscar os valores de acordo com o que é digitado no gtk.Entry. Ela deve ser uma função com a seguinte assinatura
def match_func(completion, key_string, iter, func_data):
onde completion é o próprio objeto gtk.EntryCompletion usado pela função, key_string é a palavra que está no entry no momento da verificação, iter é um gtk.TreeIter que aponta para um item da lista de dados da gtk.EntryCompletion (uma gtk.ListStore, no caso do exemplo acima) e func_data é um argumento adicional que pode ser passado no método set_match_func do gtk.EntryCompletion.

Essa função será executada para cada item do gtk.ListStore e deve retornar True caso o item deva ser mostrado como opção de sugestão e False caso não deva. Na documentação da PyGTK a seguinte função está disponível como exemplo:
# Assumes that the func_data is set to the number of the text column in the
# model.

def match_func(completion, key, iter, column):
model = completion.get_model()
text = model.get_value(iter, column)
if text.startswith(key):
return True
return False
Ela cobre um dos usos mais comuns de um completion, que é mostrar as palavras na lista cujo início seja igual à palavra digitada. Um exemplo é mostrado na imagem abaixo: