<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7648329809512175190</id><updated>2011-08-02T12:58:28.247-03:00</updated><category term='ruby'/><category term='linux'/><category term='git desenvolvimento'/><category term='vim'/><category term='ssh segurança linux'/><category term='unix'/><title type='text'>Bolo de Foobar</title><subtitle type='html'>Ruby, Javascript, Apache, Linux e o que mais der na telha.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://bolodefoobar.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7648329809512175190/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://bolodefoobar.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>7</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7648329809512175190.post-70397520349023469</id><published>2011-07-25T10:08:00.005-03:00</published><updated>2011-07-25T10:44:33.478-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><title type='text'>Pequenas coisas que incomodam em Ruby</title><content type='html'>&lt;p&gt;
Ruby é uma linguagem maravilhosa, mas tem alguns poréns. O que eu vou citar é algo bem pequeno mas a linguagem está repleta de coisas do tipo.
&lt;/p&gt;

&lt;pre&gt;
&gt; class Foo
&gt;   def bar; @bar; end
&gt;   def bar=(other)
&gt;     puts "bar= has been called"
&gt;     @bar = other
&gt;   end
&gt; end
&lt;/pre&gt;

&lt;p&gt;
Basicamente escrevemos um setter para um variável.
&lt;/p&gt;

&lt;pre&gt;
&gt; foo = Foo.new
&gt; foo.bar = 1
bar= has been called
=&gt; 1 
&lt;/pre&gt;

&lt;p&gt;
Ok, exatamente como esperávamos.
&lt;/p&gt;

&lt;pre&gt;
&gt; foo.bar = foo.bar || 2
bar= has been called
=&gt; 1 
&lt;/pre&gt;

&lt;p&gt;
Ok, sem surpresas ainda.
&lt;/p&gt;

&lt;pre&gt;
&gt; foo.bar ||= 2
=&gt; 1 
&lt;/pre&gt;

&lt;p&gt;
Ops, notem que bar= não foi chamado.
&lt;/p&gt;

&lt;p&gt;
Portanto, ao contrário do que muitos pensam foo.bar ||= 2 é diferente de foo.bar = foo.bar || 2.
&lt;/p&gt;

&lt;p&gt;
foo.bar ||= 2 só realiza a atribuição se bar não avaliar para uma expressão verdadeira.
&lt;/p&gt;

&lt;p&gt;
É algo muito bobo e muito sútil, mas se o programador realizar alguma computação na atribuição, essa computação pode não ser executada em alguns casos.
&lt;/p&gt;

&lt;p&gt;
Isso não é um grande problema, porém existem diversas coisas do tipo na linguagem. O &lt;a href="http://en.wikipedia.org/wiki/Yukihiro_Matsumoto"&gt;Matz&lt;/a&gt; diz que a &lt;a href="http://www.ruby-lang.org/en/about/"&gt;linguagem deve ter o comportamento que o programador espera&lt;/a&gt;, isso é bom porque a linguagem torna-se natural, mas e casos como esse, o que o programador espera?
&lt;/p&gt;

&lt;p&gt;
Outra coisa decorrente é que isto dificulta outras implementações Ruby 100% compatíveis.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7648329809512175190-70397520349023469?l=bolodefoobar.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bolodefoobar.blogspot.com/feeds/70397520349023469/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://bolodefoobar.blogspot.com/2011/07/pequenas-coisas-que-incomodam-em-ruby.html#comment-form' title='4 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7648329809512175190/posts/default/70397520349023469'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7648329809512175190/posts/default/70397520349023469'/><link rel='alternate' type='text/html' href='http://bolodefoobar.blogspot.com/2011/07/pequenas-coisas-que-incomodam-em-ruby.html' title='Pequenas coisas que incomodam em Ruby'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7648329809512175190.post-6115727475117088123</id><published>2011-01-27T16:28:00.007-02:00</published><updated>2011-01-27T17:38:28.840-02:00</updated><title type='text'>Um novo Object#tap</title><content type='html'>Implementação atual de tap:

&lt;pre&gt;
class Object
  def tap
    yield(self)
    self
  end
end
&lt;/pre&gt;

Mas o Daniel aqui discorda. Minha proposta é:

&lt;pre&gt;
class Object
  def tap
    yield(self)
  end

  def tee
    yield(self)
    self
  end
end
&lt;/pre&gt;

&lt;dl&gt;
&lt;dt&gt;Object#tap&lt;/dt&gt;
&lt;dd&gt;altera a method chain&lt;/dd&gt;
&lt;dt&gt;Object#tee&lt;/dt&gt;
&lt;dd&gt;não altera a method chain (atual Object#tap)&lt;/dd&gt;
&lt;/dl&gt;

Para Enumerable, nós temos Enumerable#collect, que funciona exatamente igual ao meu tap.

&lt;pre&gt;
[1,2,3].collect {|i| i + i} =&gt; [2,4,6]
&lt;/pre&gt;

Porém não temos isso para objetos:

&lt;pre&gt;
1.tap {|i| i + i } =&gt; 2
&lt;/pre&gt;

Object#tap executa um bloco na method chain sem altera-la.

&lt;pre&gt;
[1,2,3].collect {|i| i * i }.tap {|a| puts a.size }.inject {|sum, i| sum + i } =&gt; 14 (escreve 3 na STDOUT antes do retorno)
&lt;/pre&gt;

Porém se você quer justamente passar um bloco apenas para alterar a method chain? Não deveria ser justamente essa a função de Object#tap?

&lt;pre&gt;
[1,2,3].collect {|i| i * i }.tap {|a| a + a }.inject {|sum, i| sum + i } =&gt; 28
&lt;/pre&gt;

A origem do atual Object#tap vem do comando tee. Portanto, nada mais justo que:

&lt;pre&gt;
class Object
  alias tee tap
  def tap
    yield(self)
  end
end
&lt;/pre&gt;

É preciosismo e a discussão é meramente teórica, já que podemos implementar este novo Object#tap com outro nome e evitar o alias, o que exigiria um refactoring de todo código que utiliza Object#tap.

Possíveis nomes para meu Object#tap: get, come, become, go e grow.

Viajei muito?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7648329809512175190-6115727475117088123?l=bolodefoobar.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bolodefoobar.blogspot.com/feeds/6115727475117088123/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://bolodefoobar.blogspot.com/2011/01/ruby-objecttap-e-objectsap.html#comment-form' title='3 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7648329809512175190/posts/default/6115727475117088123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7648329809512175190/posts/default/6115727475117088123'/><link rel='alternate' type='text/html' href='http://bolodefoobar.blogspot.com/2011/01/ruby-objecttap-e-objectsap.html' title='Um novo Object#tap'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7648329809512175190.post-8783748366623984509</id><published>2010-02-18T15:42:00.007-02:00</published><updated>2010-02-18T15:55:37.678-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git desenvolvimento'/><title type='text'>Use branches no Git!</title><content type='html'>&lt;p&gt;Apesar da ampla adoção do Git, ainda são poucas as equipes que utilizam com eficácia os branchs. Acredito que a culpa disso seja em grande parte pelo baixo uso de branches no SVN ou CVS. Talvez isso tenha até contribuido para criar um certo medo de branches.&lt;/p&gt;

&lt;p&gt;Porém, existe ínumeras situações do dia a dia em que o uso de branches irá poupar muito trabalho, viabilizar experimentos ou organizar o desenvolvimento.&lt;/p&gt;

&lt;p&gt;É fundamental compreender o uso de branches para que você possa compreender a sua correta utilização.&lt;/p&gt;

&lt;p&gt;A diretriz que eu tenho seguido é simples: criar um branch novo para qualquer linha de desenvolvimento. Caso seja necessário o desenvolvimento em conjunto com algum outro desenvolvedor, faça um branch remoto. Fazer pequenos commits irá te ajudar na hora de selecionar um commit defeituoso e a procurar erros com git bisect.&lt;/p&gt;

&lt;p&gt;Realize merges entre as linhas de desenvolvimento o máximo de vezes que for permitido. Quanto maior a divergência entre as linhas de desenvolvimento, maior será o número de conflitos e mais díficil será o merge. O momento do merge é um gargalo, pois os conflitos tem de serem resolvidos localmente, ou seja, apenas um desenvolvedor pode resolver os conflitos entre dois merges.&lt;/p&gt;

&lt;p&gt;Desconheço qualquer forma de resolver conflitos que não seja local e isso me parece uma limitação grave, se alguém souber de algo ficarei muito contente se me explicar.&lt;/p&gt;

&lt;p&gt;Nos primeiros dias que segui essa abordagem, apanhei um pouco do Git (um pouco mais do que o habitual), mas foram os momentos em que mais aprendi sobre o seu funcionamento. Comece nesse exato momento a utilizar branches, mesmo que o seu projeto esteja atrasado 28 dias, 6 horas, 42 minutos e 12 segundos *.&lt;/p&gt;

&lt;p&gt;Apenas para o não ficar incompleto, seguem as receitinhas de bolo mais simples para criação e remoção de branches remotos.&lt;/p&gt;

&lt;h2&gt;Criando um branch remoto&lt;/h2&gt;

&lt;code&gt;$ git push repos src:dst&lt;/code&gt;

&lt;dl&gt;
&lt;dt&gt;repos&lt;/dt&gt;&lt;dd&gt;Repositório&lt;/dd&gt;
&lt;dt&gt;src&lt;/dt&gt;&lt;dd&gt;Branch de origem no repositório&lt;/dd&gt;
&lt;dt&gt;dst&lt;/dt&gt;&lt;dd&gt;Branch de destino no repositório&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2&gt;Deletando um branch remoto&lt;/h2&gt;

&lt;code&gt;$ git push repos :dst&lt;/code&gt;

&lt;p&gt;
&lt;i&gt;* Este é o tempo que falta para o mundo acabar quando Donnie Darko encontra Frank pela primeira vez.&lt;/i&gt;
&lt;/p&gt;

&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_f-74bdvR5wM/S31_BQviHkI/AAAAAAAAABI/UrW7pmyH-40/s1600-h/donnie.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 229px; height: 320px;" src="http://3.bp.blogspot.com/_f-74bdvR5wM/S31_BQviHkI/AAAAAAAAABI/UrW7pmyH-40/s320/donnie.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5439643584584359490" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7648329809512175190-8783748366623984509?l=bolodefoobar.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bolodefoobar.blogspot.com/feeds/8783748366623984509/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://bolodefoobar.blogspot.com/2010/02/overdose-de-branches-no-git.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7648329809512175190/posts/default/8783748366623984509'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7648329809512175190/posts/default/8783748366623984509'/><link rel='alternate' type='text/html' href='http://bolodefoobar.blogspot.com/2010/02/overdose-de-branches-no-git.html' title='Use branches no Git!'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_f-74bdvR5wM/S31_BQviHkI/AAAAAAAAABI/UrW7pmyH-40/s72-c/donnie.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7648329809512175190.post-616524166723226942</id><published>2010-02-08T17:04:00.010-02:00</published><updated>2010-02-09T11:47:41.937-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ssh segurança linux'/><title type='text'>Aumentando a segurança do SSH com 3 medidas simples (leiam a conclusão também)</title><content type='html'>&lt;p&gt;Aqui vão 3 dicas de fácil implementação e que com certeza aumentarão &lt;span style="font-weight:bold;"&gt;muito&lt;/span&gt; a segurança do seu servidor SSH. Ao alterar a configuração do SSH você deve reiniciar o servidor SSH para que a nova configuração seja carregada.&lt;/p&gt;

&lt;h2&gt;Arquivos&lt;/h2&gt;

&lt;p&gt;Configuração do servidor SSH:&lt;br/&gt;
&lt;span style="font-weight:bold;"&gt;/etc/ssh/sshd_config&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Reiniciar o servidor SSH:&lt;br/&gt;
&lt;span style="font-weight:bold;"&gt;/etc/init.d/ssh restart&lt;/span&gt;&lt;/p&gt;

&lt;h2&gt;1. Restrinja o uso ao Protocol 2&lt;/h2&gt;

&lt;p&gt;O Protocol 2 é o padrão, porém, muitas distribuições vem com a configuração padrão Protocol 1,2. A release mais recente do Ubuntu, Karmic, já vem configurada para apenas Protocol 2, porém, muitas vezes temos um sistema que foi atualizado de releases mais atingas sem trocar os arquivos de configuração, portanto vale a pena você verificar quais protocolos o seu servidor SSH está aceitando.&lt;/p&gt;

&lt;p&gt;/etc/ssh/ssh_config:&lt;br/&gt;
&lt;span style="font-weight:bold;"&gt;Protocol 2&lt;/span&gt;&lt;/p&gt;

&lt;h2&gt;2. Restrinja o acesso root&lt;/h2&gt;

&lt;p&gt;Existem diversos usuários que são criados automaticamente nas distribuições. Uma boa distribuição retira a senha destes usuários, impedindo a autenticação através de senha. Porém, muitos administradores configuram uma senha para o root.&lt;/p&gt;

&lt;p&gt;A forma mais básica de um script de acesso à força bruta em um sistema funciona da seguinte forma: achar um IP que aceita uma conexão na porta 22 e tentar diversas senhas com o usuário root.&lt;/p&gt;

&lt;p&gt;Impedir o login do root já cria uma dificuldade extra: qual usuário utilizar para se logar?&lt;/p&gt;

&lt;p&gt;/etc/ssh/ssh_config:&lt;br/&gt;
&lt;span style="font-weight:bold;"&gt;PermitRootLogin no&lt;/span&gt;&lt;/p&gt;

&lt;h2&gt;3. Impeça a autenticação por senha&lt;/h2&gt;

&lt;p&gt;De nada adianta qualquer outra medida de segurança se as senhas utilizadas forem fracas. Com um pouco de sorte, um ataque de dicionário consegue quebra-las. Podemos implementar diversas políticas de criação de senha, atualização etc. Geralmente essas medidas tendem a piorar o problema, pois elas se sustentam exatamente no aspecto mais falho do sistema: o ser humano.&lt;/p&gt;

&lt;p&gt;Impossibilitar a autenticação atavés de senhas e permitir apenas através de troca de chaves ou certificados nos trás dois benefícios: elimina a necessidade de memorização da senha e impede ataques de dicionário.&lt;/p&gt;

&lt;p&gt;/etc/ssh/ssh_config:&lt;br/&gt;
&lt;span style="font-weight:bold;"&gt;PasswordAuthentication no&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;NOTA: É de extrema importância que você já possua ao menos um usuário com as chaves já configuradas e acesso previlegiado ao sistema, do contrário, ao reiniciar o SSH você ficará impossibilitado de se autenticar.&lt;/p&gt;

&lt;p&gt;NOTA 2: Você deve configurar as chaves para cada máquina que irá se autenticar com aquele usuário. Isto pode gerar um pequeno trabalho para transportar as chaves públicas das suas máquinas para o servidor de uma vez só. Ex. desktop do trabalho e notebook de casa. É melhor configurar todas as chaves e só depois proibir autenticação por senha.&lt;/p&gt;

&lt;h2&gt;Conclusão&lt;/h2&gt;

&lt;p&gt;Estes 3 passos estão longe de ser uma solução completa de segurança, mas acho sejam o &lt;span style="font-weight:bold;"&gt;mínimo&lt;/span&gt; de segurança que devemos prover a qualquer máquina com servidor SSH na internet.&lt;/p&gt;

&lt;p&gt;O melhor destas 3 iniciativas é que elas requerem muito pouco trabalho e dão um bom resultado. Isto é muito importante para equipes enxutas aonde uma única pessoa tem diversas roles ou é responsável por diversos servidores.&lt;/p&gt;

&lt;p&gt;Outras medidas são o uso de TCP Wrappers, mudança de porta do SSH, knocking doors, lista de usuários que podem se autenticar e mais um infinito de soluções.&lt;/p&gt;

&lt;p&gt;PS: Muitas pessoas acreditam que apenas alterar a porta SSH oferece alguma proteção, porém se esquecem que é extremamente simples construir um script que busque uma porta SSH aberta.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7648329809512175190-616524166723226942?l=bolodefoobar.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bolodefoobar.blogspot.com/feeds/616524166723226942/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://bolodefoobar.blogspot.com/2010/02/aumentando-seguranca-do-ssh-com-3.html#comment-form' title='5 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7648329809512175190/posts/default/616524166723226942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7648329809512175190/posts/default/616524166723226942'/><link rel='alternate' type='text/html' href='http://bolodefoobar.blogspot.com/2010/02/aumentando-seguranca-do-ssh-com-3.html' title='Aumentando a segurança do SSH com 3 medidas simples (leiam a conclusão também)'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7648329809512175190.post-3656000549553248530</id><published>2009-08-28T14:00:00.011-03:00</published><updated>2009-08-28T14:31:18.686-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vim'/><title type='text'>Desfazendo no VIm</title><content type='html'>&lt;p&gt;O que fazemos quando erramos, desfazemos o erro. Para isso serve a ferramenta undo, tão popular nos mais diversos tipos de editores. Hoje veremos o que o Vim nos oferece para desfazer e refazer a edições.&lt;/p&gt;

&lt;h4&gt;Desfazendo e refazendo&lt;/h4&gt;

&lt;p&gt;Desfazer uma ação é extremamente simples, mas pode haver algumas particularidades.&lt;/p&gt;

&lt;p&gt;O comando &lt;strong&gt;u&lt;/strong&gt; desfaz a última edição, enquanto o comando &lt;strong&gt;CTRL-R&lt;/strong&gt; refaz a última edição desfeita.&lt;/p&gt;

&lt;pre&gt;
    iFoo&lt;ESC&gt;
    iBar&lt;ESC&gt;
    iFooBar&lt;ESC&gt;
    u            &lt;- Desfazendo iFooBar
    CTRL-R       &lt;- Refazendo iFooBar
&lt;/pre&gt;

&lt;p&gt;Os comandos &lt;strong&gt;u&lt;/strong&gt; e &lt;strong&gt;CTRL-R&lt;/strong&gt; aceitam um &lt;em&gt;count&lt;/em&gt; como argumento, portanto, podemos fazer &lt;strong&gt;2u&lt;/strong&gt; ou &lt;strong&gt;4CTRL-R&lt;/strong&gt; para desfazer 2 edições ou refazer a últimas 4 edições desfeitas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt;: &lt;strong&gt;CTRL-R&lt;/strong&gt; difere de &lt;strong&gt;.&lt;/strong&gt; pois o primeiro refaz a última edição desfeita, enquanto o segundo reexecuta o último comando de edição.&lt;/p&gt;

&lt;h4&gt; Listas&lt;/h4&gt;

&lt;p&gt;Listas são estruturas recorrentes em programação. Uma lista é um conjunto de elementos dispostos em um seqüência, aonde um elemento tem um elemento anterior e posterior associado a ele, exceto o primeiro elemento, que não possui o anterior e o último elemento, que não possui um posterior.&lt;/p&gt;

&lt;p&gt;Um apontador nada mais faz do que apontar para um determinado elemento de uma lista.&lt;/p&gt;

&lt;h4&gt;Lista de edição&lt;/h4&gt;

&lt;p&gt;Uma lista de edição, é uma estrutura que contém as edições realizadas em ordem seqüencial. Os comandos &lt;strong&gt;u&lt;/strong&gt; e &lt;strong&gt;CTRL-R&lt;/strong&gt; simplesmente manipulam está lista para desfazer ou refazer as edições.&lt;/p&gt;

&lt;pre&gt;
     Conteúdo -  Lista de edição
     |        - Alteração feita: iFoo&lt;ESC&gt;
     Foo
     |        - Alteração feita: iBar&lt;ESC&gt;
     Foo
     Bar
     |        - Alteração feita: iFooBar&lt;ESC&gt; &lt;-- Apontador
     Foo
     Bar
     FooBar
&lt;/pre&gt;

&lt;p&gt;Utilizando o comando &lt;strong&gt;u&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;
     Vazio
     |      Alteração feita: iFoo&lt;ESC&gt;
     Foo
     |      Alteração feita: iBar&lt;ESC&gt;        &lt;-- Apontador
     Foo
     Bar
            Alteração desfeita: iFooBar&lt;ESC&gt;
&lt;/pre&gt;

&lt;p&gt;Utilizando o comando &lt;strong&gt;u&lt;/strong&gt; novamente:&lt;/p&gt;

&lt;pre&gt;
     Vazio
     |      Alteração feita: iFoo&lt;ESC&gt;        &lt;-- Apontador
     Foo
            Alteração feita: iBar&lt;ESC&gt;
            Alteração desfeita: iFooBar&lt;ESC&gt;
&lt;/pre&gt;

&lt;p&gt;Utilizando o comando &lt;strong&gt;CTRL-R&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;
     Vazio
     |      Alteração feita: iFoo&lt;ESC&gt;
     Foo
     |      Alteração feita: iBar&lt;ESC&gt;        &lt;-- Apontador
     Foo
     Bar
            Alteração desfeita: iFooBar&lt;ESC&gt;
&lt;/pre&gt;

&lt;h4&gt;Quero mais!&lt;/h4&gt;

&lt;p&gt;Depois que você pega o jeito, editar no VIm é uma delícia. Desfazer uma ação é extremamente freqüente e a tecla &lt;strong&gt;u&lt;/strong&gt; em teclados QWERTY é facilmente acessada.&lt;/p&gt;

&lt;p&gt;Undo é um assunto extenso dentro do VIm pois ele envolve a função básica de editação. Outros tópicos interessantes são: bloco de edição, arvore de edição e timeline de edição. Estes dois últimos serão abordados futuramente, pois são de ampla utilidade.&lt;/p&gt;

&lt;p&gt;Para os mais impacientes ou curiosos, vocês podem obter TUDO sobre undo no help, pesquisando sobre undo ou no capítulo 32.&lt;/p&gt;

&lt;pre&gt;
  :help undo
  :help 32
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7648329809512175190-3656000549553248530?l=bolodefoobar.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bolodefoobar.blogspot.com/feeds/3656000549553248530/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://bolodefoobar.blogspot.com/2009/08/o-bascico-de-undo-no-vim.html#comment-form' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7648329809512175190/posts/default/3656000549553248530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7648329809512175190/posts/default/3656000549553248530'/><link rel='alternate' type='text/html' href='http://bolodefoobar.blogspot.com/2009/08/o-bascico-de-undo-no-vim.html' title='Desfazendo no VIm'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7648329809512175190.post-4113133484210484935</id><published>2009-08-03T14:01:00.008-03:00</published><updated>2009-08-03T17:21:12.586-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='vim'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><title type='text'>Shell no VIm com agilidade</title><content type='html'>&lt;p&gt;Muitas vezes você está editando no VIm e precisa executar algo no shell, pegar algum output ou simplesmente ir embora para casa. Hoje vamos ver algumas soluções que o VIm nos oferece para essas situações, mostrando porque ele é O editor.&lt;/p&gt;

&lt;h4&gt;Suspendendo o VIm&lt;/h4&gt;

&lt;p&gt;Para mim essa é a solução mais elegante que existe, porém ela é baseado no uso do Bash como shell e para mim a beleza consiste nessa junção Bash + VIm. Não sei como funciona e se funciona em outros shells.&lt;/p&gt;

&lt;p&gt;Quando o Bash está com o Job Control ligado, ao inicializarmos um processo, ele &amp;#8216;herda&amp;#8217; do Bash o tratamento de alguns sinais, um deles é o SIGTSTP.  O tratamento do SIGTSTP suspende o processo, retornando o controle do terminal ao Bash. A maioria dos terminais mapeia o SIGTSTP para as teclas Ctrl-Z, mas isso é uma configuração do terminal, não do Bash. Você pode verificar a configuração do seu terminal utilizando:&lt;/p&gt;

&lt;pre&gt;
$ stty -a
&lt;/pre&gt;

&lt;p&gt;A beleza disto, é que o VIm não sobrescreve o tratamento do SIGTSTP herdado do Bash, portanto, você podê suspender o seu VIm!  Com isso, você retornará o controle do terminal ao processo Bash pai do VIm.  Você pode executar quantos comandos forem necessários e depois retornar o controle do terminal ao VIm utilizando o &lt;strong&gt;fg&lt;/strong&gt;.&lt;/p&gt;

&lt;pre&gt;
$ vim foo

Edição, edição, edição
Voltando para o Bash
Ctrl-Z

Tarefas que queremos executar no Bash...
$ rake db:migrate

Voltando para o VIm
$ fg
De volta ao VIm
&lt;/pre&gt;

&lt;p&gt;Outro modo de obter um shell é através do comando &lt;strong&gt;:sh&lt;/strong&gt; ou &lt;strong&gt;:shell&lt;/strong&gt;.&lt;/p&gt;

&lt;pre&gt;
:sh
&lt;/pre&gt;

&lt;p&gt;Para retornar ao shell, Ctrl-D (EOF) ou exit.&lt;/p&gt;

&lt;p&gt;O shell criado depende do valor da variável &amp;#8216;shell&amp;#8217; do VIm.&lt;/p&gt;

&lt;pre&gt;
:set shell
&lt;/pre&gt;

&lt;h4&gt;Executando dentro do VIm&lt;/h4&gt;

&lt;p&gt;Para executar um comando simples, como remover um arquivo, obter uma listagem de diretório, executar uma migration, basta utilizar &lt;strong&gt;:!&lt;/strong&gt;.&lt;/p&gt;

&lt;pre&gt;
:!ls
&lt;/pre&gt;

&lt;p&gt;Você pode especificar um ponto para o qual deseja enviar a saída do comando.&lt;/p&gt;

&lt;pre&gt;
:.!ls
:0!ls
:$!ls
&lt;/pre&gt;

&lt;p&gt;Um atalho para &lt;strong&gt;:.!&lt;/strong&gt; é &lt;strong&gt;!!&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Nota: &lt;strong&gt;!!&lt;/strong&gt; é diferente de &lt;strong&gt;:!!&lt;/strong&gt;, o segundo re-executa no shell o último comando executado anteriormente.&lt;/p&gt;

&lt;h4&gt;Criando uma sessão&lt;/h4&gt;

&lt;p&gt;Você está no meio de um trabalho pesado: 4 arquivos em edição, outros 10 na buffer list, um monte de marcadores, alguns lugares na stack.&lt;/p&gt;

&lt;p&gt;Porém chegou a hora do seu merecido descanso, mas não quer perder o ambiente da edição. Deixar o computador ligado é uma solução, mas a energia pode acabar, sem contar o desperdício.&lt;/p&gt;

&lt;p&gt;O segredo é salvar uma sessão do VIm e carrega-la posteriormente. Pode parecer complicado, mas é extremamente simples: &lt;strong&gt;:mks&lt;/strong&gt; ou &lt;strong&gt;:mksession&lt;/strong&gt;, você pode passar como argumento o nome da sessão, do contrário, o arquivo padrão é Session.vim.&lt;/p&gt;

&lt;pre&gt;
:mks
&lt;/pre&gt;

&lt;p&gt;O arquivo gerado nada mais é quem um aglomerado de opções e comandos do VIm. Portanto, para carregar de volta uma sessão, basta &amp;#8216;executar&amp;#8217; o script com o comando &lt;strong&gt;:source&lt;/strong&gt; ou &lt;strong&gt;:so&lt;/strong&gt;.&lt;/p&gt;

&lt;pre&gt;
:so Session.vim
&lt;/pre&gt;

&lt;p&gt;O mais provável é que você vá carregar uma sessão a partir do terminal.&lt;/p&gt;

&lt;pre&gt;
$ vim -S Session.vim
&lt;/pre&gt;

&lt;p&gt;Por padrão, a opção -S carrega o arquivo Session.vim, portanto o comando abaixo tem o mesmo efeito.&lt;/p&gt;

&lt;pre&gt;
$ vim -S
&lt;/pre&gt;

&lt;h4&gt;Conclusão&lt;/h4&gt;

&lt;p&gt;Parece que perdemos um pouco da cultura de ferramentas especializadas do UNIX. Hoje é normal quererem fazer tudo no seu editor preferido, na sua linguagem preferida etc. Eu acho isso uma bobagem que, em minha opinião, é fomentada por grandes empresas que espalham a todos que sua solução é completa: o desenvolvedor que sabe XYZ não precisa saber mais nada.&lt;/p&gt;

&lt;p&gt;A relação disto com as dicas é indireta mas muito importante.&lt;/p&gt;

&lt;p&gt;Perdemos um tempo considerável para achar uma solução pura no VIm, Ruby, o que for, mesmo existindo ferramentas UNIX próprias para a função. Hoje aprendemos como trocar agilmente do shell para o VIm e vice-versa, mostrando que faz parte do VIm colaborar com essas outras ferramentas.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7648329809512175190-4113133484210484935?l=bolodefoobar.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bolodefoobar.blogspot.com/feeds/4113133484210484935/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://bolodefoobar.blogspot.com/2009/08/shell-no-vim-com-agilidade.html#comment-form' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7648329809512175190/posts/default/4113133484210484935'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7648329809512175190/posts/default/4113133484210484935'/><link rel='alternate' type='text/html' href='http://bolodefoobar.blogspot.com/2009/08/shell-no-vim-com-agilidade.html' title='Shell no VIm com agilidade'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7648329809512175190.post-8689116902198494747</id><published>2009-07-22T18:55:00.020-03:00</published><updated>2009-08-03T14:25:25.384-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>Obtendo código fonte dos pacotes da sua distro</title><content type='html'>&lt;h4&gt;Por que não baixar direto do site oficial?&lt;/h4&gt;

&lt;p&gt;O código do projeto pode diferir da sua distribuição. Isso pode acontecer por diversos motivos:&lt;/p&gt;

&lt;ol&gt;

&lt;li&gt;
&lt;h5&gt;A distro pode não adotar a última release.&lt;/h5&gt;
&lt;p&gt;No Ubuntu, por exemplo, os pacotes são 'freezados' depois de uma release de uma versão e as atualizações geralmente são apenas para corrigir falhas de segurança e estabilidade. Apenas na próxima versão do Ubuntu você terá pacotes atualizados.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;h5&gt;A distro pode alterar o código fonte para adequar aos seus propósitos.&lt;/h5&gt;
&lt;p&gt;De um modo geral, cada distribuição tem um foco específico, por exemplo, facilidade. É comum distribuições com ênfase em segurança aplicarem 'patches' próprios ou de terceiros.&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;h5&gt;A distro pode 'quebrar' um projeto em diversos pacotes.&lt;/h5&gt;
&lt;p&gt;Alguns módulos do Apache, por exemplo, que são distribuídos no código fonte oficial, estão espalhados em diversos pacotes no Ubuntu.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;Através de arquivos .deb&lt;/h4&gt;

&lt;p&gt;
Por padrão os arquivos deb ficam cacheados, basta copia-los para o local desejado e 'abri-los'. O local padrão de cache é /var/cache/apt/archives/. O aplicativo ar serve para abrir os arquivos .deb.
&lt;/p&gt;

&lt;pre&gt;
$ cp /var/cache/apt/archives/&lt;i&gt;nome-do-pacote&lt;tab&gt;&lt;tab&gt;&lt;/i&gt;
$ ar x &lt;i&gt;nome-do-pacote&lt;tab&gt;&lt;tab&gt;&lt;/i&gt;
&lt;/pre&gt;

&lt;h4&gt;Utilizando o APT para obter os pacotes&lt;/h4&gt;
&lt;p&gt;Para obter o código fonte do pacote não é necessário qualquer permissão, visto que nada será alterado no sistema, apenas iremos baixar o pacote. Este pacote pode diferir do que foi instalado, pois o código fonte é baixado de outro repositório assinalado por deb-src. Isto explica os diversos deb-src que podem haver na sua source list.&lt;/p&gt;

&lt;pre&gt;
$ apt-get source &lt;i&gt;nome-do-pacote&lt;/i&gt;
&lt;/pre&gt;

&lt;p&gt;
Com isso, obteremos 3 arquivos:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.orig.tar.gz: arquivo original;&lt;/li&gt;
&lt;li&gt;.diff.gz: arquivo com as diferenças entre o original e a distribuição;&lt;/li&gt;
&lt;li&gt;.dsc: arquivo que descreve o pacote do código fonte;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
Sem parâmetros adicionais, apt-get source irá efetuar o download, descompactar os arquivos .gz e aplicar o diff. No final teremos um diretório com o código fonte que obteríamos caso fizéssemos um apt-get install ou um apt-get update (Isto partindo do pressuposto que os repositórios deb e deb-src estejam condizentes, o que acontece numa condição normal).
&lt;/p&gt;

&lt;h4&gt;Por que utilizar o código fonte de um projeto?&lt;/h4&gt;

&lt;p&gt;
Para a coisa mais preciosa que existe: &lt;b&gt;estudar&lt;/b&gt;.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7648329809512175190-8689116902198494747?l=bolodefoobar.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bolodefoobar.blogspot.com/feeds/8689116902198494747/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://bolodefoobar.blogspot.com/2009/07/obtendo-codigo-fonte-de-pacotes-deb.html#comment-form' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7648329809512175190/posts/default/8689116902198494747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7648329809512175190/posts/default/8689116902198494747'/><link rel='alternate' type='text/html' href='http://bolodefoobar.blogspot.com/2009/07/obtendo-codigo-fonte-de-pacotes-deb.html' title='Obtendo código fonte dos pacotes da sua distro'/><author><name>Daniel</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
