sup 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|