X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=vim%2Fplugin%2Fnotmuch.vim;h=18e6a59889823fe04ea2200ffab7bdd2baeee783;hp=865624fed01c698e90797b2894109d1c2ff29244;hb=c53b9455049e638ac2cb03d8e1b9e1f01e5eb625;hpb=0265a0030348dbed4816d0619ac8806e76640184 diff --git a/vim/plugin/notmuch.vim b/vim/plugin/notmuch.vim index 865624fe..18e6a598 100644 --- a/vim/plugin/notmuch.vim +++ b/vim/plugin/notmuch.vim @@ -25,27 +25,67 @@ if !exists('g:notmuch_cmd') let g:notmuch_cmd = 'notmuch' endif +if !exists('g:notmuch_search_reverse') + let g:notmuch_search_reverse = 1 +endif + +" --- used to match output of notmuch + +let s:notmuch_show_message_begin_regexp = '^ message{' +let s:notmuch_show_message_end_regexp = '^ message}' +let s:notmuch_show_header_begin_regexp = '^ header{' +let s:notmuch_show_header_end_regexp = '^ header}' +let s:notmuch_show_body_begin_regexp = '^ body{' +let s:notmuch_show_body_end_regexp = '^ body}' +let s:notmuch_show_attachment_begin_regexp = '^ attachment{' +let s:notmuch_show_attachment_end_regexp = '^ attachment}' +let s:notmuch_show_part_begin_regexp = '^ part{' +let s:notmuch_show_part_end_regexp = '^ part}' +let s:notmuch_show_marker_regexp = '^ \\(message\\|header\\|body\\|attachment\\|part\\)[{}].*$' + +let s:notmuch_show_message_parse_regexp = '\(id:[^ ]*\) depth:\([0-9]*\) filename:\(.*\)$' +let s:notmuch_show_tags_regexp = '(\([^)]*\))$' + +let s:notmuch_show_signature_regexp = '^\(-- \?\|_\+\)$' +let s:notmuch_show_signature_lines_max = 12 + +let s:notmuch_show_citation_regexp = '^\s*>' + +let s:notmuch_show_headers = [ 'Subject', 'From' ] + +let s:notmuch_show_fold_signatures = 1 +let s:notmuch_show_fold_citations = 1 " --- implement search screen function! s:NM_cmd_search(words) - let data = split(s:NM_run(['search'] + a:words), "\n") - let disp = copy(data) + let cmd = ['search'] + if g:notmuch_search_reverse + let cmd = cmd + ['--reverse'] + endif + let data = s:NM_run(cmd + a:words) + "let data = substitute(data, '27/27', '25/27', '') + "let data = substitute(data, '\[4/4\]', '[0/4]', '') + let lines = split(data, "\n") + let disp = copy(lines) call map(disp, 'substitute(v:val, "^thread:\\S* ", "", "")' ) call s:NM_newBuffer('search', join(disp, "\n")) - let b:nm_raw_data = data + let b:nm_raw_lines = lines nnoremap :call NM_search_display() + nnoremap s :call NM_cmd_search(split(input('NotMuch Search:'))) + setlocal cursorline + setlocal nowrap endfunction function! s:NM_search_display() - let line = line('.') - if !exists('b:nm_raw_data') - echo 'no b:nm_raw_data' + if !exists('b:nm_raw_lines') + echo 'no b:nm_raw_lines' else - let info = b:nm_raw_data[line] - let what = split(info, '\W\+')[0] + let line = line('.') + let info = b:nm_raw_lines[line-1] + let what = split(info, '\s\+')[0] call s:NM_cmd_show([what]) endif endfunction @@ -54,24 +94,206 @@ endfunction " --- implement show screen function! s:NM_cmd_show(words) + let bufnr = bufnr('%') let data = s:NM_run(['show'] + a:words) + let lines = split(data, "\n") + + let info = s:NM_cmd_show_parse(lines) - call s:NM_newBuffer('show', data) - let b:nm_raw_data = data + call s:NM_newBuffer('show', join(info['disp'], "\n")) + setlocal bufhidden=delete + let b:nm_raw_info = info + + call s:NM_cmd_show_mkfolds() + setlocal foldtext=NM_cmd_show_foldtext() + setlocal fillchars= + setlocal foldcolumn=5 + + exec printf("nnoremap q :b %d", bufnr) endfunction +" s:NM_cmd_show_parse returns the following dictionary: +" 'disp': lines to display +" 'msgs': message info dicts { start, end, id, depth, filename, descr, header } +" 'folds': fold info arrays [ type, start, end ] +" 'foldtext': fold text indexed by start line +function! s:NM_cmd_show_parse(inlines) + let info = { 'disp': [], + \ 'msgs': [], + \ 'folds': [], + \ 'foldtext': {} } + let msg = {} + let hdr = {} + + let in_message = 0 + let in_header = 0 + let in_body = 0 + let in_part = 0 + + let body_start = -1 + + let mode_type = '' + let mode_start = -1 + + let inlnum = 0 + for line in a:inlines + let inlnum = inlnum + 1 + let foldinfo = [] + + if in_part + if match(line, s:notmuch_show_part_end_regexp) != -1 + call add(info['disp'], '') + let in_part = 0 + else + call add(info['disp'], line) + end + + if in_part && mode_type == '' + if match(line, s:notmuch_show_signature_regexp) != -1 + let mode_type = 'sig' + let mode_start = len(info['disp']) + "echoe 'TYPE: ' . mode_type . ' @' . mode_start + elseif match(line, s:notmuch_show_citation_regexp) != -1 + let mode_type = 'cit' + let mode_start = len(info['disp']) + "echoe 'TYPE: ' . mode_type . ' @' . mode_start + endif + elseif mode_type == 'cit' + if !in_part || match(line, s:notmuch_show_citation_regexp) == -1 + let outlnum = len(info['disp']) + let foldinfo = [ mode_type, mode_start, outlnum, + \ printf('[ %d-line citation. Press "c" to show. ]', outlnum - mode_start) ] + let mode_type = '' + endif + elseif mode_type == 'sig' + let outlnum = len(info['disp']) + if (outlnum - mode_start) > s:notmuch_show_signature_lines_max + let mode_type = '' + elseif !in_part + let outlnum = outlnum - 1 + let foldinfo = [ mode_type, mode_start, outlnum, + \ printf('[ %d-line signature. Press "s" to show. ]', outlnum - mode_start) ] + let mode_type = '' + endif + endif + + elseif in_body + if match(line, s:notmuch_show_body_end_regexp) != -1 + let body_end = len(info['disp']) + let foldinfo = [ 'body', body_start, body_end, + \ printf('[ BODY %d - %d lines ]', len(info['msgs']), body_end - body_start) ] + + let in_body = 0 -" --- helper function + elseif match(line, s:notmuch_show_part_begin_regexp) != -1 + let in_part = 1 + let m = matchlist(line, 'ID: \(\d\+\), Content-type: \(\S\+\)') + if len(m) + call add(info['disp'], + \ printf('--- part %d --- %s ---', m[1], m[2])) + endif + endif + + elseif in_header + if in_header == 1 + let msg['descr'] = line + call add(info['disp'], line) + let in_header = 2 + + else + if match(line, s:notmuch_show_header_end_regexp) != -1 + let msg['header'] = hdr + let in_header = 0 + let hdr = {} + else + let m = matchlist(line, '^\(\w\+\):\s*\(.*\)$') + if len(m) + let hdr[m[1]] = m[2] + if match(s:notmuch_show_headers, m[1]) != -1 + call add(info['disp'], line) + endif + endif + endif + endif + + elseif in_message + if match(line, s:notmuch_show_message_end_regexp) != -1 + let msg['end'] = len(info['disp']) + call add(info['disp'], '') + + let foldinfo = [ 'match', msg['start'], msg['end'], + \ printf('[ MSG %d - %s ]', len(info['msgs']), msg['descr']) ] + + call add(info['msgs'], msg) + let msg = {} + let in_message = 0 + let in_header = 0 + let in_body = 0 + let in_part = 0 + + elseif match(line, s:notmuch_show_header_begin_regexp) != -1 + let in_header = 1 + continue + + elseif match(line, s:notmuch_show_body_begin_regexp) != -1 + let body_start = len(info['disp']) + 1 + let in_body = 1 + continue + endif + + else + if match(line, s:notmuch_show_message_begin_regexp) != -1 + let msg['start'] = len(info['disp']) + 1 + + let m = matchlist(line, s:notmuch_show_message_parse_regexp) + if len(m) + let msg['id'] = m[1] + let msg['depth'] = m[2] + let msg['filename'] = m[3] + endif + + let in_message = 1 + endif + endif + + if len(foldinfo) + call add(info['folds'], foldinfo[0:2]) + let info['foldtext'][foldinfo[1]] = foldinfo[3] + endif + endfor + return info +endfunction + +function! s:NM_cmd_show_mkfolds() + let info = b:nm_raw_info + + for afold in info['folds'] + exec printf('%d,%dfold', afold[1], afold[2]) + if (afold[0] == 'sig' && s:notmuch_show_fold_signatures) + \ || (afold[0] == 'cit' && s:notmuch_show_fold_citations) + exec printf('%dfoldclose', afold[1]) + else + exec printf('%dfoldopen', afold[1]) + endif + endfor +endfunction + +function! NM_cmd_show_foldtext() + let foldtext = b:nm_raw_info['foldtext'] + return foldtext[v:foldstart] +endfunction + + +" --- helper functions function! s:NM_newBuffer(ft, content) enew setlocal buftype=nofile readonly modifiable - setlocal bufhidden=delete silent put=a:content keepjumps 0d setlocal nomodifiable - setlocal cursorline - execute printf('setlocal filetype=notmuch-%s', a:ft) + execute printf('set filetype=notmuch-%s', a:ft) + execute printf('set syntax=notmuch-%s', a:ft) endfunction function! s:NM_run(args)