sup 0.1 → 0.2
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 +9 -0
- data/Manifest.txt +5 -1
- data/Rakefile +2 -1
- data/bin/sup +27 -10
- data/bin/sup-add +2 -1
- data/bin/sup-sync-back +51 -23
- data/doc/FAQ.txt +29 -37
- data/doc/Hooks.txt +38 -0
- data/doc/{UserGuide.txt → NewUserGuide.txt} +27 -21
- data/doc/TODO +91 -57
- data/lib/sup.rb +17 -1
- data/lib/sup/buffer.rb +80 -16
- data/lib/sup/colormap.rb +0 -2
- data/lib/sup/contact.rb +3 -2
- data/lib/sup/crypto.rb +110 -0
- data/lib/sup/draft.rb +2 -6
- data/lib/sup/hook.rb +131 -0
- data/lib/sup/imap.rb +27 -16
- data/lib/sup/index.rb +38 -14
- data/lib/sup/keymap.rb +0 -2
- data/lib/sup/label.rb +30 -9
- data/lib/sup/logger.rb +12 -1
- data/lib/sup/maildir.rb +48 -3
- data/lib/sup/mbox.rb +1 -1
- data/lib/sup/mbox/loader.rb +22 -12
- data/lib/sup/mbox/ssh-loader.rb +1 -1
- data/lib/sup/message-chunks.rb +198 -0
- data/lib/sup/message.rb +154 -115
- data/lib/sup/modes/compose-mode.rb +18 -0
- data/lib/sup/modes/contact-list-mode.rb +1 -1
- data/lib/sup/modes/edit-message-mode.rb +112 -31
- data/lib/sup/modes/file-browser-mode.rb +1 -1
- data/lib/sup/modes/inbox-mode.rb +1 -1
- data/lib/sup/modes/label-list-mode.rb +8 -6
- data/lib/sup/modes/label-search-results-mode.rb +4 -1
- data/lib/sup/modes/log-mode.rb +1 -1
- data/lib/sup/modes/reply-mode.rb +18 -16
- data/lib/sup/modes/search-results-mode.rb +1 -1
- data/lib/sup/modes/thread-index-mode.rb +61 -33
- data/lib/sup/modes/thread-view-mode.rb +111 -102
- data/lib/sup/person.rb +5 -1
- data/lib/sup/poll.rb +36 -7
- data/lib/sup/sent.rb +1 -0
- data/lib/sup/source.rb +7 -3
- data/lib/sup/textfield.rb +48 -34
- data/lib/sup/thread.rb +9 -5
- data/lib/sup/util.rb +16 -22
- metadata +7 -3
data/History.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
== 0.2 / 2007-10-29
|
2
|
+
* Complete hook system for user-inserted code.
|
3
|
+
* GPG signature verification and decryption.
|
4
|
+
* Automatically scold users who top-post.
|
5
|
+
* Automatically warn when sending a message with words like
|
6
|
+
"attachment" in the body if there aren't actually any attachments to
|
7
|
+
the message.
|
8
|
+
* Millions of bugfixes.
|
9
|
+
|
1
10
|
== 0.1 / 2007-07-17
|
2
11
|
* MIME attachment creation.
|
3
12
|
* i18n support: character set conversion and rfc2047 header decoding.
|
data/Manifest.txt
CHANGED
@@ -12,15 +12,18 @@ bin/sup-recover-sources
|
|
12
12
|
bin/sup-sync
|
13
13
|
bin/sup-sync-back
|
14
14
|
doc/FAQ.txt
|
15
|
+
doc/Hooks.txt
|
16
|
+
doc/NewUserGuide.txt
|
15
17
|
doc/Philosophy.txt
|
16
18
|
doc/TODO
|
17
|
-
doc/UserGuide.txt
|
18
19
|
lib/sup.rb
|
19
20
|
lib/sup/account.rb
|
20
21
|
lib/sup/buffer.rb
|
21
22
|
lib/sup/colormap.rb
|
22
23
|
lib/sup/contact.rb
|
24
|
+
lib/sup/crypto.rb
|
23
25
|
lib/sup/draft.rb
|
26
|
+
lib/sup/hook.rb
|
24
27
|
lib/sup/imap.rb
|
25
28
|
lib/sup/index.rb
|
26
29
|
lib/sup/keymap.rb
|
@@ -31,6 +34,7 @@ lib/sup/mbox.rb
|
|
31
34
|
lib/sup/mbox/loader.rb
|
32
35
|
lib/sup/mbox/ssh-file.rb
|
33
36
|
lib/sup/mbox/ssh-loader.rb
|
37
|
+
lib/sup/message-chunks.rb
|
34
38
|
lib/sup/message.rb
|
35
39
|
lib/sup/mode.rb
|
36
40
|
lib/sup/modes/buffer-list-mode.rb
|
data/Rakefile
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'hoe'
|
5
|
+
$:.unshift 'lib' # force loading from ./lib/ if it exists
|
5
6
|
require 'sup'
|
6
7
|
|
7
8
|
class Hoe
|
@@ -23,7 +24,7 @@ rule 'ss?.png' => 'ss?-small.png' do |t|
|
|
23
24
|
end
|
24
25
|
|
25
26
|
## is there really no way to make a rule for this?
|
26
|
-
WWW_FILES = %w(www/index.html README.txt doc/Philosophy.txt doc/FAQ.txt doc/
|
27
|
+
WWW_FILES = %w(www/index.html README.txt doc/Philosophy.txt doc/FAQ.txt doc/NewUserGuide.txt www/main.css)
|
27
28
|
|
28
29
|
SCREENSHOTS = FileList["www/ss?.png"]
|
29
30
|
SCREENSHOTS_SMALL = []
|
data/bin/sup
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'ncurses'
|
5
|
+
require 'curses'
|
5
6
|
require 'fileutils'
|
6
7
|
require 'trollop'
|
7
8
|
require "sup"
|
@@ -16,9 +17,15 @@ Usage:
|
|
16
17
|
|
17
18
|
Options are:
|
18
19
|
EOS
|
20
|
+
opt :list_hooks, "List all hooks and descriptions thereof, and quit."
|
19
21
|
opt :no_threads, "Turn of threading. Helps with debugging. (Necessarily disables background polling for new messages.)"
|
20
22
|
end
|
21
23
|
|
24
|
+
if $opts[:list_hooks]
|
25
|
+
Redwood::HookManager.print_hooks
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
|
22
29
|
Thread.abort_on_exception = true # make debugging possible
|
23
30
|
|
24
31
|
module Redwood
|
@@ -85,6 +92,7 @@ EOS
|
|
85
92
|
end
|
86
93
|
|
87
94
|
begin
|
95
|
+
extend CanSpawnComposeMode
|
88
96
|
Redwood::start
|
89
97
|
Index.load
|
90
98
|
|
@@ -120,6 +128,10 @@ begin
|
|
120
128
|
c.add :alternate_patina_color, Ncurses::COLOR_BLACK, Ncurses::COLOR_BLUE
|
121
129
|
c.add :missing_message_color, Ncurses::COLOR_BLACK, Ncurses::COLOR_RED
|
122
130
|
c.add :attachment_color, Ncurses::COLOR_CYAN, Ncurses::COLOR_BLACK
|
131
|
+
c.add :cryptosig_valid_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK, Ncurses::A_BOLD
|
132
|
+
c.add :cryptosig_unknown_color, Ncurses::COLOR_CYAN, Ncurses::COLOR_BLACK
|
133
|
+
c.add :cryptosig_invalid_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_RED, Ncurses::A_BOLD
|
134
|
+
c.add :generic_notice_patina_color, Ncurses::COLOR_CYAN, Ncurses::COLOR_BLACK
|
123
135
|
c.add :quote_patina_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK
|
124
136
|
c.add :sig_patina_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK
|
125
137
|
c.add :quote_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK
|
@@ -139,6 +151,9 @@ begin
|
|
139
151
|
Ncurses::A_BOLD
|
140
152
|
c.add :completion_character_color, Ncurses::COLOR_WHITE,
|
141
153
|
Ncurses::COLOR_BLACK, Ncurses::A_BOLD
|
154
|
+
c.add :reply_mode_selected_color, Ncurses::COLOR_YELLOW, Ncurses::COLOR_BLACK, Ncurses::A_BOLD
|
155
|
+
c.add :reply_mode_unselected_color, Ncurses::COLOR_CYAN, Ncurses::COLOR_BLACK
|
156
|
+
c.add :reply_mode_label_color, Ncurses::COLOR_CYAN, Ncurses::COLOR_BLACK
|
142
157
|
end
|
143
158
|
|
144
159
|
log "initializing buffer manager"
|
@@ -217,28 +232,30 @@ begin
|
|
217
232
|
bm.flash "Couldn't parse query."
|
218
233
|
end
|
219
234
|
when :list_labels
|
220
|
-
labels = LabelManager.
|
235
|
+
labels = LabelManager.listable_labels.map { |l| LabelManager.string_for l }
|
221
236
|
user_label = bm.ask_with_completions :label, "Show threads with label (enter for listing): ", labels
|
222
|
-
user_label =
|
237
|
+
user_label =
|
238
|
+
case user_label
|
239
|
+
when nil, /^\s*$/
|
240
|
+
bm.spawn_modal("Label list", LabelListMode.new) if user_label && user_label.empty?
|
241
|
+
else
|
242
|
+
LabelManager.label_for user_label
|
243
|
+
end
|
223
244
|
|
224
|
-
|
225
|
-
case label
|
245
|
+
case user_label
|
226
246
|
when nil
|
227
247
|
when :inbox
|
228
248
|
BufferManager.raise_to_front InboxMode.instance.buffer
|
229
249
|
else
|
230
250
|
b = BufferManager.spawn_unless_exists("All threads with label '#{user_label}'") do
|
231
|
-
mode = LabelSearchResultsMode.new([
|
251
|
+
mode = LabelSearchResultsMode.new([user_label])
|
232
252
|
end
|
233
253
|
b.mode.load_threads :num => b.content_height
|
234
254
|
end
|
235
255
|
|
236
256
|
when :compose
|
237
|
-
|
238
|
-
bm.spawn "New Message", mode
|
239
|
-
mode.edit
|
257
|
+
spawn_compose_mode
|
240
258
|
when :poll
|
241
|
-
# bm.raise_to_front PollManager.buffer
|
242
259
|
reporting_thread { PollManager.poll }
|
243
260
|
when :recall_draft
|
244
261
|
case Index.num_results_for :label => :draft
|
@@ -249,7 +266,7 @@ begin
|
|
249
266
|
Index.each_id_by_date(:label => :draft) { |mid, builder| m = builder.call }
|
250
267
|
r = ResumeMode.new(m)
|
251
268
|
BufferManager.spawn "Edit message", r
|
252
|
-
r.
|
269
|
+
r.edit_message
|
253
270
|
else
|
254
271
|
b = BufferManager.spawn_unless_exists("All drafts") do
|
255
272
|
mode = LabelSearchResultsMode.new [:draft]
|
data/bin/sup-add
CHANGED
@@ -93,7 +93,6 @@ begin
|
|
93
93
|
end
|
94
94
|
|
95
95
|
parsed_uri = URI(uri)
|
96
|
-
Trollop::die "no path component to uri: #{parsed_uri}" unless parsed_uri.path
|
97
96
|
|
98
97
|
source =
|
99
98
|
case parsed_uri.scheme
|
@@ -109,6 +108,8 @@ begin
|
|
109
108
|
Redwood::Maildir.new uri, nil, !$opts[:unusual], $opts[:archive], nil, labels
|
110
109
|
when "mbox"
|
111
110
|
Redwood::MBox::Loader.new uri, nil, !$opts[:unusual], $opts[:archive], nil, labels
|
111
|
+
when nil
|
112
|
+
Trollop::die "Sources must be specified with an URI"
|
112
113
|
else
|
113
114
|
Trollop::die "Unknown source type #{parsed_uri.scheme.inspect}"
|
114
115
|
end
|
data/bin/sup-sync-back
CHANGED
@@ -8,14 +8,17 @@ require "sup"
|
|
8
8
|
|
9
9
|
## save a message 'm' to an open file pointer 'fp'
|
10
10
|
def save m, fp
|
11
|
-
m.source.
|
11
|
+
m.source.each_raw_message_line(m.source_info) { |l| fp.print l }
|
12
|
+
end
|
13
|
+
def die msg
|
14
|
+
$stderr.puts "Error: #{msg}"
|
15
|
+
exit(-1)
|
12
16
|
end
|
13
17
|
|
14
18
|
opts = Trollop::options do
|
15
19
|
version "sup-sync-back (sup #{Redwood::VERSION})"
|
16
20
|
banner <<EOS
|
17
|
-
|
18
|
-
or moving any messages from the source that are marked as deleted or
|
21
|
+
Drop or move messages from Sup sources that are marked as deleted or
|
19
22
|
spam in the Sup index.
|
20
23
|
|
21
24
|
Currently only works with mbox sources.
|
@@ -26,20 +29,30 @@ Usage:
|
|
26
29
|
where <source>* is zero or more source URIs. If no sources are given,
|
27
30
|
sync back all usual sources.
|
28
31
|
|
29
|
-
You
|
32
|
+
You almost certainly want to run sup-sync --changed after this command.
|
33
|
+
Running this does not change the index.
|
30
34
|
|
31
35
|
Options include:
|
32
36
|
EOS
|
33
|
-
opt :
|
37
|
+
opt :drop_deleted, "Drop deleted messages.", :default => false, :short => "d"
|
34
38
|
opt :move_deleted, "Move deleted messages to a local mbox file.", :type => String, :short => :none
|
35
|
-
opt :
|
39
|
+
opt :drop_spam, "Drop spam messages.", :default => false, :short => "s"
|
36
40
|
opt :move_spam, "Move spam messages to a local mbox file.", :type => String, :short => :none
|
41
|
+
|
42
|
+
opt :with_dotlockfile, "Specific dotlockfile location (mbox files only).", :default => "/usr/bin/dotlockfile", :short => :none
|
43
|
+
opt :dont_use_dotlockfile, "Don't use dotlockfile to lock mbox files. Dangerous if other processes modify them concurrently.", :default => false, :short => :none
|
44
|
+
|
37
45
|
opt :verbose, "Print message ids as they're processed."
|
38
46
|
opt :dry_run, "Don't actually modify the index. Probably only useful with --verbose.", :short => "-n"
|
39
47
|
opt :version, "Show version information", :short => :none
|
40
48
|
|
41
|
-
conflicts :
|
42
|
-
conflicts :
|
49
|
+
conflicts :drop_deleted, :move_deleted
|
50
|
+
conflicts :drop_spam, :move_spam
|
51
|
+
end
|
52
|
+
|
53
|
+
unless opts[:drop_deleted] || opts[:move_deleted] || opts[:drop_spam] || opts[:move_spam]
|
54
|
+
puts "Nothing to do."
|
55
|
+
exit
|
43
56
|
end
|
44
57
|
|
45
58
|
Redwood::start
|
@@ -52,12 +65,14 @@ unless opts[:dry_run]
|
|
52
65
|
spam_fp = File.open(opts[:move_spam], "a") if opts[:move_spam]
|
53
66
|
end
|
54
67
|
|
68
|
+
dotlockfile = opts[:with_dotlockfile] || "/usr/bin/dotlockfile"
|
69
|
+
|
55
70
|
begin
|
56
71
|
index.load
|
57
72
|
|
58
73
|
sources = ARGV.map do |uri|
|
59
|
-
s = index.source_for(uri) or
|
60
|
-
s.is_a?(Redwood::MBox::Loader) or
|
74
|
+
s = index.source_for(uri) or die "unknown source: #{uri}. Did you add it with sup-add first?"
|
75
|
+
s.is_a?(Redwood::MBox::Loader) or die "#{uri} is not an mbox source."
|
61
76
|
s
|
62
77
|
end
|
63
78
|
|
@@ -65,17 +80,25 @@ begin
|
|
65
80
|
sources = index.usual_sources.select { |s| s.is_a? Redwood::MBox::Loader }
|
66
81
|
end
|
67
82
|
|
83
|
+
unless sources.all? { |s| s.file_path.nil? } || File.executable?(dotlockfile) || opts[:dont_use_dotlockfile]
|
84
|
+
die <<EOS
|
85
|
+
can't execute dotlockfile binary: #{dotlockfile}. Specify --with-dotlockfile
|
86
|
+
if it's in a nonstandard location, or, if you want to live dangerously, try
|
87
|
+
--dont-use-dotlockfile
|
88
|
+
EOS
|
89
|
+
end
|
90
|
+
|
68
91
|
modified_sources = []
|
69
92
|
sources.each do |source|
|
70
93
|
$stderr.puts "Scanning #{source}..."
|
71
94
|
|
72
|
-
unless ((opts[:
|
95
|
+
unless ((opts[:drop_deleted] || opts[:move_deleted]) && index.has_any_from_source_with_label?(source, :deleted)) || ((opts[:drop_spam] || opts[:move_spam]) && index.has_any_from_source_with_label?(source, :spam))
|
73
96
|
$stderr.puts "Nothing to do from this source; skipping"
|
74
97
|
next
|
75
98
|
end
|
76
99
|
|
77
100
|
source.reset!
|
78
|
-
|
101
|
+
num_dropped = num_moved = num_scanned = 0
|
79
102
|
|
80
103
|
out_fp = Tempfile.new "sup-sync-back-#{source.id}"
|
81
104
|
Redwood::PollManager.add_messages_from source do |m, offset, entry|
|
@@ -85,9 +108,9 @@ begin
|
|
85
108
|
labels = entry[:label].split.map { |x| x.intern }.to_boolean_h
|
86
109
|
|
87
110
|
if labels.member? :deleted
|
88
|
-
if opts[:
|
111
|
+
if opts[:drop_deleted]
|
89
112
|
puts "Dropping deleted message #{source}##{offset}" if opts[:verbose]
|
90
|
-
|
113
|
+
num_dropped += 1
|
91
114
|
elsif opts[:move_deleted] && labels.member?(:deleted)
|
92
115
|
puts "Moving deleted message #{source}##{offset}" if opts[:verbose]
|
93
116
|
save m, deleted_fp unless opts[:dry_run]
|
@@ -95,9 +118,9 @@ begin
|
|
95
118
|
end
|
96
119
|
|
97
120
|
elsif labels.member? :spam
|
98
|
-
if opts[:
|
99
|
-
puts "
|
100
|
-
|
121
|
+
if opts[:drop_spam]
|
122
|
+
puts "Dropping spam message #{source}##{offset}" if opts[:verbose]
|
123
|
+
num_dropped += 1
|
101
124
|
elsif opts[:move_spam] && labels.member?(:spam)
|
102
125
|
puts "Moving spam message #{source}##{offset}" if opts[:verbose]
|
103
126
|
save m, spam_fp unless opts[:dry_run]
|
@@ -112,15 +135,21 @@ begin
|
|
112
135
|
|
113
136
|
nil # don't actually add anything!
|
114
137
|
end
|
115
|
-
$stderr.puts "Scanned #{num_scanned},
|
116
|
-
modified_sources << source if
|
138
|
+
$stderr.puts "Scanned #{num_scanned}, dropped #{num_dropped}, moved #{num_moved} messages from #{source}."
|
139
|
+
modified_sources << source if num_dropped > 0 || num_moved > 0
|
117
140
|
out_fp.close unless opts[:dry_run]
|
118
141
|
|
119
|
-
unless opts[:dry_run] || (
|
142
|
+
unless opts[:dry_run] || (num_dropped == 0 && num_moved == 0)
|
120
143
|
deleted_fp.flush if deleted_fp
|
121
144
|
spam_fp.flush if spam_fp
|
122
|
-
|
123
|
-
|
145
|
+
unless opts[:dont_use_dotlockfile]
|
146
|
+
puts "Locking #{source.file_path}..."
|
147
|
+
system "#{opts[:dotlockfile]} -l #{source.file_path}"
|
148
|
+
puts "Writing #{source.file_path}..."
|
149
|
+
FileUtils.cp out_fp.path, source.file_path
|
150
|
+
puts "Unlocking #{source.file_path}..."
|
151
|
+
system "#{opts[:dotlockfile]} -u #{source.file_path}"
|
152
|
+
end
|
124
153
|
end
|
125
154
|
end
|
126
155
|
|
@@ -137,7 +166,6 @@ rescue Exception => e
|
|
137
166
|
File.open("sup-exception-log.txt", "w") { |f| f.puts e.backtrace }
|
138
167
|
raise
|
139
168
|
ensure
|
140
|
-
index.save
|
141
169
|
Redwood::finish
|
142
170
|
index.unlock
|
143
171
|
end
|
data/doc/FAQ.txt
CHANGED
@@ -4,21 +4,22 @@ Sup FAQ
|
|
4
4
|
Q: What is Sup?
|
5
5
|
A: Sup is a console-based email client for people with a lot of email.
|
6
6
|
It supports tagging, very fast full-text search, automatic contact-
|
7
|
-
list management,
|
8
|
-
|
7
|
+
list management, custom code insertion via a hook system, and more.
|
8
|
+
If you're the type of person who treats email as an extension of your
|
9
|
+
long-term memory, Sup is for you.
|
9
10
|
|
10
11
|
Q: What does Sup stand for?
|
11
12
|
A: "What's up?"
|
12
13
|
|
13
|
-
Q: Sup looks
|
14
|
-
A: I stole
|
14
|
+
Q: Sup looks like a text-based Gmail.
|
15
|
+
A: I stole their ideas. And improved them!
|
15
16
|
|
16
|
-
Q:
|
17
|
-
A: I hate ads, I hate using a mouse, and I hate
|
18
|
-
and non-extensibility.
|
17
|
+
Q: Why not just use Gmail?
|
18
|
+
A: I wrote Sup because I hate ads, I hate using a mouse, and I hate
|
19
|
+
non-programmability and non-extensibility.
|
19
20
|
|
20
21
|
Also, Gmail doesn't let you use a monospace font, which is just
|
21
|
-
|
22
|
+
lame.
|
22
23
|
|
23
24
|
Also, Gmail encourages top-posting. THIS CANNOT BE TOLERATED!
|
24
25
|
|
@@ -43,17 +44,16 @@ Q: But I want to delete it for real, not just add a 'deleted' flag in
|
|
43
44
|
A: Currently, for mbox sources, there is a batch deletion tool that
|
44
45
|
will strip out all messages marked as spam or deleted.
|
45
46
|
|
46
|
-
Q:
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
47
|
+
Q: How well does Sup play with other mail clients?
|
48
|
+
A: Not well at all. If messages have been moved, deleted, or altered
|
49
|
+
due to some other client, Sup will have to rebuild its index for
|
50
|
+
that message source. For example, for mbox files, reading a single
|
51
|
+
unread message changes the offsets of every file on disk. Rather
|
52
|
+
than rescanning every time, Sup assumes sources don't change except
|
53
|
+
by having new messages added. If that assumption is violated,
|
54
|
+
you'll have to sync the index.
|
54
55
|
|
55
56
|
Q: How do I back up my index?
|
56
|
-
Q: How do I make a state dump?
|
57
57
|
A: Since the contents of the messages are recoverable from their
|
58
58
|
sources using sup-sync, all you need to back up is the message
|
59
59
|
state. To do this, simply run:
|
@@ -66,13 +66,10 @@ A: Run:
|
|
66
66
|
sup-sync [<source>+] --restored --restore <dumpfile>
|
67
67
|
where <dumpfile> was created as above.
|
68
68
|
|
69
|
-
Q: I upgraded Ferret and the index format changed. I need to
|
70
|
-
completely rebuild my index. How do I do this?
|
71
69
|
Q: Ferret crashed and I can't read my index. Luckily I made a state
|
72
70
|
dump. What should I do?
|
73
|
-
|
74
|
-
|
75
|
-
above. Then run these commands:
|
71
|
+
Q: How do I rebuild the index completely?
|
72
|
+
A: Run:
|
76
73
|
rm -rf ~/.sup/ferret # omg wtf
|
77
74
|
sup-sync --all-sources --all --restore <dumpfile>
|
78
75
|
Voila! A brand new index.
|
@@ -82,29 +79,24 @@ Q: I want to move messages from one source to another. (E.g., my
|
|
82
79
|
some of those messages to local mbox files.) How do I do that while
|
83
80
|
preserving message state?
|
84
81
|
A: Move the messages from the source to the target using whatever tool
|
85
|
-
you'd like.
|
82
|
+
you'd like. Mutt's a good one. :) Then run:
|
86
83
|
sup-sync --changed <source1> <source2>
|
87
84
|
|
88
|
-
|
89
|
-
the
|
90
|
-
index, which means that their
|
91
|
-
other source.
|
85
|
+
Note that if you sup-sync only one source at a time, depending on
|
86
|
+
the order in which you do it, the messages may be treated as
|
87
|
+
missing and then deleted from the index, which means that their
|
88
|
+
states will be lost when you sync the other source. So do them both
|
89
|
+
in one go.
|
92
90
|
|
93
91
|
Q: What are all these "Redwood" references I see in the code?
|
94
|
-
A: That was Sup's original name. (Think pine, elm. Although I
|
95
|
-
Mutt user, I couldn't think of a good progression there.) But it
|
96
|
-
taken by another project on RubyForge, and wasn't that
|
97
|
-
and was too long to type anyways.
|
92
|
+
A: That was Sup's original name. (Think pine, elm. Although I was a
|
93
|
+
Mutt user, I couldn't think of a good progression there.) But it
|
94
|
+
was taken by another project on RubyForge, and wasn't that
|
95
|
+
original, and was too long to type anyways.
|
98
96
|
|
99
97
|
Maybe one day I'll do a huge search-and-replace on the code, but it
|
100
98
|
doesn't seem that important at this point.
|
101
99
|
|
102
|
-
Q: How is Sup possible?
|
103
|
-
A: Sup is only possible through the hard work of Dave Balmain, the
|
104
|
-
author of ferret, which is the search engine behind Sup. Ferret is
|
105
|
-
really a first-class piece of software, and it's due to the
|
106
|
-
tremendous amount of time and effort he's put in to it.
|
107
|
-
|
108
100
|
Common Problems
|
109
101
|
---------------
|
110
102
|
|
data/doc/Hooks.txt
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
Sup's Hook System
|
2
|
+
-----------------
|
3
|
+
|
4
|
+
Sup can be easily customized via its hook system, which allows custom
|
5
|
+
user code to be injected into Sup's execution path by "hooking" the
|
6
|
+
code onto pre-defined events. When those events occur, the code is
|
7
|
+
executed.
|
8
|
+
|
9
|
+
To see which hooks are available, simply run sup -l. Each hook sits in
|
10
|
+
a file in ~/.sup/hooks/. Hooks are written in Ruby, and require no
|
11
|
+
class or method definitions, just the executable code itself.
|
12
|
+
|
13
|
+
Information passes from Sup to the hook code via Ruby variables
|
14
|
+
(actually method calls), and from the hook code back to Sup via a
|
15
|
+
return value. Each hook description lists the variables and return
|
16
|
+
value expected, if any.
|
17
|
+
|
18
|
+
Some example hooks:
|
19
|
+
|
20
|
+
before-poll:
|
21
|
+
## runs fetchmail before polling
|
22
|
+
if (@last_fetchmail_time || Time.now) < Time.now - 60
|
23
|
+
say "Running fetchmail..."
|
24
|
+
system "fetchmail >& /dev/null"
|
25
|
+
say "Done running fetchmail."
|
26
|
+
end
|
27
|
+
@last_fetchmail_time = Time.now
|
28
|
+
|
29
|
+
|
30
|
+
mime-decode:
|
31
|
+
## turn text/html attachments into plain text, unless they are part
|
32
|
+
## of a multipart/alternative pair
|
33
|
+
unless sibling_types.member? "text/plain"
|
34
|
+
case content_type
|
35
|
+
when "text/html"
|
36
|
+
`/usr/bin/w3m -dump -T #{content_type} '#{filename}'`
|
37
|
+
end
|
38
|
+
end
|