lib/sup/modes/thread-view-mode.rb in sup-0.9.1 vs lib/sup/modes/thread-view-mode.rb in sup-0.10
- old
+ new
@@ -56,18 +56,20 @@
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'
+ k.add :save_all_to_disk, "Save all attachments to disk", 'A'
k.add :search, "Search for messages from particular people", 'S'
k.add :compose, "Compose message to person", 'm'
k.add :subscribe_to_list, "Subscribe to/unsubscribe from mailing list", "("
k.add :unsubscribe_from_list, "Subscribe to/unsubscribe from mailing list", ")"
k.add :pipe_message, "Pipe message or attachment to a shell command", '|'
k.add :archive_and_next, "Archive this thread, kill buffer, and view next", 'a'
k.add :delete_and_next, "Delete this thread, kill buffer, and view next", 'd'
+ k.add :toggle_wrap, "Toggle wrapping of text", 'w'
k.add_multi "(a)rchive/(d)elete/mark as (s)pam/mark as u(N)read:", '.' do |kk|
kk.add :archive_and_kill, "Archive this thread and kill buffer", 'a'
kk.add :delete_and_kill, "Delete this thread and kill buffer", 'd'
kk.add :spam_and_kill, "Mark this thread as spam and kill buffer", 's'
@@ -125,15 +127,23 @@
latest_date = m.date
latest = m
end
end
+ @wrap = true
+
@layout[latest].state = :open if @layout[latest].state == :closed
@layout[earliest].state = :detailed if earliest.has_label?(:unread) || @thread.size == 1
@thread.remove_label :unread
+ Index.save_thread @thread
+ end
+
+ def toggle_wrap
+ @wrap = !@wrap
regen_text
+ buffer.mark_dirty if buffer
end
def draw_line ln, opts={}
if ln == curpos
super ln, :highlight => true
@@ -142,21 +152,29 @@
end
end
def lines; @text.length; end
def [] i; @text[i]; end
+ ## a little hacky---since regen_text can depend on buffer features like the
+ ## content_width, we don't call it in the constructor, and instead call it
+ ## here, which is set before we're responsible for drawing ourself.
+ def buffer= b
+ super
+ regen_text
+ end
+
def show_header
m = @message_lines[curpos] or return
BufferManager.spawn_unless_exists("Full header for #{m.id}") do
- TextMode.new m.raw_header
+ TextMode.new m.raw_header.ascii
end
end
def show_message
m = @message_lines[curpos] or return
BufferManager.spawn_unless_exists("Raw message for #{m.id}") do
- TextMode.new m.raw_message
+ TextMode.new m.raw_message.ascii
end
end
def toggle_detailed_header
m = @message_lines[curpos] or return
@@ -256,12 +274,14 @@
return unless new_labels
@thread.labels = Set.new(reserved_labels) + new_labels
new_labels.each { |l| LabelManager << l }
update
UpdateManager.relay self, :labeled, @thread.first
+ Index.save_thread @thread
UndoManager.register "labeling thread" do
@thread.labels = old_labels
+ Index.save_thread @thread
UpdateManager.relay self, :labeled, @thread.first
end
end
def toggle_starred
@@ -282,10 +302,11 @@
end
## TODO: don't recalculate EVERYTHING just to add a stupid little
## star to the display
update
UpdateManager.relay self, :single_message_labeled, m
+ Index.save_thread @thread
end
## called when someone presses enter when the cursor is highlighting
## a chunk. for expandable chunks (including messages) we toggle
## open/closed state; for viewable chunks (like attachments) we
@@ -324,12 +345,14 @@
def save_to_disk
chunk = @chunk_lines[curpos] or return
case chunk
when Chunk::Attachment
- default_dir = File.join(($config[:default_attachment_save_dir] || "."), chunk.filename)
- fn = BufferManager.ask_for_filename :filename, "Save attachment to file: ", default_dir
+ default_dir = $config[:default_attachment_save_dir]
+ default_dir = ENV["HOME"] if default_dir.nil? || default_dir.empty?
+ default_fn = File.expand_path File.join(default_dir, chunk.filename)
+ fn = BufferManager.ask_for_filename :filename, "Save attachment to file: ", default_fn
save_to_file(fn) { |f| f.print chunk.raw_content } if fn
else
m = @message_lines[curpos]
fn = BufferManager.ask_for_filename :filename, "Save message to file: "
return unless fn
@@ -337,10 +360,36 @@
m.each_raw_message_line { |l| f.print l }
end
end
end
+ def save_all_to_disk
+ m = @message_lines[curpos] or return
+ default_dir = ($config[:default_attachment_save_dir] || ".")
+ folder = BufferManager.ask_for_filename :filename, "Save all attachments to folder: ", default_dir, true
+ return unless folder
+
+ num = 0
+ num_errors = 0
+ m.chunks.each do |chunk|
+ next unless chunk.is_a?(Chunk::Attachment)
+ fn = File.join(folder, chunk.filename)
+ num_errors += 1 unless save_to_file(fn, false) { |f| f.print chunk.raw_content }
+ num += 1
+ end
+
+ if num == 0
+ BufferManager.flash "Didn't find any attachments!"
+ else
+ if num_errors == 0
+ BufferManager.flash "Wrote #{num.pluralize 'attachment'} to #{folder}."
+ else
+ BufferManager.flash "Wrote #{(num - num_errors).pluralize 'attachment'} to #{folder}; couldn't write #{num_errors} of them (see log)."
+ end
+ end
+ end
+
def edit_draft
m = @message_lines[curpos] or return
if m.is_draft?
mode = ResumeMode.new m
BufferManager.spawn "Edit message", mode
@@ -474,43 +523,50 @@
def archive_and_then op
dispatch op do
@thread.remove_label :inbox
UpdateManager.relay self, :archived, @thread.first
+ Index.save_thread @thread
UndoManager.register "archiving 1 thread" do
@thread.apply_label :inbox
+ Index.save_thread @thread
UpdateManager.relay self, :unarchived, @thread.first
end
end
end
def spam_and_then op
dispatch op do
@thread.apply_label :spam
UpdateManager.relay self, :spammed, @thread.first
+ Index.save_thread @thread
UndoManager.register "marking 1 thread as spam" do
@thread.remove_label :spam
+ Index.save_thread @thread
UpdateManager.relay self, :unspammed, @thread.first
end
end
end
def delete_and_then op
dispatch op do
@thread.apply_label :deleted
UpdateManager.relay self, :deleted, @thread.first
+ Index.save_thread @thread
UndoManager.register "deleting 1 thread" do
@thread.remove_label :deleted
+ Index.save_thread @thread
UpdateManager.relay self, :undeleted, @thread.first
end
end
end
def unread_and_then op
dispatch op do
@thread.apply_label :unread
UpdateManager.relay self, :unread, @thread.first
+ Index.save_thread @thread
end
end
def do_nothing_and_then op
dispatch op
@@ -555,11 +611,11 @@
message.each_raw_message_line { |l| stream.print l }
end
end
if output
- BufferManager.spawn "Output of '#{command}'", TextMode.new(output)
+ BufferManager.spawn "Output of '#{command}'", TextMode.new(output.ascii)
else
BufferManager.flash "'#{command}' done!"
end
end
@@ -732,11 +788,16 @@
(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
if chunk.inlineable?
- chunk.lines.map { |line| [[chunk.color, "#{prefix}#{line}"]] }
+ lines = chunk.lines
+ if @wrap
+ width = buffer.content_width
+ lines = lines.map { |l| l.chomp.wrap width }.flatten
+ end
+ lines.map { |line| [[chunk.color, "#{prefix}#{line}"]] }
elsif chunk.expandable?
case state
when :closed
[[[chunk.patina_color, "#{prefix}+ #{chunk.patina_text}"]]]
when :open
@@ -752,10 +813,10 @@
BufferManager.flash "viewing #{chunk.content_type} attachment..."
success = chunk.view!
BufferManager.erase_flash
BufferManager.completely_redraw_screen
unless success
- BufferManager.spawn "Attachment: #{chunk.filename}", TextMode.new(chunk.to_s, chunk.filename)
+ BufferManager.spawn "Attachment: #{chunk.filename}", TextMode.new(chunk.to_s.ascii, chunk.filename)
BufferManager.flash "Couldn't execute view command, viewing as text."
end
end
end