A (fairly) simple equation evaluation service for Snow Leopard

[Tweet : ADN : nvALT]

ExpressionevalheaderDownload the Evaluate Expression Snow Leopard service: EvaluateExpressionService.zip

This is a stripped down version of a command I have in the TextMate bundle we use at TUAW. It allows you to select any basic numeric equation and evaluate it, replacing the selected text with the results. It will ignore your text if it contains anything but numbers and basic mathematical symbols. Sure, there are plenty of ways to do calculations in OS X (Spotlight, Launchbar, Quicksilver), but I’ve had more and more incidents lately where I just wanted to do quick calculations inline, so I whipped this up. A little explanation…

The service is built for Snow Leopard only, but I’m including the code here because it could be wrapped up in ThisService or Bellhop pretty quickly for Leopard. It’s built in Ruby and uses the eval function to process text such as 20*(3.5/2) and return the result. It will add commas to numbers longer than 3 digits, but I stripped out the part of the original command that trimmed decimal places; I figured the accuracy might be important and the results are easy to edit manually in this case. I also added a silly feature that I actually find quite useful: it evaluates +/- percentage strings, such as 23.99-15%, which I find most useful for calculating savings during sales or quickly handling markup or tax on services and goods. It can’t get too complex, but for most everyday purposes, it does a good job.

The code:

def ts( st )
  # Adds commas to longer numbers
  # Removes .00 left over from % calculations
  mynum = st.to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse
  dec = mynum.split('.')
  return dec[0] if dec[1].to_i == 0
  mynum
end

ARGF.each do |f|
	# check if the text passed is actually an equation
	if f.match(/^[\%\$\d\*\/\+\-,\. \(\)]+$/)
		# add a preceding 0 to decimals passed for floating point calculation
		num = f.gsub(/(^|[^\d])(\.\d+)/,'\10\2')
		# convert basic percentage equations for eval
		num = num.gsub(/([\d\.]+)(?:\s+?)?([+-])(?:\s+?)?([\d\.]+)%([^\d]|$)/,'\1\2(\1*(\3.to_f * 0.01))\4')
		# process the result to add commas, trim unnecessary decimal places
		print ts(eval(num).to_s)
	# if it's not an equation, return the input (no effect)
	else
		print f
	end
end

You can download a ready-to-go Snow Leopard service, or build your own with the code above. Don’t forget to use the Keyboard preference panel to assign a keyboard shortcut to it (I’m using Control-Shift-=). I’d love to hear back if you find it useful!