sup 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +12 -0
- data/CONTRIBUTORS +84 -0
- data/Gemfile +3 -0
- data/HACKING +42 -0
- data/History.txt +361 -0
- data/LICENSE +280 -0
- data/README.md +70 -0
- data/Rakefile +12 -0
- data/ReleaseNotes +231 -0
- data/bin/sup +434 -0
- data/bin/sup-add +118 -0
- data/bin/sup-config +243 -0
- data/bin/sup-dump +43 -0
- data/bin/sup-import-dump +101 -0
- data/bin/sup-psych-ify-config-files +21 -0
- data/bin/sup-recover-sources +87 -0
- data/bin/sup-sync +210 -0
- data/bin/sup-sync-back-maildir +127 -0
- data/bin/sup-tweak-labels +140 -0
- data/contrib/colorpicker.rb +100 -0
- data/contrib/completion/_sup.zsh +114 -0
- data/devel/console.sh +3 -0
- data/devel/count-loc.sh +3 -0
- data/devel/load-index.rb +9 -0
- data/devel/profile.rb +12 -0
- data/devel/start-console.rb +5 -0
- data/doc/FAQ.txt +119 -0
- data/doc/Hooks.txt +79 -0
- data/doc/Philosophy.txt +69 -0
- data/lib/sup.rb +467 -0
- data/lib/sup/account.rb +90 -0
- data/lib/sup/buffer.rb +768 -0
- data/lib/sup/colormap.rb +239 -0
- data/lib/sup/contact.rb +67 -0
- data/lib/sup/crypto.rb +461 -0
- data/lib/sup/draft.rb +119 -0
- data/lib/sup/hook.rb +159 -0
- data/lib/sup/horizontal_selector.rb +59 -0
- data/lib/sup/idle.rb +42 -0
- data/lib/sup/index.rb +882 -0
- data/lib/sup/interactive_lock.rb +89 -0
- data/lib/sup/keymap.rb +140 -0
- data/lib/sup/label.rb +87 -0
- data/lib/sup/logger.rb +77 -0
- data/lib/sup/logger/singleton.rb +10 -0
- data/lib/sup/maildir.rb +257 -0
- data/lib/sup/mbox.rb +187 -0
- data/lib/sup/message.rb +803 -0
- data/lib/sup/message_chunks.rb +328 -0
- data/lib/sup/mode.rb +140 -0
- data/lib/sup/modes/buffer_list_mode.rb +50 -0
- data/lib/sup/modes/completion_mode.rb +55 -0
- data/lib/sup/modes/compose_mode.rb +38 -0
- data/lib/sup/modes/console_mode.rb +125 -0
- data/lib/sup/modes/contact_list_mode.rb +148 -0
- data/lib/sup/modes/edit_message_async_mode.rb +110 -0
- data/lib/sup/modes/edit_message_mode.rb +728 -0
- data/lib/sup/modes/file_browser_mode.rb +109 -0
- data/lib/sup/modes/forward_mode.rb +82 -0
- data/lib/sup/modes/help_mode.rb +19 -0
- data/lib/sup/modes/inbox_mode.rb +85 -0
- data/lib/sup/modes/label_list_mode.rb +138 -0
- data/lib/sup/modes/label_search_results_mode.rb +38 -0
- data/lib/sup/modes/line_cursor_mode.rb +203 -0
- data/lib/sup/modes/log_mode.rb +57 -0
- data/lib/sup/modes/person_search_results_mode.rb +12 -0
- data/lib/sup/modes/poll_mode.rb +19 -0
- data/lib/sup/modes/reply_mode.rb +228 -0
- data/lib/sup/modes/resume_mode.rb +52 -0
- data/lib/sup/modes/scroll_mode.rb +252 -0
- data/lib/sup/modes/search_list_mode.rb +204 -0
- data/lib/sup/modes/search_results_mode.rb +59 -0
- data/lib/sup/modes/text_mode.rb +76 -0
- data/lib/sup/modes/thread_index_mode.rb +1033 -0
- data/lib/sup/modes/thread_view_mode.rb +941 -0
- data/lib/sup/person.rb +134 -0
- data/lib/sup/poll.rb +272 -0
- data/lib/sup/rfc2047.rb +56 -0
- data/lib/sup/search.rb +110 -0
- data/lib/sup/sent.rb +58 -0
- data/lib/sup/service/label_service.rb +45 -0
- data/lib/sup/source.rb +244 -0
- data/lib/sup/tagger.rb +50 -0
- data/lib/sup/textfield.rb +253 -0
- data/lib/sup/thread.rb +452 -0
- data/lib/sup/time.rb +93 -0
- data/lib/sup/undo.rb +38 -0
- data/lib/sup/update.rb +30 -0
- data/lib/sup/util.rb +747 -0
- data/lib/sup/util/ncurses.rb +274 -0
- data/lib/sup/util/path.rb +9 -0
- data/lib/sup/util/query.rb +17 -0
- data/lib/sup/util/uri.rb +15 -0
- data/lib/sup/version.rb +3 -0
- data/sup.gemspec +53 -0
- data/test/dummy_source.rb +61 -0
- data/test/gnupg_test_home/gpg.conf +1 -0
- data/test/gnupg_test_home/pubring.gpg +0 -0
- data/test/gnupg_test_home/receiver_pubring.gpg +0 -0
- data/test/gnupg_test_home/receiver_secring.gpg +0 -0
- data/test/gnupg_test_home/receiver_trustdb.gpg +0 -0
- data/test/gnupg_test_home/secring.gpg +0 -0
- data/test/gnupg_test_home/sup-test-2@foo.bar.asc +20 -0
- data/test/gnupg_test_home/trustdb.gpg +0 -0
- data/test/integration/test_label_service.rb +18 -0
- data/test/messages/bad-content-transfer-encoding-1.eml +8 -0
- data/test/messages/binary-content-transfer-encoding-2.eml +21 -0
- data/test/messages/missing-line.eml +9 -0
- data/test/test_crypto.rb +109 -0
- data/test/test_header_parsing.rb +168 -0
- data/test/test_helper.rb +7 -0
- data/test/test_message.rb +532 -0
- data/test/test_messages_dir.rb +147 -0
- data/test/test_yaml_migration.rb +85 -0
- data/test/test_yaml_regressions.rb +17 -0
- data/test/unit/service/test_label_service.rb +19 -0
- data/test/unit/test_horizontal_selector.rb +40 -0
- data/test/unit/util/test_query.rb +46 -0
- data/test/unit/util/test_string.rb +57 -0
- data/test/unit/util/test_uri.rb +19 -0
- metadata +423 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
|
|
3
|
+
require 'ncursesw'
|
|
4
|
+
|
|
5
|
+
Ncurses.initscr
|
|
6
|
+
Ncurses.noecho
|
|
7
|
+
Ncurses.cbreak
|
|
8
|
+
Ncurses.start_color
|
|
9
|
+
|
|
10
|
+
Ncurses.curs_set 0
|
|
11
|
+
Ncurses.move 0, 0
|
|
12
|
+
Ncurses.clear
|
|
13
|
+
Ncurses.refresh
|
|
14
|
+
cc = Ncurses.COLORS
|
|
15
|
+
|
|
16
|
+
Ncurses::keypad(Ncurses::stdscr, 1)
|
|
17
|
+
Ncurses::mousemask(Ncurses::ALL_MOUSE_EVENTS | Ncurses::REPORT_MOUSE_POSITION, [])
|
|
18
|
+
|
|
19
|
+
fail "color count is #{cc}, expected 256" unless cc == 256
|
|
20
|
+
|
|
21
|
+
1.upto(255) do |c|
|
|
22
|
+
Ncurses.init_pair(c, 0, c)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def cell y, x, c
|
|
26
|
+
@map[[y,x]] = c
|
|
27
|
+
Ncurses.attron(Ncurses.COLOR_PAIR(c))
|
|
28
|
+
Ncurses.mvaddstr(y, x, " ")
|
|
29
|
+
Ncurses.attroff(Ncurses.COLOR_PAIR(c))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def handle_click y, x
|
|
33
|
+
c = @map[[y,x]] or return
|
|
34
|
+
name = case c
|
|
35
|
+
when 0...16
|
|
36
|
+
c.to_s
|
|
37
|
+
when 16...232
|
|
38
|
+
'c' + (c-16).to_s(6).rjust(3,'0')
|
|
39
|
+
when 232...256
|
|
40
|
+
'g' + (c-232).to_s
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
Ncurses.mvaddstr 11, 0, "#{name} "
|
|
44
|
+
|
|
45
|
+
Ncurses.attron(Ncurses.COLOR_PAIR(c))
|
|
46
|
+
10.times do |i|
|
|
47
|
+
20.times do |j|
|
|
48
|
+
y = 13 + i
|
|
49
|
+
x = j
|
|
50
|
+
Ncurses.mvaddstr(y, x, " ")
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
Ncurses.attroff(Ncurses.COLOR_PAIR(c))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
@map = {}
|
|
57
|
+
@fg = @bg = 0
|
|
58
|
+
|
|
59
|
+
begin
|
|
60
|
+
16.times do |i|
|
|
61
|
+
cell 0, i, i
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
6.times do |i|
|
|
65
|
+
6.times do |j|
|
|
66
|
+
6.times do |k|
|
|
67
|
+
c = 16 + 6*6*i + 6*j + k
|
|
68
|
+
y = 2 + j
|
|
69
|
+
x = 7*i + k
|
|
70
|
+
cell y, x, c
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
16.times do |i|
|
|
76
|
+
c = 16 + 6*6*6 + i
|
|
77
|
+
cell 9, i, c
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
handle_click 0, 0
|
|
81
|
+
Ncurses.refresh
|
|
82
|
+
|
|
83
|
+
while (c = Ncurses.getch)
|
|
84
|
+
case c
|
|
85
|
+
when 113 #q
|
|
86
|
+
break
|
|
87
|
+
when Ncurses::KEY_MOUSE
|
|
88
|
+
mev = Ncurses::MEVENT.new
|
|
89
|
+
Ncurses.getmouse(mev)
|
|
90
|
+
case(mev.bstate)
|
|
91
|
+
when Ncurses::BUTTON1_CLICKED
|
|
92
|
+
handle_click mev.y, mev.x
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
Ncurses.refresh
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
ensure
|
|
99
|
+
Ncurses.endwin
|
|
100
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#compdef sup sup-add sup-config sup-dump sup-sync sup-tweak-labels sup-recover-sources
|
|
2
|
+
# vim: set et sw=2 sts=2 ts=2 ft=zsh :
|
|
3
|
+
|
|
4
|
+
# TODO: sources completion: maildir://some/dir, mbox://some/file, ...
|
|
5
|
+
# for sup-add, sup-sync, sup-tweak-labels
|
|
6
|
+
|
|
7
|
+
(( ${+functions[_sup_cmd]} )) ||
|
|
8
|
+
_sup_cmd()
|
|
9
|
+
{
|
|
10
|
+
_arguments -s : \
|
|
11
|
+
"(--list-hooks -l)"{--list-hooks,-l}"[list all hooks and descriptions, and quit]" \
|
|
12
|
+
"(--no-threads -n)"{--no-threads,-n}"[turn off threading]" \
|
|
13
|
+
"(--no-initial-poll -o)"{--no-initial-poll,-o}"[Don't poll for new messages when starting]" \
|
|
14
|
+
"(--search -s)"{--search,-s}"[search for this query upon startup]:Query: " \
|
|
15
|
+
"(--compose -c)"{--compose,-c}"[compose message to this recipient upon startup]:Email: " \
|
|
16
|
+
"--version[show version information]" \
|
|
17
|
+
"(--help -h)"{--help,-h}"[show help]"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
(( ${+functions[_sup_add_cmd]} )) ||
|
|
21
|
+
_sup_add_cmd()
|
|
22
|
+
{
|
|
23
|
+
_arguments -s : \
|
|
24
|
+
"(--archive -a)"{--archive,-a}"[automatically archive all new messages from this source]" \
|
|
25
|
+
"(--unusual -u)"{--unusual,-u}"[do not automatically poll for new messages from this source]" \
|
|
26
|
+
"(--labels -l)"{--labels,-l}"[set of labels to apply to all messages from this source]:Labels: " \
|
|
27
|
+
"(--force-new -f)"{--force-new,-f}"[create a new account for this source, even if one already exists]" \
|
|
28
|
+
"--version[show version information]" \
|
|
29
|
+
"(--help -h)"{--help,-h}"[show help]"
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
(( ${+functions[_sup_config_cmd]} )) ||
|
|
33
|
+
_sup_config_cmd()
|
|
34
|
+
{
|
|
35
|
+
_arguments -s : \
|
|
36
|
+
"--version[show version information]" \
|
|
37
|
+
"(--help -h)"{--help,-h}"[show help]"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
(( ${+functions[_sup_dump_cmd]} )) ||
|
|
41
|
+
_sup_dump_cmd()
|
|
42
|
+
{
|
|
43
|
+
_arguments -s : \
|
|
44
|
+
"--version[show version information]" \
|
|
45
|
+
"(--help -h)"{--help,-h}"[show help]"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
(( ${+functions[_sup_recover_sources_cmd]} )) ||
|
|
49
|
+
_sup_recover_sources_cmd()
|
|
50
|
+
{
|
|
51
|
+
_arguments -s : \
|
|
52
|
+
"--archive[automatically archive all new messages from this source]" \
|
|
53
|
+
"--scan-num[number of messages to scan per source]:" \
|
|
54
|
+
"--unusual[do not automatically poll for new messages from this source]" \
|
|
55
|
+
"(--help -h)"{--help,-h}"[show help]"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
(( ${+functions[_sup_sync_cmd]} )) ||
|
|
59
|
+
_sup_sync_cmd()
|
|
60
|
+
{
|
|
61
|
+
# XXX Add only when --restore is given: (--restored -r)
|
|
62
|
+
# Add only when --changed or--all are given: (--start-at -s)
|
|
63
|
+
_arguments -s : \
|
|
64
|
+
"--new[operate on new messages only]" \
|
|
65
|
+
"(--changed -c)"{--changed,-c}"[scan over the entire source for messages that have been deleted, altered, or moved from another source]" \
|
|
66
|
+
"(--restored -r)"{--restored,-r}"[operate only on those messages included in a dump file as specified by --restore which have changed state]" \
|
|
67
|
+
"(--all -a)"{--all,-a}"[operate on all messages in the source, regardless of newness or changedness]" \
|
|
68
|
+
"(--start-at -s)"{--start-at,-s}"[start at a particular offset]:Offset: " \
|
|
69
|
+
"--asis[if the message is already in the index, preserve its state, otherwise, use default source state]" \
|
|
70
|
+
"--restore[restore message state from a dump file created with sup-dump]:File:_file" \
|
|
71
|
+
"--discard[discard any message state in the index and use the default source state]" \
|
|
72
|
+
"(--archive -x)"{--archive,-x}"[mark messages as archived when using the default source state]" \
|
|
73
|
+
"(--read -e)"{--read,-e}"[mark messages as read when using the default source state]" \
|
|
74
|
+
"--extra-labels[apply these labels when using the default source state]:Labels: " \
|
|
75
|
+
"(--verbose -v)"{--verbose,-v}"[print message ids as they're processed]" \
|
|
76
|
+
"(--optimize -o)"{--optimize,-o}"[as the final operation, optimize the index]" \
|
|
77
|
+
"--all-sources[scan over all sources]" \
|
|
78
|
+
"(--dry-run -n)"{--dry-run,-n}"[don't actually modify the index]" \
|
|
79
|
+
"--version[show version information]" \
|
|
80
|
+
"(--help -h)"{--help,-h}"[show help]"
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
(( ${+functions[_sup_sync_back_cmd]} )) ||
|
|
84
|
+
_sup_sync_back_cmd()
|
|
85
|
+
{
|
|
86
|
+
_arguments -s : \
|
|
87
|
+
"(--drop-deleted -d)"{--drop-deleted,-d}"[drop deleted messages]" \
|
|
88
|
+
"--move-deleted[move deleted messages to a local mbox file]:File:_file" \
|
|
89
|
+
"(--drop-spam -s)"{--drop-spam,-s}"[drop spam messages]" \
|
|
90
|
+
"--move-spam[move spam messages to a local mbox file]:File:_file" \
|
|
91
|
+
"--with-dotlockfile[specific dotlockfile location (mbox files only)]:File:_file" \
|
|
92
|
+
"--dont-use-dotlockfile[don't use dotlockfile to lock mbox files]" \
|
|
93
|
+
"(--verbose -v)"{--verbose,-v}"[print message ids as they're processed]" \
|
|
94
|
+
"(--dry-run -n)"{--dry-run,-n}"[don't actually modify the index]" \
|
|
95
|
+
"--version[show version information]" \
|
|
96
|
+
"(--help -h)"{--help,-h}"[show help]"
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
(( ${+functions[_sup_tweak_labels_cmd]} )) ||
|
|
100
|
+
_sup_tweak_labels_cmd()
|
|
101
|
+
{
|
|
102
|
+
_arguments -s : \
|
|
103
|
+
"(--add -a)"{--add,-a}"[which labels to add to every message from the specified sources]:Labels: " \
|
|
104
|
+
"(--remove -r)"{--remove,-r}"[which labels to remove from every message from the specified sources]:Labels: " \
|
|
105
|
+
"--all-sources[scan over all sources]" \
|
|
106
|
+
"(--verbose -v)"{--verbose,-v}"[print message ids as they're processed]" \
|
|
107
|
+
"(--dry-run -n)"{--dry-run,-n}"[don't actually modify the index]" \
|
|
108
|
+
"--version[show version information]" \
|
|
109
|
+
"(--help -h)"{--help,-h}"[show help]"
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
_call_function ret _${words[1]//-/_}_cmd
|
|
113
|
+
return ret
|
|
114
|
+
|
data/devel/console.sh
ADDED
data/devel/count-loc.sh
ADDED
data/devel/load-index.rb
ADDED
data/devel/profile.rb
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'ruby-prof'
|
|
3
|
+
require "redwood"
|
|
4
|
+
|
|
5
|
+
result = RubyProf.profile do
|
|
6
|
+
Redwood::ThreadSet.new(ARGV.map { |fn| Redwood::MBox::Scanner.new fn }).load_n_threads 100
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
printer = RubyProf::GraphHtmlPrinter.new(result)
|
|
10
|
+
File.open("profile.html", "w") { |f| printer.print(f, 1) }
|
|
11
|
+
puts "report in profile.html"
|
|
12
|
+
|
data/doc/FAQ.txt
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Sup FAQ
|
|
2
|
+
-------
|
|
3
|
+
|
|
4
|
+
Q: What is Sup?
|
|
5
|
+
A: A console-based email client for people with a lot of email.
|
|
6
|
+
|
|
7
|
+
Q: What does Sup stand for?
|
|
8
|
+
A: "What's up?"
|
|
9
|
+
|
|
10
|
+
Q: Sup looks like a text-based Gmail.
|
|
11
|
+
A: First I stole their ideas. Then I improved them.
|
|
12
|
+
|
|
13
|
+
Q: Why not just use Gmail?
|
|
14
|
+
A: I hate ads, I hate using a mouse, and I hate non-programmability and
|
|
15
|
+
non-extensibility.
|
|
16
|
+
|
|
17
|
+
Also, Gmail doesn't let you use a monospace font, which is just
|
|
18
|
+
lame.
|
|
19
|
+
|
|
20
|
+
Also, Gmail encourages top-posting. THIS CANNOT BE TOLERATED!
|
|
21
|
+
|
|
22
|
+
Q: Why the console?
|
|
23
|
+
A: Because a keystroke is worth a hundred mouse clicks, as any Unix
|
|
24
|
+
user knows. Because you don't need a web browser. Because you get
|
|
25
|
+
an instantaneous response and a simple interface.
|
|
26
|
+
|
|
27
|
+
Q: How does Sup deal with spam?
|
|
28
|
+
A: You can manually mark messages as spam, which prevents them from
|
|
29
|
+
showing up in future searches. Later, you can run a batch process to
|
|
30
|
+
remove such messages from your sources. That's as far as Sup goes.
|
|
31
|
+
Spam filtering should be done by a dedicated tool like SpamAssassin.
|
|
32
|
+
|
|
33
|
+
Q: How do I delete a message?
|
|
34
|
+
A: Why delete? Unless it's spam, you might as well just archive it.
|
|
35
|
+
|
|
36
|
+
Q: C'mon, really now!
|
|
37
|
+
A: Ok, press the 'd' key.
|
|
38
|
+
|
|
39
|
+
Q: But I want to delete it for real, not just add a 'deleted' flag in
|
|
40
|
+
the index. I want it gone from disk!
|
|
41
|
+
A: Currently, for mbox sources, there is a batch deletion tool that
|
|
42
|
+
will strip out all messages marked as spam or deleted.
|
|
43
|
+
|
|
44
|
+
Q: How well does Sup play with other mail clients?
|
|
45
|
+
A: Not well at all. If messages have been moved, deleted, or altered
|
|
46
|
+
due to some other client, Sup will have to rebuild its index for
|
|
47
|
+
that message source. For example, for mbox files, reading a single
|
|
48
|
+
unread message changes the offsets of every file on disk. Rather
|
|
49
|
+
than rescanning every time, Sup assumes sources don't change except
|
|
50
|
+
by having new messages added. If that assumption is violated,
|
|
51
|
+
you'll have to sync the index.
|
|
52
|
+
|
|
53
|
+
Q: How do I back up my index?
|
|
54
|
+
A: Since the contents of the messages are recoverable from their
|
|
55
|
+
sources using sup-sync, all you need to back up is the message
|
|
56
|
+
state. To do this, simply run:
|
|
57
|
+
sup-dump > <dumpfile>
|
|
58
|
+
This will save all message state in a big text file, which you
|
|
59
|
+
should probably compress.
|
|
60
|
+
|
|
61
|
+
Q: How do I restore the message state I saved in my state dump?
|
|
62
|
+
A: Run:
|
|
63
|
+
sup-sync [<source>+] --restored --restore <dumpfile>
|
|
64
|
+
where <dumpfile> was created as above.
|
|
65
|
+
|
|
66
|
+
Q: Xapian crashed and I can't read my index. Luckily I made a state
|
|
67
|
+
dump. What should I do?
|
|
68
|
+
Q: How do I rebuild the index completely?
|
|
69
|
+
A: Run:
|
|
70
|
+
rm -rf ~/.sup/xapian # omg wtf
|
|
71
|
+
sup-sync --all-sources --all --restore <dumpfile>
|
|
72
|
+
Voila! A brand new index.
|
|
73
|
+
|
|
74
|
+
Q: I want to move messages from one source to another. (E.g., my
|
|
75
|
+
primary inbox is an mbox file, and I want to move some of those
|
|
76
|
+
messages to a Maildir.) How do I do that while preserving message
|
|
77
|
+
state?
|
|
78
|
+
A: Move the messages from the source to the target using whatever tool
|
|
79
|
+
you'd like. Mutt's a good one. :) Then run:
|
|
80
|
+
sup-sync --changed <source1> <source2>
|
|
81
|
+
|
|
82
|
+
Note that if you sup-sync only one source at a time, depending on
|
|
83
|
+
the order in which you do it, the messages may be treated as
|
|
84
|
+
missing and then deleted from the index, which means that their
|
|
85
|
+
states will be lost when you sync the other source. So do them both
|
|
86
|
+
in one go.
|
|
87
|
+
|
|
88
|
+
Q: What are all these "Redwood" references I see in the code?
|
|
89
|
+
A: That was Sup's original name. (Think pine, elm. Although I was a
|
|
90
|
+
Mutt user, I couldn't think of a good progression there.) But it was
|
|
91
|
+
taken by another project on RubyForge, and wasn't that original, and
|
|
92
|
+
was too long to type anyways.
|
|
93
|
+
|
|
94
|
+
Common Problems
|
|
95
|
+
---------------
|
|
96
|
+
|
|
97
|
+
P: I get some error message from Rubymail about frozen strings when
|
|
98
|
+
importing messages with attachments.
|
|
99
|
+
S: The current solution is to directly modify RubyMail. Change line 159 of
|
|
100
|
+
multipart.rb to:
|
|
101
|
+
chunk = chunk[0..start]
|
|
102
|
+
This is because RubyMail hasn't been updated since like Ruby 1.8.2.
|
|
103
|
+
Please bug Matt Armstrong.
|
|
104
|
+
|
|
105
|
+
P: I see this error:
|
|
106
|
+
/usr/local/lib/ruby/1.8/yaml.rb:133:in `transfer': allocator undefined for Bignum (TypeError)
|
|
107
|
+
S: You need to upgrade to Ruby 1.8.5. YAML in earlier versions can't
|
|
108
|
+
parse BigNums, but Sup relies on that for Maildir.
|
|
109
|
+
|
|
110
|
+
P: When I run Sup remotely and view an HTML attachment, an existing
|
|
111
|
+
Firefox on the *local* machine is redirected to the attachment
|
|
112
|
+
file, which it can't find (since it's on the remote machine). How do
|
|
113
|
+
I view HTML attachments in this environment?
|
|
114
|
+
S: Put this in your ~/.mailcap on the machine you run Sup on:
|
|
115
|
+
text/html; /usr/bin/firefox -a sup %s; description=HTML Text; test=test -n "$DISPLAY"; nametemplate=%s.html
|
|
116
|
+
|
|
117
|
+
Please read
|
|
118
|
+
https://github.com/sup-heliotrope/sup/wiki/Viewing-Attachments for
|
|
119
|
+
some security concerns on opening attachments.
|
data/doc/Hooks.txt
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
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. The values of variables persists across calls to the
|
|
16
|
+
same hook, but is NOT available to other hooks. To make the value of a
|
|
17
|
+
variable available to other hooks, use the get and set methods. Each
|
|
18
|
+
hook description lists the variables and return value expected, if
|
|
19
|
+
any.
|
|
20
|
+
|
|
21
|
+
The following special functions are available to hooks:
|
|
22
|
+
* say msg
|
|
23
|
+
Displays the string msg to the user at the bottom of the screen.
|
|
24
|
+
* log msg
|
|
25
|
+
Adds the string msg to the log, which the user can access via the
|
|
26
|
+
buffer list.
|
|
27
|
+
* ask_yes_or_no question
|
|
28
|
+
Prompts the user with the string question for a yes or no
|
|
29
|
+
response. Returns true if the user answered yes, false otherwise.
|
|
30
|
+
* get key
|
|
31
|
+
Gets the cross-hook value associated with key (which is typically a
|
|
32
|
+
string). If there is no value for a given key, nil is returned.
|
|
33
|
+
* set key value
|
|
34
|
+
Sets the cross-hook value associated with key to value. key is
|
|
35
|
+
typically a string, while value can be whatever type it needs to be,
|
|
36
|
+
including nil.
|
|
37
|
+
|
|
38
|
+
Some example hooks:
|
|
39
|
+
|
|
40
|
+
before-poll:
|
|
41
|
+
## runs fetchmail before polling
|
|
42
|
+
if (@last_fetchmail_time || Time.now) < Time.now - 60
|
|
43
|
+
say "Running fetchmail..."
|
|
44
|
+
system "fetchmail >& /dev/null"
|
|
45
|
+
say "Done running fetchmail."
|
|
46
|
+
end
|
|
47
|
+
@last_fetchmail_time = Time.now
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
mime-decode:
|
|
51
|
+
## Please read:
|
|
52
|
+
https://github.com/sup-heliotrope/sup/wiki/Viewing-Attachments for
|
|
53
|
+
some security concerns on opening attachments.
|
|
54
|
+
|
|
55
|
+
## turn text/html attachments into plain text, unless they are part
|
|
56
|
+
## of a multipart/alternative pair
|
|
57
|
+
require 'shellwords'
|
|
58
|
+
unless sibling_types.member? "text/plain"
|
|
59
|
+
case content_type
|
|
60
|
+
when "text/html"
|
|
61
|
+
`/usr/bin/w3m -dump -T #{content_type} #{Shellwords.escape filename}`
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
startup:
|
|
66
|
+
## runs a background task
|
|
67
|
+
@bgtask_pid = fork
|
|
68
|
+
if @bgtask_pid
|
|
69
|
+
set 'bgtask_pid' @bgtask_pid
|
|
70
|
+
Process.detach(@bgtask_pid) # so we don't have to wait on it when we go to kill it
|
|
71
|
+
else
|
|
72
|
+
exec "background-task args 2&>1 >> /tmp/logfile"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
after-poll:
|
|
76
|
+
## kills the background task after the first poll
|
|
77
|
+
@bgtask_pid = get 'bgtask_pid'
|
|
78
|
+
Process.kill("TERM", @bgtask_pid) unless @bgtask_pid == nil
|
|
79
|
+
set 'bgtask_pid' nil
|