sup 0.4 → 0.5
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/History.txt +8 -0
- data/Manifest.txt +1 -0
- data/Rakefile +11 -3
- data/ReleaseNotes +6 -0
- data/bin/sup +21 -6
- data/bin/sup-sync +3 -2
- data/bin/sup-sync-back +5 -1
- data/doc/FAQ.txt +1 -1
- data/lib/sup.rb +4 -3
- data/lib/sup/buffer.rb +14 -3
- data/lib/sup/contact.rb +1 -1
- data/lib/sup/crypto.rb +1 -1
- data/lib/sup/hook.rb +1 -1
- data/lib/sup/imap.rb +1 -1
- data/lib/sup/index.rb +62 -33
- data/lib/sup/maildir.rb +13 -11
- data/lib/sup/mbox.rb +20 -19
- data/lib/sup/mbox/loader.rb +3 -2
- data/lib/sup/mbox/ssh-file.rb +1 -0
- data/lib/sup/message-chunks.rb +4 -2
- data/lib/sup/message.rb +16 -8
- data/lib/sup/modes/compose-mode.rb +1 -1
- data/lib/sup/modes/contact-list-mode.rb +1 -1
- data/lib/sup/modes/edit-message-mode.rb +7 -3
- data/lib/sup/modes/inbox-mode.rb +1 -1
- data/lib/sup/modes/label-search-results-mode.rb +2 -2
- data/lib/sup/modes/reply-mode.rb +4 -0
- data/lib/sup/modes/scroll-mode.rb +22 -7
- data/lib/sup/modes/search-results-mode.rb +3 -3
- data/lib/sup/modes/thread-index-mode.rb +66 -22
- data/lib/sup/modes/thread-view-mode.rb +36 -16
- data/lib/sup/person.rb +6 -2
- data/lib/sup/poll.rb +3 -3
- data/lib/sup/sent.rb +3 -4
- data/lib/sup/tagger.rb +4 -2
- data/lib/sup/textfield.rb +1 -1
- data/lib/sup/thread.rb +4 -10
- data/test/test_maildir.rb +25 -0
- metadata +4 -2
@@ -49,20 +49,28 @@ EOS
|
|
49
49
|
k.add :unsubscribe_from_list, "Subscribe to/unsubscribe from mailing list", ")"
|
50
50
|
k.add :pipe_message, "Pipe message or attachment to a shell command", '|'
|
51
51
|
|
52
|
-
k.add_multi "(
|
52
|
+
k.add_multi "(a)rchive/(d)elete/mark as (s)pam/mark as u(N)read:", '.' do |kk|
|
53
53
|
kk.add :archive_and_kill, "Archive this thread and kill buffer", 'a'
|
54
54
|
kk.add :delete_and_kill, "Delete this thread and kill buffer", 'd'
|
55
55
|
kk.add :spam_and_kill, "Mark this thread as spam and kill buffer", 's'
|
56
56
|
kk.add :unread_and_kill, "Mark this thread as unread and kill buffer", 'N'
|
57
57
|
end
|
58
58
|
|
59
|
-
k.add_multi "(
|
59
|
+
k.add_multi "(a)rchive/(d)elete/mark as (s)pam/mark as u(N)read/do (n)othing:", ',' do |kk|
|
60
60
|
kk.add :archive_and_next, "Archive this thread, kill buffer, and view next", 'a'
|
61
61
|
kk.add :delete_and_next, "Delete this thread, kill buffer, and view next", 'd'
|
62
62
|
kk.add :spam_and_next, "Mark this thread as spam, kill buffer, and view next", 's'
|
63
63
|
kk.add :unread_and_next, "Mark this thread as unread, kill buffer, and view next", 'N'
|
64
64
|
kk.add :do_nothing_and_next, "Kill buffer, and view next", 'n'
|
65
65
|
end
|
66
|
+
|
67
|
+
k.add_multi "(a)rchive/(d)elete/mark as (s)pam/mark as u(N)read/do (n)othing:", ']' do |kk|
|
68
|
+
kk.add :archive_and_prev, "Archive this thread, kill buffer, and view previous", 'a'
|
69
|
+
kk.add :delete_and_prev, "Delete this thread, kill buffer, and view previous", 'd'
|
70
|
+
kk.add :spam_and_prev, "Mark this thread as spam, kill buffer, and view previous", 's'
|
71
|
+
kk.add :unread_and_prev, "Mark this thread as unread, kill buffer, and view previous", 'N'
|
72
|
+
kk.add :do_nothing_and_prev, "Kill buffer, and view previous", 'n'
|
73
|
+
end
|
66
74
|
end
|
67
75
|
|
68
76
|
## there are a couple important instance variables we hold to format
|
@@ -318,6 +326,8 @@ EOS
|
|
318
326
|
end
|
319
327
|
end
|
320
328
|
|
329
|
+
IDEAL_TOP_CONTEXT = 3 # try and give 3 rows of top context
|
330
|
+
IDEAL_LEFT_CONTEXT = 4 # try and give 4 columns of left context
|
321
331
|
def jump_to_message m, loose_alignment=false
|
322
332
|
l = @layout[m]
|
323
333
|
left = l.depth * INDENT_SPACES
|
@@ -325,19 +335,20 @@ EOS
|
|
325
335
|
|
326
336
|
## jump to the top line
|
327
337
|
if loose_alignment
|
328
|
-
jump_to_line [l.top -
|
338
|
+
jump_to_line [l.top - IDEAL_TOP_CONTEXT, 0].max # give 3 lines of top context
|
329
339
|
else
|
330
340
|
jump_to_line l.top
|
331
341
|
end
|
332
342
|
|
333
343
|
## jump to the left column
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
344
|
+
ideal_left = left +
|
345
|
+
if loose_alignment
|
346
|
+
-IDEAL_LEFT_CONTEXT + (l.width - buffer.content_width + IDEAL_LEFT_CONTEXT + 1).clamp(0, IDEAL_LEFT_CONTEXT)
|
347
|
+
else
|
348
|
+
0
|
349
|
+
end
|
350
|
+
|
351
|
+
jump_to_col [ideal_left, 0].max
|
341
352
|
|
342
353
|
## either way, move the cursor to the first line
|
343
354
|
set_cursor_pos l.top
|
@@ -380,6 +391,12 @@ EOS
|
|
380
391
|
def unread_and_next; unread_and_then :next end
|
381
392
|
def do_nothing_and_next; do_nothing_and_then :next end
|
382
393
|
|
394
|
+
def archive_and_prev; archive_and_then :prev end
|
395
|
+
def spam_and_prev; spam_and_then :prev end
|
396
|
+
def delete_and_prev; delete_and_then :prev end
|
397
|
+
def unread_and_prev; unread_and_then :prev end
|
398
|
+
def do_nothing_and_prev; do_nothing_and_then :prev end
|
399
|
+
|
383
400
|
def archive_and_then op
|
384
401
|
dispatch op do
|
385
402
|
@thread.remove_label :inbox
|
@@ -416,15 +433,18 @@ EOS
|
|
416
433
|
return if @dying
|
417
434
|
@dying = true
|
418
435
|
|
436
|
+
l = lambda do
|
437
|
+
yield if block_given?
|
438
|
+
BufferManager.kill_buffer_safely buffer
|
439
|
+
end
|
440
|
+
|
419
441
|
case op
|
420
442
|
when :next
|
421
|
-
@index_mode.launch_next_thread_after
|
422
|
-
|
423
|
-
|
424
|
-
end
|
443
|
+
@index_mode.launch_next_thread_after @thread, &l
|
444
|
+
when :prev
|
445
|
+
@index_mode.launch_prev_thread_before @thread, &l
|
425
446
|
when :kill
|
426
|
-
|
427
|
-
BufferManager.kill_buffer_safely buffer
|
447
|
+
l.call
|
428
448
|
else
|
429
449
|
raise ArgumentError, "unknown thread dispatch operation #{op.inspect}"
|
430
450
|
end
|
data/lib/sup/person.rb
CHANGED
@@ -9,7 +9,7 @@ class PersonManager
|
|
9
9
|
|
10
10
|
## read in stored people
|
11
11
|
IO.readlines(fn).map do |l|
|
12
|
-
l =~ /^(.*)?:\s+(\d+)\s+(.*)$/ or
|
12
|
+
l =~ /^(.*)?:\s+(\d+)\s+(.*)$/ or next
|
13
13
|
email, time, name = $1, $2, $3
|
14
14
|
@@people[email] = Person.new name, email, time, false
|
15
15
|
end if File.exists? fn
|
@@ -21,7 +21,7 @@ class PersonManager
|
|
21
21
|
File.open(@fn, "w") do |f|
|
22
22
|
@@people.each do |email, p|
|
23
23
|
next if p.email == p.name
|
24
|
-
next if p.
|
24
|
+
next if p.name =~ /=/ # drop rfc2047-encoded, and lots of other useless emails. definitely a heuristic.
|
25
25
|
f.puts "#{p.email}: #{p.timestamp} #{p.name}"
|
26
26
|
end
|
27
27
|
end
|
@@ -162,6 +162,10 @@ class Person
|
|
162
162
|
Person.new name, email
|
163
163
|
end
|
164
164
|
|
165
|
+
def indexable_content
|
166
|
+
[name, email, email.split(/@/).first].join(" ")
|
167
|
+
end
|
168
|
+
|
165
169
|
def eql? o; email.eql? o.email end
|
166
170
|
def hash; email.hash end
|
167
171
|
end
|
data/lib/sup/poll.rb
CHANGED
@@ -134,7 +134,7 @@ EOS
|
|
134
134
|
## labels. it is likely that callers will want to replace these with
|
135
135
|
## the index labels, if they exist, so that state is not lost when
|
136
136
|
## e.g. a new version of a message from a mailing list comes in.
|
137
|
-
def add_messages_from source
|
137
|
+
def add_messages_from source, opts={}
|
138
138
|
begin
|
139
139
|
return if source.done? || source.has_errors?
|
140
140
|
|
@@ -156,8 +156,8 @@ EOS
|
|
156
156
|
|
157
157
|
docid, entry = Index.load_entry_for_id m.id
|
158
158
|
HookManager.run "before-add-message", :message => m
|
159
|
-
m = yield(m, offset, entry) or next
|
160
|
-
Index.sync_message m, docid, entry
|
159
|
+
m = yield(m, offset, entry) or next if block_given?
|
160
|
+
Index.sync_message m, docid, entry, opts
|
161
161
|
UpdateManager.relay self, :added, m unless entry
|
162
162
|
rescue MessageFormatError => e
|
163
163
|
Redwood::log "ignoring erroneous message at #{source}##{offset}: #{e.message}"
|
data/lib/sup/sent.rb
CHANGED
@@ -22,10 +22,9 @@ class SentManager
|
|
22
22
|
yield f
|
23
23
|
end
|
24
24
|
|
25
|
-
@source
|
26
|
-
m
|
27
|
-
|
28
|
-
UpdateManager.relay self, :added, m
|
25
|
+
PollManager.add_messages_from(@source) do |m, o, e|
|
26
|
+
m.remove_label :unread
|
27
|
+
m
|
29
28
|
end
|
30
29
|
end
|
31
30
|
end
|
data/lib/sup/tagger.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
module Redwood
|
2
2
|
|
3
3
|
class Tagger
|
4
|
-
def initialize mode
|
4
|
+
def initialize mode, noun="thread", plural_noun=nil
|
5
5
|
@mode = mode
|
6
6
|
@tagged = {}
|
7
|
+
@noun = noun
|
8
|
+
@plural_noun = plural_noun || (@noun + "s")
|
7
9
|
end
|
8
10
|
|
9
11
|
def tagged? o; @tagged[o]; end
|
@@ -21,7 +23,7 @@ class Tagger
|
|
21
23
|
return
|
22
24
|
end
|
23
25
|
|
24
|
-
noun = num_tagged == 1 ?
|
26
|
+
noun = num_tagged == 1 ? @noun : @plural_noun
|
25
27
|
|
26
28
|
unless action
|
27
29
|
c = BufferManager.ask_getch "apply to #{num_tagged} tagged #{noun}:"
|
data/lib/sup/textfield.rb
CHANGED
@@ -100,7 +100,7 @@ class TextField
|
|
100
100
|
Ncurses::Form::REQ_NEXT_CHAR
|
101
101
|
when Ncurses::KEY_DC
|
102
102
|
Ncurses::Form::REQ_DEL_CHAR
|
103
|
-
when Ncurses::KEY_BACKSPACE
|
103
|
+
when Ncurses::KEY_BACKSPACE, 127 # 127 is also a backspace keysym
|
104
104
|
Ncurses::Form::REQ_DEL_PREV
|
105
105
|
when 1 #ctrl-a
|
106
106
|
Ncurses::Form::REQ_BEG_FIELD
|
data/lib/sup/thread.rb
CHANGED
@@ -259,7 +259,7 @@ class ThreadSet
|
|
259
259
|
@thread_by_subj = thread_by_subj
|
260
260
|
end
|
261
261
|
|
262
|
-
def thread_for_id mid; (
|
262
|
+
def thread_for_id mid; @messages.member?(mid) && @messages[mid].root.thread end
|
263
263
|
def contains_id? id; @messages.member?(id) && !@messages[id].empty? end
|
264
264
|
def thread_for m; thread_for_id m.id end
|
265
265
|
def contains? m; contains_id? m.id end
|
@@ -324,7 +324,7 @@ class ThreadSet
|
|
324
324
|
## load in (at most) num number of threads from the index
|
325
325
|
def load_n_threads num, opts={}
|
326
326
|
@index.each_id_by_date opts do |mid, builder|
|
327
|
-
break if size >= num
|
327
|
+
break if size >= num unless num == -1
|
328
328
|
next if contains_id? mid
|
329
329
|
|
330
330
|
m = builder.call
|
@@ -415,14 +415,8 @@ class ThreadSet
|
|
415
415
|
## that we first added a child message with a different
|
416
416
|
## subject)
|
417
417
|
if root.thread
|
418
|
-
|
419
|
-
|
420
|
-
root.thread.empty!
|
421
|
-
@threads[key] << root
|
422
|
-
root.thread = @threads[key]
|
423
|
-
else
|
424
|
-
@threads[key] = root.thread
|
425
|
-
end
|
418
|
+
if @threads.member?(key) && @threads[key] != root.thread
|
419
|
+
@threads.delete key
|
426
420
|
end
|
427
421
|
else
|
428
422
|
thread = @threads[key]
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'sup'
|
5
|
+
require 'mockfs/override.rb'
|
6
|
+
|
7
|
+
module Redwood
|
8
|
+
class TestMaildir < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def setup
|
11
|
+
MockFS.mock = true
|
12
|
+
MockFS.dir.mkdir "maildir-test"
|
13
|
+
MockFS.dir.mkdir "maildir-test/cur"
|
14
|
+
MockFS.dir.mkdir "maildir-test/tmp"
|
15
|
+
MockFS.dir.mkdir "maildir-test/new"
|
16
|
+
end
|
17
|
+
|
18
|
+
def teardown
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_empty_maildir
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "0.
|
4
|
+
version: "0.5"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- William Morgan
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-04-22 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -121,6 +121,7 @@ files:
|
|
121
121
|
- Manifest.txt
|
122
122
|
- README.txt
|
123
123
|
- Rakefile
|
124
|
+
- ReleaseNotes
|
124
125
|
- bin/sup
|
125
126
|
- bin/sup-add
|
126
127
|
- bin/sup-config
|
@@ -218,3 +219,4 @@ specification_version: 2
|
|
218
219
|
summary: A console-based email client with the best features of GMail, mutt, and emacs. Features full text search, labels, tagged operations, multiple buffers, recent contacts, and more.
|
219
220
|
test_files:
|
220
221
|
- test/test_message.rb
|
222
|
+
- test/test_maildir.rb
|