X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=lib%2Fsup%2Fmodes%2Fthread-view-mode.rb;h=8842e59abf479be4de6ceef388770a23ad56563a;hb=7039653b8d8989977e8c6bafc8e17e7b6e1922c2;hp=fde979ea9b70e2c55af6476ac7f62af2ecd3050c;hpb=a6a34697a08d2c177d4bdc7178f77c6ababbed3d;p=sup diff --git a/lib/sup/modes/thread-view-mode.rb b/lib/sup/modes/thread-view-mode.rb index fde979e..8842e59 100644 --- a/lib/sup/modes/thread-view-mode.rb +++ b/lib/sup/modes/thread-view-mode.rb @@ -30,6 +30,7 @@ EOS k.add :activate_chunk, "Expand/collapse or activate item", :enter k.add :expand_all_messages, "Expand/collapse all messages", 'E' k.add :edit_draft, "Edit draft", 'e' + k.add :send_draft, "Send draft", 'y' k.add :edit_labels, "Edit or add labels for a thread", 'l' k.add :expand_all_quotes, "Expand/collapse all quotes in a message", 'o' k.add :jump_to_next_open, "Jump to next open message", 'n' @@ -40,6 +41,7 @@ EOS # k.add :collapse_non_new_messages, "Collapse all but unread messages", 'N' k.add :reply, "Reply to a message", 'r' k.add :forward, "Forward a message or attachment", 'f' + k.add :bounce, "Bounce message to other recipient(s)", '!' k.add :alias, "Edit alias/nickname for a person", 'i' k.add :edit_as_new, "Edit message as new", 'D' k.add :save_to_disk, "Save message/attachment to disk", 's' @@ -63,6 +65,14 @@ EOS kk.add :unread_and_next, "Mark this thread as unread, kill buffer, and view next", 'N' kk.add :do_nothing_and_next, "Kill buffer, and view next", 'n' end + + k.add_multi "(a)rchive/(d)elete/mark as (s)pam/mark as u(N)read/do (n)othing:", ']' do |kk| + kk.add :archive_and_prev, "Archive this thread, kill buffer, and view previous", 'a' + kk.add :delete_and_prev, "Delete this thread, kill buffer, and view previous", 'd' + kk.add :spam_and_prev, "Mark this thread as spam, kill buffer, and view previous", 's' + kk.add :unread_and_prev, "Mark this thread as unread, kill buffer, and view previous", 'N' + kk.add :do_nothing_and_prev, "Kill buffer, and view previous", 'n' + end end ## there are a couple important instance variables we hold to format @@ -140,7 +150,7 @@ EOS def subscribe_to_list m = @message_lines[curpos] or return if m.list_subscribe && m.list_subscribe =~ // - ComposeMode.spawn_nicely :from => AccountManager.account_for(m.recipient_email), :to => [PersonManager.person_for($1)], :subj => $3 + ComposeMode.spawn_nicely :from => AccountManager.account_for(m.recipient_email), :to => [Person.from_address($1)], :subj => $3 else BufferManager.flash "Can't find List-Subscribe header for this message." end @@ -149,7 +159,7 @@ EOS def unsubscribe_from_list m = @message_lines[curpos] or return if m.list_unsubscribe && m.list_unsubscribe =~ // - ComposeMode.spawn_nicely :from => AccountManager.account_for(m.recipient_email), :to => [PersonManager.person_for($1)], :subj => $3 + ComposeMode.spawn_nicely :from => AccountManager.account_for(m.recipient_email), :to => [Person.from_address($1)], :subj => $3 else BufferManager.flash "Can't find List-Unsubscribe header for this message." end @@ -163,6 +173,38 @@ EOS end end + def bounce + m = @message_lines[curpos] or return + to = BufferManager.ask_for_contacts(:people, "Bounce To: ") or return + + defcmd = AccountManager.default_account.sendmail.sub(/\s(\-(ti|it|t))\b/) do |match| + case "$1" + when '-t' then '' + else ' -i' + end + end + + cmd = case $config[:bounce_sendmail] + when nil, /^$/ then defcmd + else $config[:bounce_sendmail] + end + ' ' + to.map { |t| t.email }.join(' ') + + bt = to.size > 1 ? "#{to.size} recipients" : to.to_s + + if BufferManager.ask_yes_or_no "Really bounce to #{bt}?" + Redwood::log "Bounce Command: #{cmd}" + begin + IO.popen(cmd, 'w') do |sm| + sm.puts m.raw_message + end + raise SendmailCommandFailed, "Couldn't execute #{cmd}" unless $? == 0 + rescue SystemCallError, SendmailCommandFailed => e + Redwood::log "Problem sending mail: #{e.message}" + BufferManager.flash "Problem sending mail: #{e.message}" + end + end + end + include CanAliasContacts def alias p = @person_lines[curpos] or return @@ -180,7 +222,7 @@ EOS def compose p = @person_lines[curpos] if p - ComposeMode.spawn_nicely :to => [p] + ComposeMode.spawn_nicely :to_default => p else ComposeMode.spawn_nicely end @@ -242,7 +284,7 @@ EOS def edit_as_new m = @message_lines[curpos] or return - mode = ComposeMode.new(:body => m.quotable_body_lines, :to => m.to, :cc => m.cc, :subj => m.subj, :bcc => m.bcc) + mode = ComposeMode.new(:body => m.quotable_body_lines, :to => m.to, :cc => m.cc, :subj => m.subj, :bcc => m.bcc, :refs => m.refs, :replytos => m.replytos) BufferManager.spawn "edit as new", mode mode.edit_message end @@ -251,7 +293,8 @@ EOS chunk = @chunk_lines[curpos] or return case chunk when Chunk::Attachment - fn = BufferManager.ask_for_filename :filename, "Save attachment to file: ", chunk.filename + default_dir = File.join(($config[:default_attachment_save_dir] || "."), chunk.filename) + fn = BufferManager.ask_for_filename :filename, "Save attachment to file: ", default_dir save_to_file(fn) { |f| f.print chunk.raw_content } if fn else m = @message_lines[curpos] @@ -275,6 +318,18 @@ EOS end end + def send_draft + m = @message_lines[curpos] or return + if m.is_draft? + mode = ResumeMode.new m + BufferManager.spawn "Send message", mode + BufferManager.kill_buffer self.buffer + mode.send_message + else + BufferManager.flash "Not a draft message!" + end + end + def jump_to_first_open loose_alignment=false m = @message_lines[0] or return if @layout[m].state != :closed @@ -383,6 +438,12 @@ EOS def unread_and_next; unread_and_then :next end def do_nothing_and_next; do_nothing_and_then :next end + def archive_and_prev; archive_and_then :prev end + def spam_and_prev; spam_and_then :prev end + def delete_and_prev; delete_and_then :prev end + def unread_and_prev; unread_and_then :prev end + def do_nothing_and_prev; do_nothing_and_then :prev end + def archive_and_then op dispatch op do @thread.remove_label :inbox @@ -419,15 +480,18 @@ EOS return if @dying @dying = true + l = lambda do + yield if block_given? + BufferManager.kill_buffer_safely buffer + end + case op when :next - @index_mode.launch_next_thread_after(@thread) do - yield if block_given? - BufferManager.kill_buffer_safely buffer - end + @index_mode.launch_next_thread_after @thread, &l + when :prev + @index_mode.launch_prev_thread_before @thread, &l when :kill - yield if block_given? - BufferManager.kill_buffer_safely buffer + l.call else raise ArgumentError, "unknown thread dispatch operation #{op.inspect}" end @@ -509,7 +573,7 @@ private (0 ... text.length).each do |i| @chunk_lines[@text.length + i] = m @message_lines[@text.length + i] = m - lw = text[i].flatten.select { |x| x.is_a? String }.map { |x| x.length }.sum + lw = text[i].flatten.select { |x| x.is_a? String }.map { |x| x.display_length }.sum end @text += text @@ -530,7 +594,7 @@ private (0 ... text.length).each do |i| @chunk_lines[@text.length + i] = c @message_lines[@text.length + i] = m - lw = text[i].flatten.select { |x| x.is_a? String }.map { |x| x.length }.sum - (depth * INDENT_SPACES) + lw = text[i].flatten.select { |x| x.is_a? String }.map { |x| x.display_length }.sum - (depth * INDENT_SPACES) l.width = lw if lw > l.width end @text += text @@ -545,29 +609,29 @@ private open_widget = [color, (state == :closed ? "+ " : "- ")] new_widget = [color, (m.has_label?(:unread) ? "N" : " ")] - starred_widget = - if m.has_label?(:starred) - [star_color, "* "] + starred_widget = if m.has_label?(:starred) + [star_color, "*"] else - [color, " "] + [color, " "] end + attach_widget = [color, (m.has_label?(:attachment) ? "@" : " ")] case state when :open @person_lines[start] = m.from - [[prefix_widget, open_widget, new_widget, starred_widget, + [[prefix_widget, open_widget, new_widget, attach_widget, starred_widget, [color, "#{m.from ? m.from.mediumname : '?'} to #{m.recipients.map { |l| l.shortname }.join(', ')} #{m.date.to_nice_s} (#{m.date.to_nice_distance_s})"]]] when :closed @person_lines[start] = m.from - [[prefix_widget, open_widget, new_widget, starred_widget, + [[prefix_widget, open_widget, new_widget, attach_widget, starred_widget, [color, "#{m.from ? m.from.mediumname : '?'}, #{m.date.to_nice_s} (#{m.date.to_nice_distance_s}) #{m.snippet}"]]] when :detailed @person_lines[start] = m.from - from_line = [[prefix_widget, open_widget, new_widget, starred_widget, + from_line = [[prefix_widget, open_widget, new_widget, attach_widget, starred_widget, [color, "From: #{m.from ? format_person(m.from) : '?'}"]]] addressee_lines = [] @@ -604,7 +668,7 @@ private def format_person_list prefix, people ptext = people.map { |p| format_person p } - pad = " " * prefix.length + pad = " " * prefix.display_length [prefix + ptext.first + (ptext.length > 1 ? "," : "")] + ptext[1 .. -1].map_with_index do |e, i| pad + e + (i == ptext.length - 1 ? "" : ",") @@ -625,7 +689,7 @@ private [[[:missing_message_color, "#{prefix}"]]] when Message message_patina_lines(chunk, state, start, parent, prefix, color, star_color) + - (chunk.is_draft? ? [[[:draft_notification_color, prefix + " >>> This message is a draft. To edit, hit 'e'. <<<"]]] : []) + (chunk.is_draft? ? [[[:draft_notification_color, prefix + " >>> This message is a draft. Hit 'e' to edit, 'y' to send. <<<"]]] : []) else raise "Bad chunk: #{chunk.inspect}" unless chunk.respond_to?(:inlineable?) ## debugging