## time.
 Redwood::HookManager.new Redwood::HOOK_DIR
 
+## everything we need to get logging working
+require "sup/buffer"
+require "sup/keymap"
+require "sup/mode"
+require "sup/modes/scroll-mode"
+require "sup/modes/text-mode"
+require "sup/modes/log-mode"
+require "sup/logger"
+module Redwood
+  def log s; Logger.log s; end
+  module_function :log
+end
+
+## now everything else (which can feel free to call Redwood::log at load time)
 require "sup/update"
 require "sup/suicide"
 require "sup/message-chunks"
 require "sup/thread"
 require "sup/index"
 require "sup/textfield"
-require "sup/buffer"
-require "sup/keymap"
-require "sup/mode"
 require "sup/colormap"
 require "sup/label"
 require "sup/contact"
 require "sup/draft"
 require "sup/poll"
 require "sup/crypto"
-require "sup/modes/scroll-mode"
-require "sup/modes/text-mode"
 require "sup/modes/line-cursor-mode"
 require "sup/modes/help-mode"
 require "sup/modes/edit-message-mode"
 require "sup/modes/person-search-results-mode"
 require "sup/modes/inbox-mode"
 require "sup/modes/buffer-list-mode"
-require "sup/modes/log-mode"
 require "sup/modes/poll-mode"
 require "sup/modes/file-browser-mode"
 require "sup/modes/completion-mode"
-require "sup/logger"
 require "sup/sent"
 
-module Redwood
-  def log s; Logger.log s; end
-  module_function :log
-end
-
 $:.each do |base|
   d = File.join base, "sup/share/modes/"
   Redwood::Mode.load_all_modes d if File.directory? d
 
 ## the index structure for redwood. interacts with ferret.
 
-require 'thread'
 require 'fileutils'
 require 'ferret'
+begin
+  require 'chronic'
+  $have_chronic = true
+rescue LoadError => e
+  Redwood::log "'chronic' library not found. run 'gem install chronic' to install."
+  $have_chronic = false
+end
 
 module Redwood
 
 
 protected
 
+  ## do any specialized parsing
+  ## returns nil and flashes error message if parsing failed
   def parse_user_query_string str
-    str2 = str.gsub(/(to|from):(\S+)/) do
+    result = str.gsub(/\b(to|from):(\S+)\b/) do
       field, name = $1, $2
       if(p = ContactManager.contact_for(name))
         [field, p.email]
       end.join(":")
     end
     
-    Redwood::log "translated #{str} to #{str2}" unless str2 == str
-    @qparser.parse str2
+    if $have_chronic
+      chronic_failure = false
+      result = result.gsub(/\b(before|after):(\((.+?)\)\B|(\S+)\b)/) do
+        break if chronic_failure
+        field, datestr = $1, ($3 || $4)
+        realdate = Chronic.parse datestr
+        if realdate
+          Redwood::log "chronic: translated #{field}:#{datestr} to #{realdate}"
+          if field == "after"
+            "date:(>= #{sprintf "%012d", realdate.to_i})"
+          else
+            "date:(<= #{sprintf "%012d", realdate.to_i})"
+          end
+        else
+          BufferManager.flash "Don't understand date #{datestr.inspect}!"
+          chronic_failure = true
+        end
+      end
+      result = nil if chronic_failure
+    end
+    
+    Redwood::log "translated #{str.inspect} to #{result}" unless result == str
+    @qparser.parse result if result
   end
 
   def build_query opts
 
 
   def self.spawn_from_query text
     begin
-      qobj = Index.parse_user_query_string text
+      qobj = Index.parse_user_query_string(text) or return
       short_text = text.length < 20 ? text : text[0 ... 20] + "..."
       mode = SearchResultsMode.new qobj
       BufferManager.spawn "search: \"#{short_text}\"", mode