sup 0.9.1 → 0.10
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/CONTRIBUTORS +10 -6
- data/History.txt +11 -0
- data/ReleaseNotes +10 -0
- data/bin/sup +55 -19
- data/bin/sup-add +18 -8
- data/bin/sup-config +2 -2
- data/bin/sup-convert-ferret-index +84 -0
- data/bin/sup-dump +4 -3
- data/bin/sup-sync +4 -3
- data/bin/sup-sync-back +3 -2
- data/bin/sup-tweak-labels +3 -3
- data/lib/sup.rb +35 -4
- data/lib/sup/buffer.rb +12 -6
- data/lib/sup/colormap.rb +1 -0
- data/lib/sup/crypto.rb +76 -55
- data/lib/sup/ferret_index.rb +6 -1
- data/lib/sup/index.rb +62 -8
- data/lib/sup/logger.rb +2 -1
- data/lib/sup/maildir.rb +4 -2
- data/lib/sup/mbox/loader.rb +4 -3
- data/lib/sup/message-chunks.rb +9 -7
- data/lib/sup/message.rb +29 -27
- data/lib/sup/mode.rb +11 -4
- data/lib/sup/modes/buffer-list-mode.rb +5 -0
- data/lib/sup/modes/console-mode.rb +4 -0
- data/lib/sup/modes/edit-message-mode.rb +4 -2
- data/lib/sup/modes/file-browser-mode.rb +1 -1
- data/lib/sup/modes/inbox-mode.rb +18 -1
- data/lib/sup/modes/label-list-mode.rb +44 -3
- data/lib/sup/modes/text-mode.rb +1 -1
- data/lib/sup/modes/thread-index-mode.rb +63 -52
- data/lib/sup/modes/thread-view-mode.rb +68 -7
- data/lib/sup/poll.rb +20 -5
- data/lib/sup/source.rb +1 -0
- data/lib/sup/thread.rb +1 -1
- data/lib/sup/util.rb +49 -11
- data/lib/sup/xapian_index.rb +151 -112
- metadata +4 -10
- data/lib/sup/hook.rb.BACKUP.8625.rb +0 -158
- data/lib/sup/hook.rb.BACKUP.8681.rb +0 -158
- data/lib/sup/hook.rb.BASE.8625.rb +0 -155
- data/lib/sup/hook.rb.BASE.8681.rb +0 -155
- data/lib/sup/hook.rb.LOCAL.8625.rb +0 -142
- data/lib/sup/hook.rb.LOCAL.8681.rb +0 -142
- data/lib/sup/hook.rb.REMOTE.8625.rb +0 -145
- data/lib/sup/hook.rb.REMOTE.8681.rb +0 -145
data/lib/sup/modes/text-mode.rb
CHANGED
@@ -37,7 +37,7 @@ EOS
|
|
37
37
|
k.add :toggle_spam, "Mark/unmark thread as spam", 'S'
|
38
38
|
k.add :toggle_deleted, "Delete/undelete thread", 'd'
|
39
39
|
k.add :kill, "Kill thread (never to be seen in inbox again)", '&'
|
40
|
-
k.add :
|
40
|
+
k.add :flush_index, "Flush all changes now", '$'
|
41
41
|
k.add :jump_to_next_new, "Jump to next new thread", :tab
|
42
42
|
k.add :reply, "Reply to latest message in a thread", 'r'
|
43
43
|
k.add :reply_all, "Reply to all participants of the latest message in a thread", 'G'
|
@@ -66,7 +66,7 @@ EOS
|
|
66
66
|
@date_width = DATE_WIDTH
|
67
67
|
|
68
68
|
@interrupt_search = false
|
69
|
-
|
69
|
+
|
70
70
|
initialize_threads # defines @ts and @ts_mutex
|
71
71
|
update # defines @text and @lines
|
72
72
|
|
@@ -220,12 +220,14 @@ EOS
|
|
220
220
|
end
|
221
221
|
|
222
222
|
def update
|
223
|
+
old_cursor_thread = cursor_thread
|
223
224
|
@mutex.synchronize do
|
224
225
|
## let's see you do THIS in python
|
225
226
|
@threads = @ts.threads.select { |t| !@hidden_threads[t] }.sort_by { |t| [t.date, t.first.id] }.reverse
|
226
227
|
@size_widgets = @threads.map { |t| size_widget_for_thread t }
|
227
228
|
@size_widget_width = @size_widgets.max_of { |w| w.display_length }
|
228
229
|
end
|
230
|
+
set_cursor_pos @threads.index(old_cursor_thread)||curpos
|
229
231
|
|
230
232
|
regen_text
|
231
233
|
end
|
@@ -266,15 +268,18 @@ EOS
|
|
266
268
|
def toggle_starred
|
267
269
|
t = cursor_thread or return
|
268
270
|
undo = actually_toggle_starred t
|
269
|
-
UndoManager.register "toggling thread starred status", undo
|
271
|
+
UndoManager.register "toggling thread starred status", undo, lambda { Index.save_thread t }
|
270
272
|
update_text_for_line curpos
|
271
273
|
cursor_down
|
274
|
+
Index.save_thread t
|
272
275
|
end
|
273
276
|
|
274
277
|
def multi_toggle_starred threads
|
275
278
|
UndoManager.register "toggling #{threads.size.pluralize 'thread'} starred status",
|
276
|
-
threads.map { |t| actually_toggle_starred t }
|
279
|
+
threads.map { |t| actually_toggle_starred t },
|
280
|
+
lambda { threads.each { |t| Index.save_thread t } }
|
277
281
|
regen_text
|
282
|
+
threads.each { |t| Index.save_thread t }
|
278
283
|
end
|
279
284
|
|
280
285
|
## returns an undo lambda
|
@@ -350,14 +355,18 @@ EOS
|
|
350
355
|
def toggle_archived
|
351
356
|
t = cursor_thread or return
|
352
357
|
undo = actually_toggle_archived t
|
353
|
-
UndoManager.register "deleting/undeleting thread #{t.first.id}", undo, lambda { update_text_for_line curpos }
|
358
|
+
UndoManager.register "deleting/undeleting thread #{t.first.id}", undo, lambda { update_text_for_line curpos },
|
359
|
+
lambda { Index.save_thread t }
|
354
360
|
update_text_for_line curpos
|
361
|
+
Index.save_thread t
|
355
362
|
end
|
356
363
|
|
357
364
|
def multi_toggle_archived threads
|
358
365
|
undos = threads.map { |t| actually_toggle_archived t }
|
359
|
-
UndoManager.register "deleting/undeleting #{threads.size.pluralize 'thread'}", undos, lambda { regen_text }
|
366
|
+
UndoManager.register "deleting/undeleting #{threads.size.pluralize 'thread'}", undos, lambda { regen_text },
|
367
|
+
lambda { threads.each { |t| Index.save_thread t } }
|
360
368
|
regen_text
|
369
|
+
threads.each { |t| Index.save_thread t }
|
361
370
|
end
|
362
371
|
|
363
372
|
def toggle_new
|
@@ -365,11 +374,13 @@ EOS
|
|
365
374
|
t.toggle_label :unread
|
366
375
|
update_text_for_line curpos
|
367
376
|
cursor_down
|
377
|
+
Index.save_thread t
|
368
378
|
end
|
369
379
|
|
370
380
|
def multi_toggle_new threads
|
371
381
|
threads.each { |t| t.toggle_label :unread }
|
372
382
|
regen_text
|
383
|
+
threads.each { |t| Index.save_thread t }
|
373
384
|
end
|
374
385
|
|
375
386
|
def multi_toggle_tagged threads
|
@@ -385,6 +396,7 @@ EOS
|
|
385
396
|
|
386
397
|
def multi_join_threads threads
|
387
398
|
@ts.join_threads threads or return
|
399
|
+
threads.each { |t| Index.save_thread t }
|
388
400
|
@tags.drop_all_tags # otherwise we have tag pointers to invalid threads!
|
389
401
|
update
|
390
402
|
end
|
@@ -399,14 +411,13 @@ EOS
|
|
399
411
|
jump_to_line n unless n >= topline && n < botline
|
400
412
|
set_cursor_pos n
|
401
413
|
else
|
402
|
-
BufferManager.flash "No new messages"
|
414
|
+
BufferManager.flash "No new messages."
|
403
415
|
end
|
404
416
|
end
|
405
417
|
|
406
418
|
def toggle_spam
|
407
419
|
t = cursor_thread or return
|
408
420
|
multi_toggle_spam [t]
|
409
|
-
HookManager.run("mark-as-spam", :thread => t)
|
410
421
|
end
|
411
422
|
|
412
423
|
## both spam and deleted have the curious characteristic that you
|
@@ -418,9 +429,11 @@ EOS
|
|
418
429
|
## you also want them to disappear immediately.
|
419
430
|
def multi_toggle_spam threads
|
420
431
|
undos = threads.map { |t| actually_toggle_spammed t }
|
432
|
+
threads.each { |t| HookManager.run("mark-as-spam", :thread => t) }
|
421
433
|
UndoManager.register "marking/unmarking #{threads.size.pluralize 'thread'} as spam",
|
422
|
-
undos, lambda { regen_text }
|
434
|
+
undos, lambda { regen_text }, lambda { threads.each { |t| Index.save_thread t } }
|
423
435
|
regen_text
|
436
|
+
threads.each { |t| Index.save_thread t }
|
424
437
|
end
|
425
438
|
|
426
439
|
def toggle_deleted
|
@@ -432,8 +445,9 @@ EOS
|
|
432
445
|
def multi_toggle_deleted threads
|
433
446
|
undos = threads.map { |t| actually_toggle_deleted t }
|
434
447
|
UndoManager.register "deleting/undeleting #{threads.size.pluralize 'thread'}",
|
435
|
-
undos, lambda { regen_text }
|
448
|
+
undos, lambda { regen_text }, lambda { threads.each { |t| Index.save_thread t } }
|
436
449
|
regen_text
|
450
|
+
threads.each { |t| Index.save_thread t }
|
437
451
|
end
|
438
452
|
|
439
453
|
def kill
|
@@ -441,12 +455,19 @@ EOS
|
|
441
455
|
multi_kill [t]
|
442
456
|
end
|
443
457
|
|
458
|
+
def flush_index
|
459
|
+
@flush_id = BufferManager.say "Flushing index..."
|
460
|
+
Index.save_index
|
461
|
+
BufferManager.clear @flush_id
|
462
|
+
end
|
463
|
+
|
444
464
|
## m-m-m-m-MULTI-KILL
|
445
465
|
def multi_kill threads
|
446
466
|
UndoManager.register "killing #{threads.size.pluralize 'thread'}" do
|
447
467
|
threads.each do |t|
|
448
468
|
t.remove_label :killed
|
449
469
|
add_or_unhide t.first
|
470
|
+
Index.save_thread t
|
450
471
|
end
|
451
472
|
regen_text
|
452
473
|
end
|
@@ -458,29 +479,7 @@ EOS
|
|
458
479
|
|
459
480
|
regen_text
|
460
481
|
BufferManager.flash "#{threads.size.pluralize 'thread'} killed."
|
461
|
-
|
462
|
-
|
463
|
-
def save background=true
|
464
|
-
if background
|
465
|
-
Redwood::reporting_thread("saving thread") { actually_save }
|
466
|
-
else
|
467
|
-
actually_save
|
468
|
-
end
|
469
|
-
end
|
470
|
-
|
471
|
-
def actually_save
|
472
|
-
@save_thread_mutex.synchronize do
|
473
|
-
BufferManager.say("Saving contacts...") { ContactManager.instance.save }
|
474
|
-
dirty_threads = @mutex.synchronize { (@threads + @hidden_threads.keys).select { |t| t.dirty? } }
|
475
|
-
next if dirty_threads.empty?
|
476
|
-
|
477
|
-
BufferManager.say("Saving threads...") do |say_id|
|
478
|
-
dirty_threads.each_with_index do |t, i|
|
479
|
-
BufferManager.say "Saving modified thread #{i + 1} of #{dirty_threads.length}...", say_id
|
480
|
-
t.save_state Index
|
481
|
-
end
|
482
|
-
end
|
483
|
-
end
|
482
|
+
threads.each { |t| Index.save_thread t }
|
484
483
|
end
|
485
484
|
|
486
485
|
def cleanup
|
@@ -492,7 +491,8 @@ EOS
|
|
492
491
|
sleep 0.1 # TODO: necessary?
|
493
492
|
BufferManager.erase_flash
|
494
493
|
end
|
495
|
-
|
494
|
+
dirty_threads = @mutex.synchronize { (@threads + @hidden_threads.keys).select { |t| t.dirty? } }
|
495
|
+
fail "dirty threads remain" unless dirty_threads.empty?
|
496
496
|
super
|
497
497
|
end
|
498
498
|
|
@@ -543,9 +543,11 @@ EOS
|
|
543
543
|
thread.labels = old_labels
|
544
544
|
update_text_for_line pos
|
545
545
|
UpdateManager.relay self, :labeled, thread.first
|
546
|
+
Index.save_thread thread
|
546
547
|
end
|
547
548
|
|
548
549
|
UpdateManager.relay self, :labeled, thread.first
|
550
|
+
Index.save_thread thread
|
549
551
|
end
|
550
552
|
|
551
553
|
def multi_edit_labels threads
|
@@ -579,9 +581,12 @@ EOS
|
|
579
581
|
threads.zip(old_labels).map do |t, old_labels|
|
580
582
|
t.labels = old_labels
|
581
583
|
UpdateManager.relay self, :labeled, t.first
|
584
|
+
Index.save_thread t
|
582
585
|
end
|
583
586
|
regen_text
|
584
587
|
end
|
588
|
+
|
589
|
+
threads.each { |t| Index.save_thread t }
|
585
590
|
end
|
586
591
|
|
587
592
|
def reply type_arg=nil
|
@@ -759,30 +764,36 @@ protected
|
|
759
764
|
@lines = threads.map_with_index { |t, i| [t, i] }.to_h
|
760
765
|
buffer.mark_dirty if buffer
|
761
766
|
end
|
762
|
-
|
767
|
+
|
763
768
|
def authors; map { |m, *o| m.from if m }.compact.uniq; end
|
764
769
|
|
770
|
+
## preserve author order from the thread
|
765
771
|
def author_names_and_newness_for_thread t, limit=nil
|
766
772
|
new = {}
|
767
|
-
|
768
|
-
t.
|
769
|
-
next unless m
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
773
|
+
seen = {}
|
774
|
+
authors = t.map do |m, *o|
|
775
|
+
next unless m && m.from
|
776
|
+
new[m.from] ||= m.has_label?(:unread)
|
777
|
+
next if seen[m.from]
|
778
|
+
seen[m.from] = true
|
779
|
+
m.from
|
780
|
+
end.compact
|
781
|
+
|
782
|
+
result = []
|
783
|
+
authors.each do |a|
|
784
|
+
break if limit && result.size >= limit
|
785
|
+
name = if AccountManager.is_account?(a)
|
786
|
+
"me"
|
787
|
+
elsif t.authors.size == 1
|
788
|
+
a.mediumname
|
789
|
+
else
|
790
|
+
a.shortname
|
791
|
+
end
|
780
792
|
|
781
|
-
new[
|
782
|
-
authors << name
|
793
|
+
result << [name, new[a]]
|
783
794
|
end
|
784
795
|
|
785
|
-
|
796
|
+
result
|
786
797
|
end
|
787
798
|
|
788
799
|
AUTHOR_LIMIT = 5
|
@@ -843,7 +854,7 @@ protected
|
|
843
854
|
|
844
855
|
[
|
845
856
|
[:tagged_color, @tags.tagged?(t) ? ">" : " "],
|
846
|
-
[:
|
857
|
+
[:date_color, sprintf("%#{@date_width}s", date)],
|
847
858
|
(starred ? [:starred_color, "*"] : [:none, " "]),
|
848
859
|
] +
|
849
860
|
from +
|
@@ -58,6 +58,7 @@ EOS
|
|
58
58
|
k.add :alias, "Edit alias/nickname for a person", 'i'
|
59
59
|
k.add :edit_as_new, "Edit message as new", 'D'
|
60
60
|
k.add :save_to_disk, "Save message/attachment to disk", 's'
|
61
|
+
k.add :save_all_to_disk, "Save all attachments to disk", 'A'
|
61
62
|
k.add :search, "Search for messages from particular people", 'S'
|
62
63
|
k.add :compose, "Compose message to person", 'm'
|
63
64
|
k.add :subscribe_to_list, "Subscribe to/unsubscribe from mailing list", "("
|
@@ -66,6 +67,7 @@ EOS
|
|
66
67
|
|
67
68
|
k.add :archive_and_next, "Archive this thread, kill buffer, and view next", 'a'
|
68
69
|
k.add :delete_and_next, "Delete this thread, kill buffer, and view next", 'd'
|
70
|
+
k.add :toggle_wrap, "Toggle wrapping of text", 'w'
|
69
71
|
|
70
72
|
k.add_multi "(a)rchive/(d)elete/mark as (s)pam/mark as u(N)read:", '.' do |kk|
|
71
73
|
kk.add :archive_and_kill, "Archive this thread and kill buffer", 'a'
|
@@ -127,11 +129,19 @@ EOS
|
|
127
129
|
end
|
128
130
|
end
|
129
131
|
|
132
|
+
@wrap = true
|
133
|
+
|
130
134
|
@layout[latest].state = :open if @layout[latest].state == :closed
|
131
135
|
@layout[earliest].state = :detailed if earliest.has_label?(:unread) || @thread.size == 1
|
132
136
|
|
133
137
|
@thread.remove_label :unread
|
138
|
+
Index.save_thread @thread
|
139
|
+
end
|
140
|
+
|
141
|
+
def toggle_wrap
|
142
|
+
@wrap = !@wrap
|
134
143
|
regen_text
|
144
|
+
buffer.mark_dirty if buffer
|
135
145
|
end
|
136
146
|
|
137
147
|
def draw_line ln, opts={}
|
@@ -144,17 +154,25 @@ EOS
|
|
144
154
|
def lines; @text.length; end
|
145
155
|
def [] i; @text[i]; end
|
146
156
|
|
157
|
+
## a little hacky---since regen_text can depend on buffer features like the
|
158
|
+
## content_width, we don't call it in the constructor, and instead call it
|
159
|
+
## here, which is set before we're responsible for drawing ourself.
|
160
|
+
def buffer= b
|
161
|
+
super
|
162
|
+
regen_text
|
163
|
+
end
|
164
|
+
|
147
165
|
def show_header
|
148
166
|
m = @message_lines[curpos] or return
|
149
167
|
BufferManager.spawn_unless_exists("Full header for #{m.id}") do
|
150
|
-
TextMode.new m.raw_header
|
168
|
+
TextMode.new m.raw_header.ascii
|
151
169
|
end
|
152
170
|
end
|
153
171
|
|
154
172
|
def show_message
|
155
173
|
m = @message_lines[curpos] or return
|
156
174
|
BufferManager.spawn_unless_exists("Raw message for #{m.id}") do
|
157
|
-
TextMode.new m.raw_message
|
175
|
+
TextMode.new m.raw_message.ascii
|
158
176
|
end
|
159
177
|
end
|
160
178
|
|
@@ -258,8 +276,10 @@ EOS
|
|
258
276
|
new_labels.each { |l| LabelManager << l }
|
259
277
|
update
|
260
278
|
UpdateManager.relay self, :labeled, @thread.first
|
279
|
+
Index.save_thread @thread
|
261
280
|
UndoManager.register "labeling thread" do
|
262
281
|
@thread.labels = old_labels
|
282
|
+
Index.save_thread @thread
|
263
283
|
UpdateManager.relay self, :labeled, @thread.first
|
264
284
|
end
|
265
285
|
end
|
@@ -284,6 +304,7 @@ EOS
|
|
284
304
|
## star to the display
|
285
305
|
update
|
286
306
|
UpdateManager.relay self, :single_message_labeled, m
|
307
|
+
Index.save_thread @thread
|
287
308
|
end
|
288
309
|
|
289
310
|
## called when someone presses enter when the cursor is highlighting
|
@@ -326,8 +347,10 @@ EOS
|
|
326
347
|
chunk = @chunk_lines[curpos] or return
|
327
348
|
case chunk
|
328
349
|
when Chunk::Attachment
|
329
|
-
default_dir =
|
330
|
-
|
350
|
+
default_dir = $config[:default_attachment_save_dir]
|
351
|
+
default_dir = ENV["HOME"] if default_dir.nil? || default_dir.empty?
|
352
|
+
default_fn = File.expand_path File.join(default_dir, chunk.filename)
|
353
|
+
fn = BufferManager.ask_for_filename :filename, "Save attachment to file: ", default_fn
|
331
354
|
save_to_file(fn) { |f| f.print chunk.raw_content } if fn
|
332
355
|
else
|
333
356
|
m = @message_lines[curpos]
|
@@ -339,6 +362,32 @@ EOS
|
|
339
362
|
end
|
340
363
|
end
|
341
364
|
|
365
|
+
def save_all_to_disk
|
366
|
+
m = @message_lines[curpos] or return
|
367
|
+
default_dir = ($config[:default_attachment_save_dir] || ".")
|
368
|
+
folder = BufferManager.ask_for_filename :filename, "Save all attachments to folder: ", default_dir, true
|
369
|
+
return unless folder
|
370
|
+
|
371
|
+
num = 0
|
372
|
+
num_errors = 0
|
373
|
+
m.chunks.each do |chunk|
|
374
|
+
next unless chunk.is_a?(Chunk::Attachment)
|
375
|
+
fn = File.join(folder, chunk.filename)
|
376
|
+
num_errors += 1 unless save_to_file(fn, false) { |f| f.print chunk.raw_content }
|
377
|
+
num += 1
|
378
|
+
end
|
379
|
+
|
380
|
+
if num == 0
|
381
|
+
BufferManager.flash "Didn't find any attachments!"
|
382
|
+
else
|
383
|
+
if num_errors == 0
|
384
|
+
BufferManager.flash "Wrote #{num.pluralize 'attachment'} to #{folder}."
|
385
|
+
else
|
386
|
+
BufferManager.flash "Wrote #{(num - num_errors).pluralize 'attachment'} to #{folder}; couldn't write #{num_errors} of them (see log)."
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
342
391
|
def edit_draft
|
343
392
|
m = @message_lines[curpos] or return
|
344
393
|
if m.is_draft?
|
@@ -476,8 +525,10 @@ EOS
|
|
476
525
|
dispatch op do
|
477
526
|
@thread.remove_label :inbox
|
478
527
|
UpdateManager.relay self, :archived, @thread.first
|
528
|
+
Index.save_thread @thread
|
479
529
|
UndoManager.register "archiving 1 thread" do
|
480
530
|
@thread.apply_label :inbox
|
531
|
+
Index.save_thread @thread
|
481
532
|
UpdateManager.relay self, :unarchived, @thread.first
|
482
533
|
end
|
483
534
|
end
|
@@ -487,8 +538,10 @@ EOS
|
|
487
538
|
dispatch op do
|
488
539
|
@thread.apply_label :spam
|
489
540
|
UpdateManager.relay self, :spammed, @thread.first
|
541
|
+
Index.save_thread @thread
|
490
542
|
UndoManager.register "marking 1 thread as spam" do
|
491
543
|
@thread.remove_label :spam
|
544
|
+
Index.save_thread @thread
|
492
545
|
UpdateManager.relay self, :unspammed, @thread.first
|
493
546
|
end
|
494
547
|
end
|
@@ -498,8 +551,10 @@ EOS
|
|
498
551
|
dispatch op do
|
499
552
|
@thread.apply_label :deleted
|
500
553
|
UpdateManager.relay self, :deleted, @thread.first
|
554
|
+
Index.save_thread @thread
|
501
555
|
UndoManager.register "deleting 1 thread" do
|
502
556
|
@thread.remove_label :deleted
|
557
|
+
Index.save_thread @thread
|
503
558
|
UpdateManager.relay self, :undeleted, @thread.first
|
504
559
|
end
|
505
560
|
end
|
@@ -509,6 +564,7 @@ EOS
|
|
509
564
|
dispatch op do
|
510
565
|
@thread.apply_label :unread
|
511
566
|
UpdateManager.relay self, :unread, @thread.first
|
567
|
+
Index.save_thread @thread
|
512
568
|
end
|
513
569
|
end
|
514
570
|
|
@@ -557,7 +613,7 @@ EOS
|
|
557
613
|
end
|
558
614
|
|
559
615
|
if output
|
560
|
-
BufferManager.spawn "Output of '#{command}'", TextMode.new(output)
|
616
|
+
BufferManager.spawn "Output of '#{command}'", TextMode.new(output.ascii)
|
561
617
|
else
|
562
618
|
BufferManager.flash "'#{command}' done!"
|
563
619
|
end
|
@@ -734,7 +790,12 @@ private
|
|
734
790
|
else
|
735
791
|
raise "Bad chunk: #{chunk.inspect}" unless chunk.respond_to?(:inlineable?) ## debugging
|
736
792
|
if chunk.inlineable?
|
737
|
-
|
793
|
+
lines = chunk.lines
|
794
|
+
if @wrap
|
795
|
+
width = buffer.content_width
|
796
|
+
lines = lines.map { |l| l.chomp.wrap width }.flatten
|
797
|
+
end
|
798
|
+
lines.map { |line| [[chunk.color, "#{prefix}#{line}"]] }
|
738
799
|
elsif chunk.expandable?
|
739
800
|
case state
|
740
801
|
when :closed
|
@@ -754,7 +815,7 @@ private
|
|
754
815
|
BufferManager.erase_flash
|
755
816
|
BufferManager.completely_redraw_screen
|
756
817
|
unless success
|
757
|
-
BufferManager.spawn "Attachment: #{chunk.filename}", TextMode.new(chunk.to_s, chunk.filename)
|
818
|
+
BufferManager.spawn "Attachment: #{chunk.filename}", TextMode.new(chunk.to_s.ascii, chunk.filename)
|
758
819
|
BufferManager.flash "Couldn't execute view command, viewing as text."
|
759
820
|
end
|
760
821
|
end
|