end
 
 begin
-  extend CanSpawnComposeMode
   Redwood::start
   Index.load
 
       when :list_labels
         labels = LabelManager.listable_labels.map { |l| LabelManager.string_for l }
         user_label = bm.ask_with_completions :label, "Show threads with label (enter for listing): ", labels
-        user_label =
-          case user_label
-          when nil, /^\s*$/
-            bm.spawn_modal("Label list", LabelListMode.new) if user_label && user_label.empty?
+        unless user_label.nil?
+          if user_label.empty?
+            bm.spawn_unless_exists("Label list") { LabelListMode.new } if user_label && user_label.empty?
           else
-            LabelManager.label_for user_label
+            LabelSearchResultsMode.spawn_nicely user_label
           end
-        
-        case user_label
-        when nil
-        when :inbox
-          BufferManager.raise_to_front InboxMode.instance.buffer
-        else
-          b = BufferManager.spawn_unless_exists("All threads with label '#{user_label}'") do
-            mode = LabelSearchResultsMode.new([user_label])
-          end
-          b.mode.load_threads :num => b.content_height
         end
-
       when :compose
-        spawn_compose_mode
+        ComposeMode.spawn_nicely
       when :poll
         reporting_thread { PollManager.poll }
       when :recall_draft
 
 module Redwood
 
-module CanSpawnComposeMode
-  def spawn_compose_mode opts={}
-    to = opts[:to] || BufferManager.ask_for_contacts(:people, "To: ") or return
-    cc = opts[:cc] || BufferManager.ask_for_contacts(:people, "Cc: ") or return if $config[:ask_for_cc]
-    bcc = opts[:bcc] || BufferManager.ask_for_contacts(:people, "Bcc: ") or return if $config[:ask_for_bcc]
-    subj = opts[:subj] || BufferManager.ask(:subject, "Subject: ") or return if $config[:ask_for_subject]
-    
-    mode = ComposeMode.new :from => opts[:from], :to => to, :cc => cc, :bcc => bcc, :subj => subj
-    BufferManager.spawn "New Message", mode
-    mode.edit_message
-  end
-end
-
 class ComposeMode < EditMessageMode
   def initialize opts={}
     header = {}
     BufferManager.kill_buffer self.buffer unless edited
     edited
   end
+
+  def self.spawn_nicely opts={}
+    to = opts[:to] || BufferManager.ask_for_contacts(:people, "To: ") or return
+    cc = opts[:cc] || BufferManager.ask_for_contacts(:people, "Cc: ") or return if $config[:ask_for_cc]
+    bcc = opts[:bcc] || BufferManager.ask_for_contacts(:people, "Bcc: ") or return if $config[:ask_for_bcc]
+    subj = opts[:subj] || BufferManager.ask(:subject, "Subject: ") or return if $config[:ask_for_subject]
+    
+    mode = ComposeMode.new :from => opts[:from], :to => to, :cc => cc, :bcc => bcc, :subj => subj
+    BufferManager.spawn "New Message", mode
+    mode.edit_message
+  end
 end
 
 end
 
 module Redwood
 
-module CanSpawnForwardMode
-  def spawn_forward_mode m, opts={}
-    to = opts[:to] || BufferManager.ask_for_contacts(:people, "To: ") or return
-    cc = opts[:cc] || BufferManager.ask_for_contacts(:people, "Cc: ") or return if $config[:ask_for_cc]
-    bcc = opts[:bcc] || BufferManager.ask_for_contacts(:people, "Bcc: ") or return if $config[:ask_for_bcc]
-    
-    mode = ForwardMode.new m, :to => to, :cc => cc, :bcc => bcc
-    BufferManager.spawn "Forwarding #{m.subj}", mode
-    mode.edit_message
-  end
-end
-
 class ForwardMode < EditMessageMode
 
   ## todo: share some of this with reply-mode
     super :header => header, :body => forward_body_lines(m)
   end
 
+  def self.spawn_nicely m, opts={}
+    to = opts[:to] || BufferManager.ask_for_contacts(:people, "To: ") or return
+    cc = opts[:cc] || BufferManager.ask_for_contacts(:people, "Cc: ") or return if $config[:ask_for_cc]
+    bcc = opts[:bcc] || BufferManager.ask_for_contacts(:people, "Bcc: ") or return if $config[:ask_for_bcc]
+    
+    mode = ForwardMode.new m, :to => to, :cc => cc, :bcc => bcc
+    BufferManager.spawn "Forwarding #{m.subj}", mode
+    mode.edit_message
+  end
+
 protected
 
   def forward_body_lines m
 
   end
 
   def is_relevant? m; @labels.all? { |l| m.has_label? l }; end
+
+  def self.spawn_nicely label
+    label = LabelManager.label_for(label) unless label.is_a?(Symbol)
+    case label
+    when nil
+    when :inbox
+      BufferManager.raise_to_front InboxMode.instance.buffer
+    else
+      BufferManager.spawn_unless_exists("All threads with label '#{label}'") do
+        mode = LabelSearchResultsMode.new([label])
+        mode.load_threads :num => b.content_height
+      end
+    end
+  end
 end
 
 end
 
 ## - is_relevant?
 
 class ThreadIndexMode < LineCursorMode
-  include CanSpawnForwardMode
-
   DATE_WIDTH = Time::TO_NICE_S_MAX_LEN
   MIN_FROM_WIDTH = 15
   LOAD_MORE_THREAD_NUM = 20
     m = t.latest_message
     return if m.nil? # probably won't happen
     m.load_from_source!
-    spawn_forward_mode m
+    ForwardMode.spawn_nicely m
   end
 
   def load_n_threads_background n=LOAD_MORE_THREAD_NUM, opts={}
 
 module Redwood
 
 class ThreadViewMode < LineCursorMode
-  include CanSpawnComposeMode
-  include CanSpawnForwardMode
-
   ## this holds all info we need to lay out a message
   class MessageLayout
     attr_accessor :top, :bot, :prev, :next, :depth, :width, :state, :color, :star_color, :orig_new
   def subscribe_to_list
     m = @message_lines[curpos] or return
     if m.list_subscribe && m.list_subscribe =~ /<mailto:(.*?)\?(subject=(.*?))>/
-      spawn_compose_mode :from => AccountManager.account_for(m.recipient_email), :to => [PersonManager.person_for($1)], :subj => $3
+      ComposeMode.spawn_nicely :from => AccountManager.account_for(m.recipient_email), :to => [PersonManager.person_for($1)], :subj => $3
     else
       BufferManager.flash "Can't find List-Subscribe header for this message."
     end