sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/

lib/sup/modes/label_list_mode.rb (3894B) - raw

      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   HookManager.register "label-list-filter", <<EOS
     12 Filter the label list, typically to sort.
     13 Variables:
     14   counted: an array of counted labels.
     15 Return value:
     16   An array of counted labels with sort_by output structure.
     17 EOS
     18 
     19   HookManager.register "label-list-format", <<EOS
     20 Create the sprintf format string for label-list-mode.
     21 Variables:
     22   width: the maximum label width
     23   tmax: the maximum total message count
     24   umax: the maximum unread message count
     25 Return value:
     26   A format string for sprintf
     27 EOS
     28 
     29   def initialize
     30     @labels = []
     31     @text = []
     32     @unread_only = false
     33     super
     34     UpdateManager.register self
     35     regen_text
     36   end
     37 
     38   def cleanup
     39     UpdateManager.unregister self
     40     super
     41   end
     42 
     43   def lines; @text.length end
     44   def [] i; @text[i] end
     45 
     46   def jump_to_next_new
     47     n = ((curpos + 1) ... lines).find { |i| @labels[i][1] > 0 } || (0 ... curpos).find { |i| @labels[i][1] > 0 }
     48     if n
     49       ## jump there if necessary
     50       jump_to_line n unless n >= topline && n < botline
     51       set_cursor_pos n
     52     else
     53       BufferManager.flash "No labels messages with unread messages."
     54     end
     55   end
     56 
     57   def focus
     58     reload # make sure unread message counts are up-to-date
     59   end
     60 
     61   def handle_added_update sender, m
     62     reload
     63   end
     64 
     65 protected
     66 
     67   def toggle_show_unread_only
     68     @unread_only = !@unread_only
     69     reload
     70   end
     71 
     72   def reload
     73     regen_text
     74     buffer.mark_dirty if buffer
     75   end
     76 
     77   def regen_text
     78     @text = []
     79     labels = LabelManager.all_labels
     80 
     81     counted = labels.map do |label|
     82       string = LabelManager.string_for label
     83       total = Index.num_results_for :label => label
     84       unread = (label == :unread)? total : Index.num_results_for(:labels => [label, :unread])
     85       [label, string, total, unread]
     86     end
     87 
     88     if HookManager.enabled? "label-list-filter"
     89       counts = HookManager.run "label-list-filter", :counted => counted
     90     else
     91       counts = counted.sort_by { |l, s, t, u| s.downcase }
     92     end
     93 
     94     width = counts.max_of { |l, s, t, u| s.length }
     95     tmax  = counts.max_of { |l, s, t, u| t }
     96     umax  = counts.max_of { |l, s, t, u| u }
     97 
     98     if @unread_only
     99       counts.delete_if { | l, s, t, u | u == 0 }
    100     end
    101 
    102     @labels = []
    103     counts.map do |label, string, total, unread|
    104       ## if we've done a search and there are no messages for this label, we can delete it from the
    105       ## list. BUT if it's a brand-new label, the user may not have sync'ed it to the index yet, so
    106       ## don't delete it in this case.
    107       ##
    108       ## this is all a hack. what should happen is:
    109       ##   TODO make the labelmanager responsible for label counts
    110       ## and then it can listen to labeled and unlabeled events, etc.
    111       if total == 0 && !LabelManager::RESERVED_LABELS.include?(label) && !LabelManager.new_label?(label)
    112         debug "no hits for label #{label}, deleting"
    113         LabelManager.delete label
    114         next
    115       end
    116 
    117       fmt = HookManager.run "label-list-format", :width => width, :tmax => tmax, :umax => umax
    118       if !fmt
    119         fmt = "%#{width + 1}s %5d %s, %5d unread"
    120       end
    121 
    122       @text << [[(unread == 0 ? :labellist_old_color : :labellist_new_color),
    123           sprintf(fmt, string, total, total == 1 ? " message" : "messages", unread)]]
    124       @labels << [label, unread]
    125       yield i if block_given?
    126     end.compact
    127 
    128     BufferManager.flash "No labels with unread messages!" if counts.empty? && @unread_only
    129   end
    130 
    131   def select_label
    132     label, _num_unread = @labels[curpos]
    133     return unless label
    134     LabelSearchResultsMode.spawn_nicely label
    135   end
    136 end
    137 
    138 end