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 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