vmail 0.0.1
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/.gitignore +4 -0
- data/NOTES +541 -0
- data/README.markdown +29 -0
- data/Rakefile +21 -0
- data/bin/vmail +11 -0
- data/bin/vmail_client +13 -0
- data/config/environment.rb +18 -0
- data/config/gmail.orig.yml +8 -0
- data/gmail.vim +180 -0
- data/lib/contacts_extractor.rb +50 -0
- data/lib/gmail.rb +145 -0
- data/lib/vmail.rb +45 -0
- data/lib/vmail/imap_client.rb +495 -0
- data/lib/vmail/message_formatter.rb +113 -0
- data/lib/vmail/string_ext.rb +11 -0
- data/lib/vmail/version.rb +3 -0
- data/test/base64_test.rb +13 -0
- data/test/fixtures/euc-kr-header.eml +23 -0
- data/test/fixtures/euc-kr-html.eml +162 -0
- data/test/fixtures/google-affiliate.eml +1049 -0
- data/test/fixtures/htmlbody.eml +68 -0
- data/test/fixtures/moleskine-html.eml +82 -0
- data/test/fixtures/textbody-nocontenttype.eml +118 -0
- data/test/fixtures/with-attachments.eml +123 -0
- data/test/message_formatter_test.rb +84 -0
- data/test/test_helper.rb +10 -0
- data/test/time_format_test.rb +15 -0
- data/viewer.vim +623 -0
- data/vmail.gemspec +23 -0
- data/wrapper.rb +8 -0
- metadata +117 -0
data/test/test_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
describe "TimeFormat methods" do
|
5
|
+
before do
|
6
|
+
@time_string = "2010-11-27T06:08:03-05:00"
|
7
|
+
@time = Time.parse @time_string
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should convert pacific to eastern" do
|
11
|
+
string = "2010-11-27T06:08:03-08:00"
|
12
|
+
time = Time.parse(string)
|
13
|
+
time.to_s.must_equal "2010-11-27 09:08:03 -0500"
|
14
|
+
end
|
15
|
+
end
|
data/viewer.vim
ADDED
@@ -0,0 +1,623 @@
|
|
1
|
+
let s:mailbox = ''
|
2
|
+
let s:num_msgs = 0 " number of messages
|
3
|
+
let s:query = ''
|
4
|
+
|
5
|
+
let s:drb_uri = $DRB_URI
|
6
|
+
|
7
|
+
let s:client_script = "vmail_client " . s:drb_uri . " "
|
8
|
+
let s:window_width_command = s:client_script . "window_width= "
|
9
|
+
let s:list_mailboxes_command = s:client_script . "list_mailboxes "
|
10
|
+
let s:lookup_command = s:client_script . "lookup "
|
11
|
+
let s:update_command = s:client_script . "update"
|
12
|
+
let s:fetch_headers_command = s:client_script . "fetch_headers "
|
13
|
+
let s:select_mailbox_command = s:client_script . "select_mailbox "
|
14
|
+
let s:search_command = s:client_script . "search "
|
15
|
+
let s:more_messages_command = s:client_script . "more_messages "
|
16
|
+
let s:flag_command = s:client_script . "flag "
|
17
|
+
let s:move_to_command = s:client_script . "move_to "
|
18
|
+
let s:new_message_template_command = s:client_script . "new_message_template "
|
19
|
+
let s:reply_template_command = s:client_script . "reply_template "
|
20
|
+
let s:forward_template_command = s:client_script . "forward_template "
|
21
|
+
let s:deliver_command = s:client_script . "deliver "
|
22
|
+
let s:save_draft_command = s:client_script . "save_draft "
|
23
|
+
let s:save_attachments_command = s:client_script . "save_attachments "
|
24
|
+
let s:open_html_command = s:client_script . "open_html_part "
|
25
|
+
let s:message_bufname = "MessageWindow"
|
26
|
+
let s:list_bufname = "MessageListWindow"
|
27
|
+
|
28
|
+
function! VmailStatusLine()
|
29
|
+
return "%<%f\ " . s:mailbox . "%r%=%-14.(%l,%c%V%)\ %P"
|
30
|
+
endfunction
|
31
|
+
|
32
|
+
function! s:create_list_window()
|
33
|
+
"setlocal bufhidden=delete
|
34
|
+
"setlocal buftype=nofile
|
35
|
+
setlocal nomodifiable
|
36
|
+
setlocal noswapfile
|
37
|
+
"setlocal nomodifiable
|
38
|
+
setlocal nowrap
|
39
|
+
setlocal nonumber
|
40
|
+
setlocal foldcolumn=0
|
41
|
+
setlocal nospell
|
42
|
+
" setlocal nobuflisted
|
43
|
+
setlocal textwidth=0
|
44
|
+
setlocal noreadonly
|
45
|
+
" hi CursorLine cterm=NONE ctermbg=darkred ctermfg=white guibg=darkred guifg=white
|
46
|
+
setlocal cursorline
|
47
|
+
" we need the bufnr to find the window later
|
48
|
+
let s:listbufnr = bufnr('%')
|
49
|
+
setlocal statusline=%!VmailStatusLine()
|
50
|
+
endfunction
|
51
|
+
|
52
|
+
" the message display buffer window
|
53
|
+
function! s:create_message_window()
|
54
|
+
exec "split " . s:message_bufname
|
55
|
+
setlocal buftype=nofile
|
56
|
+
" setlocal noswapfile
|
57
|
+
" setlocal nobuflisted
|
58
|
+
let s:message_window_bufnr = bufnr('%')
|
59
|
+
" message window bindings
|
60
|
+
noremap <silent> <buffer> <cr> :call <SID>focus_list_window()<CR>
|
61
|
+
noremap <silent> <buffer> <Leader>q :call <SID>focus_list_window()<CR>
|
62
|
+
noremap <silent> <buffer> q <Leader>q
|
63
|
+
noremap <silent> <buffer> <Leader>r :call <SID>compose_reply(0)<CR>
|
64
|
+
noremap <silent> <buffer> <Leader>a :call <SID>compose_reply(1)<CR>
|
65
|
+
noremap <silent> <buffer> <Leader>R :call <SID>show_raw()<cr>
|
66
|
+
noremap <silent> <buffer> <Leader>R :call <SID>show_raw()<cr>
|
67
|
+
noremap <silent> <buffer> <Leader>f :call <SID>compose_forward()<CR><cr>
|
68
|
+
" TODO improve this
|
69
|
+
noremap <silent> <buffer> <Leader>o yE :!open '<C-R>"'<CR><CR>
|
70
|
+
noremap <silent> <buffer> <leader>j :call <SID>show_next_message()<CR>
|
71
|
+
noremap <silent> <buffer> <leader>k :call <SID>show_previous_message()<CR>
|
72
|
+
noremap <silent> <buffer> <Leader>c :call <SID>compose_message()<CR>
|
73
|
+
noremap <silent> <buffer> <Leader>h :call <SID>open_html_part()<CR><cr>
|
74
|
+
nnoremap <silent> <buffer> q :close<cr>
|
75
|
+
nnoremap <silent> <buffer> <leader>d :call <SID>focus_list_window()<cr>:call <SID>delete_messages("Deleted")<cr>
|
76
|
+
nnoremap <silent> <buffer> s :call <SID>focus_list_window()<cr>:call <SID>toggle_star()<cr>
|
77
|
+
nnoremap <silent> <buffer> <Leader>m :call <SID>focus_list_window()<cr>:call <SID>mailbox_window()<CR>
|
78
|
+
nnoremap <silent> <buffer> <Leader>A :call <SID>save_attachments()<cr>
|
79
|
+
" go fullscreen
|
80
|
+
nnoremap <silent> <buffer> <Space> :call <SID>toggle_fullscreen()<cr>
|
81
|
+
close
|
82
|
+
endfunction
|
83
|
+
|
84
|
+
function! s:show_message()
|
85
|
+
let line = getline(line("."))
|
86
|
+
if match(line, '^> Load') != -1
|
87
|
+
setlocal modifiable
|
88
|
+
delete
|
89
|
+
call s:more_messages()
|
90
|
+
return
|
91
|
+
endif
|
92
|
+
" remove the unread flag [+]
|
93
|
+
let newline = substitute(line, "\\[+\]\\s*", "", '')
|
94
|
+
setlocal modifiable
|
95
|
+
call setline(line('.'), newline)
|
96
|
+
setlocal nomodifiable
|
97
|
+
write
|
98
|
+
" this just clears the command line and prevents the screen from
|
99
|
+
" moving up when the next echo statement executes:
|
100
|
+
call feedkeys(":\<cr>")
|
101
|
+
redraw
|
102
|
+
let selected_uid = matchstr(line, '^\d\+')
|
103
|
+
let s:current_uid = selected_uid
|
104
|
+
let command = s:lookup_command . s:current_uid
|
105
|
+
echo "Loading message. Please wait..."
|
106
|
+
let res = system(command)
|
107
|
+
call s:focus_message_window()
|
108
|
+
setlocal modifiable
|
109
|
+
1,$delete
|
110
|
+
put =res
|
111
|
+
" critical: don't call execute 'normal \<cr>'
|
112
|
+
" call feedkeys("<cr>")
|
113
|
+
1delete
|
114
|
+
normal 1
|
115
|
+
normal jk
|
116
|
+
setlocal nomodifiable
|
117
|
+
redraw
|
118
|
+
endfunction
|
119
|
+
|
120
|
+
function! s:show_next_message()
|
121
|
+
call s:focus_list_window()
|
122
|
+
execute "normal j"
|
123
|
+
execute "normal \<cr>"
|
124
|
+
endfunction
|
125
|
+
|
126
|
+
function! s:show_previous_message()
|
127
|
+
call s:focus_list_window()
|
128
|
+
execute "normal k"
|
129
|
+
if line('.') != 1
|
130
|
+
execute "normal \<cr>"
|
131
|
+
endif
|
132
|
+
endfunction
|
133
|
+
|
134
|
+
" invoked from withint message window
|
135
|
+
function! s:show_raw()
|
136
|
+
let command = s:lookup_command . s:current_uid . ' raw'
|
137
|
+
echo command
|
138
|
+
setlocal modifiable
|
139
|
+
1,$delete
|
140
|
+
let res = system(command)
|
141
|
+
put =res
|
142
|
+
1delete
|
143
|
+
normal 1G
|
144
|
+
setlocal nomodifiable
|
145
|
+
endfunction
|
146
|
+
|
147
|
+
|
148
|
+
function! s:focus_list_window()
|
149
|
+
let winnr = bufwinnr(s:listbufnr)
|
150
|
+
if winnr == -1
|
151
|
+
" create window
|
152
|
+
split
|
153
|
+
exec "buffer" . s:listbufnr
|
154
|
+
else
|
155
|
+
exec winnr . "wincmd w"
|
156
|
+
endif
|
157
|
+
" set up syntax highlighting
|
158
|
+
if has("syntax")
|
159
|
+
syn clear
|
160
|
+
syn match BufferFlagged /^.*[*].*$/hs=s
|
161
|
+
hi def BufferFlagged ctermfg=red ctermbg=black
|
162
|
+
endif
|
163
|
+
" vertically center the cursor line
|
164
|
+
normal z.
|
165
|
+
call feedkeys("\<c-l>") " prevents screen artifacts when user presses return too fast
|
166
|
+
endfunction
|
167
|
+
|
168
|
+
function! s:focus_message_window()
|
169
|
+
let winnr = bufwinnr(s:message_window_bufnr)
|
170
|
+
if winnr == -1
|
171
|
+
" create window
|
172
|
+
exec "botright split " . s:message_bufname
|
173
|
+
else
|
174
|
+
exec winnr . "wincmd w"
|
175
|
+
endif
|
176
|
+
endfunction
|
177
|
+
|
178
|
+
" gets new messages since last update
|
179
|
+
function! s:update()
|
180
|
+
let command = s:update_command
|
181
|
+
echo command
|
182
|
+
let res = system(command)
|
183
|
+
if match(res, '^\d\+') != -1
|
184
|
+
setlocal modifiable
|
185
|
+
let line = line('$')
|
186
|
+
$put =res
|
187
|
+
setlocal nomodifiable
|
188
|
+
let num = len(split(res, '\n', ''))
|
189
|
+
redraw
|
190
|
+
call cursor(line + 1, 0)
|
191
|
+
normal z.
|
192
|
+
redraw
|
193
|
+
echo "you have " . num . " new message" . (num == 1 ? '' : 's') . "!"
|
194
|
+
else
|
195
|
+
redraw
|
196
|
+
echo "no new messages"
|
197
|
+
endif
|
198
|
+
endfunction
|
199
|
+
|
200
|
+
function! s:toggle_star() range
|
201
|
+
let lnum = a:firstline
|
202
|
+
let n = 0
|
203
|
+
let uids = []
|
204
|
+
while lnum <= a:lastline
|
205
|
+
let line = getline(lnum)
|
206
|
+
let message_uid = matchstr(line, '^\d\+')
|
207
|
+
call add(uids, message_uid)
|
208
|
+
let lnum = lnum + 1
|
209
|
+
endwhile
|
210
|
+
let uid_set = join(uids, ",")
|
211
|
+
let flag_symbol = "[*]"
|
212
|
+
" check if starred already
|
213
|
+
let action = " +FLAGS"
|
214
|
+
if (match(line, flag_symbol) != -1)
|
215
|
+
let action = " -FLAGS"
|
216
|
+
endif
|
217
|
+
let command = s:flag_command . uid_set . action . " Flagged"
|
218
|
+
echo command
|
219
|
+
" toggle [*] on lines
|
220
|
+
let res = system(command)
|
221
|
+
setlocal modifiable
|
222
|
+
exec a:firstline . "," . a:lastline . "delete"
|
223
|
+
exec (a:firstline - 1). "put =res"
|
224
|
+
setlocal nomodifiable
|
225
|
+
" if more than 2 lines change, vim forces us to look at a message.
|
226
|
+
" dismiss it.
|
227
|
+
if len(split(res, "\n")) > 2
|
228
|
+
call feedkeys("\<cr>")
|
229
|
+
endif
|
230
|
+
endfunction
|
231
|
+
|
232
|
+
" flag can be Deleted or [Gmail]/Spam
|
233
|
+
func! s:delete_messages(flag) range
|
234
|
+
let lnum = a:firstline
|
235
|
+
let n = 0
|
236
|
+
let uids = []
|
237
|
+
while lnum <= a:lastline
|
238
|
+
let line = getline(lnum)
|
239
|
+
let message_uid = matchstr(line, '^\d\+')
|
240
|
+
call add(uids, message_uid)
|
241
|
+
let lnum = lnum + 1
|
242
|
+
endwhile
|
243
|
+
let uid_set = join(uids, ",")
|
244
|
+
let command = s:flag_command . uid_set . " +FLAGS " . a:flag
|
245
|
+
echo command
|
246
|
+
let res = system(command)
|
247
|
+
setlocal modifiable
|
248
|
+
exec a:firstline . "," . a:lastline . "delete"
|
249
|
+
setlocal nomodifiable
|
250
|
+
" if more than 2 lines change, vim forces us to look at a message.
|
251
|
+
" dismiss it.
|
252
|
+
if len(uids) > 2
|
253
|
+
call feedkeys("\<cr>")
|
254
|
+
endif
|
255
|
+
endfunc
|
256
|
+
|
257
|
+
" --------------------------------------------------------------------------------
|
258
|
+
" move to another mailbox
|
259
|
+
function! s:move_to_mailbox() range
|
260
|
+
let lnum = a:firstline
|
261
|
+
let n = 0
|
262
|
+
let uids = []
|
263
|
+
while lnum <= a:lastline
|
264
|
+
let line = getline(lnum)
|
265
|
+
let message_uid = matchstr(line, '^\d\+')
|
266
|
+
call add(uids, message_uid)
|
267
|
+
let lnum = lnum + 1
|
268
|
+
endwhile
|
269
|
+
let s:uid_set = join(uids, ",")
|
270
|
+
" now prompt use to select mailbox
|
271
|
+
if !exists("s:mailboxes")
|
272
|
+
call s:get_mailbox_list()
|
273
|
+
endif
|
274
|
+
topleft split MailboxSelect
|
275
|
+
setlocal buftype=nofile
|
276
|
+
setlocal noswapfile
|
277
|
+
setlocal modifiable
|
278
|
+
resize 1
|
279
|
+
inoremap <silent> <buffer> <cr> <Esc>:call <SID>complete_move_to_mailbox()<CR>
|
280
|
+
inoremap <silent> <buffer> <esc> <Esc>:q<cr>
|
281
|
+
set completefunc=CompleteMoveMailbox
|
282
|
+
" c-p clears the line
|
283
|
+
let s:firstline = a:firstline
|
284
|
+
let s:lastline = a:lastline
|
285
|
+
call feedkeys("i\<c-x>\<c-u>\<c-p>", 't')
|
286
|
+
" save these in script scope to delete the lines when move completes
|
287
|
+
endfunction
|
288
|
+
|
289
|
+
" Open command window to choose a mailbox to move a message to.
|
290
|
+
" Very similar to mailbox_window() function
|
291
|
+
function! s:complete_move_to_mailbox()
|
292
|
+
let mailbox = getline(line('.'))
|
293
|
+
close
|
294
|
+
" check if mailbox is a real mailbox
|
295
|
+
if (index(s:mailboxes, mailbox) == -1)
|
296
|
+
return
|
297
|
+
endif
|
298
|
+
let command = s:move_to_command . s:uid_set . ' ' . shellescape(mailbox)
|
299
|
+
echo command
|
300
|
+
let res = system(command)
|
301
|
+
setlocal modifiable
|
302
|
+
exec s:firstline . "," . s:lastline . "delete"
|
303
|
+
setlocal nomodifiable
|
304
|
+
endfunction
|
305
|
+
|
306
|
+
function! CompleteMoveMailbox(findstart, base)
|
307
|
+
if !exists("s:mailboxes")
|
308
|
+
call s:get_mailbox_list()
|
309
|
+
endif
|
310
|
+
if a:findstart
|
311
|
+
" locate the start of the word
|
312
|
+
return 0
|
313
|
+
else
|
314
|
+
" find months matching with "a:base"
|
315
|
+
let res = []
|
316
|
+
for m in s:mailboxes
|
317
|
+
if m == s:mailbox
|
318
|
+
continue
|
319
|
+
endif
|
320
|
+
if m =~ '^' . a:base
|
321
|
+
call add(res, m)
|
322
|
+
endif
|
323
|
+
endfor
|
324
|
+
return res
|
325
|
+
endif
|
326
|
+
endfun
|
327
|
+
" --------------------------------------------------------------------------------
|
328
|
+
|
329
|
+
function! s:get_mailbox_list()
|
330
|
+
let command = s:list_mailboxes_command
|
331
|
+
redraw
|
332
|
+
echo command
|
333
|
+
let res = system(command)
|
334
|
+
let s:mailboxes = split(res, "\n", '')
|
335
|
+
endfunction
|
336
|
+
|
337
|
+
function! CompleteMailbox(findstart, base)
|
338
|
+
if !exists("s:mailboxes")
|
339
|
+
call s:get_mailbox_list()
|
340
|
+
endif
|
341
|
+
if a:findstart
|
342
|
+
" locate the start of the word
|
343
|
+
return 0
|
344
|
+
else
|
345
|
+
" find mailboxes matching with "a:base"
|
346
|
+
let res = []
|
347
|
+
for m in s:mailboxes
|
348
|
+
if m =~ '^' . a:base
|
349
|
+
call add(res, m)
|
350
|
+
endif
|
351
|
+
endfor
|
352
|
+
return res
|
353
|
+
endif
|
354
|
+
endfun
|
355
|
+
|
356
|
+
" -------------------------------------------------------------------------------
|
357
|
+
" select mailbox
|
358
|
+
|
359
|
+
function! s:mailbox_window()
|
360
|
+
if !exists("s:mailboxes")
|
361
|
+
call s:get_mailbox_list()
|
362
|
+
endif
|
363
|
+
topleft split MailboxSelect
|
364
|
+
setlocal buftype=nofile
|
365
|
+
setlocal noswapfile
|
366
|
+
setlocal modifiable
|
367
|
+
resize 1
|
368
|
+
inoremap <silent> <buffer> <cr> <Esc>:call <SID>select_mailbox()<CR>
|
369
|
+
inoremap <silent> <buffer> <esc> <Esc>:q<cr>
|
370
|
+
set completefunc=CompleteMailbox
|
371
|
+
" c-p clears the line
|
372
|
+
call feedkeys("i\<c-x>\<c-u>\<c-p>", 't')
|
373
|
+
endfunction
|
374
|
+
|
375
|
+
function! s:select_mailbox()
|
376
|
+
let mailbox = getline(line('.'))
|
377
|
+
close
|
378
|
+
call s:focus_message_window()
|
379
|
+
close
|
380
|
+
" check if mailbox is a real mailbox
|
381
|
+
if (index(s:mailboxes, mailbox) == -1)
|
382
|
+
return
|
383
|
+
endif
|
384
|
+
let s:mailbox = mailbox
|
385
|
+
let command = s:select_mailbox_command . shellescape(s:mailbox)
|
386
|
+
echo command
|
387
|
+
call system(command)
|
388
|
+
redraw
|
389
|
+
" now get latest 100 messages
|
390
|
+
call s:focus_list_window()
|
391
|
+
setlocal modifiable
|
392
|
+
let command = s:search_command . "100 all"
|
393
|
+
echo "Please wait. Loading messages..."
|
394
|
+
let res = system(command)
|
395
|
+
1,$delete
|
396
|
+
put! =res
|
397
|
+
execute "normal Gdd\<c-y>"
|
398
|
+
normal G
|
399
|
+
setlocal nomodifiable
|
400
|
+
normal z.
|
401
|
+
endfunction
|
402
|
+
|
403
|
+
function! s:search_window()
|
404
|
+
topleft split SearchWindow
|
405
|
+
setlocal buftype=nofile
|
406
|
+
setlocal noswapfile
|
407
|
+
resize 1
|
408
|
+
setlocal modifiable
|
409
|
+
noremap! <silent> <buffer> <cr> <Esc>:call <SID>do_search()<CR>
|
410
|
+
call feedkeys("i")
|
411
|
+
endfunction
|
412
|
+
|
413
|
+
function! s:do_search()
|
414
|
+
let s:query = getline(line('.'))
|
415
|
+
close
|
416
|
+
" empty query
|
417
|
+
if match(s:query, '^\s*$') != -1
|
418
|
+
return
|
419
|
+
endif
|
420
|
+
" close message window if open
|
421
|
+
call s:focus_message_window()
|
422
|
+
close
|
423
|
+
" TODO should we really hardcode 100 as the quantity?
|
424
|
+
let command = s:search_command . "100 " . shellescape(s:query)
|
425
|
+
echo command
|
426
|
+
call s:focus_list_window()
|
427
|
+
let res = system(command)
|
428
|
+
setlocal modifiable
|
429
|
+
1,$delete
|
430
|
+
put! =res
|
431
|
+
execute "normal Gdd\<c-y>"
|
432
|
+
normal z.
|
433
|
+
setlocal nomodifiable
|
434
|
+
endfunction
|
435
|
+
|
436
|
+
function! s:more_messages()
|
437
|
+
let line = getline(line('.'))
|
438
|
+
let uid = matchstr(line, '^\d\+')
|
439
|
+
let command = s:more_messages_command . uid
|
440
|
+
echo command
|
441
|
+
let res = system(command)
|
442
|
+
setlocal modifiable
|
443
|
+
let lines = split(res, "\n")
|
444
|
+
call append(0, lines)
|
445
|
+
" execute "normal Gdd\<c-y>"
|
446
|
+
setlocal nomodifiable
|
447
|
+
|
448
|
+
endfunction
|
449
|
+
|
450
|
+
" --------------------------------------------------------------------------------
|
451
|
+
" compose reply, compose, forward, save draft
|
452
|
+
|
453
|
+
function! s:compose_reply(all)
|
454
|
+
let command = s:reply_template_command . s:current_uid
|
455
|
+
if a:all
|
456
|
+
let command = command . ' 1'
|
457
|
+
endif
|
458
|
+
call s:open_compose_window(command)
|
459
|
+
" cursor after headers
|
460
|
+
normal }
|
461
|
+
normal o
|
462
|
+
endfunction
|
463
|
+
|
464
|
+
function! s:compose_message()
|
465
|
+
write
|
466
|
+
let command = s:new_message_template_command
|
467
|
+
call s:open_compose_window(command)
|
468
|
+
" position cursor after to:
|
469
|
+
call search("^to:")
|
470
|
+
normal $
|
471
|
+
call feedkeys("a")
|
472
|
+
endfunction
|
473
|
+
|
474
|
+
function! s:compose_forward()
|
475
|
+
write
|
476
|
+
let command = s:forward_template_command . s:current_uid
|
477
|
+
call s:open_compose_window(command)
|
478
|
+
call search("^to:")
|
479
|
+
normal $
|
480
|
+
call feedkeys("a")
|
481
|
+
endfunction
|
482
|
+
|
483
|
+
func! s:open_compose_window(command)
|
484
|
+
redraw
|
485
|
+
echo a:command
|
486
|
+
let res = system(a:command)
|
487
|
+
split ComposeMessage
|
488
|
+
wincmd p
|
489
|
+
close
|
490
|
+
setlocal modifiable
|
491
|
+
1,$delete
|
492
|
+
put! =res
|
493
|
+
normal 1G
|
494
|
+
noremap <silent> <buffer> <Leader>d :call <SID>deliver_message()<CR>
|
495
|
+
nnoremap <silent> <buffer> q :call <SID>cancel_compose()<cr>
|
496
|
+
nnoremap <silent> <buffer> <leader>q :call <SID>cancel_compose()<cr>
|
497
|
+
nnoremap <silent> <buffer> <Leader>s :call <SID>save_draft()<CR>
|
498
|
+
set completefunc=CompleteContact
|
499
|
+
endfunc
|
500
|
+
|
501
|
+
" contacts.txt file should be generated.
|
502
|
+
" grep works well, does partial matches
|
503
|
+
function! CompleteContact(findstart, base)
|
504
|
+
if !exists("s:mailboxes")
|
505
|
+
call s:get_mailbox_list()
|
506
|
+
endif
|
507
|
+
if a:findstart
|
508
|
+
" locate the start of the word
|
509
|
+
let line = getline('.')
|
510
|
+
let start = col('.') - 1
|
511
|
+
while start > 0 && line[start - 1] =~ '\a'
|
512
|
+
let start -= 1
|
513
|
+
endwhile
|
514
|
+
return start
|
515
|
+
else
|
516
|
+
" find contacts matching with "a:base"
|
517
|
+
let matches = system("grep " . shellescape(a:base) . " contacts.txt")
|
518
|
+
return split(matches, "\n")
|
519
|
+
endif
|
520
|
+
endfun
|
521
|
+
|
522
|
+
function! s:cancel_compose()
|
523
|
+
call s:focus_list_window()
|
524
|
+
wincmd p
|
525
|
+
close!
|
526
|
+
endfunction
|
527
|
+
|
528
|
+
function! s:deliver_message()
|
529
|
+
write
|
530
|
+
let mail = join(getline(1,'$'), "\n")
|
531
|
+
exec ":!" . s:deliver_command . " < ComposeMessage"
|
532
|
+
redraw
|
533
|
+
call s:focus_list_window()
|
534
|
+
wincmd p
|
535
|
+
close!
|
536
|
+
endfunction
|
537
|
+
|
538
|
+
func! s:save_draft()
|
539
|
+
write
|
540
|
+
let mail = join(getline(1,'$'), "\n")
|
541
|
+
exec ":!" . s:save_draft_command . " < ComposeMessage"
|
542
|
+
redraw
|
543
|
+
call s:focus_list_window()
|
544
|
+
wincmd p
|
545
|
+
close!
|
546
|
+
endfunc
|
547
|
+
|
548
|
+
" --------------------------------------------------------------------------------
|
549
|
+
|
550
|
+
" call from inside message window with <Leader>h
|
551
|
+
func! s:open_html_part()
|
552
|
+
let command = s:open_html_command . s:current_uid
|
553
|
+
let outfile = system(command)
|
554
|
+
" todo: allow user to change open in browser command?
|
555
|
+
exec "!open " . outfile
|
556
|
+
endfunc
|
557
|
+
|
558
|
+
func! s:save_attachments()
|
559
|
+
if !exists("s:savedir")
|
560
|
+
let s:savedir = getcwd() . "/attachments"
|
561
|
+
end
|
562
|
+
let s:savedir = input("save attachments to directory: ", s:savedir)
|
563
|
+
let command = s:save_attachments_command . s:savedir
|
564
|
+
echo command
|
565
|
+
let res = system(command)
|
566
|
+
endfunc
|
567
|
+
" --------------------------------------------------------------------------------
|
568
|
+
|
569
|
+
func! s:toggle_fullscreen()
|
570
|
+
if winnr('$') > 1
|
571
|
+
only
|
572
|
+
normal z.
|
573
|
+
else
|
574
|
+
call feedkeys("\<cr>")
|
575
|
+
endif
|
576
|
+
endfunc
|
577
|
+
|
578
|
+
call s:create_list_window()
|
579
|
+
|
580
|
+
call s:create_message_window()
|
581
|
+
|
582
|
+
call s:focus_list_window() " to go list window
|
583
|
+
" this are list window bindings
|
584
|
+
|
585
|
+
noremap <silent> <buffer> <cr> :call <SID>show_message()<CR>
|
586
|
+
noremap <silent> <buffer> q :qal!<cr>
|
587
|
+
|
588
|
+
noremap <silent> <buffer> s :call <SID>toggle_star()<CR>
|
589
|
+
noremap <silent> <buffer> <leader>d :call <SID>delete_messages("Deleted")<CR>
|
590
|
+
|
591
|
+
" TODO the range doesn't quite work as expect, need <line1> <line2>
|
592
|
+
" trying to make user defined commands that work from : prompt
|
593
|
+
" command -buffer -range VmailDelete call s:toggle_star("Deleted")
|
594
|
+
" command -buffer -range VmailStar call s:toggle_star("Flagged")
|
595
|
+
|
596
|
+
noremap <silent> <buffer> <leader>! :call <SID>delete_messages("[Gmail]/Spam")<CR>
|
597
|
+
|
598
|
+
"open a link browser (os x)
|
599
|
+
"autocmd CursorMoved <buffer> call <SID>show_message()
|
600
|
+
|
601
|
+
noremap <silent> <buffer> u :call <SID>update()<CR>
|
602
|
+
noremap <silent> <buffer> <Leader>s :call <SID>search_window()<CR>
|
603
|
+
noremap <silent> <buffer> <Leader>m :call <SID>mailbox_window()<CR>
|
604
|
+
noremap <silent> <buffer> <Leader>v :call <SID>move_to_mailbox()<CR>
|
605
|
+
|
606
|
+
noremap <silent> <buffer> <Leader>c :call <SID>compose_message()<CR>
|
607
|
+
|
608
|
+
noremap <silent> <buffer> <Leader>r :call <SID>show_message()<cr>:call <SID>compose_reply(0)<CR>
|
609
|
+
noremap <silent> <buffer> <Leader>a :call <SID>show_message()<cr>:call <SID>compose_reply(1)<CR>
|
610
|
+
|
611
|
+
" go fullscreen
|
612
|
+
nnoremap <silent> <buffer> <Space> :call <SID>toggle_fullscreen()<cr>
|
613
|
+
|
614
|
+
" press double return in list view to go full screen on a message; then
|
615
|
+
" return? again to restore the list view
|
616
|
+
|
617
|
+
" go to bottom and center cursorline
|
618
|
+
normal G
|
619
|
+
normal z.
|
620
|
+
|
621
|
+
" send window width
|
622
|
+
" system(s:set_window_width_command . winwidth(1))
|
623
|
+
|