# Copyright (C) 2005 Shugo Maeda
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
require "rast"
class MLSearchApp
DB_PATH = "/home/shugo/ruby-ml-index"
MAX_PAGES = 20
ML_OPTIONS = [
["", "すべて"],
["ruby-list", "ruby-list"],
["ruby-dev", "ruby-dev"]
]
SORT_OPTIONS = [
["score", "スコア順"],
["date", "日付順"],
["x-mail-count", "メール番号順"],
["from", "送信者順"],
["subject", "件名順"],
]
SORT_PROPERTIES = ["date", "x-mail-count", "from", "subject"]
ORDER_OPTIONS = [
["asc", "昇順"],
["desc", "降順"],
]
NUM_OPTIONS = [10, 20, 30, 50, 100]
MESSAGE = <
このプログラムは、
全文検索システムRast
のデモ用プログラムです。
EOF
end
def format_options(options, value)
return options.collect { |val, label|
if val == value
""
else
""
end
}.join("\n")
end
def search
db = Rast::DB.open(@db_path, Rast::DB::RDONLY)
begin
options = create_search_options
query = create_query
t = Time.now
result = db.search(query, options)
secs = Time.now - t
return format_result(result, secs)
rescue
return "
エラー: #{_($!.to_s)}
\n"
ensure
db.close
end
end
def create_search_options
options = {
"properties" => [
"x-ml-name", "x-mail-count", "subject", "from", "date"
],
"need_summary" => true,
"summary_nchars" => 200,
"start_no" => @start,
"num_items" => @num
}
if SORT_PROPERTIES.include?(@sort)
options["sort_method"] = Rast::SORT_METHOD_PROPERTY
options["sort_property"] = @sort
end
if @order == "asc"
options["sort_order"] = Rast::SORT_ORDER_ASCENDING
else
options["sort_order"] = Rast::SORT_ORDER_DESCENDING
end
return options
end
def create_query
q = @query
if !@ml.empty?
q += " x-ml-name = #{@ml}"
end
return q
end
def format_result(result, secs)
buf = ""
buf.concat(<
#{_(@query)} の検索結果
#{result.hit_count} 件中 #{@start + 1} - #{@start + result.items.length} 件目
(#{secs} 秒)
EOF
for item in result.items
buf.concat(format_result_item(result, item))
end
if result.hit_count > 0
buf.concat(format_links(result))
end
return buf
end
def format_result_item(result, item)
x_ml_name, x_mail_count, subject, from, date = *item.properties
summary = item.summary
for s in [subject, from, summary]
s.gsub!(/([A-Za-z0-9])@[A-Za-z0-9\-.]+/, %q%\\1@...%)
end
summary = _(summary)
for term in result.terms
summary.gsub!(Regexp.new(Regexp.quote(term.term), true, "utf-8"),
"\\&")
end
return <#{_(subject)}
\n"
if current_page > 1
buf.concat(format_link("前へ", @start - @num, @num))
end
if first_page > 1
buf.concat("... ")
end
for i in first_page..last_page
if i == current_page
buf.concat("#{i} ")
else
buf.concat(format_link(i.to_s, (i - 1) * @num, @num))
end
end
if last_page < page_count
buf.concat("... ")
end
if current_page < page_count
buf.concat(format_link("次へ", @start + @num, @num))
end
buf.concat("