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\+:', 'bn')) else return getline('.') endif endfunction function! s:search_mutt_aliases(query) let l:aliases = {} let l:aliases_file = '~/.mutt/aliases' if exists('g:mutt_aliases') let l:aliases_file = g:mutt_aliases endif "echomsg 'l:aliases_file = ' . l:aliases_file if filereadable(expand(l:aliases_file)) for l:myline in readfile(expand(l:aliases_file)) if l:myline =~ '^alias' "echomsg "Found an alias..." let l:mylist = split(l:myline) let l:myname = l:mylist[1] if l:myname =~ a:query "echomsg 'Found matching alias: ' . l:myname let l:addresses = join(l:mylist[2:]) "echomsg 'l:addresses before final processing: ' . l:addresses let l:aliases[l:myname] = substitute(l:addresses, '\\"', '', 'g') "echomsg 'l:addresses after final processing: ' . l:aliases[l:myname] endif else continue endif endfor endif return l: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) if a:address !~ ',' "echomsg 'Address is not a list of adresses... ' . a:address return { \ 'menu': '[muttgoobook]', \ 'abbr': a:name, \ 'word': a:name . ' <' . a:address . '>' \} else "echomsg 'Address is a list of adresses... ' . a:address return { \ 'menu': '[muttgoobook]', \ 'abbr': a:name, \ 'word': a:address \} endif endfunction function! asyncomplete#sources#muttgoobook#completor(opt, ctx) abort "echomsg 'Calling completor...' let l:matches = {} "let l:cur = getpos('.') if !s:is_address_field(s:get_section()) "echomsg 'Not in an address field. Exiting...' "call setpos(l:cur) "call asyncomplete#complete(a:opt['name'], a:ctx, l:startcol, l:matches, 1) return endif " restore position "call setpos(l:cur) "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:fields = s:get_fields() "echomsg "Fields: " . l:fields if l:typed =~? l:fields "echomsg "Matched a field. l:typed = " . l:typed let l:kw = substitute(l:typed, '\c' . l:fields . '\(.*\)$', '\2', '') else "echomsg "Did not match a field. l:typed = " . l:typed let l:kw = substitute(l:typed, '^\s\+', '', '') endif 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