sup 0.6 → 0.7
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 +7 -3
- data/History.txt +12 -0
- data/README.txt +2 -2
- data/ReleaseNotes +11 -0
- data/bin/sup +26 -5
- data/bin/sup-tweak-labels +5 -0
- data/lib/sup.rb +2 -1
- data/lib/sup/buffer.rb +3 -3
- data/lib/sup/crypto.rb +1 -1
- data/lib/sup/draft.rb +4 -1
- data/lib/sup/hook.rb +12 -1
- data/lib/sup/imap.rb +24 -4
- data/lib/sup/index.rb +154 -98
- data/lib/sup/label.rb +1 -1
- data/lib/sup/mbox.rb +8 -8
- data/lib/sup/message-chunks.rb +5 -3
- data/lib/sup/message.rb +4 -4
- data/lib/sup/modes/thread-index-mode.rb +2 -1
- data/lib/sup/modes/thread-view-mode.rb +16 -2
- data/lib/sup/rfc2047.rb +1 -6
- data/lib/sup/textfield.rb +1 -1
- data/lib/sup/util.rb +17 -0
- metadata +56 -81
- data/HACKING +0 -42
- data/Manifest.txt +0 -75
- data/Rakefile +0 -60
- data/doc/FAQ.txt +0 -132
- data/doc/Hooks.txt +0 -38
- data/doc/NewUserGuide.txt +0 -255
- data/doc/Philosophy.txt +0 -69
- data/test/test_mbox_parsing.rb +0 -114
- data/test/test_message.rb +0 -441
data/HACKING
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
Running Sup from your git checkout
|
2
|
-
----------------------------------
|
3
|
-
|
4
|
-
Invoke it like this:
|
5
|
-
|
6
|
-
ruby -I lib -w bin/sup
|
7
|
-
|
8
|
-
You'll have to install all gems mentioned in the Rakefile (look for the line
|
9
|
-
setting p.extra_deps). If you're on a Debian or Debian-based system (e.g.
|
10
|
-
Ubuntu), you'll have to make sure you have a complete Ruby installation,
|
11
|
-
especially libssl-ruby. You will need libruby-devel, gcc, and make installed
|
12
|
-
to build certain gems like Ferret. Gem install does not do a good job of
|
13
|
-
detecting when these things are missing and the build fails.
|
14
|
-
|
15
|
-
Rubygems also is particularly aggressive about picking up libraries from
|
16
|
-
installed gems. If you do have Sup installed as a gem, please examine
|
17
|
-
backtraces to make sure you're loading files from the repository and NOT from
|
18
|
-
the installed gem before submitting any bug reports.
|
19
|
-
|
20
|
-
Coding standards
|
21
|
-
----------------
|
22
|
-
|
23
|
-
- Don't wrap code unless it really benefits from it.
|
24
|
-
- Do wrap comments at 72 characters.
|
25
|
-
- Old lisp-style comment differentiations:
|
26
|
-
# one for comments on the same line as a line of code
|
27
|
-
## two for comments on their own line, except:
|
28
|
-
### three for comments that demarcate large sections of code (rare)
|
29
|
-
- Use {} for one-liner blocks and do/end for multi-line blocks.
|
30
|
-
- I like poetry mode. Don't use parentheses unless you must.
|
31
|
-
- The one exception to poetry mode is if-statements that have an assignment in
|
32
|
-
the condition. To make it clear this is not a comparison, surround the
|
33
|
-
condition by parentheses. E.g.:
|
34
|
-
if a == b if(a = some.computation)
|
35
|
-
... BUT ... something with a
|
36
|
-
end end
|
37
|
-
- and/or versus ||/&&. In Ruby, "and" and "or" bind very loosely---even
|
38
|
-
more loosely than function application. This makes them ideal for
|
39
|
-
end-of-line short-circuit control in poetry mode. So, use || and &&
|
40
|
-
for ordinary logical comparisons, and "and" and "or" for end-of-line
|
41
|
-
flow control. E.g.:
|
42
|
-
x = a || b or raise "neither is true"
|
data/Manifest.txt
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
CONTRIBUTORS
|
2
|
-
HACKING
|
3
|
-
History.txt
|
4
|
-
LICENSE
|
5
|
-
Manifest.txt
|
6
|
-
README.txt
|
7
|
-
Rakefile
|
8
|
-
ReleaseNotes
|
9
|
-
bin/sup
|
10
|
-
bin/sup-add
|
11
|
-
bin/sup-config
|
12
|
-
bin/sup-dump
|
13
|
-
bin/sup-recover-sources
|
14
|
-
bin/sup-sync
|
15
|
-
bin/sup-sync-back
|
16
|
-
bin/sup-tweak-labels
|
17
|
-
doc/FAQ.txt
|
18
|
-
doc/Hooks.txt
|
19
|
-
doc/NewUserGuide.txt
|
20
|
-
doc/Philosophy.txt
|
21
|
-
lib/sup.rb
|
22
|
-
lib/sup/account.rb
|
23
|
-
lib/sup/buffer.rb
|
24
|
-
lib/sup/colormap.rb
|
25
|
-
lib/sup/contact.rb
|
26
|
-
lib/sup/crypto.rb
|
27
|
-
lib/sup/draft.rb
|
28
|
-
lib/sup/hook.rb
|
29
|
-
lib/sup/horizontal-selector.rb
|
30
|
-
lib/sup/imap.rb
|
31
|
-
lib/sup/index.rb
|
32
|
-
lib/sup/keymap.rb
|
33
|
-
lib/sup/label.rb
|
34
|
-
lib/sup/logger.rb
|
35
|
-
lib/sup/maildir.rb
|
36
|
-
lib/sup/mbox.rb
|
37
|
-
lib/sup/mbox/loader.rb
|
38
|
-
lib/sup/mbox/ssh-file.rb
|
39
|
-
lib/sup/mbox/ssh-loader.rb
|
40
|
-
lib/sup/message-chunks.rb
|
41
|
-
lib/sup/message.rb
|
42
|
-
lib/sup/mode.rb
|
43
|
-
lib/sup/modes/buffer-list-mode.rb
|
44
|
-
lib/sup/modes/completion-mode.rb
|
45
|
-
lib/sup/modes/compose-mode.rb
|
46
|
-
lib/sup/modes/contact-list-mode.rb
|
47
|
-
lib/sup/modes/edit-message-mode.rb
|
48
|
-
lib/sup/modes/file-browser-mode.rb
|
49
|
-
lib/sup/modes/forward-mode.rb
|
50
|
-
lib/sup/modes/help-mode.rb
|
51
|
-
lib/sup/modes/inbox-mode.rb
|
52
|
-
lib/sup/modes/label-list-mode.rb
|
53
|
-
lib/sup/modes/label-search-results-mode.rb
|
54
|
-
lib/sup/modes/line-cursor-mode.rb
|
55
|
-
lib/sup/modes/log-mode.rb
|
56
|
-
lib/sup/modes/person-search-results-mode.rb
|
57
|
-
lib/sup/modes/poll-mode.rb
|
58
|
-
lib/sup/modes/reply-mode.rb
|
59
|
-
lib/sup/modes/resume-mode.rb
|
60
|
-
lib/sup/modes/scroll-mode.rb
|
61
|
-
lib/sup/modes/search-results-mode.rb
|
62
|
-
lib/sup/modes/text-mode.rb
|
63
|
-
lib/sup/modes/thread-index-mode.rb
|
64
|
-
lib/sup/modes/thread-view-mode.rb
|
65
|
-
lib/sup/person.rb
|
66
|
-
lib/sup/poll.rb
|
67
|
-
lib/sup/rfc2047.rb
|
68
|
-
lib/sup/sent.rb
|
69
|
-
lib/sup/source.rb
|
70
|
-
lib/sup/suicide.rb
|
71
|
-
lib/sup/tagger.rb
|
72
|
-
lib/sup/textfield.rb
|
73
|
-
lib/sup/thread.rb
|
74
|
-
lib/sup/update.rb
|
75
|
-
lib/sup/util.rb
|
data/Rakefile
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'hoe'
|
3
|
-
$:.unshift 'lib' # force loading from ./lib/ if it exists
|
4
|
-
require 'sup'
|
5
|
-
|
6
|
-
class Hoe
|
7
|
-
def extra_deps; @extra_deps.reject { |x| Array(x).first == "hoe" } end
|
8
|
-
end # thanks to "Mike H"
|
9
|
-
|
10
|
-
## allow people who use development versions by running "rake gem"
|
11
|
-
## and installing the resulting gem it to be able to do this. (gem
|
12
|
-
## versions must be in dotted-digit notation only and can be passed
|
13
|
-
## with the REL environment variable to "rake gem").
|
14
|
-
if ENV['REL']
|
15
|
-
version = ENV['REL']
|
16
|
-
else
|
17
|
-
version = Redwood::VERSION == "git" ? "999" : Redwood::VERSION
|
18
|
-
end
|
19
|
-
Hoe.new('sup', version) do |p|
|
20
|
-
p.rubyforge_name = 'sup'
|
21
|
-
p.author = "William Morgan"
|
22
|
-
p.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.'
|
23
|
-
p.description = p.paragraphs_of('README.txt', 2..9).join("\n\n")
|
24
|
-
p.url = p.paragraphs_of('README.txt', 0).first.split(/\n/)[2].gsub(/^\s+/, "")
|
25
|
-
p.changes = p.paragraphs_of('History.txt', 0..0).join("\n\n")
|
26
|
-
p.email = "wmorgan-sup@masanjin.net"
|
27
|
-
p.extra_deps = [['ferret', '>= 0.10.13'], ['ncurses', '>= 0.9.1'], ['rmail', '>= 0.17'], 'highline', 'net-ssh', ['trollop', '>= 1.7'], 'lockfile', 'mime-types', 'gettext', 'fastthread']
|
28
|
-
end
|
29
|
-
|
30
|
-
rule 'ss?.png' => 'ss?-small.png' do |t|
|
31
|
-
end
|
32
|
-
|
33
|
-
## is there really no way to make a rule for this?
|
34
|
-
WWW_FILES = %w(www/index.html README.txt doc/Philosophy.txt doc/FAQ.txt doc/NewUserGuide.txt www/main.css)
|
35
|
-
|
36
|
-
SCREENSHOTS = FileList["www/ss?.png"]
|
37
|
-
SCREENSHOTS_SMALL = []
|
38
|
-
SCREENSHOTS.each do |fn|
|
39
|
-
fn =~ /ss(\d+)\.png/
|
40
|
-
sfn = "www/ss#{$1}-small.png"
|
41
|
-
file sfn => [fn] do |t|
|
42
|
-
sh "cat #{fn} | pngtopnm | pnmscale -xysize 320 240 | pnmtopng > #{sfn}"
|
43
|
-
end
|
44
|
-
SCREENSHOTS_SMALL << sfn
|
45
|
-
end
|
46
|
-
|
47
|
-
task :upload_webpage => WWW_FILES do |t|
|
48
|
-
sh "rsync -essh -cavz #{t.prerequisites * ' '} wmorgan@rubyforge.org:/var/www/gforge-projects/sup/"
|
49
|
-
end
|
50
|
-
|
51
|
-
task :upload_webpage_images => (SCREENSHOTS + SCREENSHOTS_SMALL) do |t|
|
52
|
-
sh "rsync -essh -cavz #{t.prerequisites * ' '} wmorgan@rubyforge.org:/var/www/gforge-projects/sup/"
|
53
|
-
end
|
54
|
-
|
55
|
-
# vim: syntax=ruby
|
56
|
-
# -*- ruby -*-
|
57
|
-
task :upload_report do |t|
|
58
|
-
sh "ditz html ditz"
|
59
|
-
sh "rsync -essh -cavz ditz wmorgan@rubyforge.org:/var/www/gforge-projects/sup/"
|
60
|
-
end
|
data/doc/FAQ.txt
DELETED
@@ -1,132 +0,0 @@
|
|
1
|
-
Sup FAQ
|
2
|
-
-------
|
3
|
-
|
4
|
-
Q: What is Sup?
|
5
|
-
A: Sup is a console-based email client for people with a lot of email.
|
6
|
-
It supports tagging, very fast full-text search, automatic contact-
|
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.
|
10
|
-
|
11
|
-
Q: What does Sup stand for?
|
12
|
-
A: "What's up?"
|
13
|
-
|
14
|
-
Q: Sup looks like a text-based Gmail.
|
15
|
-
A: I stole their ideas. And improved them!
|
16
|
-
|
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.
|
20
|
-
|
21
|
-
Also, Gmail doesn't let you use a monospace font, which is just
|
22
|
-
lame.
|
23
|
-
|
24
|
-
Also, Gmail encourages top-posting. THIS CANNOT BE TOLERATED!
|
25
|
-
|
26
|
-
Q: Why the console?
|
27
|
-
A: Because a keystroke is worth a hundred mouse clicks, as any Unix
|
28
|
-
user knows. Because you don't need web browser. Because you get
|
29
|
-
instantaneous response and a simple interface.
|
30
|
-
|
31
|
-
Q: How does Sup deal with spam?
|
32
|
-
A: You can manually mark messages as spam, which prevents them from
|
33
|
-
showing up in future searches, but that's as far as Sup goes. Spam
|
34
|
-
filtering should be done by a dedicated tool like SpamAssassin.
|
35
|
-
|
36
|
-
Q: How do I delete a message?
|
37
|
-
A: Why delete? Unless it's spam, you might as well just archive it.
|
38
|
-
|
39
|
-
Q: C'mon, really now!
|
40
|
-
A: Ok, press the 'd' key.
|
41
|
-
|
42
|
-
Q: But I want to delete it for real, not just add a 'deleted' flag in
|
43
|
-
the index. I want it gone from disk!
|
44
|
-
A: Currently, for mbox sources, there is a batch deletion tool that
|
45
|
-
will strip out all messages marked as spam or deleted.
|
46
|
-
|
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.
|
55
|
-
|
56
|
-
Q: How do I back up my index?
|
57
|
-
A: Since the contents of the messages are recoverable from their
|
58
|
-
sources using sup-sync, all you need to back up is the message
|
59
|
-
state. To do this, simply run:
|
60
|
-
sup-dump > <dumpfile>
|
61
|
-
This will save all message state in a big text file, which you
|
62
|
-
should probably compress.
|
63
|
-
|
64
|
-
Q: How do I restore the message state I saved in my state dump?
|
65
|
-
A: Run:
|
66
|
-
sup-sync [<source>+] --restored --restore <dumpfile>
|
67
|
-
where <dumpfile> was created as above.
|
68
|
-
|
69
|
-
Q: Ferret crashed and I can't read my index. Luckily I made a state
|
70
|
-
dump. What should I do?
|
71
|
-
Q: How do I rebuild the index completely?
|
72
|
-
A: Run:
|
73
|
-
rm -rf ~/.sup/ferret # omg wtf
|
74
|
-
sup-sync --all-sources --all --restore <dumpfile>
|
75
|
-
Voila! A brand new index.
|
76
|
-
|
77
|
-
Q: I want to move messages from one source to another. (E.g., my
|
78
|
-
primary inbox is an IMAP server with a quota, and I want to move
|
79
|
-
some of those messages to local mbox files.) How do I do that while
|
80
|
-
preserving message state?
|
81
|
-
A: Move the messages from the source to the target using whatever tool
|
82
|
-
you'd like. Mutt's a good one. :) Then run:
|
83
|
-
sup-sync --changed <source1> <source2>
|
84
|
-
|
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.
|
90
|
-
|
91
|
-
Q: What are all these "Redwood" references I see in the code?
|
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.
|
96
|
-
|
97
|
-
Maybe one day I'll do a huge search-and-replace on the code, but it
|
98
|
-
doesn't seem that important at this point.
|
99
|
-
|
100
|
-
Common Problems
|
101
|
-
---------------
|
102
|
-
|
103
|
-
P: I see this message from Ferret:
|
104
|
-
Error occured in index.c:825 - sis_find_segments_file
|
105
|
-
S: Yikes! You've upgraded Ferret and the index format changed beneath
|
106
|
-
you. Follow the index rebuild instructions above.
|
107
|
-
|
108
|
-
P: I get some error message from Rubymail about frozen strings when
|
109
|
-
importing messages with attachments.
|
110
|
-
S: The current solution is to directly modify RubyMail. Change line 159 of
|
111
|
-
multipart.rb to:
|
112
|
-
chunk = chunk[0..start]
|
113
|
-
This is because RubyMail hasn't been updated since like Ruby 1.8.2.
|
114
|
-
Please bug Matt Armstrong.
|
115
|
-
|
116
|
-
P: I see this error:
|
117
|
-
/usr/local/lib/ruby/1.8/yaml.rb:133:in `transfer': allocator undefined for Bignum (TypeError)
|
118
|
-
S: You need to upgrade to Ruby 1.8.5. YAML in earlier versions can't
|
119
|
-
parse BigNums, but Sup relies on that for Maildir and IMAP.
|
120
|
-
|
121
|
-
P: I see this error:
|
122
|
-
/usr/lib/ruby/1.8/net/imap.rb:204: uninitialized constant Net::IMAP::SSL (NameError)
|
123
|
-
S: You need to install a package called libssl-ruby or something similar.
|
124
|
-
Or, don't use imaps:// sources. Ruby's IMAP library otherwise fails in
|
125
|
-
this completely uninformative manner.
|
126
|
-
|
127
|
-
P: When I run Sup remotely and view an HTML attachment, an existing
|
128
|
-
Firefox on the *local* machine is redirected to the attachment
|
129
|
-
file, which it can't find (since it's on the remote machine). How do
|
130
|
-
I view HTML attachments in this environment?
|
131
|
-
S: Put this in your ~/.mailcap on the machine you run Sup on:
|
132
|
-
text/html; /usr/bin/firefox -a sup '%s'; description=HTML Text; test=test -n "$DISPLAY"; nametemplate=%s.html
|
data/doc/Hooks.txt
DELETED
@@ -1,38 +0,0 @@
|
|
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
|
data/doc/NewUserGuide.txt
DELETED
@@ -1,255 +0,0 @@
|
|
1
|
-
Welcome to Sup! Here's how to get started.
|
2
|
-
|
3
|
-
First, try running 'sup'. Since this is your first time, you'll be
|
4
|
-
confronted with a mostly blank screen, and a notice at the bottom that
|
5
|
-
you have no new messages. That's because Sup doesn't hasn't loaded
|
6
|
-
anything into its index yet, and has no idea where to look for them
|
7
|
-
anyways.
|
8
|
-
|
9
|
-
If you want to play around a little at this point, you can press 'b'
|
10
|
-
to cycle between buffers and 'x' to kill a buffer. There's probably
|
11
|
-
not too much interesting there, but there's a log buffer with some
|
12
|
-
cryptic messages. You can also press '?' at any point to get a list of
|
13
|
-
keyboard commands, but in the absence of any email, these will be
|
14
|
-
mostly useless. When you get bored, press 'q' to quit.
|
15
|
-
|
16
|
-
To use Sup for email, we need to load messages into the index. The
|
17
|
-
index is where Sup stores all message state (e.g. read or unread, any
|
18
|
-
message labels), and all information necessary for searching and for
|
19
|
-
threading messages. Sup only knows about messages in its index.
|
20
|
-
|
21
|
-
We can add messages to the index by telling Sup about the "source"
|
22
|
-
where the messages reside. Sources are things like IMAP folders, mbox
|
23
|
-
folders, maildir directories, and Gmail accounts (in the future). Sup
|
24
|
-
doesn't duplicate the actual message content in the index; it only
|
25
|
-
stores whatever information is necessary for searching, threading and
|
26
|
-
labelling. So when you search for messages or view your inbox, Sup
|
27
|
-
talks only to the index (stored locally on disk). When you view a
|
28
|
-
thread, Sup requests the full content of all the messages from the
|
29
|
-
source.
|
30
|
-
|
31
|
-
The easiest way to set up all your sources is to run "sup-config".
|
32
|
-
This will interactively walk you through some basic configuration,
|
33
|
-
prompt you for all the sources you need, and optionally import
|
34
|
-
messages from them. Sup-config uses two other tools, sup-add and
|
35
|
-
sup-sync, to load messages into the index. In the future you may make
|
36
|
-
use of these tools directly (see below).
|
37
|
-
|
38
|
-
Once you've run sup-config, you're ready to run 'sup'. You should see
|
39
|
-
the most recent unarchived messages appear in your inbox.
|
40
|
-
Congratulations, you've got Sup working!
|
41
|
-
|
42
|
-
If you're coming from the world of traditional MUAs, there are a
|
43
|
-
couple differences you should be aware of at this point. First, Sup
|
44
|
-
has no folders. Instead, you organize and find messages by a
|
45
|
-
combination of search and labels (knowns as 'tags' everywhere else in
|
46
|
-
the world). Search and labels are an integral part of Sup because in
|
47
|
-
Sup, rather than viewing the contents of a folder, you view the
|
48
|
-
results of a search. I mentioned above that your inbox is, by
|
49
|
-
definition, the set of all messages that aren't archived. This means
|
50
|
-
that your inbox is nothing more than the result of the search for all
|
51
|
-
messages with the label "inbox". (It's actually slightly more
|
52
|
-
complicated---we omit messages marked as killed, deleted or spam.)
|
53
|
-
|
54
|
-
You could replicate the folder paradigm easily under this scheme, by
|
55
|
-
giving each message exactly one label and only viewing the results of
|
56
|
-
simple searches for those labels. But you'd quickly find out that life
|
57
|
-
can be easier than that if you just trust the search engine, and use
|
58
|
-
labels judiciously for things that are too hard to find with search.
|
59
|
-
The idea is that a labeling system that allows arbitrary, user-defined
|
60
|
-
labels, supplemented by a quick and easy-to-access search mechanism
|
61
|
-
provides all the functionality that folders does, plus much more, at a
|
62
|
-
far lower cost to the user. (The Sup philosophical treatise has a
|
63
|
-
little more on this.)
|
64
|
-
|
65
|
-
Now let's take a look at your inbox. You'll see that Sup groups
|
66
|
-
messages together into threads: each line in the inbox is a thread,
|
67
|
-
and the number in parentheses is the number of messages in that
|
68
|
-
thread. (If there's no number, there's just one message in the
|
69
|
-
thread.) In Sup, most operations are on threads, not individual
|
70
|
-
messages. The idea is that you rarely want to operate on a message
|
71
|
-
independent of its context. You typically want to view, archive, kill,
|
72
|
-
or label all the messages in a thread at one time.
|
73
|
-
|
74
|
-
Use the up and down arrows to highlight a thread. ('j' and 'k' do the
|
75
|
-
same thing, and 'J' and 'K' will scroll the whole window. Even the
|
76
|
-
left and right arrow keys work.) By default, Sup only loads as many
|
77
|
-
threads as it takes to fill the window; if you'd like to load more,
|
78
|
-
press 'M'. You can hit tab to cycle between only threads with new
|
79
|
-
messages.
|
80
|
-
|
81
|
-
Highlight a thread and press enter to view it. You'll notice that all
|
82
|
-
messages in the thread are displayed together, laid out graphically by
|
83
|
-
their relationship to each other (replies are nested under parents).
|
84
|
-
By default, only the new messages in a thread are expanded, and the
|
85
|
-
others are hidden. You can toggle an individual message's state by
|
86
|
-
highlighting a green line and pressing enter. You can use 'E' to
|
87
|
-
expand or collapse all messages or 'N' to expand only the new
|
88
|
-
messages. You'll also notice that Sup hides quoted text and
|
89
|
-
signatures. If you highlight a particular hidden chunk, you can press
|
90
|
-
enter to expand it, or you can press 'o' to toggle every hidden chunk
|
91
|
-
in a particular message. (Remember, you can hit '?' to see the full
|
92
|
-
list of keyboard commands at any point.)
|
93
|
-
|
94
|
-
A few other useful commands while viewing a thread. Press 'd' to
|
95
|
-
toggle a detailed header for a message. If you've scrolled too far to
|
96
|
-
the right, press '[' to jump all the way to the left. Finally, you can
|
97
|
-
press 'n' and 'p' to jump forward and backward between open messages,
|
98
|
-
aligning the display as necessary.
|
99
|
-
|
100
|
-
Now press 'x' to kill the thread view buffer. You should see the inbox
|
101
|
-
again. If you don't, you can cycle through the buffers by pressing
|
102
|
-
'b', or you can press 'B' to see a list of all buffers and simply
|
103
|
-
select the inbox.
|
104
|
-
|
105
|
-
There are many operations you can perform on threads beyond viewing
|
106
|
-
them. To archive a thread, press 'a'. The thread will disappear from
|
107
|
-
your inbox, but will still appear in search results. If someone
|
108
|
-
replies an archived thread, it will reappear in your inbox. To kill a
|
109
|
-
thread, press '&'. Killed threads will never come back to your inbox,
|
110
|
-
even if people reply, but will still be searchable. (This is useful
|
111
|
-
for those interminable threads that you really have no interest in,
|
112
|
-
but which seem to pop up on every mailing list.)
|
113
|
-
|
114
|
-
If a thread is spam, press 'S'. It will disappear and won't come back.
|
115
|
-
It won't even appear in search results, unless you explicitly search
|
116
|
-
for spam.
|
117
|
-
|
118
|
-
You can star a thread by pressing '*'. Starred threads are displayed
|
119
|
-
with a little yellow asterisk next to them, but otherwise have no
|
120
|
-
special semantics. But you can also search for them easily---we'll see
|
121
|
-
how in a moment.
|
122
|
-
|
123
|
-
To edit the labels for (all the messages in) a thread, press 'l'. Type
|
124
|
-
in the labels as a sequence of space-separated words. To cancel the
|
125
|
-
input, press Ctrl-G.
|
126
|
-
|
127
|
-
Many of these operations can be applied to a group of threads. Press
|
128
|
-
't' to tag a thread. Tag a couple, then press ';' to apply the next
|
129
|
-
command to the set of threads. ';t', of course, will untag all tagged
|
130
|
-
messages.
|
131
|
-
|
132
|
-
Ok, let's try using labels and search. Press 'L' to do a quick label
|
133
|
-
search. You'll be prompted for a label; simply hit enter to bring up
|
134
|
-
scrollable list of all the labels you've ever used, along with some
|
135
|
-
special labels (Draft, Starred, Sent, Spam, etc.). Highlight a label
|
136
|
-
and press enter to view all the messages with that label.
|
137
|
-
|
138
|
-
What you just did was actually a specific search. For a general search,
|
139
|
-
press "\" (backslash---forward slash is used for in-buffer search,
|
140
|
-
following console conventions). Now type in your query (again, Ctrl-G to
|
141
|
-
cancel at any point.) You can just type in arbitrary text, which will be
|
142
|
-
matched on a per-word basis against the bodies of all email in the
|
143
|
-
index, or you can make use of the full Ferret query syntax:
|
144
|
-
|
145
|
-
- Phrasal queries using double-quotes, e.g.: "three contiguous words"
|
146
|
-
- Queries against a particular field using <field name>:<query>,
|
147
|
-
e.g.: label:ruby-talk, or from:matz@ruby-lang.org. (Fields include:
|
148
|
-
body, from, to, and subject.)
|
149
|
-
- Force non-occurrence by -, e.g. -body:"hot soup".
|
150
|
-
- If you have the chronic gem installed, date queries like
|
151
|
-
"before:today", "on:today", "after:yesterday", "after:(2 days ago)"
|
152
|
-
(parentheses required for multi-word descriptions).
|
153
|
-
|
154
|
-
You can combine those all together. For example:
|
155
|
-
label:ruby-talk subject:\[ANN\] -rails on:today
|
156
|
-
|
157
|
-
Play around with the search, and see the Ferret documentation for
|
158
|
-
details on more sophisticated queries (date ranges, "within n words",
|
159
|
-
etc.)
|
160
|
-
|
161
|
-
At this point, you're well on your way to figuring out all the cool
|
162
|
-
things Sup can do. By repeated application of the '?' key, see if you
|
163
|
-
can figure out how to:
|
164
|
-
- List some recent contacts
|
165
|
-
- Easily search for all mail from a recent contact
|
166
|
-
- Easily search for all mail from several recent contacts
|
167
|
-
- Add someone to your address book
|
168
|
-
- Postpone a message (i.e., save a draft)
|
169
|
-
- Quickly re-edit a just-saved draft message
|
170
|
-
- View the raw header of a message
|
171
|
-
- Star an individual message, not just a thread
|
172
|
-
|
173
|
-
There's one last thing to be aware of when using Sup: how it interacts
|
174
|
-
with other email programs. As I described above, Sup stores data about
|
175
|
-
messages in the index, but doesn't duplicate the message contents
|
176
|
-
themselves. The messages remain on the source. If the index and the
|
177
|
-
source every fall out of sync, e.g. due to another email client
|
178
|
-
modifying the source, then Sup will be unable to operate on that
|
179
|
-
source. For example, for mbox files, Sup stores a byte offset into the
|
180
|
-
file for each message. If a message deleted from that file by another
|
181
|
-
client, or even marked as read (yeah, mbox sucks), all succeeding
|
182
|
-
offsets will be wrong.
|
183
|
-
|
184
|
-
That's the bad news. The good news is that Sup is pretty good at being
|
185
|
-
able to detect this type of situation, and fixing it is just a matter
|
186
|
-
of running sup-sync --changed on the source. Sup will even tell you
|
187
|
-
how to invoke sup-sync when it detects a problem. This is a
|
188
|
-
complication you will almost certainly run in to if you use both Sup
|
189
|
-
and another MUA on the same source, so it's good to be aware of it.
|
190
|
-
|
191
|
-
Have fun, and let me know if you have any problems!
|
192
|
-
|
193
|
-
Appending A: sup-add and sup-sync
|
194
|
-
---------------------------------
|
195
|
-
|
196
|
-
Instead of using sup-config to add a new source, you can manually run
|
197
|
-
'sup-add' with a URI pointing to it. The URI should be of the form:
|
198
|
-
- mbox://path/to/a/filename, for an mbox file on disk.
|
199
|
-
- maildir://path/to/a/filename, for a maildir directory on disk.
|
200
|
-
- imap://imap.server/folder for an unsecure IMAP folder.
|
201
|
-
- imaps://secure.imap.server/folder for a secure IMAP folder.
|
202
|
-
- mbox+ssh://remote.machine/path/to/a/filename for a remote mbox file.
|
203
|
-
|
204
|
-
Before you add the source, you need make three decisions. The first is
|
205
|
-
whether you want Sup to regularly poll this source for new messages.
|
206
|
-
By default it will, but if this is a source that will never have new
|
207
|
-
messages, you can specify --unusual. Sup polls only "usual" sources
|
208
|
-
when checking for new mail (unless you manually invoke sup-sync).
|
209
|
-
|
210
|
-
The second is whether you want messages from the source to be
|
211
|
-
automatically archived. An archived message will not show up in your
|
212
|
-
inbox, but will be found when you search. (Your inbox in Sup is, by
|
213
|
-
definition, the set of all all non-archived messages). Specify
|
214
|
-
--archive to automatically archive all messages from the source. This
|
215
|
-
is useful for sources that contain, for example, high-traffic mailing
|
216
|
-
lists that you don't want polluting your inbox.
|
217
|
-
|
218
|
-
The final decision is whether you want any labels automatically
|
219
|
-
applied to messages from this source. You can use --labels to do this.
|
220
|
-
|
221
|
-
If Sup requires account information, e.g. for IMAP servers and remote
|
222
|
-
mbox files, sup-add will ask for it.
|
223
|
-
|
224
|
-
Now that you've added the source, let's import all the current
|
225
|
-
messages from it, by running sup-sync with the source URI. You can
|
226
|
-
specify --archive to automatically archive all messages in this
|
227
|
-
import; typically you'll want to specify this for every source you
|
228
|
-
import except your actual inbox. You can also specify --read to mark
|
229
|
-
all imported messages as read; the default is to preserve the
|
230
|
-
read/unread status from the source.
|
231
|
-
|
232
|
-
Sup-sync will now load all the messages from the source into the
|
233
|
-
index. Depending on the size of the source, this may take a while.
|
234
|
-
Don't panic! It's a one-time process.
|
235
|
-
|
236
|
-
Appendix B: Handling high-volume mailing lists
|
237
|
-
----------------------------------------------
|
238
|
-
|
239
|
-
Here's what I recommend:
|
240
|
-
1. Use procmail to filter messages from the list into a distinct source.
|
241
|
-
2. Add that source to Sup as a usual source with auto-archive turned
|
242
|
-
on, and with a label corresponding to the mailing list name.
|
243
|
-
(E.g.: sup-add mbox:/home/me/Mail/ruby-talk -a -l ruby-talk)
|
244
|
-
3. Voila! Sup will load new messages into the index but not into the
|
245
|
-
inbox, and you can browse the mailing list traffic at any point by
|
246
|
-
searching for that label.
|
247
|
-
|
248
|
-
|
249
|
-
Appendix C: Reading blogs with Sup
|
250
|
-
----------------------------------
|
251
|
-
|
252
|
-
Really, blog posts should be read like emails are read---you should be
|
253
|
-
able to mark them as unread, flag them, label them, etc. Use rss2email
|
254
|
-
to transform RSS feeds into emails, direct them all into a source, and
|
255
|
-
add that source to Sup. Voila!
|