From ff8ce104f85ae3a236c1c5dbf2156cd9593c6d3b Mon Sep 17 00:00:00 2001 From: Marcus Williams Date: Sat, 22 Dec 2007 15:49:53 -0800 Subject: [PATCH] additional gmail-style query language additions original message: Simple patch attached. Adds the "during" operator to the date searches so you can say during:today or during:november . I prefer it to in/on today :) Also adds an alias for the label search of "is" so that you can do more gmail like searches is:starred, is:unread, is:spam, is:deleted. The last two required changing the return value to a list/pair in parse_user_string_query and I'm not sure what the best way to do this in ruby is. For now its a simple list. Also is there a better way to deal with a nil result other than returning [nil,nil]? The first element is the parsed query string, the second allows the parser to add options to the query like :load_spam, :load_deleted which are then used in the code already to drop (or not) the spam/deleted labeled messages. I figured you'd never want to search killed threads... and it made the patch nastier because of the :skip_killed flag. I'd like to add a has:attachment operator but the ferret index doesnt appear to store enough info for this. It would be really nice to be able to search for attachments (of certain types as well with filename:...) I took a look at extending the index to add a new field "filename" that contains a list of filenames attached to a message, but this would break everyones index so I'm just requesting it as a wishlist item rather than submitting a patch. With it you could do wildcard filename attachment searches and the has:attachment search would just be converted to a search for the presence of any filename. --- lib/sup/index.rb | 26 ++++++++++++++++++++++++-- lib/sup/modes/search-results-mode.rb | 13 ++++++++----- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/lib/sup/index.rb b/lib/sup/index.rb index fd46495..97fe722 100644 --- a/lib/sup/index.rb +++ b/lib/sup/index.rb @@ -394,6 +394,7 @@ protected ## do any specialized parsing ## returns nil and flashes error message if parsing failed def parse_user_query_string str + extraopts = {} result = str.gsub(/\b(to|from):(\S+)\b/) do field, name = $1, $2 if(p = ContactManager.contact_for(name)) @@ -405,9 +406,26 @@ protected end.join(":") end + # gmail style "is" operator + result = result.gsub(/\b(is):(\S+)\b/) do + field, label = $1, $2 + case label + when "read" + "-label:unread" + when "spam" + extraopts[:load_spam] = true + "label:spam" + when "deleted" + extraopts[:load_deleted] = true + "label:deleted" + else + "label:#{$2}" + end + end + if $have_chronic chronic_failure = false - result = result.gsub(/\b(before|on|in|after):(\((.+?)\)\B|(\S+)\b)/) do + result = result.gsub(/\b(before|on|in|during|after):(\((.+?)\)\B|(\S+)\b)/) do break if chronic_failure field, datestr = $1, ($3 || $4) realdate = Chronic.parse(datestr, :guess => false, :context => :none) @@ -432,7 +450,11 @@ protected end Redwood::log "translated #{str.inspect} to #{result}" unless result == str - @qparser.parse result if result + if result + [@qparser.parse(result), extraopts] + else + [nil,nil] + end end def build_query opts diff --git a/lib/sup/modes/search-results-mode.rb b/lib/sup/modes/search-results-mode.rb index feef1c3..f64a227 100644 --- a/lib/sup/modes/search-results-mode.rb +++ b/lib/sup/modes/search-results-mode.rb @@ -1,9 +1,11 @@ module Redwood class SearchResultsMode < ThreadIndexMode - def initialize qobj + def initialize qobj, qopts = nil @qobj = qobj - super [], { :qobj => @qobj } + @qopts = qopts + + super [], { :qobj => @qobj }.merge(@qopts) end register_keymap do |k| @@ -13,7 +15,7 @@ class SearchResultsMode < ThreadIndexMode def refine_search query = BufferManager.ask :search, "query: ", (@qobj.to_s + " ") return unless query && query !~ /^\s*$/ - SearchResultsMode.spawn_from_query query + SearchResultsMode.spawn_from_query query, @qopts end ## a proper is_relevant? method requires some way of asking ferret @@ -24,9 +26,10 @@ class SearchResultsMode < ThreadIndexMode def self.spawn_from_query text begin - qobj = Index.parse_user_query_string(text) or return + qobj, extraopts = Index.parse_user_query_string(text) + return unless qobj short_text = text.length < 20 ? text : text[0 ... 20] + "..." - mode = SearchResultsMode.new qobj + mode = SearchResultsMode.new qobj, extraopts BufferManager.spawn "search: \"#{short_text}\"", mode mode.load_threads :num => mode.buffer.content_height rescue Ferret::QueryParser::QueryParseException => e -- 2.45.2