vmail 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
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
- echom "done"
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
 
@@ -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 fetch_envelopes(id_set, are_uids=false, is_update=false)
152
- log "fetch_envelopes: #{id_set.inspect}"
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
- @message_list.
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
- @message_list = @message_list.concat new_message_rows
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
- @message_list = new_message_rows + @message_list
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 "returning #{new_message_rows.size} new rows"
193
- return new_message_rows.
194
- map {|x| x[:row_text]}.
195
- join("\n")
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
- log "@all_search #{@all_search}"
294
- @query = query
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
- @message_list = [] # this will hold all the data extracted from these message envelopes
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 = fetch_envelopes(fetch_ids)
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 = @message_list[-1][: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 = fetch_envelopes(new_ids, false, true)
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 = @message_list[0][:seqno]
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 = fetch_envelopes((x..y))
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 = fetch_envelopes(@ids[x..y])
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
- envelope_data = @message_list[index]
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 = @message_list[index]
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 = @message_list[eval(index_range_as_string)].map {|row| row[:uid]}
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 @message_list
535
+ # delete from cached @ids and current_message_list_cache
502
536
  seqnos_to_delete = []
503
537
  uid_set.each {|uid|
504
- row = @message_list.detect {|row| row[:uid] == uid}
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 = @message_list.size
546
+ startsize = current_message_list_cache.size
513
547
  log "deleting row with seqno #{seqno}"
514
- @message_list = @message_list.delete_if {|x| x[:seqno] == seqno}
515
- endsize = @message_list.size
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
- @message_list.each do |row|
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
@@ -1,3 +1,3 @@
1
1
  module Vmail
2
- VERSION = "0.9.3"
2
+ VERSION = "0.9.4"
3
3
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 9
8
- - 3
9
- version: 0.9.3
8
+ - 4
9
+ version: 0.9.4
10
10
  platform: ruby
11
11
  authors:
12
12
  - Daniel Choi