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,274 @@
|
|
|
1
|
+
require 'ncursesw'
|
|
2
|
+
require 'sup/util'
|
|
3
|
+
|
|
4
|
+
if defined? Ncurses
|
|
5
|
+
module Ncurses
|
|
6
|
+
|
|
7
|
+
## Helper class for storing keycodes
|
|
8
|
+
## and multibyte characters.
|
|
9
|
+
class CharCode < String
|
|
10
|
+
## Status code allows us to detect
|
|
11
|
+
## printable characters and control codes.
|
|
12
|
+
attr_reader :status
|
|
13
|
+
|
|
14
|
+
## Reads character from user input.
|
|
15
|
+
def self.nonblocking_getwch
|
|
16
|
+
# If we get input while we're shelled, we'll ignore it for the
|
|
17
|
+
# moment and use Ncurses.sync to wait until the shell_out is done.
|
|
18
|
+
begin
|
|
19
|
+
s, c = Redwood::BufferManager.shelled? ? Ncurses.sync { nil } : Ncurses.get_wch
|
|
20
|
+
break if s != Ncurses::ERR
|
|
21
|
+
end until IO.select([$stdin], nil, nil, 2)
|
|
22
|
+
[s, c]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
## Returns empty singleton.
|
|
26
|
+
def self.empty
|
|
27
|
+
Empty.instance
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
## Creates new instance of CharCode
|
|
31
|
+
## that keeps a given keycode.
|
|
32
|
+
def self.keycode(c)
|
|
33
|
+
generate c, Ncurses::KEY_CODE_YES
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
## Creates new instance of CharCode
|
|
37
|
+
## that keeps a printable character.
|
|
38
|
+
def self.character(c)
|
|
39
|
+
generate c, Ncurses::OK
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
## Generates new object like new
|
|
43
|
+
## but for empty or erroneous objects
|
|
44
|
+
## it returns empty singleton.
|
|
45
|
+
def self.generate(c = nil, status = Ncurses::OK)
|
|
46
|
+
if status == Ncurses::ERR || c.nil? || c === Ncurses::ERR
|
|
47
|
+
empty
|
|
48
|
+
else
|
|
49
|
+
new(c, status)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
## Gets character from input.
|
|
54
|
+
## Pretends ctrl-c's are ctrl-g's.
|
|
55
|
+
def self.get handle_interrupt=true
|
|
56
|
+
begin
|
|
57
|
+
status, code = nonblocking_getwch
|
|
58
|
+
generate code, status
|
|
59
|
+
rescue Interrupt => e
|
|
60
|
+
raise e unless handle_interrupt
|
|
61
|
+
keycode Ncurses::KEY_CANCEL
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
## Enables dumb mode for any new instance.
|
|
66
|
+
def self.dumb!
|
|
67
|
+
@dumb = true
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
## Asks if dumb mode was set
|
|
71
|
+
def self.dumb?
|
|
72
|
+
defined?(@dumb) && @dumb
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def initialize(c = "", status = Ncurses::OK)
|
|
76
|
+
@status = status
|
|
77
|
+
c = "" if c.nil?
|
|
78
|
+
return super("") if status == Ncurses::ERR
|
|
79
|
+
c = enc_char(c) if c.is_a?(Fixnum)
|
|
80
|
+
super c.length > 1 ? c[0,1] : c
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
## Proxy method for String's replace
|
|
84
|
+
def replace(c)
|
|
85
|
+
return self if c.object_id == object_id
|
|
86
|
+
if c.is_a?(self.class)
|
|
87
|
+
@status = c.status
|
|
88
|
+
super(c)
|
|
89
|
+
else
|
|
90
|
+
@status = Ncurses::OK
|
|
91
|
+
c = "" if c.nil?
|
|
92
|
+
c = enc_char(c) if c.is_a?(Fixnum)
|
|
93
|
+
super c.length > 1 ? c[0,1] : c
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def to_character ; character? ? self : "<#{code}>" end ## Returns character or code as a string
|
|
98
|
+
def to_keycode ; keycode? ? code : Ncurses::ERR end ## Returns keycode or ERR if it's not a keycode
|
|
99
|
+
def to_sequence ; bytes.to_a end ## Returns unpacked sequence of bytes for a character
|
|
100
|
+
def code ; ord end ## Returns decimal representation of a character
|
|
101
|
+
def is_keycode?(c) ; keycode? && code == c end ## Tests if keycode matches
|
|
102
|
+
def is_character?(c); character? && self == c end ## Tests if character matches
|
|
103
|
+
def try_keycode ; keycode? ? code : nil end ## Returns dec. code if keycode, nil otherwise
|
|
104
|
+
def try_character ; character? ? self : nil end ## Returns character if character, nil otherwise
|
|
105
|
+
def keycode ; try_keycode end ## Alias for try_keycode
|
|
106
|
+
def character ; try_character end ## Alias for try_character
|
|
107
|
+
def character? ; dumb? || @status == Ncurses::OK end ## Returns true if character
|
|
108
|
+
def character! ; @status = Ncurses::OK ; self end ## Sets character flag
|
|
109
|
+
def keycode? ; dumb? || @status == Ncurses::KEY_CODE_YES end ## Returns true if keycode
|
|
110
|
+
def keycode! ; @status = Ncurses::KEY_CODE_YES ; self end ## Sets keycode flag
|
|
111
|
+
def keycode=(c) ; replace(c); keycode! ; self end ## Sets keycode
|
|
112
|
+
def present? ; not empty? end ## Proxy method
|
|
113
|
+
def printable? ; character? end ## Alias for character?
|
|
114
|
+
def dumb? ; self.class.dumb? end ## True if we cannot distinguish keycodes from characters
|
|
115
|
+
|
|
116
|
+
# Empty singleton that
|
|
117
|
+
# keeps GC from going crazy.
|
|
118
|
+
class Empty < CharCode
|
|
119
|
+
include Redwood::Singleton
|
|
120
|
+
|
|
121
|
+
## Wrap methods that may change us
|
|
122
|
+
## and generate new object instead.
|
|
123
|
+
[ :"[]=", :"<<", :replace, :insert, :prepend, :append, :concat, :force_encoding, :setbyte ].
|
|
124
|
+
select{ |m| public_method_defined?(m) }.
|
|
125
|
+
concat(public_instance_methods.grep(/!\z/)).
|
|
126
|
+
each do |m|
|
|
127
|
+
class_eval <<-EVAL
|
|
128
|
+
def #{m}(*args)
|
|
129
|
+
CharCode.new.#{m}(*args)
|
|
130
|
+
end
|
|
131
|
+
EVAL
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
## proxy with class-level instance variable delegation
|
|
135
|
+
def self.dumb?
|
|
136
|
+
superclass.dumb? or !!@dumb
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def self.empty
|
|
140
|
+
instance
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def initialize
|
|
144
|
+
super("", Ncurses::ERR)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def empty? ; true end ## always true
|
|
148
|
+
def present? ; false end ## always false
|
|
149
|
+
def clear ; self end ## always self
|
|
150
|
+
|
|
151
|
+
self
|
|
152
|
+
end.init # CharCode::Empty
|
|
153
|
+
|
|
154
|
+
private
|
|
155
|
+
|
|
156
|
+
## Tries to make external character right.
|
|
157
|
+
def enc_char(c)
|
|
158
|
+
begin
|
|
159
|
+
character = c.chr($encoding)
|
|
160
|
+
rescue RangeError, ArgumentError
|
|
161
|
+
begin
|
|
162
|
+
character = [c].pack('U')
|
|
163
|
+
rescue RangeError
|
|
164
|
+
begin
|
|
165
|
+
character = c.chr
|
|
166
|
+
rescue
|
|
167
|
+
begin
|
|
168
|
+
character = [c].pack('C')
|
|
169
|
+
rescue
|
|
170
|
+
character = ""
|
|
171
|
+
@status = Ncurses::ERR
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
character.fix_encoding!
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end # class CharCode
|
|
179
|
+
|
|
180
|
+
def rows
|
|
181
|
+
lame, lamer = [], []
|
|
182
|
+
stdscr.getmaxyx lame, lamer
|
|
183
|
+
lame.first
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def cols
|
|
187
|
+
lame, lamer = [], []
|
|
188
|
+
stdscr.getmaxyx lame, lamer
|
|
189
|
+
lamer.first
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def curx
|
|
193
|
+
lame, lamer = [], []
|
|
194
|
+
stdscr.getyx lame, lamer
|
|
195
|
+
lamer.first
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
## Create replacement wrapper for form_driver_w (), which is not (yet) a standard
|
|
199
|
+
## function in ncurses. Some systems (Mac OS X) does not have a working
|
|
200
|
+
## form_driver that accepts wide chars. We are just falling back to form_driver, expect problems.
|
|
201
|
+
def prepare_form_driver
|
|
202
|
+
if not defined? Form.form_driver_w
|
|
203
|
+
warn "Your Ncursesw does not have a form_driver_w function (wide char aware), " \
|
|
204
|
+
"non-ASCII chars may not work on your system."
|
|
205
|
+
Form.module_eval <<-FRM_DRV, __FILE__, __LINE__ + 1
|
|
206
|
+
def form_driver_w form, status, c
|
|
207
|
+
form_driver form, c
|
|
208
|
+
end
|
|
209
|
+
module_function :form_driver_w
|
|
210
|
+
module DriverHelpers
|
|
211
|
+
def form_driver c
|
|
212
|
+
if !c.dumb? && c.printable?
|
|
213
|
+
c.each_byte do |code|
|
|
214
|
+
Ncurses::Form.form_driver @form, code
|
|
215
|
+
end
|
|
216
|
+
else
|
|
217
|
+
Ncurses::Form.form_driver @form, c.code
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
FRM_DRV
|
|
222
|
+
end # if not defined? Form.form_driver_w
|
|
223
|
+
if not defined? Ncurses.get_wch
|
|
224
|
+
warn "Your Ncursesw does not have a get_wch function (wide char aware), " \
|
|
225
|
+
"non-ASCII chars may not work on your system."
|
|
226
|
+
Ncurses.module_eval <<-GET_WCH, __FILE__, __LINE__ + 1
|
|
227
|
+
def get_wch
|
|
228
|
+
c = getch
|
|
229
|
+
c == Ncurses::ERR ? [c, 0] : [Ncurses::OK, c]
|
|
230
|
+
end
|
|
231
|
+
module_function :get_wch
|
|
232
|
+
GET_WCH
|
|
233
|
+
CharCode.dumb!
|
|
234
|
+
end # if not defined? Ncurses.get_wch
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def mutex; @mutex ||= Mutex.new; end
|
|
238
|
+
def sync &b; mutex.synchronize(&b); end
|
|
239
|
+
|
|
240
|
+
module_function :rows, :cols, :curx, :mutex, :sync, :prepare_form_driver
|
|
241
|
+
|
|
242
|
+
remove_const :KEY_ENTER
|
|
243
|
+
remove_const :KEY_CANCEL
|
|
244
|
+
|
|
245
|
+
KEY_ENTER = 10
|
|
246
|
+
KEY_CANCEL = 7 # ctrl-g
|
|
247
|
+
KEY_TAB = 9
|
|
248
|
+
|
|
249
|
+
module Form
|
|
250
|
+
## This module contains helpers that ease
|
|
251
|
+
## using form_driver_ methods when @form is present.
|
|
252
|
+
module DriverHelpers
|
|
253
|
+
private
|
|
254
|
+
|
|
255
|
+
## Ncurses::Form.form_driver_w wrapper for keycodes and control characters.
|
|
256
|
+
def form_driver_key c
|
|
257
|
+
form_driver CharCode.keycode(c)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
## Ncurses::Form.form_driver_w wrapper for printable characters.
|
|
261
|
+
def form_driver_char c
|
|
262
|
+
form_driver CharCode.character(c)
|
|
263
|
+
#c.is_a?(Fixnum) ? c : c.ord
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
## Ncurses::Form.form_driver_w wrapper for charcodes.
|
|
267
|
+
def form_driver c
|
|
268
|
+
Ncurses::Form.form_driver_w @form, c.status, c.code
|
|
269
|
+
end
|
|
270
|
+
end # module DriverHelpers
|
|
271
|
+
end # module Form
|
|
272
|
+
|
|
273
|
+
end # module Ncurses
|
|
274
|
+
end # if defined? Ncurses
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Redwood
|
|
2
|
+
module Util
|
|
3
|
+
module Query
|
|
4
|
+
class QueryDescriptionError < ArgumentError; end
|
|
5
|
+
|
|
6
|
+
def self.describe(query, fallback = nil)
|
|
7
|
+
d = query.description.force_encoding("UTF-8")
|
|
8
|
+
|
|
9
|
+
unless d.valid_encoding?
|
|
10
|
+
raise QueryDescriptionError.new(d) unless fallback
|
|
11
|
+
d = fallback
|
|
12
|
+
end
|
|
13
|
+
return d
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/sup/util/uri.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require "uri"
|
|
2
|
+
|
|
3
|
+
require "sup/util/path"
|
|
4
|
+
|
|
5
|
+
module Redwood
|
|
6
|
+
module Util
|
|
7
|
+
module Uri
|
|
8
|
+
def self.build(components)
|
|
9
|
+
components = components.dup
|
|
10
|
+
components[:path] = Path.expand(components[:path])
|
|
11
|
+
::URI::Generic.build(components)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/sup/version.rb
ADDED
data/sup.gemspec
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
|
2
|
+
|
|
3
|
+
require 'sup/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = "sup"
|
|
7
|
+
s.version = ENV["REL"] || (::Redwood::VERSION == "git" ? "999" : ::Redwood::VERSION)
|
|
8
|
+
s.date = Time.now.strftime "%Y-%m-%d"
|
|
9
|
+
s.authors = ["William Morgan", "Gaute Hope", "Hamish Downer", "Matthieu Rakotojaona"]
|
|
10
|
+
s.email = "supmua@googlegroups.com"
|
|
11
|
+
s.summary = "A console-based email client with the best features of GMail, mutt and Emacs"
|
|
12
|
+
s.homepage = "http://supmua.org"
|
|
13
|
+
s.license = 'GPL-2'
|
|
14
|
+
s.description = <<-DESC
|
|
15
|
+
Sup is a console-based email client for people with a lot of email.
|
|
16
|
+
|
|
17
|
+
* GMail-like thread-centered archiving, tagging and muting
|
|
18
|
+
* Handling mail from multiple mbox and Maildir sources
|
|
19
|
+
* Blazing fast full-text search with a rich query language
|
|
20
|
+
* Multiple accounts - pick the right one when sending mail
|
|
21
|
+
* Ruby-programmable hooks
|
|
22
|
+
* Automatically tracking recent contacts
|
|
23
|
+
DESC
|
|
24
|
+
s.post_install_message = <<-EOF
|
|
25
|
+
SUP: please note that our old mailing lists have been shut down,
|
|
26
|
+
re-subscribe to supmua@googlegroups.com to discuss and follow
|
|
27
|
+
updates on sup (send email to: supmua+subscribe@googlegroups.com).
|
|
28
|
+
EOF
|
|
29
|
+
|
|
30
|
+
s.files = `git ls-files -z`.split("\x0")
|
|
31
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
32
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
|
33
|
+
s.require_paths = ["lib"]
|
|
34
|
+
|
|
35
|
+
s.required_ruby_version = '>= 1.9.3'
|
|
36
|
+
|
|
37
|
+
s.add_runtime_dependency "xapian-ruby", "~> 1.2.15"
|
|
38
|
+
s.add_runtime_dependency "ncursesw", "~> 1.4.0"
|
|
39
|
+
s.add_runtime_dependency "rmail-sup", "~> 1.0.1"
|
|
40
|
+
s.add_runtime_dependency "highline"
|
|
41
|
+
s.add_runtime_dependency "trollop", ">= 1.12"
|
|
42
|
+
s.add_runtime_dependency "lockfile"
|
|
43
|
+
s.add_runtime_dependency "mime-types", "~> 1.0"
|
|
44
|
+
s.add_runtime_dependency "locale", "~> 2.0"
|
|
45
|
+
s.add_runtime_dependency "chronic", "~> 0.9.1"
|
|
46
|
+
s.add_runtime_dependency "unicode", "~> 0.4.4"
|
|
47
|
+
|
|
48
|
+
s.add_development_dependency "bundler", "~> 1.3"
|
|
49
|
+
s.add_development_dependency "rake"
|
|
50
|
+
s.add_development_dependency "minitest", "~> 4.7"
|
|
51
|
+
s.add_development_dependency "rr", "~> 1.0.5"
|
|
52
|
+
s.add_development_dependency "gpgme", ">= 2.0.2"
|
|
53
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
|
|
3
|
+
require 'sup'
|
|
4
|
+
require 'stringio'
|
|
5
|
+
require 'rmail'
|
|
6
|
+
require 'uri'
|
|
7
|
+
|
|
8
|
+
module Redwood
|
|
9
|
+
|
|
10
|
+
class DummySource < Source
|
|
11
|
+
|
|
12
|
+
attr_accessor :messages
|
|
13
|
+
|
|
14
|
+
def initialize uri, last_date=nil, usual=true, archived=false, id=nil, labels=[]
|
|
15
|
+
super uri, usual, archived, id
|
|
16
|
+
@messages = nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def start_offset
|
|
20
|
+
0
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def end_offset
|
|
24
|
+
# should contain the number of test messages -1
|
|
25
|
+
return @messages ? @messages.length - 1 : 0
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def load_header offset
|
|
29
|
+
Source.parse_raw_email_header StringIO.new(raw_header(offset))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def load_message offset
|
|
33
|
+
RMail::Parser.read raw_message(offset)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def raw_header offset
|
|
37
|
+
ret = ""
|
|
38
|
+
f = StringIO.new(@messages[offset])
|
|
39
|
+
until f.eof? || (l = f.gets) =~ /^$/
|
|
40
|
+
ret += l
|
|
41
|
+
end
|
|
42
|
+
ret
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def raw_message offset
|
|
46
|
+
@messages[offset]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def each_raw_message_line offset
|
|
50
|
+
ret = ""
|
|
51
|
+
f = StringIO.new(@messages[offset])
|
|
52
|
+
until f.eof?
|
|
53
|
+
yield f.gets
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# vim:noai:ts=2:sw=2:
|
|
61
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
default-key 789E7011
|
|
Binary file
|
|
Binary file
|
|
Binary file
|