bin/sup in sup-0.2 vs bin/sup in sup-0.3

- old
+ new

@@ -5,10 +5,11 @@ require 'curses' require 'fileutils' require 'trollop' require "sup" +$exceptions = [] $opts = Trollop::options do version "sup v#{Redwood::VERSION}" banner <<EOS Sup is a curses-based email client. @@ -17,10 +18,11 @@ Options are: EOS opt :list_hooks, "List all hooks and descriptions thereof, and quit." opt :no_threads, "Turn of threading. Helps with debugging. (Necessarily disables background polling for new messages.)" + opt :search, "Search for threads ", :type => String end if $opts[:list_hooks] Redwood::HookManager.print_hooks exit @@ -37,14 +39,15 @@ # k.add :roll_buffers_backwards, "Switch to previous buffer", 'B' k.add :kill_buffer, "Kill the current buffer", 'x' k.add :list_buffers, "List all buffers", 'B' k.add :list_contacts, "List contacts", 'C' k.add :redraw, "Redraw screen", :ctrl_l - k.add :search, "Search messages", '/' + k.add :search, "Search all messages", '\\', 'F' k.add :list_labels, "List labels", 'L' k.add :poll, "Poll for new messages", 'P' - k.add :compose, "Compose new message", 'm' + k.add :compose, "Compose new message", 'm', 'c' + k.add :nothing, "Do nothing", :ctrl_g k.add :recall_draft, "Edit most recent draft message", 'R' end def start_cursing Ncurses.initscr @@ -90,30 +93,30 @@ exit end end begin - extend CanSpawnComposeMode Redwood::start Index.load if(s = Index.source_for DraftManager.source_name) DraftManager.source = s else + Redwood::log "no draft source, auto-adding..." Index.add_source DraftManager.new_source end if(s = Index.source_for SentManager.source_name) SentManager.source = s else + Redwood::log "no sent mail source, auto-adding..." Index.add_source SentManager.new_source end log "starting curses" start_cursing - log "initializing colormap" Colormap.new do |c| c.add :status_color, Ncurses::COLOR_WHITE, Ncurses::COLOR_BLUE, Ncurses::A_BOLD c.add :index_old_color, Ncurses::COLOR_WHITE, Ncurses::COLOR_BLACK c.add :index_new_color, Ncurses::COLOR_WHITE, Ncurses::COLOR_BLACK, Ncurses::A_BOLD @@ -152,13 +155,13 @@ c.add :completion_character_color, Ncurses::COLOR_WHITE, Ncurses::COLOR_BLACK, Ncurses::A_BOLD c.add :reply_mode_selected_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK, Ncurses::A_BOLD c.add :reply_mode_unselected_color, Ncurses::COLOR_CYAN, Ncurses::COLOR_BLACK c.add :reply_mode_label_color, Ncurses::COLOR_CYAN, Ncurses::COLOR_BLACK + c.add :search_highlight_color, Ncurses::COLOR_BLACK, Ncurses::COLOR_YELLOW, Ncurses::A_BOLD, :highlight => :search_highlight_color end - log "initializing buffer manager" bm = BufferManager.new log "initializing mail index buffer" imode = InboxMode.new ibuf = bm.spawn "Inbox", imode @@ -166,36 +169,34 @@ log "ready for interaction!" Logger.make_buf bm.draw_screen - begin - Index.usual_sources.each { |s| s.check } - rescue SourceError - # do nothing! we'll report it at the next step - end - Redwood::report_broken_sources - Index.usual_sources.each do |s| - reporting_thread do + next unless s.respond_to? :connect + reporting_thread("call #connect on #{s}") do begin s.connect rescue SourceError => e Redwood::log "fatal error loading from #{s}: #{e.message}" end - end if s.respond_to? :connect + end end + + imode.load_threads :num => ibuf.content_height, :when_done => lambda { reporting_thread("poll after loading inbox") { sleep 1; PollManager.poll } unless $opts[:no_threads] } - imode.load_threads :num => ibuf.content_height, :when_done => lambda { reporting_thread { sleep 1; PollManager.poll } unless $opts[:no_threads] } - unless $opts[:no_threads] PollManager.start SuicideManager.start Index.start_lock_update_thread end - until $exception || SuicideManager.die? + if $opts[:search] + SearchResultsMode.spawn_from_query $opts[:search] + end + + until $exceptions.nonempty? || SuicideManager.die? c = Ncurses.nonblocking_getch next unless c bm.erase_flash unless bm.handle_input(c) @@ -213,52 +214,30 @@ when :kill_buffer bm.kill_buffer_safely bm.focus_buf when :list_buffers bm.spawn_unless_exists("Buffer List") { BufferListMode.new } when :list_contacts - b = bm.spawn_unless_exists("Contact List") { ContactListMode.new } - b.mode.load_in_background + b, new = bm.spawn_unless_exists("Contact List") { ContactListMode.new } + b.mode.load_in_background if new when :search - text = bm.ask :search, "query: " - next unless text && text !~ /^\s*$/ - - begin - qobj = Index.parse_user_query_string text - short_text = text.length < 20 ? text : text[0 ... 20] + "..." - log "built query from #{text.inspect}: #{qobj}" - mode = SearchResultsMode.new qobj - bm.spawn "search: \"#{short_text}\"", mode - mode.load_threads :num => mode.buffer.content_height - rescue Ferret::QueryParser::QueryParseException => e - bm.flash "Couldn't parse query." - end + query = BufferManager.ask :search, "search all messages: " + next unless query && query !~ /^\s*$/ + SearchResultsMode.spawn_from_query query 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 } + reporting_thread("user-invoked poll") { PollManager.poll } when :recall_draft case Index.num_results_for :label => :draft when 0 bm.flash "No draft messages." when 1 @@ -266,27 +245,25 @@ Index.each_id_by_date(:label => :draft) { |mid, builder| m = builder.call } r = ResumeMode.new(m) BufferManager.spawn "Edit message", r r.edit_message else - b = BufferManager.spawn_unless_exists("All drafts") do - mode = LabelSearchResultsMode.new [:draft] - end - b.mode.load_threads :num => b.content_height + b, new = BufferManager.spawn_unless_exists("All drafts") { LabelSearchResultsMode.new [:draft] } + b.mode.load_threads :num => b.content_height if new end when :nothing when :redraw bm.completely_redraw_screen else - bm.flash "Unknown key press '#{c.to_character}' for #{bm.focus_buf.mode.name}." + bm.flash "Unknown keypress '#{c.to_character}' for #{bm.focus_buf.mode.name}." end end bm.draw_screen end rescue Exception => e - $exception ||= e + $exceptions << [e, "main"] ensure unless $opts[:no_threads] PollManager.stop if PollManager.instantiated? SuicideManager.stop if PollManager.instantiated? Index.stop_lock_update_thread @@ -298,36 +275,41 @@ if SuicideManager.instantiated? && SuicideManager.die? Redwood::log "I've been ordered to commit sepuku. I obey!" end - case $exception - when nil + if $exceptions.empty? Redwood::log "no fatal errors. good job, william." Index.save else Redwood::log "oh crap, an exception" end Index.unlock end -if $exception +unless $exceptions.empty? + File.open("sup-exception-log.txt", "w") do |f| + $exceptions.each do |e, name| + f.puts "--- #{e.class.name} from thread: #{name}" + f.puts e.message, e.backtrace + end + end $stderr.puts <<EOS ---------------------------------------------------------------- -I'm very sorry, but it seems that an error occurred in Sup. -Please accept my sincere apologies. If you don't mind, please -send the backtrace below and a brief report of the circumstances -to sup-talk at rubyforge dot orgs so that I might address this -problem. Thank you! +I'm very sorry. It seems that an error occurred in Sup. Please +accept my sincere apologies. If you don't mind, please send the +contents of sup-exception-log.txt and a brief report of the +circumstances to sup-talk at rubyforge dot orgs so that I might +address this problem. Thank you! Sincerely, William ---------------------------------------------------------------- - -The problem was: '#{$exception.message}' (error type #{$exception.class.name}) -A backtrace follows: EOS - raise $exception + $exceptions.each do |e, name| + puts "--- #{e.class.name} from thread: #{name}" + puts e.message, e.backtrace + end end end