DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Nano-search Engine

07.26.2011
| 1908 views |
  • submit to reddit
        Query macher is like a regexp but take a liste of word/-word 'a la google' 
as request.

Exemple :
mot1 mot2 "two word" -mot3 -"g m" /f\d+/ 
give search on :
 mot1 AND mot2 AND "two word" AND NOT mot3 AND NOT "g m" AND regexp(f[0-9]+)

class QueryMatcher  
  def initialize(str0)
    str=str0.to_s
    lexclu0=str.scan(/\s-"[^"]*"/)  ; lexclu0.map! {|mot| str.gsub!(mot,"") ; mot.gsub(/["\-]/,'') }
    lexclu1=str.scan(/\s-[^\s]*/)   ; lexclu1.map!  {|mot| str.gsub!(mot,"") ;  mot.gsub('-','')}
    lmot0=str.scan(/"[^"]*"/)     ; lmot0.map!   {|mot| str.gsub!(mot,"") ; mot.gsub('"','') }
    lmot1=str.scan(/\/[^\/]+\//)  ; lmot1.each   {|mot| str.gsub!(mot,"") ; }
    lmot2=str.split(/\s+/)        
    lexclu=lexclu0+lexclu1
    lmot=lmot0+lmot1+lmot2-lexclu

    @squery="(" + lmot.map  { |mot| Regexp.escape(mot)}.join(" && ") +")"
    @rquery= lmot.size>0 ? lmot.map  { |mot| Regexp.new(  mot=~/^\/.*\/$/ ? mot[1..-2] : Regexp.escape(mot) ) } : nil

    @sequery= "(" +  lexclu.map {|mot| Regexp.escape(mot[1..-1])}.join(")|(")  +")"
    @equery= lexclu.size>0 ? Regexp.new( @sequery ) : nil
    
    @echo= @squery+ ((lexclu.size>0) ? ("  AND NOT "+(@sequery)) : "")
  end
  def match(str)
    return(false) if !@rquery
    return(false) if (str||"").strip.length==0
    @rquery.select { |re| return(false) if str !~ re }
    return(true)           unless @equery
    return(str !~ @equery) rescue false
  end
  def to_s
    @echo
  end
  def search_file(filename)
  	  IO.readlines(filename).select { |line| match(line) }.map(&:chomp)
  end
  def search_dir(dir,glob)
  	res=[]
  	Dir.glob("#{dir}/#{glob}").each do |entry|
  		next if File.directory?(entry)
  		m=search_file(entry)
  		res << [entry,m] if m.size>0
  	end
  	res
  end
end 

Test :
qm =QueryMatcher.new("create dir -Declare")
l  =qm.search_dir("ruby19/lib/ruby/1.9.1","*.rb")

puts "Search '#{qm}' in ruby19/lib/ruby/1.9.1 ::"

l.each { |f,ls| puts "  %-15s :\n     %s" % [File.basename(f),ls.join("\n     ")] }


this give :
Search '(create && dir)  AND NOT (Declare)' in ruby19/lib/ruby/1.9.1 ::
  fileutils.rb    :
       #   FileUtils.mkdir 'notexist', :noop => true  # Does not really create.
       # If +new+ already exists and it is a directory, creates a link +new/old+.
       # exists and it is a directory, creates a symbolic link +new/old+.  If +new+
  rake.rb         :
       # Tasks are not usually created directly using the new method, but rather
  rubygems.rb     :
       # subdirectories.  If we can't create a directory due to a permission
  tmpdir.rb       :
       # Dir.mktmpdir creates a temporary directory.
       # The directory is created with 0700 permission.
       # The directory is created under Dir.tmpdir or
         path = Tmpname.create(prefix_suffix || "d", *rest) {|n| mkdir(n, 0700)}