Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 241 lines (226 sloc) 7.44 KB
#!/usr/bin/env ruby
require 'rubygems'
require 'readline'
require 'indextank'
COMMANDS = {
"url" => "[url] sets the api url",
"list" => "lists all the indexes",
"index" => "[index name] sets the index name",
"create" => "[index name] creates an index",
"search" => "[query] searches the current index",
"suggest" => "[prefix] suggests query terms starting with \"prefix\"",
"add" => "[docid] creates a new document",
"delete" => "[docid] deletes a document identified by docid",
"drop" => "[index name] drops index name for good. really, for good.",
"start" => "[n] show results starting from n",
"len" => "[n] show n results",
"function" => "[n] use scoring function n for searching\n\t\t[n] [definition] define scoring function n as definition",
"functions" => "list current scoring functions",
"set" => "shows current settings",
"reset" => "resets settings. WARNING: it will 'clear' your .console file",
"status" => "shows index status",
"doc-var" => "[docid] [var index] [var value] sets var index as var value on docid",
"query-var" => "[var index] [var value] sets var index as var value for queries\n\t\t[var index] 'clear' clears var index for queries",
"promote" => "[docid] [query] promotes docid when searching for query",
"quit" => "exits this shell"
}
comp = proc { |s| if s =~ /^search/ then
# TODO find a rubier way to split / tail
@index.suggest(s.split(' ')[1..10].join(' '))['suggestions'].map { |sug| "search #{sug}" }
else
# default, complete with commands
COMMANDS.keys.grep( /^#{Regexp.escape(s)}/ )
end
}
# change the work break character, hacky way to allow multi word suggest :)
Readline.completer_word_break_characters = "|"
Readline.completion_append_character = " "
Readline.completion_proc = comp
def get_prompt()
if @idxname
return @idxname + "> "
else
return "> "
end
end
def reset()
@apiurl = nil
@idxname = nil
@api = nil
@index = nil
@data = {}
@start = 0
@len = 10
@scoring_function = 0
@qvars = {}
@data['start'] = @start
@data['len'] = @len
@data['function'] = @scoring_function
@data['qvars'] = @qvars
end
def command(line)
args = line.split
case args[0]
when "url"
@apiurl = args[1]
@api = IndexTank::Client.new @apiurl
@data['url'] = @apiurl
printf "api url set to %s\n", @apiurl
when "list"
if !@api
puts "no api url set yet. Did you run 'url' .. ?"
else
@api.indexes.each {|x| puts x}
end
when "create"
if !@api
puts "no api url set yet. Did you run 'url' .. ?"
else
@idxname = args[1]
tmp_index = @api.indexes @idxname
tmp_index.add()
puts "index #{@idxname} created. you may want to run 'index #{@idxname}' to use it"
end
when "index"
if !args[1]
puts @idxname
else
@idxname = args[1]
@index = @api.indexes @idxname
@data['idxname'] = @idxname
@index.refresh
printf "index set to %s\n", @idxname
end
when "drop"
if !args[1]
puts "if you really want to drop '#{@idxname}', you should write 'drop #{@idxname}'"
else
@idxname = args[1]
@index = @api.indexes @idxname
@index.delete
puts "#{@idxname} dropped. Gone for good."
@idxname = ""
@data['idxname'] = @idxname
end
when "search"
query = args[1..args.length].join ' '
results = @index.search(query, :start => @start, :len => @len, :variables => @qvars, :function => @scoring_function)
printf "%s results in %s seconds\n", results['matches'], results['search_time']
results['results'].each {|doc|
docid = doc['docid']
printf "docid: #{docid}\n"
}
when "suggest"
query = args[1..args.length].join ' '
results = @index.suggest(query)
if results['suggestions'].length > 0
puts results['suggestions'].join ' '
else
printf "no suggestions for %s :(\n", query
end
when "promote"
if args.length < 3
printf "usage: 'promote' %s\n", COMMANDS['promote']
else
docid = args[1]
query = args[2..args.length].join ' '
result = @index.promote(docid, query)
end
when "add"
if @index == nil
puts 'set an index first'
else
if !args[1]
docid = Readline.readline('enter docid (blank to abort):', true)
else
docid = args[1]
end
if docid.strip != ''
doc = {}
while true
field = Readline.readline('field name (or blank to end): ', true)
if field.strip == ''
break
end
value = Readline.readline('field value: ', true)
doc[field] = value
end
@index.document(docid).add(doc)
printf("added %s\n", docid)
end
end
when "delete"
docid = args[1]
@index.document(docid).delete()
when "set"
@data.each {|x| p x}
when "reset"
reset
when "status"
if not @index
puts "no index selected. Did you run 'index <idxname>'?"
else
puts @index.running?
end
when "len"
@len = args[1].to_i
@data['len'] = @len
when "start"
@start = args[1].to_i
@data['start'] = @start
when "function"
scoring_function_idx = args[1].to_i
if args.length > 2
@fn = @index.functions scoring_function_idx, args[2..100].join(" ")
@fn.add
else
@scoring_function = scoring_function_idx
@data['function'] = @scoring_function
end
when "functions"
@fns = @index.functions
@fns.each { |fn| printf "%d => %s\n", fn.index, fn.definition }
when "doc-var"
docid = args[1]
varidx = args[2].to_i
varval = args[3].to_f
@index.document(docid).update_variables(varidx => varval)
when "query-var"
varidx = args[1].to_i
varval = args[2]
if varval.strip() == 'clear'
@qvars.delete(varidx)
else
@qvars[varidx] = varval.to_f
end
@data['qvars'] = @qvars
when "help"
printf "possible commands are:\n\n"
COMMANDS.sort.each{|k,v| printf "%s\t%s%s\n", k, k.length < 8 ? "\t":"",v}
else
puts 'no such command, try "help"'
end
end
if File.exists? '.console'
puts 'reading previous session from .console'
@data = Marshal.load File.open('.console')
@api = IndexTank::Client.new @data['url']
@idxname = @data['idxname']
@index = @api.indexes @idxname
@len = @data['len']
@start = @data['start']
@scoring_function = @data['function']
@qvars = @data['qvars']
printf "using %s as connection url\n", @data['url']
end
while line = Readline.readline(get_prompt, true) and line.strip() != 'quit'
begin
command line
f = File.open '.console', 'w'
Marshal.dump(@data, f)
f.close
rescue Exception => e
puts e
end
end
puts 'bye'