/* CODIFICANDO */

Relatos de um programador em contínua aprendizagem.

Archive for the ‘VIM’ Category

Dica rápida: identificando arquivos do Prawnto como arquivos Ruby no Vim

sem comentários

Dica para quem usa o Vim/Gvim como editor e está usando a dupla Prawn + plugin Prawnto para gerar PDF: Se você estiver criando suas views para geração de PDF com o Prawnto (os arquivos *.pdf.prawn) e o Vim/Gvim não estiver reconhecendo este arquivo como um arquivo Ruby (e consequentemente você estiver sem autoindent, sem syntax highlight e tudo mais), você pode resolver o problema adicionando as seguintes linhas no seu .vimrc:

augroup filetypedetect
  autocmd BufRead,BufNewFile *.prawn set filetype=ruby
augroup END

Caso seu .vimrc já possua uma seção autgroup filetypedetect apenas insira a linha autocmd BufRead,BufNewFile *.prawn set filetype=ruby dentro da mesma.

Escrito por cassiomarques

Março 23, 2009 em 2:48 pm

Publicado em VIM, rails

Running Rspec files from VIM, showing the results in Firefox

com 16 comentários

The Problem

In Gedit I was always using this script to execute the current Rspec file, when developing Rails apps. It was very useful to me since the script already includes all the necessary rspec dependencies in the load path and executes the declared specs wtihout running the dbtest:prepare Rake task. This makes the tests much faster, in special if all we want is to run the specs of a single Rspec file. Another thing that I like in the script is that it uses the Rspec HTML output, generating an HTML page which is shown in a new Firefox tab. This page shows even the code fragments for the failing specs, which is very useful for solving problems.
Since I moved back to VIM recently, I wanted to do the same using the rails.vim plugin. In rails.vim, when we have an open Rspec file and run :Rake this file is executed with Rspec. The downside is that all the test database is reloaded, making the tests unnecessarily slow. Another thing that I dislike is that VIM will put all specs execution output in a temporary view mode and wait until you press or run another command, going back immediately to the spec buffer. If you forget what was the error message or the failing spec, you will need to re-run the whole thing, since the output shown by VIM was temporary.

The Solution

The solution was to adapt the Gedit script, put it in an external Ruby file and create a new function to execute this script in my .vimrc. For this solution to work your VIM must have been compiled with the +ruby option, which enables a Ruby interface for VIM. To see if your VIM has the Ruby support, run :version and search for “+ruby”. If all you have is “-ruby” you’ll need to re-compile VIM with this option enabled. Take a look at the VIM Makefile and serch for something like enable ruby-interp.

This solution was tested using VIM 7.2 in a Ubuntu 8.04 box.

Create a new file with the following content and put it in ~/.vim/bin/run_rspec.rb

spec_dir=File.dirname(ARGV[0])
rails_project_dir="#{spec_dir}/../.."

report_file="#{rails_project_dir}/doc/rspec_report.html"

rspec_rails_plugin = File.join(rails_project_dir,'vendor','plugins','rspec','lib')
if File.directory?(rspec_rails_plugin)
  $LOAD_PATH.unshift(rspec_rails_plugin)
end
require 'rubygems'
require 'spec'
require 'spec/runner/formatter/html_formatter'

module Spec
  module Runner
    module Formatter
      class HtmlFormatter
        def backtrace_line(line)
          line.gsub(/([^:]*\.rb):(\d*)/) do
            "<a href=\"vim://#{File.expand_path($1)}?#{$2}\">#{$1}:#{$2}</a> "
          end
        end
      end
    end
  end
end

if File.exists? report_file
  File.delete report_file
end

argv = [ARGV[0]]
argv << "--c"
argv << "--format"
argv << "html:#{report_file}"

::Spec::Runner::CommandLine.run(::Spec::Runner::OptionParser.parse(argv, STDERR, STDOUT))

if File.exists? report_file
  `firefox #{report_file}`
end

Then edit your .vimrc file, which should be located at $HOME/.vimrc, adding the following lines:


" Run Rspec for the current spec file
function! RunRspec()
ruby << EOF
  buffer = VIM::Buffer.current
  spec_file = VIM::Buffer.current.name
  command = "ruby ~/.vim/bin/run_rspec.rb #{spec_file}"
  print "Running Rspec for #{spec_file}. Results will be displayed in Firefox."
  system(command)
EOF
endfunction
map <F7> :call RunRspec()<cr>

Here I mapped the F7 key to execute the specs, but you can change the function to use any key combination you like. Now all you need to do is press F7 to run all the specs for the current Rspec file and present the output in a new Firefox tab.

UPDATED:
Pay attention to the fact that each error shown in Firefox will have a clickable link, which will open the respective file in Vim and take you right to the line of the failing spec. For this to work, you’ll need to make some configurations:

  • Open the address about:config in your Firefox
  • Firefox will show you a warning page, you can tell him that you know what you’re doing…
  • Right-click anywhere on the page, choose “new option” and then “boolean”. Put network.protocol-handler.external.vim as the option’s name and set its value to true
  • Again, right-click, choose “new option” and then “string”. Put network.protocol-handler.app.vim as the option’s name and ~/.vim/bin/open_vim as its value
  • Now just close the about:config page

Now you’ll need to create the script that will get called when you click an error line and will take care of opening your spec file in Vim (actually it’s configured to use GVim, you can change it if you want). The file will be opened in an already running GVim instante, using a new tab. Create a file called open_vim inside $HOME/.vim/bin, with the following contents:

#!/usr/bin/ruby
regex = /(.+)\?(\d+)/
ARGV[0] =~ regex
system("gvim --remote-silent +#{$2} #{$1}")

Save and close it. Now give it execution permition by running chmod +x ~/.vim/bin/open_vim. The first time you click in an error line in Firefox, it will prompt you to confirm that you want to use open_vim as the program to open vim:// links. Just accept it and you’re good to go.

If you’ve made some changes to your development database and want them to exist in your test database before running the specs, just run rake db:test:prepare once and you’re good to go.

Escrito por cassiomarques

Janeiro 9, 2009 em 5:05 pm

Publicado em VIM, rails, testes

Executando specs no VIM e exibindo os resultados no Firefox

com 5 comentários

O problema

No Gedit eu usava esse script para executar o arquivo do Rspec atual, quando desenvolvendo aplicações Rails. Isso sempre foi muito útil para mim porque o script já inclui as depedências necessárias no load path e executa as specs declaradas no arquivo atual sem executar a Rake task db:test:prepare. Isso torna os testes bem mais rápidos, principalmente se quisermos executar apenas as specs de um único arquivo específico. Outra coisa que gosto muito nesse script é que ele utiliza o modo de visualização dos resultados em HTML, exibindo a página gerada em uma nova aba no Firefox. Essa página exibe até mesmo os trechos de código das specs que falharam, o que ajuda bastante na hora de solucionar os problemas.
Como voltei recentemente a utilizar o VIM para desenvolver em Ruby/Rails, fui ver como fazer o mesmo usando o plugin rails.vim. No rails.vim, quando temos um arquivo de specs aberto e executamos :Rake esse arquivo é executado com o Rspec. O lado ruim disso é que todo o banco de dados é carregado, deixando a execução dos testes muito mais lenta do que necessário. Outra coisa que não gosto é que o VIM irá colocar todo o output da execução das specs em um modo de visualização temporário e esperar que você pressione ou execute algum outro comando, voltando imediatamente para o buffer com o arquivo de specs. Se você não lembrar exatamente qual foi a mensagem de erro ou qual spec falhou, vai ter que executar tudo de novo, porque a saída que o VIM mostrou era temporária.

A solução

A solução foi adaptar o script utilizado no Gedit, colocá-lo em um arquivo Ruby externo e criar uma função no meu .vimrc que executa este script. Para utilizar essa solução é necessário que o seu VIM tenha sido compilado com a opção +ruby, a qual habilita uma interface Ruby para criar funções dentro de scripts do VIM. Para verificar se o seu VIM possui essa funcionalidade, faça :version e procure por “+ruby”. Se tudo o que você encontrar for “-ruby”, será necessário que você recompile seu VIM com essa opção habilitada. Dê uma olhada no Makefile do VIM e procure por enable ruby-interp.

Essa funcionalidade foi testada no VIM 7.2 em um Ubuntu 8.04.

Crie um arquivo com o conteúdo abaixo e coloque-o em ~/.vim/bin/run_rspec.rb

spec_dir=File.dirname(ARGV[0])
rails_project_dir="#{spec_dir}/../.."

report_file="#{rails_project_dir}/doc/rspec_report.html"

rspec_rails_plugin = File.join(rails_project_dir,'vendor','plugins','rspec','lib')
if File.directory?(rspec_rails_plugin)
  $LOAD_PATH.unshift(rspec_rails_plugin)
end
require 'rubygems'
require 'spec'
require 'spec/runner/formatter/html_formatter'

module Spec
  module Runner
    module Formatter
      class HtmlFormatter
        def backtrace_line(line)
          line.gsub(/([^:]*\.rb):(\d*)/) do
            "<a href=\"vim://#{File.expand_path($1)}?#{$2}\">#{$1}:#{$2}</a> "
          end
        end
      end
    end
  end
end

if File.exists? report_file
  File.delete report_file
end

argv = [ARGV[0]]
argv << "--c"
argv << "--format"
argv << "html:#{report_file}"

::Spec::Runner::CommandLine.run(::Spec::Runner::OptionParser.parse(argv, STDERR, STDOUT))

if File.exists? report_file
  `firefox #{report_file}`
end

Em seguida edite o seu .vimrc, que deve estar localizado em $HOME/.vimrc, adicionando o conteúdo a seguir


" Run Rspec for the current spec file
function! RunRspec()
ruby << EOF
  buffer = VIM::Buffer.current
  spec_file = VIM::Buffer.current.name
  command = "ruby ~/.vim/bin/run_rspec.rb #{spec_file}"
  print "Running Rspec for #{spec_file}. Results will be displayed in Firefox."
  system(command)
EOF
endfunction
map <F7> :call RunRspec()<cr>


Aqui eu mapeei a tecla F7 para executar as specs, mas você pode alterar a função e mapear a combinação de teclas que preferir. Agora basta estar com algum arquivo de specs aberto e apertar F7 para que suas specs sejam executadas e o resultado apresentado no Firefox.

ATUALIZADO:
Preste atenção ao fato de que cada erro exibido no Firefox terá um link clicável, o qual abrirá o respectivo arquivo no Vim, exatamente na linha de código da spec que falhou. Para que isso funcione, você terá que fazer algumas configurações:

  • Abra o endereço about:config no seu Firefox
  • O Firefox irá exibir uma tela de avisa, diga a ele que você terá cuidado…
  • CLique com o botão direito em qualquer local da página, escolha “nova opção” e então “boolean”. Coloque network.protocol-handler.external.vim como o nome da opção e defina seu valor como true
  • Novamente, clique com o botão direito, escolha “nova opção” e então “string”. Coloque network.protocol-handler.app.vim como o nome da opção e ~/.vim/bin/open_vim como seu valor
  • Feche a página about:config

Agora você terá que criar o script que será chamado quando você clicar em uma linha de erro e cuidará de abrir o seu arquivo com specs usando o Vim (na verdade o script está configurado para usar o GVim, mas você pode alterar isso se quiser). O arquivo será aberto em uma instância do Vim já em execução, usando uma nova aba. Crie um arquivo chamado open_vim dentro de $HOME/.vim/bin, com o seguinte conteúdo:

#!/usr/bin/ruby
regex = /(.+)\?(\d+)/
ARGV[0] =~ regex
system("gvim --remote-silent +#{$2} #{$1}")

Salve e feche o arquivo. Agora dê permissão de execução a ele executando chmod +x ~/.vim/bin/open_vim. Na primeira vez que você clicar em uma linha de erro no Firefox ele irá exibir um diálogo para que você confirme que quer utilizar o programa open_vim para abrir links no formato vim://. Apenas dê “OK” e tudo estará certo.

Se você tiver feito alguma alteração no banco e quiser que essas alterações sejam refletidas no banco de testes antes de executar as specs, basta fazer rake db:test:prepare.

Escrito por cassiomarques

Janeiro 9, 2009 em 4:56 pm

Publicado em VIM, rails, testes

Etiquetado com