vmail 0.9.3 → 0.9.4
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.
- data/README.markdown +2 -0
- data/lib/vmail.vim +8 -2
- data/lib/vmail/imap_client.rb +72 -38
- data/lib/vmail/version.rb +1 -1
- metadata +2 -2
data/README.markdown
CHANGED
@@ -138,6 +138,8 @@ top of the list that looks something like this:
|
|
138
138
|
|
139
139
|
Put the cursor on this line and press ENTER to load more of these messages.
|
140
140
|
|
141
|
+
Tip: To go straight to the top line and load more messages, type `gg<ENTER>`.
|
142
|
+
|
141
143
|
Unread messages are marked with a `+` symbol.
|
142
144
|
|
143
145
|
To view the raw RFC822 version of a message, type `,R` while viewing the message.
|
data/lib/vmail.vim
CHANGED
@@ -493,7 +493,7 @@ function! s:select_mailbox()
|
|
493
493
|
let s:query = "100 all"
|
494
494
|
let command = s:select_mailbox_command . shellescape(s:mailbox)
|
495
495
|
redraw
|
496
|
-
echom "selecting mailbox ". s:mailbox ". please wait..."
|
496
|
+
echom "selecting mailbox: ". s:mailbox . ". please wait..."
|
497
497
|
call system(command)
|
498
498
|
redraw
|
499
499
|
" now get latest 100 messages
|
@@ -509,7 +509,8 @@ function! s:select_mailbox()
|
|
509
509
|
setlocal nomodifiable
|
510
510
|
write
|
511
511
|
normal z.
|
512
|
-
|
512
|
+
redraw
|
513
|
+
echom "current mailbox: ". s:mailbox
|
513
514
|
endfunction
|
514
515
|
|
515
516
|
func! s:search_query()
|
@@ -740,6 +741,11 @@ func! s:show_help()
|
|
740
741
|
"exec "split " . helpfile
|
741
742
|
endfunc
|
742
743
|
|
744
|
+
" --------------------------------------------------------------------------------
|
745
|
+
" CONVENIENCE FUNCS
|
746
|
+
|
747
|
+
|
748
|
+
|
743
749
|
" --------------------------------------------------------------------------------
|
744
750
|
" MAPPINGS
|
745
751
|
|
data/lib/vmail/imap_client.rb
CHANGED
@@ -46,6 +46,20 @@ module Vmail
|
|
46
46
|
@message_cache
|
47
47
|
end
|
48
48
|
|
49
|
+
# keys are [mailbox, limit, query]
|
50
|
+
def message_list_cache
|
51
|
+
@message_list_cache ||= {}
|
52
|
+
end
|
53
|
+
|
54
|
+
def current_message_list_cache
|
55
|
+
# third key is the non id_set/range part of query
|
56
|
+
(message_list_cache[[@mailbox, @limit, @query[1..-1], @all_search]] ||= [])
|
57
|
+
end
|
58
|
+
|
59
|
+
def current_message_list_cache=(val)
|
60
|
+
message_list_cache[[@mailbox, @limit, @query[1..-1], @all_search]] ||= val
|
61
|
+
end
|
62
|
+
|
49
63
|
def open
|
50
64
|
@imap = Net::IMAP.new(@imap_server, @imap_port, true, nil, false)
|
51
65
|
@imap.login(@username, @password)
|
@@ -102,7 +116,9 @@ module Vmail
|
|
102
116
|
end
|
103
117
|
end
|
104
118
|
|
119
|
+
# not used for anything
|
105
120
|
def get_mailbox_status
|
121
|
+
return
|
106
122
|
@status = @imap.status(@mailbox, ["MESSAGES", "RECENT", "UNSEEN"])
|
107
123
|
log "mailbox status: #{@status.inspect}"
|
108
124
|
end
|
@@ -148,15 +164,20 @@ module Vmail
|
|
148
164
|
end
|
149
165
|
|
150
166
|
# id_set may be a range, array, or string
|
151
|
-
def
|
152
|
-
log "
|
167
|
+
def fetch_row_text(id_set, are_uids=false, is_update=false)
|
168
|
+
log "fetch_row_text: #{id_set.inspect}"
|
153
169
|
if id_set.is_a?(String)
|
154
170
|
id_set = id_set.split(',')
|
155
171
|
end
|
156
172
|
if id_set.to_a.empty?
|
157
|
-
log "empty set"
|
173
|
+
log "- empty set"
|
158
174
|
return ""
|
159
175
|
end
|
176
|
+
new_message_rows = fetch_envelopes(id_set, are_uids, is_update)
|
177
|
+
new_message_rows.map {|x| x[:row_text]}.join("\n")
|
178
|
+
end
|
179
|
+
|
180
|
+
def fetch_envelopes(id_set, are_uids, is_update)
|
160
181
|
results = reconnect_if_necessary do
|
161
182
|
if are_uids
|
162
183
|
@imap.uid_fetch(id_set, ["FLAGS", "ENVELOPE", "RFC822.SIZE", "UID" ])
|
@@ -168,33 +189,34 @@ module Vmail
|
|
168
189
|
error = "expected fetch results but got nil"
|
169
190
|
log(error) && raise(error)
|
170
191
|
end
|
171
|
-
log "extracting headers"
|
192
|
+
log "- extracting headers"
|
193
|
+
log "- current message list cache has #{current_message_list_cache.size} items"
|
172
194
|
new_message_rows = results.map {|x| extract_row_data(x) }
|
173
195
|
if are_uids
|
174
196
|
# replace old row_text values
|
175
197
|
new_message_rows.each {|new_row_data|
|
176
|
-
|
198
|
+
current_message_list_cache.
|
177
199
|
select {|old_row_data| old_row_data[:uid] == new_row_data[:uid]}.
|
178
200
|
each {|old_row_data| old_row_data[:row_text] = new_row_data[:row_text]}
|
179
201
|
}
|
180
202
|
else
|
181
|
-
|
182
203
|
if is_update
|
183
|
-
log "adding messages from update to end of list"
|
184
|
-
|
204
|
+
log "- adding messages from update to end of list"
|
205
|
+
current_message_list_cache.concat new_message_rows
|
185
206
|
else
|
186
207
|
# this adds old messages to the top of the list
|
187
208
|
# put new rows before the current ones
|
188
|
-
log "adding more messages to head of list"
|
189
|
-
|
209
|
+
log "- adding more messages to head of list"
|
210
|
+
self.current_message_list_cache.unshift(*new_message_rows)
|
190
211
|
end
|
191
212
|
end
|
192
|
-
log "
|
193
|
-
|
194
|
-
|
195
|
-
|
213
|
+
log "- new current message list cache has #{current_message_list_cache.size} items"
|
214
|
+
# current_message_list_cache is automatically cached to keyed message_list_cache
|
215
|
+
log "- returning #{new_message_rows.size} new rows and caching result"
|
216
|
+
new_message_rows
|
196
217
|
end
|
197
218
|
|
219
|
+
|
198
220
|
# TODO extract this to another class or module and write unit tests
|
199
221
|
def extract_row_data(fetch_data)
|
200
222
|
seqno = fetch_data.seqno
|
@@ -284,15 +306,23 @@ module Vmail
|
|
284
306
|
# form a sequence range
|
285
307
|
query.unshift [[@num_messages - limit.to_i + 1 , 1].max, @num_messages].join(':')
|
286
308
|
@all_search = true
|
287
|
-
else
|
288
|
-
# this is a special query search
|
309
|
+
else # this is a special query search
|
289
310
|
# set the target range to the whole set
|
290
311
|
query.unshift "1:#@num_messages"
|
291
312
|
@all_search = false
|
292
313
|
end
|
293
|
-
|
294
|
-
@
|
314
|
+
@query = query.map {|x| x.to_s.downcase}
|
315
|
+
@limit = limit
|
295
316
|
log "search query: #{@query.inspect}"
|
317
|
+
if !current_message_list_cache.empty?
|
318
|
+
log "- CACHE HIT"
|
319
|
+
res = current_message_list_cache.map {|x| x[:row_text]}.join("\n")
|
320
|
+
@ids = current_message_list_cache.map {|x| x[:seqno]}
|
321
|
+
return add_more_message_line(res, current_message_list_cache[0][:seqno])
|
322
|
+
end
|
323
|
+
log "- CACHE MISS"
|
324
|
+
log "- @all_search #{@all_search}"
|
325
|
+
@query = query
|
296
326
|
@ids = reconnect_if_necessary(180) do # increase timeout to 3 minutes
|
297
327
|
@imap.search(@query.join(' '))
|
298
328
|
end
|
@@ -303,10 +333,11 @@ module Vmail
|
|
303
333
|
@start_index = [@ids.length - limit, 0].max
|
304
334
|
@ids[@start_index..-1]
|
305
335
|
end
|
306
|
-
log "search query got #{@ids.size} results"
|
307
|
-
|
336
|
+
log "- search query got #{@ids.size} results"
|
337
|
+
# this will hold all the data extracted from these message envelopes
|
338
|
+
current_message_list_cache = []
|
308
339
|
clear_cached_message
|
309
|
-
res =
|
340
|
+
res = fetch_row_text(fetch_ids)
|
310
341
|
add_more_message_line(res, fetch_ids[0])
|
311
342
|
end
|
312
343
|
|
@@ -315,42 +346,44 @@ module Vmail
|
|
315
346
|
old_num_messages = @num_messages
|
316
347
|
# we need to re-select the mailbox to get the new highest id
|
317
348
|
reload_mailbox
|
318
|
-
update_query = @query
|
349
|
+
update_query = @query.dup
|
319
350
|
# set a new range filter
|
351
|
+
# this may generate a negative rane, e.g., "19893:19992" but that seems harmless
|
320
352
|
update_query[0] = "#{old_num_messages}:#{@num_messages}"
|
321
353
|
ids = reconnect_if_necessary {
|
322
354
|
log "search #update_query"
|
323
355
|
@imap.search(update_query.join(' '))
|
324
356
|
}
|
325
357
|
# TODO change this. will throw error now
|
326
|
-
max_seqno =
|
358
|
+
max_seqno = current_message_list_cache[-1][:seqno]
|
327
359
|
log "looking for seqnos > #{max_seqno}"
|
328
360
|
new_ids = ids.select {|seqno| seqno > max_seqno}
|
329
361
|
@ids = @ids + new_ids
|
330
362
|
log "update: new uids: #{new_ids.inspect}"
|
331
363
|
if !new_ids.empty?
|
332
|
-
res =
|
364
|
+
res = fetch_row_text(new_ids, false, true)
|
333
365
|
res
|
366
|
+
else
|
367
|
+
nil
|
334
368
|
end
|
335
369
|
end
|
336
370
|
|
337
371
|
# gets 100 messages prior to id
|
338
372
|
def more_messages(limit=100)
|
339
|
-
message_id =
|
373
|
+
message_id = current_message_list_cache[0][:seqno]
|
340
374
|
log "more_messages: message_id #{message_id}"
|
341
375
|
message_id = message_id.to_i
|
342
376
|
if @all_search
|
343
377
|
x = [(message_id - limit), 0].max
|
344
378
|
y = [message_id - 1, 0].max
|
345
|
-
res =
|
379
|
+
res = fetch_row_text((x..y))
|
346
380
|
add_more_message_line(res, x)
|
347
|
-
else
|
348
|
-
# filter search query
|
381
|
+
else # filter search query
|
349
382
|
log "@start_index #@start_index"
|
350
383
|
x = [(@start_index - limit), 0].max
|
351
384
|
y = [@start_index - 1, 0].max
|
352
385
|
@start_index = x
|
353
|
-
res =
|
386
|
+
res = fetch_row_text(@ids[x..y])
|
354
387
|
add_more_message_line(res, @ids[x])
|
355
388
|
end
|
356
389
|
end
|
@@ -381,7 +414,8 @@ module Vmail
|
|
381
414
|
|
382
415
|
prefetch_adjacent(index)
|
383
416
|
|
384
|
-
|
417
|
+
log "show message index #{index}"
|
418
|
+
envelope_data = current_message_list_cache[index]
|
385
419
|
seqno = envelope_data[:seqno]
|
386
420
|
uid = envelope_data[:uid]
|
387
421
|
log "showing message index: #{index} seqno: #{seqno} uid #{uid}"
|
@@ -406,7 +440,7 @@ module Vmail
|
|
406
440
|
end
|
407
441
|
|
408
442
|
def fetch_and_cache(index)
|
409
|
-
envelope_data =
|
443
|
+
envelope_data = current_message_list_cache[index]
|
410
444
|
return unless envelope_data
|
411
445
|
seqno = envelope_data[:seqno]
|
412
446
|
uid = envelope_data[:uid]
|
@@ -492,16 +526,16 @@ EOF
|
|
492
526
|
raise "expecting String" unless index_range_as_string.is_a?(String)
|
493
527
|
raise "expecting a range as string" unless index_range_as_string =~ /^\d+\.\.\d+$/
|
494
528
|
log "converting index_range #{index_range_as_string} to uids"
|
495
|
-
uids =
|
529
|
+
uids = current_message_list_cache[eval(index_range_as_string)].map {|row| row[:uid]}
|
496
530
|
log "converted index_range #{index_range_as_string} to uids #{uids.inspect}"
|
497
531
|
uids
|
498
532
|
end
|
499
533
|
|
500
534
|
def remove_uid_set_from_cached_lists(uid_set)
|
501
|
-
# delete from cached @ids and
|
535
|
+
# delete from cached @ids and current_message_list_cache
|
502
536
|
seqnos_to_delete = []
|
503
537
|
uid_set.each {|uid|
|
504
|
-
row =
|
538
|
+
row = current_message_list_cache.detect {|row| row[:uid] == uid}
|
505
539
|
seqno = row[:seqno]
|
506
540
|
log "deleting seqno #{seqno} from @ids"
|
507
541
|
@ids.delete seqno
|
@@ -509,17 +543,17 @@ EOF
|
|
509
543
|
}
|
510
544
|
log "seqnos_to_delete: #{seqnos_to_delete.inspect}"
|
511
545
|
seqnos_to_delete.reverse.each do |seqno|
|
512
|
-
startsize =
|
546
|
+
startsize = current_message_list_cache.size
|
513
547
|
log "deleting row with seqno #{seqno}"
|
514
|
-
|
515
|
-
endsize =
|
548
|
+
current_message_list_cache.delete_if {|x| x[:seqno] == seqno}
|
549
|
+
endsize = current_message_list_cache.size
|
516
550
|
log "deleted #{startsize - endsize} rows"
|
517
551
|
end
|
518
552
|
# now we need to decrement all the higher sequence numbers!
|
519
553
|
basenum = seqnos_to_delete.min # this is the lowested seqno deleted
|
520
554
|
diff = seqnos_to_delete.size # substract this from all seqnos >= basenum
|
521
555
|
changes = []
|
522
|
-
|
556
|
+
current_message_list_cache.each do |row|
|
523
557
|
if row[:seqno] >= basenum
|
524
558
|
changes << "#{row[:seqno]}->#{row[:seqno] - diff}"
|
525
559
|
row[:seqno] -= diff
|
data/lib/vmail/version.rb
CHANGED