sup 0.3 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sup might be problematic. Click here for more details.
- data/HACKING +31 -9
- data/History.txt +7 -0
- data/Manifest.txt +2 -0
- data/Rakefile +9 -5
- data/bin/sup +81 -57
- data/bin/sup-config +1 -1
- data/bin/sup-sync +3 -0
- data/bin/sup-tweak-labels +127 -0
- data/doc/TODO +23 -12
- data/lib/sup.rb +13 -11
- data/lib/sup/account.rb +25 -12
- data/lib/sup/buffer.rb +61 -41
- data/lib/sup/colormap.rb +2 -0
- data/lib/sup/contact.rb +28 -18
- data/lib/sup/crypto.rb +86 -31
- data/lib/sup/draft.rb +12 -6
- data/lib/sup/horizontal-selector.rb +47 -0
- data/lib/sup/imap.rb +50 -37
- data/lib/sup/index.rb +76 -13
- data/lib/sup/keymap.rb +27 -8
- data/lib/sup/maildir.rb +1 -1
- data/lib/sup/mbox/loader.rb +1 -1
- data/lib/sup/message-chunks.rb +43 -15
- data/lib/sup/message.rb +67 -31
- data/lib/sup/mode.rb +40 -9
- data/lib/sup/modes/completion-mode.rb +1 -1
- data/lib/sup/modes/compose-mode.rb +3 -3
- data/lib/sup/modes/contact-list-mode.rb +12 -8
- data/lib/sup/modes/edit-message-mode.rb +100 -36
- data/lib/sup/modes/file-browser-mode.rb +1 -0
- data/lib/sup/modes/forward-mode.rb +43 -8
- data/lib/sup/modes/inbox-mode.rb +8 -5
- data/lib/sup/modes/label-search-results-mode.rb +12 -1
- data/lib/sup/modes/line-cursor-mode.rb +4 -7
- data/lib/sup/modes/reply-mode.rb +59 -54
- data/lib/sup/modes/resume-mode.rb +6 -6
- data/lib/sup/modes/scroll-mode.rb +4 -3
- data/lib/sup/modes/search-results-mode.rb +8 -5
- data/lib/sup/modes/text-mode.rb +19 -2
- data/lib/sup/modes/thread-index-mode.rb +109 -40
- data/lib/sup/modes/thread-view-mode.rb +180 -49
- data/lib/sup/person.rb +3 -3
- data/lib/sup/poll.rb +9 -8
- data/lib/sup/rfc2047.rb +7 -1
- data/lib/sup/sent.rb +1 -1
- data/lib/sup/tagger.rb +10 -4
- data/lib/sup/textfield.rb +7 -7
- data/lib/sup/thread.rb +86 -49
- data/lib/sup/update.rb +11 -0
- data/lib/sup/util.rb +74 -34
- data/test/test_message.rb +441 -0
- metadata +136 -117
data/lib/sup/mode.rb
CHANGED
@@ -35,17 +35,12 @@ class Mode
|
|
35
35
|
@buffer = nil
|
36
36
|
end
|
37
37
|
|
38
|
-
## turns an input keystroke into an action symbol
|
39
38
|
def resolve_input c
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
ancestors.each do |klass|
|
45
|
-
action = @@keymaps.member?(klass) && @@keymaps[klass].action_for(c)
|
39
|
+
ancestors.each do |klass| # try all keymaps in order of ancestry
|
40
|
+
next unless @@keymaps.member?(klass)
|
41
|
+
action = BufferManager.resolve_input_with_keymap c, @@keymaps[klass]
|
46
42
|
return action if action
|
47
43
|
end
|
48
|
-
|
49
44
|
nil
|
50
45
|
end
|
51
46
|
|
@@ -75,7 +70,8 @@ EOS
|
|
75
70
|
end.compact.join "\n"
|
76
71
|
end
|
77
72
|
|
78
|
-
|
73
|
+
### helper functions
|
74
|
+
|
79
75
|
def save_to_file fn
|
80
76
|
if File.exists? fn
|
81
77
|
return unless BufferManager.ask_yes_or_no "File exists. Overwrite?"
|
@@ -87,6 +83,41 @@ EOS
|
|
87
83
|
BufferManager.flash "Error writing to file: #{e.message}"
|
88
84
|
end
|
89
85
|
end
|
86
|
+
|
87
|
+
def pipe_to_process command
|
88
|
+
Open3.popen3(command) do |input, output, error|
|
89
|
+
err, data, * = IO.select [error], [input], nil
|
90
|
+
|
91
|
+
unless err.empty?
|
92
|
+
message = err.first.read
|
93
|
+
if message =~ /^\s*$/
|
94
|
+
Redwood::log "error running #{command} (but no error message)"
|
95
|
+
BufferManager.flash "Error running #{command}!"
|
96
|
+
else
|
97
|
+
Redwood::log "error running #{command}: #{message}"
|
98
|
+
BufferManager.flash "Error: #{message}"
|
99
|
+
end
|
100
|
+
return
|
101
|
+
end
|
102
|
+
|
103
|
+
data = data.first
|
104
|
+
data.sync = false # buffer input
|
105
|
+
|
106
|
+
yield data
|
107
|
+
data.close # output will block unless input is closed
|
108
|
+
|
109
|
+
## BUG?: shows errors or output but not both....
|
110
|
+
data, * = IO.select [output, error], nil, nil
|
111
|
+
data = data.first
|
112
|
+
|
113
|
+
if data.eof
|
114
|
+
BufferManager.flash "'#{command}' done!"
|
115
|
+
nil
|
116
|
+
else
|
117
|
+
data.read
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
90
121
|
end
|
91
122
|
|
92
123
|
end
|
@@ -28,7 +28,7 @@ private
|
|
28
28
|
def update_lines
|
29
29
|
width = buffer.content_width
|
30
30
|
max_length = @list.max_of { |s| s.length }
|
31
|
-
num_per = buffer.content_width / (max_length + INTERSTITIAL.length)
|
31
|
+
num_per = [1, buffer.content_width / (max_length + INTERSTITIAL.length)].max
|
32
32
|
@lines = [@header].compact
|
33
33
|
@list.each_with_index do |s, i|
|
34
34
|
if @prefix_len
|
@@ -21,9 +21,9 @@ class ComposeMode < EditMessageMode
|
|
21
21
|
|
22
22
|
def self.spawn_nicely opts={}
|
23
23
|
to = opts[:to] || BufferManager.ask_for_contacts(:people, "To: ") or return
|
24
|
-
cc = opts[:cc] || BufferManager.ask_for_contacts(:people, "Cc: ") or return if $config[:ask_for_cc]
|
25
|
-
bcc = opts[:bcc] || BufferManager.ask_for_contacts(:people, "Bcc: ") or return if $config[:ask_for_bcc]
|
26
|
-
subj = opts[:subj] || BufferManager.ask(:subject, "Subject: ") or return if $config[:ask_for_subject]
|
24
|
+
cc = opts[:cc] || (BufferManager.ask_for_contacts(:people, "Cc: ") or return if $config[:ask_for_cc])
|
25
|
+
bcc = opts[:bcc] || (BufferManager.ask_for_contacts(:people, "Bcc: ") or return if $config[:ask_for_bcc])
|
26
|
+
subj = opts[:subj] || (BufferManager.ask(:subject, "Subject: ") or return if $config[:ask_for_subject])
|
27
27
|
|
28
28
|
mode = ComposeMode.new :from => opts[:from], :to => to, :cc => cc, :bcc => bcc, :subj => subj
|
29
29
|
BufferManager.spawn "New Message", mode
|
@@ -2,12 +2,16 @@ module Redwood
|
|
2
2
|
|
3
3
|
module CanAliasContacts
|
4
4
|
def alias_contact p
|
5
|
-
|
6
|
-
if
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
aalias = BufferManager.ask(:alias, "Alias for #{p.longname}: ", ContactManager.alias_for(p))
|
6
|
+
return if aalias.nil?
|
7
|
+
aalias = nil if aalias.empty? # allow empty aliases
|
8
|
+
|
9
|
+
name = BufferManager.ask(:name, "Name for #{p.longname}: ", p.name)
|
10
|
+
return if name.nil? || name.empty? # don't allow empty names
|
11
|
+
p.name = name
|
12
|
+
|
13
|
+
ContactManager.update_alias p, aalias
|
14
|
+
BufferManager.flash "Contact updated!"
|
11
15
|
end
|
12
16
|
end
|
13
17
|
|
@@ -17,7 +21,7 @@ class ContactListMode < LineCursorMode
|
|
17
21
|
register_keymap do |k|
|
18
22
|
k.add :load_more, "Load #{LOAD_MORE_CONTACTS_NUM} more contacts", 'M'
|
19
23
|
k.add :reload, "Drop contact list and reload", 'D'
|
20
|
-
k.add :alias, "Edit
|
24
|
+
k.add :alias, "Edit alias/or name for contact", 'a', 'i'
|
21
25
|
k.add :toggle_tagged, "Tag/untag current line", 't'
|
22
26
|
k.add :apply_to_tagged, "Apply next command to all tagged items", ';'
|
23
27
|
k.add :search, "Search for messages from particular people", 'S'
|
@@ -103,7 +107,7 @@ class ContactListMode < LineCursorMode
|
|
103
107
|
|
104
108
|
def load
|
105
109
|
@num ||= buffer.content_height
|
106
|
-
@user_contacts = ContactManager.
|
110
|
+
@user_contacts = ContactManager.contacts_with_aliases
|
107
111
|
num = [@num - @user_contacts.length, 0].max
|
108
112
|
BufferManager.say("Loading #{num} contacts from index...") do
|
109
113
|
recentc = Index.load_contacts AccountManager.user_emails, :num => num
|
@@ -8,6 +8,8 @@ module Redwood
|
|
8
8
|
class SendmailCommandFailed < StandardError; end
|
9
9
|
|
10
10
|
class EditMessageMode < LineCursorMode
|
11
|
+
DECORATION_LINES = 1
|
12
|
+
|
11
13
|
FORCE_HEADERS = %w(From To Cc Bcc Subject)
|
12
14
|
MULTI_HEADERS = %w(To Cc Bcc)
|
13
15
|
NON_EDITABLE_HEADERS = %w(Message-Id Date)
|
@@ -48,6 +50,8 @@ EOS
|
|
48
50
|
k.add :save_as_draft, "Save as draft", 'P'
|
49
51
|
k.add :attach_file, "Attach a file", 'a'
|
50
52
|
k.add :delete_attachment, "Delete an attachment", 'd'
|
53
|
+
k.add :move_cursor_right, "Move selector to the right", :right, 'l'
|
54
|
+
k.add :move_cursor_left, "Move selector to the left", :left, 'h'
|
51
55
|
end
|
52
56
|
|
53
57
|
def initialize opts={}
|
@@ -55,12 +59,26 @@ EOS
|
|
55
59
|
@header_lines = []
|
56
60
|
|
57
61
|
@body = opts.delete(:body) || []
|
58
|
-
@body += sig_lines if $config[:edit_signature]
|
62
|
+
@body += sig_lines if $config[:edit_signature] && !opts.delete(:have_signature)
|
63
|
+
|
64
|
+
if opts[:attachments]
|
65
|
+
@attachments = opts[:attachments].values
|
66
|
+
@attachment_names = opts[:attachments].keys
|
67
|
+
else
|
68
|
+
@attachments = []
|
69
|
+
@attachment_names = []
|
70
|
+
end
|
59
71
|
|
60
|
-
@attachments = []
|
61
72
|
@message_id = "<#{Time.now.to_i}-sup-#{rand 10000}@#{Socket.gethostname}>"
|
62
73
|
@edited = false
|
63
|
-
@
|
74
|
+
@selectors = []
|
75
|
+
@selector_label_width = 0
|
76
|
+
|
77
|
+
@crypto_selector =
|
78
|
+
if CryptoManager.have_crypto?
|
79
|
+
HorizontalSelector.new "Crypto:", [:none] + CryptoManager::OUTGOING_MESSAGE_OPERATIONS.keys, ["None"] + CryptoManager::OUTGOING_MESSAGE_OPERATIONS.values
|
80
|
+
end
|
81
|
+
add_selector @crypto_selector if @crypto_selector
|
64
82
|
|
65
83
|
HookManager.run "before-edit", :header => @header, :body => @body
|
66
84
|
|
@@ -68,17 +86,31 @@ EOS
|
|
68
86
|
regen_text
|
69
87
|
end
|
70
88
|
|
71
|
-
def lines; @text.length end
|
72
|
-
|
89
|
+
def lines; @text.length + (@selectors.empty? ? 0 : (@selectors.length + DECORATION_LINES)) end
|
90
|
+
|
91
|
+
def [] i
|
92
|
+
if @selectors.empty?
|
93
|
+
@text[i]
|
94
|
+
elsif i < @selectors.length
|
95
|
+
@selectors[i].line @selector_label_width
|
96
|
+
elsif i == @selectors.length
|
97
|
+
""
|
98
|
+
else
|
99
|
+
@text[i - @selectors.length - DECORATION_LINES]
|
100
|
+
end
|
101
|
+
end
|
73
102
|
|
74
|
-
##
|
103
|
+
## hook for subclasses. i hate this style of programming.
|
75
104
|
def handle_new_text header, body; end
|
76
105
|
|
77
106
|
def edit_message_or_field
|
78
|
-
|
107
|
+
lines = DECORATION_LINES + @selectors.size
|
108
|
+
if lines > curpos
|
109
|
+
return
|
110
|
+
elsif (curpos - lines) >= @header_lines.length
|
79
111
|
edit_message
|
80
112
|
else
|
81
|
-
edit_field @header_lines[curpos -
|
113
|
+
edit_field @header_lines[curpos - lines]
|
82
114
|
end
|
83
115
|
end
|
84
116
|
|
@@ -116,20 +148,45 @@ EOS
|
|
116
148
|
def attach_file
|
117
149
|
fn = BufferManager.ask_for_filename :attachment, "File name (enter for browser): "
|
118
150
|
return unless fn
|
119
|
-
@attachments <<
|
151
|
+
@attachments << RMail::Message.make_file_attachment(fn)
|
152
|
+
@attachment_names << fn
|
120
153
|
update
|
121
154
|
end
|
122
155
|
|
123
156
|
def delete_attachment
|
124
|
-
i =
|
125
|
-
if i >= 0 && i < @attachments.size && BufferManager.ask_yes_or_no("Delete attachment #{@
|
157
|
+
i = curpos - @attachment_lines_offset - DECORATION_LINES - 1
|
158
|
+
if i >= 0 && i < @attachments.size && BufferManager.ask_yes_or_no("Delete attachment #{@attachment_names[i]}?")
|
126
159
|
@attachments.delete_at i
|
160
|
+
@attachment_names.delete_at i
|
127
161
|
update
|
128
162
|
end
|
129
163
|
end
|
130
164
|
|
131
165
|
protected
|
132
166
|
|
167
|
+
def move_cursor_left
|
168
|
+
if curpos < @selectors.length
|
169
|
+
@selectors[curpos].roll_left
|
170
|
+
buffer.mark_dirty
|
171
|
+
else
|
172
|
+
col_left
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def move_cursor_right
|
177
|
+
if curpos < @selectors.length
|
178
|
+
@selectors[curpos].roll_right
|
179
|
+
buffer.mark_dirty
|
180
|
+
else
|
181
|
+
col_right
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def add_selector s
|
186
|
+
@selectors << s
|
187
|
+
@selector_label_width = [@selector_label_width, s.label.length].max
|
188
|
+
end
|
189
|
+
|
133
190
|
def update
|
134
191
|
regen_text
|
135
192
|
buffer.mark_dirty if buffer
|
@@ -145,7 +202,7 @@ protected
|
|
145
202
|
unless @attachments.empty?
|
146
203
|
@text += [""]
|
147
204
|
@attachment_lines_offset = @text.length
|
148
|
-
@text += @attachments.map { |
|
205
|
+
@text += (0 ... @attachments.size).map { |i| [[:attachment_color, "+ Attachment: #{@attachment_names[i]} (#{@attachments[i].body.size.to_human_size})"]] }
|
149
206
|
end
|
150
207
|
end
|
151
208
|
|
@@ -208,7 +265,6 @@ protected
|
|
208
265
|
return false if $config[:confirm_no_attachments] && mentions_attachments? && @attachments.size == 0 && !BufferManager.ask_yes_or_no("You haven't added any attachments. Really send?")#" stupid ruby-mode
|
209
266
|
return false if $config[:confirm_top_posting] && top_posting? && !BufferManager.ask_yes_or_no("You're top-posting. That makes you a bad person. Really send?") #" stupid ruby-mode
|
210
267
|
|
211
|
-
date = Time.now
|
212
268
|
from_email =
|
213
269
|
if @header["From"] =~ /<?(\S+@(\S+?))>?$/
|
214
270
|
$1
|
@@ -220,13 +276,15 @@ protected
|
|
220
276
|
BufferManager.flash "Sending..."
|
221
277
|
|
222
278
|
begin
|
223
|
-
|
279
|
+
date = Time.now
|
280
|
+
m = build_message date
|
281
|
+
IO.popen(acct.sendmail, "w") { |p| p.puts m }
|
224
282
|
raise SendmailCommandFailed, "Couldn't execute #{acct.sendmail}" unless $? == 0
|
225
|
-
SentManager.write_sent_message(date, from_email) { |f|
|
283
|
+
SentManager.write_sent_message(date, from_email) { |f| f.puts sanitize_body(m.to_s) }
|
226
284
|
BufferManager.kill_buffer buffer
|
227
285
|
BufferManager.flash "Message sent!"
|
228
286
|
true
|
229
|
-
rescue SystemCallError, SendmailCommandFailed => e
|
287
|
+
rescue SystemCallError, SendmailCommandFailed, CryptoManager::Error => e
|
230
288
|
Redwood::log "Problem sending mail: #{e.message}"
|
231
289
|
BufferManager.flash "Problem sending mail: #{e.message}"
|
232
290
|
false
|
@@ -239,8 +297,32 @@ protected
|
|
239
297
|
BufferManager.flash "Saved for later editing."
|
240
298
|
end
|
241
299
|
|
242
|
-
def
|
300
|
+
def build_message date
|
243
301
|
m = RMail::Message.new
|
302
|
+
m.header["Content-Type"] = "text/plain; charset=#{$encoding}"
|
303
|
+
m.body = @body.join
|
304
|
+
m.body = m.body
|
305
|
+
m.body += sig_lines.join("\n") unless $config[:edit_signature]
|
306
|
+
|
307
|
+
## there are attachments, so wrap body in an attachment of its own
|
308
|
+
unless @attachments.empty?
|
309
|
+
body_m = m
|
310
|
+
body_m.header["Content-Disposition"] = "inline"
|
311
|
+
m = RMail::Message.new
|
312
|
+
|
313
|
+
m.add_part body_m
|
314
|
+
@attachments.each { |a| m.add_part a }
|
315
|
+
end
|
316
|
+
|
317
|
+
## do whatever crypto transformation is necessary
|
318
|
+
if @crypto_selector && @crypto_selector.val != :none
|
319
|
+
from_email = PersonManager.person_for(@header["From"]).email
|
320
|
+
to_email = (@header["To"] + @header["Cc"] + @header["Bcc"]).map { |p| PersonManager.person_for(p).email }
|
321
|
+
|
322
|
+
m = CryptoManager.send @crypto_selector.val, from_email, to_email, m
|
323
|
+
end
|
324
|
+
|
325
|
+
## finally, set the top-level headers
|
244
326
|
@header.each do |k, v|
|
245
327
|
next if v.nil? || v.empty?
|
246
328
|
m.header[k] =
|
@@ -251,28 +333,10 @@ protected
|
|
251
333
|
v.join ", "
|
252
334
|
end
|
253
335
|
end
|
254
|
-
|
255
336
|
m.header["Date"] = date.rfc2822
|
256
337
|
m.header["Message-Id"] = @message_id
|
257
338
|
m.header["User-Agent"] = "Sup/#{Redwood::VERSION}"
|
258
|
-
|
259
|
-
if @attachments.empty?
|
260
|
-
m.header["Content-Type"] = "text/plain; charset=#{$encoding}"
|
261
|
-
m.body = @body.join
|
262
|
-
m.body = sanitize_body m.body if escape
|
263
|
-
m.body += sig_lines.join("\n") unless $config[:edit_signature]
|
264
|
-
else
|
265
|
-
body_m = RMail::Message.new
|
266
|
-
body_m.body = @body.join
|
267
|
-
body_m.body = sanitize_body body_m.body if escape
|
268
|
-
body_m.body += sig_lines.join("\n") unless $config[:edit_signature]
|
269
|
-
body_m.header["Content-Type"] = "text/plain; charset=#{$encoding}"
|
270
|
-
body_m.header["Content-Disposition"] = "inline"
|
271
|
-
|
272
|
-
m.add_part body_m
|
273
|
-
@attachments.each { |fn| m.add_file_attachment fn.to_s }
|
274
|
-
end
|
275
|
-
f.puts m.to_s
|
339
|
+
m
|
276
340
|
end
|
277
341
|
|
278
342
|
## TODO: remove this. redundant with write_full_message_to.
|
@@ -1,28 +1,63 @@
|
|
1
1
|
module Redwood
|
2
2
|
|
3
3
|
class ForwardMode < EditMessageMode
|
4
|
-
|
5
|
-
|
6
|
-
def initialize m, opts={}
|
4
|
+
## TODO: share some of this with reply-mode
|
5
|
+
def initialize opts={}
|
7
6
|
header = {
|
8
7
|
"From" => AccountManager.default_account.full_address,
|
9
|
-
"Subject" => "Fwd: #{m.subj}",
|
10
8
|
}
|
11
9
|
|
10
|
+
header["Subject"] =
|
11
|
+
if opts[:message]
|
12
|
+
"Fwd: " + opts[:message].subj
|
13
|
+
elsif opts[:attachments]
|
14
|
+
"Fwd: " + opts[:attachments].keys.join(", ")
|
15
|
+
end
|
16
|
+
|
12
17
|
header["To"] = opts[:to].map { |p| p.full_address }.join(", ") if opts[:to]
|
13
18
|
header["Cc"] = opts[:cc].map { |p| p.full_address }.join(", ") if opts[:cc]
|
14
19
|
header["Bcc"] = opts[:bcc].map { |p| p.full_address }.join(", ") if opts[:bcc]
|
15
20
|
|
16
|
-
|
21
|
+
body =
|
22
|
+
if opts[:message]
|
23
|
+
forward_body_lines(opts[:message])
|
24
|
+
elsif opts[:attachments]
|
25
|
+
["Note: #{opts[:attachments].size.pluralize 'attachment'}."]
|
26
|
+
end
|
27
|
+
|
28
|
+
super :header => header, :body => body, :attachments => opts[:attachments]
|
17
29
|
end
|
18
30
|
|
19
|
-
def self.spawn_nicely
|
31
|
+
def self.spawn_nicely opts={}
|
20
32
|
to = opts[:to] || BufferManager.ask_for_contacts(:people, "To: ") or return
|
21
33
|
cc = opts[:cc] || BufferManager.ask_for_contacts(:people, "Cc: ") or return if $config[:ask_for_cc]
|
22
34
|
bcc = opts[:bcc] || BufferManager.ask_for_contacts(:people, "Bcc: ") or return if $config[:ask_for_bcc]
|
23
35
|
|
24
|
-
|
25
|
-
|
36
|
+
attachment_hash = {}
|
37
|
+
attachments = opts[:attachments] || []
|
38
|
+
|
39
|
+
if(m = opts[:message])
|
40
|
+
m.load_from_source! # read the full message in. you know, maybe i should just make Message#chunks do this....
|
41
|
+
attachments += m.chunks.select { |c| c.is_a?(Chunk::Attachment) && !c.quotable? }
|
42
|
+
end
|
43
|
+
|
44
|
+
attachments.each do |c|
|
45
|
+
mime_type = MIME::Types[c.content_type].first || MIME::Types["application/octet-stream"]
|
46
|
+
attachment_hash[c.filename] = RMail::Message.make_attachment c.raw_content, mime_type.content_type, mime_type.encoding, c.filename
|
47
|
+
end
|
48
|
+
|
49
|
+
mode = ForwardMode.new :message => opts[:message], :to => to, :cc => cc, :bcc => bcc, :attachments => attachment_hash
|
50
|
+
|
51
|
+
title = "Forwarding " +
|
52
|
+
if opts[:message]
|
53
|
+
opts[:message].subj
|
54
|
+
elsif attachments
|
55
|
+
attachment_hash.keys.join(", ")
|
56
|
+
else
|
57
|
+
"something"
|
58
|
+
end
|
59
|
+
|
60
|
+
BufferManager.spawn title, mode
|
26
61
|
mode.edit_message
|
27
62
|
end
|
28
63
|
|
data/lib/sup/modes/inbox-mode.rb
CHANGED
@@ -38,11 +38,14 @@ class InboxMode < ThreadIndexMode
|
|
38
38
|
regen_text
|
39
39
|
end
|
40
40
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
def handle_unarchived_update sender, m
|
42
|
+
add_or_unhide m
|
43
|
+
end
|
44
|
+
|
45
|
+
def handle_archived_update sender, m
|
46
|
+
t = thread_containing(m) or return
|
47
|
+
hide_thread t
|
48
|
+
regen_text
|
46
49
|
end
|
47
50
|
|
48
51
|
def status
|