require 'grn_mini' require 'find' require 'kconv' require 'sinatra' require "sinatra/reloader" if ENV['SINATRA_RELOADER'] module Input module_function def from_dir(array, dir = ".") index = 1 puts "Create database .." Find.find(File.expand_path(dir)) do |filename| Find.prune if ignore_dir?(filename) if File.file? filename next if ignore_file?(filename) array << {filename: filename, text: read_file(filename), timestamp: File.stat(filename).mtime, suffix: File.extname(filename).sub('.', "")} index += 1 end end puts "Input complete : #{array.size} files" end def read_file(filename) text = File.read(filename) Kconv.kconv(text, Kconv::UTF8).gsub("\r\n", "\n") end def ignore_dir?(filename) basename = File.basename(filename) /(\A\.svn\Z)|(\A\.git\Z)|(\ACVS\Z)/.match(basename) end def ignore_file?(filename) (s = File.read(filename, 1024)) && s.index("\x00") end end class Search def initialize(array, params) @array = array @params = params @page = @params[:page] ? @params[:page].to_i : 1 end def has_query? @params[:query] && !@params[:query].empty? end def parse unless has_query? @header = "#{@array.size} files." @content = "" @pagination = "" else results = @array.select(@params[:query], default_column: "text") page_entries = results.paginate([["_score", :desc]], :page => @page, :size => 20) snippet = GrnMini::Util::html_snippet_from_selection_results(results, "", "") elements = [] page_entries.each do |record| element = "
\n#{record.filename}\n" snippet.execute(record.text).each do |segment| element += "
#{segment}
\n" end elements << element end @header = "#{page_entries.n_records} hit. (#{page_entries.start_offset} - #{page_entries.end_offset})" @content = elements.join("\n") @pagination = "" if page_entries.n_pages > 1 @pagination += page_link(@page - 1, "<-") + " " if @page > 1 @pagination += page_range(page_entries).map {|v| if (v == @page) "#{v.to_s}" else page_link(v, v.to_s) end }.join(" ") @pagination += " " + page_link(@page + 1, "->") if @page < page_entries.n_pages end end end def page_range(page_entries) first_diff = [5 - (@page - 1), 0].max last_diff = [5 - (page_entries.n_pages - @page), 0].max [@page - 5 - last_diff, 1].max .. [@page + 5 + first_diff, page_entries.n_pages].min end def page_link(page, msg) "#{msg}" end def html <
#{@content}
EOF end end ### main ### configure do GrnMini::create_or_open("mini-directory-search.db") $array = GrnMini::Array.new Input.from_dir($array) if $array.empty? end get '/' do search = Search.new($array, params) search.parse search.html end get '/:id' do record = $array[params[:id].to_i] <#{record.filename} (#{record.timestamp})

#{CGI.escapeHTML(record.text)}
EOF end post '/search' do redirect "/?query=#{escape(params[:query])}" end