]> git.cworth.org Git - sup/blob - lib/sup/modes/label-list-mode.rb
skip system buffers when rolling
[sup] / lib / sup / modes / label-list-mode.rb
1 module Redwood
2
3 class LabelListMode < LineCursorMode
4   register_keymap do |k|
5     k.add :select_label, "Search by label", :enter
6     k.add :reload, "Discard label list and reload", '@'
7     k.add :jump_to_next_new, "Jump to next new thread", :tab
8     k.add :toggle_show_unread_only, "Toggle between showing all labels and those with unread mail", 'u'
9   end
10
11   def initialize
12     @labels = []
13     @text = []
14     @unread_only = false
15     super
16     regen_text
17   end
18
19   def lines; @text.length end
20   def [] i; @text[i] end
21
22   def jump_to_next_new
23     n = ((curpos + 1) ... lines).find { |i| @labels[i][1] > 0 } || (0 ... curpos).find { |i| @labels[i][1] > 0 }
24     if n
25       ## jump there if necessary
26       jump_to_line n unless n >= topline && n < botline
27       set_cursor_pos n
28     else
29       BufferManager.flash "No labels messages with unread messages."
30     end
31   end
32
33   def focus
34     reload # make sure unread message counts are up-to-date
35   end
36
37 protected
38
39   def toggle_show_unread_only
40     @unread_only = !@unread_only
41     reload
42   end
43
44   def reload
45     regen_text
46     buffer.mark_dirty if buffer
47   end
48
49   def regen_text
50     @text = []
51     labels = LabelManager.all_labels
52
53     counts = labels.map do |label|
54       string = LabelManager.string_for label
55       total = Index.num_results_for :label => label
56       unread = (label == :unread)? total : Index.num_results_for(:labels => [label, :unread])
57       [label, string, total, unread]
58     end.sort_by { |l, s, t, u| s.downcase }
59
60     width = counts.max_of { |l, s, t, u| s.length }
61
62     if @unread_only
63       counts.delete_if { | l, s, t, u | u == 0 }
64     end
65
66     @labels = []
67     counts.map do |label, string, total, unread|
68       ## if we've done a search and there are no messages for this label, we can delete it from the
69       ## list. BUT if it's a brand-new label, the user may not have sync'ed it to the index yet, so
70       ## don't delete it in this case.
71       ##
72       ## this is all a hack. what should happen is:
73       ##   TODO make the labelmanager responsible for label counts
74       ## and then it can listen to labeled and unlabeled events, etc.
75       if total == 0 && !LabelManager::RESERVED_LABELS.include?(label) && !LabelManager.new_label?(label)
76         Redwood::log "no hits for label #{label}, deleting"
77         LabelManager.delete label
78         next
79       end
80
81       @text << [[(unread == 0 ? :labellist_old_color : :labellist_new_color),
82           sprintf("%#{width + 1}s %5d %s, %5d unread", string, total, total == 1 ? " message" : "messages", unread)]]
83       @labels << [label, unread]
84       yield i if block_given?
85     end.compact
86
87     BufferManager.flash "No labels with unread messages!" if counts.empty? && @unread_only
88   end
89
90   def select_label
91     label, num_unread = @labels[curpos]
92     return unless label
93     LabelSearchResultsMode.spawn_nicely label
94   end
95 end
96
97 end