#!/usr/bin/env ruby # -*- ruby -*- # # Searches your plugins for what ever you type in # # Usage: search ? # # - If you give no arguments, you will be prompted for an engine and # search terms # - If you give one argument, that will be the engine, you will be # prompted for search terms # - If you give more than one argument, the first will be the search # engine, the rest will be search terms # # Examples: # # % ./search # % ./search yahoo # % ./search yahoo green eggplants # require 'net/http' require 'cgi' # -------------------------------------------------- # Classes # -------------------------------------------------- # A simple search plugin with a URL and various arguments class SearchPlugin attr_reader :short_name attr_accessor :name, :description, :url def initialize(short_name) @short_name = short_name.gsub /.xml$/, "" @name = nil @description = nil @url = nil @args = {} end def add_argument(key,value) @args[key] = value end def to_external_form(q) res = url params = "" @args.each do |k,v| params += (params == "" ? "?" : "&") params += CGI.escape(k) + "=" + CGI.escape(v == "{searchTerms}" ? q : v) end return res + params end end # -------------------------------------------------- # Functions # -------------------------------------------------- # String[file] -> Array[SearchPlugin] def lookup_plugins(searchplugins) plugins = [] Dir.foreach(searchplugins) do |f| next if f !~ /^\w.*\.xml$/ File.open(searchplugins + "/" + f, "r") do |infile| plugin = SearchPlugin.new f plugins.push plugin while line = infile.gets # Google if res = /([^<]+)<\/ShortName>/i.match(line) plugin.name = res[1] end # Google Search if res = /([^<]+)<\/Description>/i.match(line) plugin.description = res[1] end # if res = //i.match(line) plugin.url = res[1] end # if res = / String[searchplugins] def find_searchplugins_dir() # look up the default profile profiles = ENV["HOME"] + "/Library/Application Support/Firefox/Profiles" searchplugins = nil if File.directory? profiles Dir.foreach(profiles) do |f| if f =~ /.*\.default/ then base = profiles + "/" + f sp = base + "/searchplugins" if File.exist? sp searchplugins = sp break end end end end return searchplugins if searchplugins # try for the new version of Firefox sp = "/Applications/Firefox.app/Contents/MacOS/searchplugins" if File.directory? sp searchplugins = sp end return searchplugins if searchplugins end # Main entry point # Void -> Boolean [success] def main(argv) # get the arguments, the first is the reqex describing # the plugin, the rest are the search terms if argv.length > 0 then engine = argv.shift end terms = "" argv.each do |arg| if terms != "" then terms += " " + arg else terms = arg end end if terms and terms != "" terms = CGI.escape terms end # Look up the search plugins dir and the find all the plugins searchplugins = find_searchplugins_dir plugins = lookup_plugins searchplugins # fail if we can't find the firefox path if !searchplugins then STDERR.puts "Couldn't find search plugins" return false end plugins_to_use = [] # Maybe prompt for the plugins if !engine short_name_max = 0 name_max = 0 # Be nice and find the longest short name, name plugins.each do |p| short_name_max = p.short_name.length if p.short_name.length > short_name_max name_max = p.name.length if p.name.length > name_max end # Prompt for one to use puts while true i = 1 plugins.each do |p| printf "[%d] %-" + (short_name_max+1).to_s + "s %-" + (name_max+1).to_s + "s\n", i.to_s, p.short_name, p.name i += 1 end STDOUT.print "Please choose an engine > " STDOUT.flush val = 0 s = nil begin s = gets val = s.to_i rescue STDERR.puts "Invalid choice '" + s + "'" end if val < 0 STDERR.puts val.to_s + " must be > 0" elsif val > plugins.length STDERR.puts val.to_s + " must be <= " + plugins.length.to_s else plugins_to_use.push plugins[val-1] break end end else # choose from the given regex re = Regexp.new ".*" + engine + ".*" plugins.each do |p| if p.name.match re or p.short_name.match re plugins_to_use.push p end end end # Get the terms, maybe while !terms or terms == "" STDOUT.print "Input search terms> " STDOUT.flush terms = gets end plugins_to_use.each do |p| url = p.to_external_form terms STDERR.puts "Using " + p.name + " with url '" + url + "'" exec "open", url end return true end # -------------------------------------------------- # Main # -------------------------------------------------- exit 1 if !main(ARGV)