Google calculator is a very powerful tool. Besides basic arithmetic, you can use it in many other interesting ways. But I always wanted to use it from the command line without opening a new Safari window.
Ruby to the rescue:
$ cat gcal
#!/usr/bin/env ruby
%w(rubygems open-uri hpricot erb).each {|lib| require lib }
doc = Hpricot(open("http://www.google.com/search?q=#{ERB::Util.u(ARGV*' ')}"))
puts (doc/'/html/body/p/table/tr/td[3]/font/b').inner_text
$ ./gcal 2^20
2^20 = 1 048 576
$ ./gcal 'sqrt(-1)'
sqrt(-1) = i
$ ./gcal 30 rubles in dollars
30 Russian rubles = 1.1379844 U.S. dollars
$ ./gcal 2 gallons in liters
2 US gallons = 7.5708236 liters
It's not too bad for three-liner like this. By the way, did I say that Hpricot is awesome?
Nice. Next up: a 3 line library you can call from your Ruby apps?
SOA!
I can't get 5+5 to work. The URL being created is:
http://www.google.com/search?q=5+5
But it should be
http://www.google.com/search?hl=en&q=5%2B5
Any ideas?
Ryan,
You are right. It seems that URI.encode is buggy. I've fixed the script.
I figured it out. You want CGI.encode, not URI.encode. Here's my version of your program:
!/usr/bin/env ruby
%w(rubygems open-uri cgi hpricot).each {|lib| require lib }
equation = ARGV * ' ';
if(equation.strip == "") puts "Usage: rcalc <expression>" puts " i.e.: rcalc 5+5" puts " i.e.: rcalc 5 feet in inches" puts " i.e.: rcalc (5^2)*2/3.0" puts " i.e.: rcalc 5+5" else
begin where = ""; equation = "#{equation}"; #puts "equation before = #{equation}"; equationWithFloats = equation.gsub(/([0-9.]+)/) { |num| if(num.index('.') == nil) then num + ".0" else num end } #puts "equation after = #{equationWithFloats}"; answer = eval(equationWithFloats); answer = "#{equation} = #{answer}"; rescue SyntaxError, NameError #puts "Error was #{$!}"; where = "According to Google: "; url = "http://www.google.com/search?q=#{CGI.escape(equation)}"; #puts url; begin doc = Hpricot(open(url)); answer = (doc/'//html/body/p/table/tr/td[3]/font/b').inner_text.strip; #puts "answer is #{answer}"; if answer == "" then answer = "Sorry, not even google could figure out your request"; end rescue SocketError answer="Google could not be reached"; end end
puts "#{where}#{answer}";
end
I would use ERB::Util#u instead of writing my own URL escaping code. It's less code to write and I don't have to worry about bugs in my code. ;)
google must have changed the page html, this seems to be working correctly:
puts (doc/'/html/body/div#res/p/table/tr/td[3]/h2/font/b').inner_text