lib/sup/modes/thread-index-mode.rb in sup-0.0.8 vs lib/sup/modes/thread-index-mode.rb in sup-0.1

- old
+ new

@@ -1,9 +1,9 @@ -require 'thread' module Redwood -## subclasses should implement load_threads +## subclasses should implement: +## - is_relevant? class ThreadIndexMode < LineCursorMode DATE_WIDTH = Time::TO_NICE_S_MAX_LEN FROM_WIDTH = 15 LOAD_MORE_THREAD_NUM = 20 @@ -25,25 +25,34 @@ k.add :forward, "Forward a thread", 'f' k.add :toggle_tagged, "Tag/untag current line", 't' k.add :apply_to_tagged, "Apply next command to all tagged threads", ';' end - def initialize required_labels=[], hidden_labels=[] + def initialize hidden_labels=[], load_thread_opts={} super() + @mutex = Mutex.new @load_thread = nil - @required_labels = required_labels - @hidden_labels = hidden_labels + LabelManager::HIDDEN_LABELS + @load_thread_opts = load_thread_opts + @hidden_labels = hidden_labels + LabelManager::HIDDEN_RESERVED_LABELS @date_width = DATE_WIDTH @from_width = FROM_WIDTH @size_width = nil - + @tags = Tagger.new self initialize_threads update UpdateManager.register self + + @last_load_more_size = nil + to_load_more do |size| + next if @last_load_more_size == 0 + load_threads :num => 1, :background => false + load_threads :num => (size - 1), + :when_done => lambda { |num| @last_load_more_size = num } + end end def lines; @text.length; end def [] i; @text[i]; end def contains_thread? t; !@lines[t].nil?; end @@ -115,12 +124,12 @@ end end def update ## let's see you do THIS in python - @threads = @ts.threads.select { |t| !@hidden_threads[t] && !t.has_label?(:killed) }.sort_by { |t| t.date }.reverse - @size_width = (@threads.map { |t| t.size }.max || 0).num_digits + @threads = @ts.threads.select { |t| !@hidden_threads[t] }.sort_by { |t| t.date }.reverse + @size_width = (@threads.max_of { |t| t.size } || 0).num_digits regen_text end def edit_message return unless(t = @threads[curpos]) @@ -190,13 +199,14 @@ @tags.drop_all_tags regen_text end def jump_to_next_new - n = ((curpos + 1) ... lines).find { |i| @threads[i].has_label? :unread } - n = (0 ... curpos).find { |i| @threads[i].has_label? :unread } unless n + n = ((curpos + 1) ... lines).find { |i| @threads[i].has_label? :unread } || (0 ... curpos).find { |i| @threads[i].has_label? :unread } if n + ## jump there if necessary + jump_to_line n unless n >= topline && n < botline set_cursor_pos n else BufferManager.flash "No new messages" end end @@ -239,16 +249,16 @@ end regen_text end def save - threads = @threads + @hidden_threads.keys + dirty_threads = (@threads + @hidden_threads.keys).select { |t| t.dirty? } + return if dirty_threads.empty? BufferManager.say("Saving threads...") do |say_id| - threads.each_with_index do |t, i| - next unless t.dirty? - BufferManager.say "Saving thread #{i +1} of #{threads.length}...", say_id + dirty_threads.each_with_index do |t, i| + BufferManager.say "Saving modified thread #{i + 1} of #{dirty_threads.length}...", say_id t.save Index end end end @@ -328,12 +338,12 @@ BufferManager.spawn "Forward of #{m.subj}", mode mode.edit end def load_n_threads_background n=LOAD_MORE_THREAD_NUM, opts={} - return if @load_thread - @load_thread = Redwood::reporting_thread do + return if @load_thread # todo: wrap in mutex + @load_thread = Redwood::reporting_thread do num = load_n_threads n, opts opts[:when_done].call(num) if opts[:when_done] @load_thread = nil end end @@ -356,19 +366,39 @@ BufferManager.clear @mbid @mbid = nil BufferManager.draw_screen @ts.size - orig_size end + synchronized :load_n_threads def status if (l = lines) == 0 - "" + "line 0 of 0" else "line #{curpos + 1} of #{l} #{dirty? ? '*modified*' : ''}" end end + def load_threads opts={} + n = opts[:num] || ThreadIndexMode::LOAD_MORE_THREAD_NUM + + myopts = @load_thread_opts.merge({ :when_done => (lambda do |num| + opts[:when_done].call(num) if opts[:when_done] + if num > 0 + BufferManager.flash "Found #{num} threads" + else + BufferManager.flash "No matches" + end + end)}) + + if opts[:background] || opts[:background].nil? + load_n_threads_background n, myopts + else + load_n_threads n, myopts + end + end + protected def cursor_thread; @threads[curpos]; end def drop_all_threads @@ -404,20 +434,24 @@ @lines = @threads.map_with_index { |t, i| [t, i] }.to_h buffer.mark_dirty if buffer end def author_text_for_thread t - if t.authors.size == 1 - t.authors.first.mediumname - else - t.authors.map { |p| AccountManager.is_account?(p) ? "me" : p.shortname }.join ", " - end + t.authors.map do |p| + if AccountManager.is_account?(p) + "me" + elsif t.authors.size == 1 + p.mediumname + else + p.shortname + end + end.uniq.join "," end def text_for_thread t - date = t.date.to_nice_s(Time.now) - from = author_text_for_thread(t) + date = t.date.to_nice_s + from = author_text_for_thread t if from.length > @from_width from = from[0 ... (@from_width - 1)] from += "." unless from[-1] == ?\s end @@ -425,16 +459,24 @@ starred = t.has_label?(:starred) dp = t.direct_participants.any? { |p| AccountManager.is_account? p } p = dp || t.participants.any? { |p| AccountManager.is_account? p } - base_color = (new ? :index_new_color : :index_old_color) + base_color = + if new + :index_new_color + elsif starred + :index_starred_color + else + :index_old_color + end + [ [:tagged_color, @tags.tagged?(t) ? ">" : " "], - [:none, sprintf("%#{@date_width}s ", date)], + [:none, sprintf("%#{@date_width}s", date)], + (starred ? [:starred_color, "*"] : [:none, " "]), [base_color, sprintf("%-#{@from_width}s", from)], - [:starred_color, starred ? "*" : " "], [:none, t.size == 1 ? " " * (@size_width + 2) : sprintf("(%#{@size_width}d)", t.size)], [:to_me_color, dp ? " >" : (p ? ' +' : " ")], [base_color, t.subj + (t.subj.empty? ? "" : " ")], ] + (t.labels - @hidden_labels).map { |label| [:label_color, "+#{label} "] } + @@ -445,10 +487,10 @@ def dirty?; (@hidden_threads.keys + @threads).any? { |t| t.dirty? }; end private def initialize_threads - @ts = ThreadSet.new Index.instance + @ts = ThreadSet.new Index.instance, $config[:thread_by_subject] @ts_mutex = Mutex.new @hidden_threads = {} end end