diff --git a/autoload/asyncomplete/sources/muttgoobook.vim b/autoload/asyncomplete/sources/muttgoobook.vim new file mode 100644 index 0000000..c78d065 --- /dev/null +++ b/autoload/asyncomplete/sources/muttgoobook.vim @@ -0,0 +1,130 @@ +function! s:get_fields() + if exists('g:muttgoobook_address_fields') + "echomsg "Found g:muttgoobook_address_fields: " . g:muttgoobook_address_fields + let fields = g:muttgoobook_address_fields + else + "echomsg "Using default fields..." + let fields = '^\s*\(from\|to\|b\?cc\):\s*' + endif + return fields +endfunction + +function! s:is_address_field(section) + "echomsg "Checking whether we're in an address field..." + + let fields = s:get_fields() + + "echomsg "Section: " . a:section + "echomsg "Fields: " . l:fields + + if a:section =~? l:fields + "echomsg "In an address field!" + return 1 + else + "echomsg "Not in an address field..." + return 0 + endif +endfunction + +function! s:get_section() + let cur = getline('.') + if cur !~ '^\w\+:' + return getline(search('^\w\+:', 'b')) + else + return getline('.') + endif +endfunction + +function! s:search_mutt_aliases(query) + let aliases = {} + if filereadable(expand('~/.mutt/aliases')) + for myline in readfile(expand('~/.mutt/aliases')) + if myline =~ '^alias' + let mylist = split(myline) + let myname = mylist[1] + if l:myname =~ a:query + let addresses = join(mylist[2:]) + let aliases[l:myname] = l:addresses + endif + else + continue + endif + endfor + endif + return aliases +endfunction + +function! s:query_goobook(query) + let addresses = {} + for myline in systemlist('goobook query ' . a:query . ' | sed "/^$/d"') + ""echomsg 'myline: ' . myline + let entry = split(myline, '\t') + let addr = entry[0] + let name = entry[1] + let addresses[l:name] = l:addr + endfor + return addresses +endfunction + +function! s:address_map(name, address) + return { + \ 'menu': '[muttgoobook]', + \ 'abbr': a:name, + \ 'word': a:address + \} +endfunction + +function! asyncomplete#sources#muttgoobook#completor(opt, ctx) abort + "echomsg 'Calling completor...' + let l:matches = {} + if !s:is_address_field(s:get_section()) + "echomsg 'Not in an address field. Exiting...' + call asyncomplete#complete(a:opt['name'], a:ctx, l:startcol, l:matches, 1) + return + endif + + "echomsg "a:ctx['col'] = " . a:ctx['col'] + "echomsg "a:ctx['typed'] = " . a:ctx['typed'] + + let l:col = a:ctx['col'] + let l:typed = a:ctx['typed'] + + "echomsg "Getting keyword..." + let l:kw = substitute(l:typed, '\c' . s:get_fields() . '\(.*\)$', '\2', '') + let l:kwlen = len(l:kw) + let l:startcol = l:col - l:kwlen + + "echomsg "l:startcol: " . l:startcol + "echomsg "keyword: " . l:kw . ", len(l:kw) " . l:kwlen + + if l:kwlen < 3 + "echomsg "a:opt['name']: " . a:opt['name'] + "echomsg "a:ctx: " . a:ctx + "echomsg "l:startcol: " . l:startcol + "echomsg "l:matches: " . l:matches + call asyncomplete#complete(a:opt['name'], a:ctx, l:startcol, l:matches, 1) + return + endif + + "echomsg "Generating address dictionary..." + let l:address_dict = extend(s:search_mutt_aliases(l:kw), s:query_goobook(l:kw)) + + "for [k, v] in items(l:address_dict) + " "echomsg "Key: " . k + " "echomsg "Value: " . v + "endfor + + "echomsg "Getting matches..." + let l:matches = values(map(l:address_dict, {key, val -> s:address_map(key, val)})) + "echomsg l:matches + + "let i = 0 + "for k in keys(l:matches) + " let l:matches[i] = l:matches[k] + " call remove(l:matches, k) + " let i+=1 + "endfor + + call asyncomplete#complete(a:opt['name'], a:ctx, l:startcol, l:matches) +endfunction +