bm.flash "Couldn't parse query."
end
when :list_labels
- b = bm.spawn_unless_exists("Label list") { LabelListMode.new }
- b.mode.load_in_background
+ labels = LabelManager.listable_label_strings
+ user_label = bm.ask_with_completions :label, "Show threads with label (enter for listing): ", labels
+ user_label = bm.spawn_modal("Label list", LabelListMode.new) if user_label && user_label.empty?
+
+ label = LabelManager.label_for user_label if user_label
+ case 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([label])
+ end
+ b.mode.load_threads :num => b.content_height
+ end
+
when :compose
mode = ComposeMode.new
bm.spawn "New Message", mode
end
end
+ def ask_with_completions domain, question, completions, default=nil
+ ask domain, question, default do |s|
+ completions.select { |x| x =~ /^#{s}/i }.map { |x| [x, x] }
+ end
+ end
+
## returns an ARRAY of filenames!
def ask_for_filenames domain, question, default=nil
answer = ask domain, question, default do |s|
next if valid_keys.empty?
[valid_keys.map { |k| keysym_to_string k }.join(", "), help]
end.compact
- llen = lines.map { |a, b| a.length }.max
+ llen = lines.max_of { |a, b| a.length }
lines.map { |a, b| sprintf " %#{llen}s : %s", a, b }.join("\n")
end
end
RESERVED_LABELS = [ :starred, :spam, :draft, :unread, :killed, :sent, :deleted ]
## labels which it nonetheless makes sense to search for by
- LISTABLE_LABELS = [ :starred, :spam, :draft, :sent, :killed, :deleted ]
+ LISTABLE_RESERVED_LABELS = [ :starred, :spam, :draft, :sent, :killed, :deleted ]
## labels that will never be displayed to the user
- HIDDEN_LABELS = [ :starred, :unread ]
+ HIDDEN_RESERVED_LABELS = [ :starred, :unread ]
def initialize fn
@fn = fn
self.class.i_am_the_instance self
end
- def user_labels; @labels.keys; end
+ ## all listable (user-defined and system listable) labels, ordered
+ ## nicely and converted to pretty strings. use #label_for to recover
+ ## the original label.
+ def listable_label_strings
+ LISTABLE_RESERVED_LABELS.sort_by { |l| l.to_s }.map { |l| l.to_s.ucfirst } +
+ @labels.keys.map { |l| l.to_s }.sort
+ end
+
+ ## reverse the label->string mapping, for convenience!
+ def label_for string
+ string.downcase.intern
+ end
+
def << t; @labels[t] = true unless @labels.member?(t) || RESERVED_LABELS.member?(t); end
def delete t; @labels.delete t; end
def save
def regen_text
@bufs = BufferManager.buffers.sort_by { |name, buf| name }
- width = @bufs.map { |name, buf| buf.mode.name.length }.max
+ width = @bufs.max_of { |name, buf| buf.mode.name.length }
@text = @bufs.map do |name, buf|
sprintf "%#{width}s %s", buf.mode.name, name
end
def update_lines
width = buffer.content_width
- max_length = @list.map { |s| s.length }.max
+ max_length = @list.max_of { |s| s.length }
num_per = buffer.content_width / (max_length + INTERSTITIAL.length)
@lines = [@header].compact
@list.each_with_index do |s, i|
[name, real_f]
end
- size_width = @files.map { |name, f| f.human_size.length }.max
- time_width = @files.map { |name, f| f.human_time.length }.max
+ size_width = @files.max_of { |name, f| f.human_size.length }
+ time_width = @files.max_of { |name, f| f.human_time.length }
@text = ["#{cwd}:"] + @files.map do |name, f|
sprintf "%#{time_width}s %#{size_width}s %s", f.human_time, f.human_size, name
class LabelListMode < LineCursorMode
register_keymap do |k|
- k.add :view_results, "View messages with the selected label", :enter
- k.add :reload, "Discard results and reload", 'D'
+ k.add :select_label, "Select label", :enter
+ k.add :reload, "Discard label list and reload", 'D'
end
+ bool_reader :done
+ attr_reader :value
+
def initialize
@labels = []
@text = []
- super()
+ @done = false
+ @value = nil
+ super
+ regen_text
end
- def lines; @text.length; end
- def [] i; @text[i]; end
-
- def load_in_background
- Redwood::reporting_thread do
- BufferManager.say("Counting labels...") { regen_text }
- BufferManager.draw_screen
- end
- end
+ def lines; @text.length end
+ def [] i; @text[i] end
protected
def reload
- buffer.mark_dirty
- BufferManager.draw_screen
- load_in_background
+ regen_text
+ buffer.mark_dirty if buffer
end
def regen_text
@text = []
- @labels = (LabelManager::LISTABLE_LABELS + LabelManager.user_labels).sort_by { |t| t.to_s }
+ @labels = LabelManager.listable_label_strings
- counts = @labels.map do |t|
- total = Index.num_results_for :label => t
- unread = Index.num_results_for :labels => [t, :unread]
- [t, total, unread]
+ counts = @labels.map do |string|
+ label = LabelManager.label_for string
+ total = Index.num_results_for :label => label
+ unread = Index.num_results_for :labels => [label, :unread]
+ [label, string, total, unread]
end
- width = @labels.map { |t| t.to_s.length }.max
+ width = @labels.max_of { |string| string.length }
- counts.map_with_index do |(t, total, unread), i|
- if total == 0 && !LabelManager::LISTABLE_LABELS.include?(t)
- Redwood::log "no hits for label #{t}, deleting"
+ counts.map do |label, string, total, unread|
+ if total == 0 && !LabelManager::RESERVED_LABELS.include?(label)
+ Redwood::log "no hits for label #{label}, deleting"
LabelManager.delete t
- @labels.delete t
next
end
- label =
- case t
- when *LabelManager::LISTABLE_LABELS
- t.to_s.ucfirst
- else
- t.to_s
- end
@text << [[(unread == 0 ? :labellist_old_color : :labellist_new_color),
- sprintf("%#{width + 1}s %5d %s, %5d unread", label, total, total == 1 ? " message" : "messages", unread)]]
+ sprintf("%#{width + 1}s %5d %s, %5d unread", string, total, total == 1 ? " message" : "messages", unread)]]
yield i if block_given?
end.compact
-
- buffer.mark_dirty
end
- def view_results
- label = @labels[curpos]
- if label == :inbox
- BufferManager.raise_to_front InboxMode.instance.buffer
- else
- b = BufferManager.spawn_unless_exists("All threads with label '#{label}'") do
- mode = LabelSearchResultsMode.new [label]
- end
- b.mode.load_threads :num => b.content_height
- end
+ def select_label
+ @value, string = @labels[curpos]
+ @done = true if @value
end
end
@mutex = Mutex.new
@load_thread = nil
@load_thread_opts = load_thread_opts
- @hidden_labels = hidden_labels + LabelManager::HIDDEN_LABELS
+ @hidden_labels = hidden_labels + LabelManager::HIDDEN_RESERVED_LABELS
@date_width = DATE_WIDTH
@from_width = FROM_WIDTH
@size_width = nil
def update
## let's see you do THIS in python
@threads = @ts.threads.select { |t| !@hidden_threads[t] }.sort_by { |t| t.date }.reverse
- @size_width = (@threads.map { |t| t.size }.max || 0).num_digits
+ @size_width = (@threads.max_of { |t| t.size } || 0).num_digits
regen_text
end
@value = nil
return false
when Ncurses::KEY_TAB # completion
- break unless @completion_block
+ return true unless @completion_block
if @completions.empty?
v = get_cur_value
c = @completion_block.call v
end
prefix
end
+
+ def max_of
+ map { |e| yield e }.max
+ end
end
class Array