X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=lib%2Fsup%2Fmodes%2Fthread-view-mode.rb;h=27132de8d9dfe1d623c2cf92d59153aaeaab4837;hb=b8dd68f59f6b9930e3cc1d30aed8ae4059874821;hp=f27f00d81ec28bb7563dac53e2ccfd406ae93e2f;hpb=9478114b592e0ba7917a65804aacd401d21d70c2;p=sup diff --git a/lib/sup/modes/thread-view-mode.rb b/lib/sup/modes/thread-view-mode.rb index f27f00d..27132de 100644 --- a/lib/sup/modes/thread-view-mode.rb +++ b/lib/sup/modes/thread-view-mode.rb @@ -1,4 +1,3 @@ -require 'open3' module Redwood class ThreadViewMode < LineCursorMode @@ -24,9 +23,22 @@ Return value: None. The variable 'headers' should be modified in place. EOS + HookManager.register "bounce-command", < m.from, :to => to) + when nil, /^$/ then defcmd + else hookcmd + 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}?" + debug "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 + warn "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 @@ -200,7 +252,7 @@ EOS new_labels = BufferManager.ask_for_labels :label, "Labels for thread: ", @thread.labels return unless new_labels - @thread.labels = (reserved_labels + new_labels).uniq + @thread.labels = Set.new(reserved_labels) + new_labels new_labels.each { |l| LabelManager << l } update UpdateManager.relay self, :labeled, @thread.first @@ -234,12 +286,16 @@ EOS ## view. def activate_chunk chunk = @chunk_lines[curpos] or return - layout = - if chunk.is_a?(Message) - @layout[chunk] - elsif chunk.expandable? - @chunk_layout[chunk] - end + if chunk.is_a? Chunk::Text + ## if the cursor is over a text region, expand/collapse the + ## entire message + chunk = @message_lines[curpos] + end + layout = if chunk.is_a?(Message) + @layout[chunk] + elsif chunk.expandable? + @chunk_layout[chunk] + end if layout layout.state = (layout.state != :closed ? :closed : :open) #cursor_down if layout.state == :closed # too annoying @@ -247,6 +303,10 @@ EOS elsif chunk.viewable? view chunk end + if chunk.is_a?(Message) + jump_to_message chunk + jump_to_next_open if layout.state == :closed + end end def edit_as_new @@ -297,16 +357,16 @@ EOS end end - def jump_to_first_open loose_alignment=false + def jump_to_first_open m = @message_lines[0] or return if @layout[m].state != :closed - jump_to_message m, loose_alignment + jump_to_message m#, true else - jump_to_next_open loose_alignment + jump_to_next_open #true end end - def jump_to_next_open loose_alignment=false + def jump_to_next_open force_alignment=nil return continue_search_in_buffer if in_search? # hack: allow 'n' to apply to both operations m = (curpos ... @message_lines.length).argfind { |i| @message_lines[i] } return unless m @@ -314,15 +374,15 @@ EOS break if @layout[nextm].state != :closed m = nextm end - jump_to_message nextm, loose_alignment if nextm + jump_to_message nextm, force_alignment if nextm end def align_current_message m = @message_lines[curpos] or return - jump_to_message m + jump_to_message m, true end - def jump_to_prev_open loose_alignment=false + def jump_to_prev_open m = (0 .. curpos).to_a.reverse.argfind { |i| @message_lines[i] } # bah, .to_a return unless m ## jump to the top of the current message if we're in the body; @@ -334,38 +394,33 @@ EOS break if @layout[prevm].state != :closed m = prevm end - jump_to_message prevm, loose_alignment if prevm + jump_to_message prevm if prevm else - jump_to_message m, loose_alignment + jump_to_message m end end - IDEAL_TOP_CONTEXT = 3 # try and give 3 rows of top context - IDEAL_LEFT_CONTEXT = 4 # try and give 4 columns of left context - def jump_to_message m, loose_alignment=false + def jump_to_message m, force_alignment=false l = @layout[m] - left = l.depth * INDENT_SPACES - right = left + l.width - ## jump to the top line - if loose_alignment - jump_to_line [l.top - IDEAL_TOP_CONTEXT, 0].max # give 3 lines of top context - else - jump_to_line l.top - end + ## boundaries of the message + message_left = l.depth * INDENT_SPACES + message_right = message_left + l.width - ## jump to the left column - ideal_left = left + - if loose_alignment - -IDEAL_LEFT_CONTEXT + (l.width - buffer.content_width + IDEAL_LEFT_CONTEXT + 1).clamp(0, IDEAL_LEFT_CONTEXT) - else - 0 - end - - jump_to_col [ideal_left, 0].max + ## calculate leftmost colum + left = if force_alignment # force mode: align exactly + message_left + else # regular: minimize cursor movement + ## leftmost and rightmost are boundaries of all valid left-column + ## alignments. + leftmost = [message_left, message_right - buffer.content_width + 1].min + rightmost = message_left + leftcol.clamp(leftmost, rightmost) + end - ## either way, move the cursor to the first line - set_cursor_pos l.top + jump_to_line l.top # move vertically + jump_to_col left # move horizontally + set_cursor_pos l.top # set cursor pos end def expand_all_messages @@ -540,7 +595,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 @@ -561,7 +616,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 @@ -635,7 +690,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 ? "" : ",")