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