]> git.notmuchmail.org Git - notmuch/blobdiff - vim/plugin/notmuch.vim
make searching, updates and returning to folder view work
[notmuch] / vim / plugin / notmuch.vim
index 2ddc8160417b5552e77274c057d8819474e658e6..308fc05d8010094bffe66678d54ceecfbc7301cf 100644 (file)
@@ -69,8 +69,25 @@ let s:notmuch_show_headers_defaults = [
         \ 'Date',
         \ ]
 
+" defaults for g:notmuch_folders
+" override with: let g:notmuch_folders = [ ... ]
+let s:notmuch_folders_defaults = [
+        \ [ 'new',    'tag:inbox and tag:unread' ],
+        \ [ 'inbox',  'tag:inbox'                ],
+        \ [ 'unread', 'tag:unread'               ],
+        \ ]
+
 " --- keyboard mapping definitions {{{1
 
+" --- --- bindings for folders mode {{{2
+
+let g:notmuch_folders_maps = {
+        \ 's':          ':call <SID>NM_search_prompt()<CR>',
+        \ 'q':          ':call <SID>NM_kill_this_buffer()<CR>',
+        \ '=':          ':call <SID>NM_folders_refresh_view()<CR>',
+        \ '<Enter>':    ':call <SID>NM_folders_show_search()<CR>',
+        \ }
+
 " --- --- bindings for search screen {{{2
 let g:notmuch_search_maps = {
         \ '<Enter>':    ':call <SID>NM_search_show_thread()<CR>',
@@ -90,7 +107,7 @@ let g:notmuch_search_maps = {
 
 " --- --- bindings for show screen {{{2
 let g:notmuch_show_maps = {
-        \ '<C-P>':      ':call <SID>NM_show_prev(1)<CR>',
+        \ '<C-P>':      ':call <SID>NM_show_previous(1)<CR>',
         \ '<C-N>':      ':call <SID>NM_show_next(1)<CR>',
         \ 'q':          ':call <SID>NM_kill_this_buffer()<CR>',
         \
@@ -113,6 +130,57 @@ let g:notmuch_show_maps = {
         \ }
 
 
+" --- implement folders screen {{{1
+
+function! s:NM_cmd_folders(words)
+        if len(a:words)
+                echoe 'Not exapecting any arguments for folders command.'
+        endif
+        let cmd = ['count']
+        let disp = []
+        let searches = []
+        for entry in g:notmuch_folders
+                let [ name, search ] = entry
+                let data = s:NM_run(cmd + [search])
+                let cnt = matchlist(data, '\(\d\+\)')[1]
+                call add(disp, printf('%9d %-20s (%s)', cnt, name, search))
+                call add(searches, search)
+        endfor
+
+        call <SID>NM_newBuffer('folders', join(disp, "\n"))
+        let b:nm_searches = searches
+        let b:nm_timestamp = reltime()
+
+        call <SID>NM_cmd_folders_mksyntax()
+        call <SID>NM_set_map(g:notmuch_folders_maps)
+        setlocal cursorline
+        setlocal nowrap
+endfunction
+
+function! s:NM_cmd_folders_mksyntax()
+endfunction
+
+" --- --- folders screen action functions {{{2
+
+function! s:NM_folders_refresh_view()
+        let lno = line('.')
+        setlocal bufhidden=delete
+        call s:NM_cmd_folders([])
+        exec printf('norm %dG', lno)
+endfunction
+
+function! s:NM_folders_show_search()
+        let line = line('.')
+        let search = b:nm_searches[line-1]
+
+        let prev_bufnr = bufnr('%')
+        setlocal bufhidden=hide
+        call <SID>NM_cmd_search([search])
+        setlocal bufhidden=delete
+        let b:nm_prev_bufnr = prev_bufnr
+endfunction
+
+
 " --- implement search screen {{{1
 
 function! s:NM_cmd_search(words)
@@ -123,11 +191,8 @@ function! s:NM_cmd_search(words)
                 let cmd = cmd + ['--sort=oldest-first']
         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 map(disp, 's:NM_cmd_search_fmtline(v:val)')
 
         call <SID>NM_newBuffer('search', join(disp, "\n"))
@@ -176,8 +241,17 @@ function! s:NM_search_prompt()
         else
                 let tags = s:notmuch_initial_search_words_defaults
         endif
-        setlocal bufhidden=delete
+        let prev_bufnr = bufnr('%')
+        if b:nm_type == 'search'
+                " TODO: we intend to replace the current buffer,
+                "       ... maybe we could just clear it
+                setlocal bufhidden=delete
+        else
+                setlocal bufhidden=hide
+        endif
         call <SID>NM_cmd_search(tags)
+        setlocal bufhidden=delete
+        let b:nm_prev_bufnr = prev_bufnr
 endfunction
 
 function! s:NM_search_edit()
@@ -189,11 +263,8 @@ function! s:NM_search_edit()
 endfunction
 
 function! s:NM_search_archive_thread()
+        call <SID>NM_add_remove_tags_on_screen('-', ['inbox'])
         call <SID>NM_add_remove_tags('-', ['inbox'])
-        " TODO: this could be made better and more generic
-        setlocal modifiable
-        s/(\([^)]*\)\<inbox\>\([^)]*\))$/(\1\2)/
-        setlocal nomodifiable
         norm j
 endfunction
 
@@ -272,21 +343,12 @@ function! s:NM_search_add_remove_tags(prompt, prefix, intags)
                 if !strlen(text)
                         return
                 endif
-                call <SID>NM_add_remove_tags(a:prefix, split(text, ' '))
+                let tags = split(text, ' ')
         else
-                call <SID>NM_add_remove_tags(a:prefix, a:intags)
+                let tags = a:intags
         endif
-        call <SID>NM_search_refresh_view()
-endfunction
-
-function! s:NM_add_remove_tags(prefix, tags)
-        let id = <SID>NM_search_find_thread_id()
-        if id == ''
-                echoe 'Eeek! I couldn''t find the thead id!'
-        endif
-        call map(a:tags, 'a:prefix . v:val')
-        " TODO: handle errors
-        call <SID>NM_run(['tag'] + a:tags + ['--', id])
+        call <SID>NM_add_remove_tags(a:prefix, tags)
+        call <SID>NM_add_remove_tags_on_screen(a:prefix, tags)
 endfunction
 
 " --- implement show screen {{{1
@@ -313,7 +375,7 @@ function! s:NM_cmd_show(words)
 
 endfunction
 
-function! s:NM_show_prev(can_change_thread)
+function! s:NM_show_previous(can_change_thread)
         let info = b:nm_raw_info
         let lnum = line('.')
         for msg in reverse(copy(info['msgs']))
@@ -334,7 +396,7 @@ function! s:NM_show_prev(can_change_thread)
                 norm k
                 call <SID>NM_search_show_thread()
                 norm G
-                call <SID>NM_show_prev(0)
+                call <SID>NM_show_previous(0)
         else
                 echo 'No more messages.'
         endif
@@ -480,8 +542,10 @@ function! s:NM_cmd_show_parse(inlines)
                                 elseif mode_type == 'cit'
                                         if part_end || match(line, g:notmuch_show_citation_regexp) == -1
                                                 let outlnum = len(info['disp'])
-                                                let foldinfo = [ mode_type, mode_start, outlnum-1,
-                                                               \ printf('[ %d-line citation.  Press "c" to show. ]', outlnum - mode_start) ]
+                                                if mode_start != outlnum
+                                                        let foldinfo = [ mode_type, mode_start, outlnum-1,
+                                                                       \ printf('[ %d-line citation.  Press "c" to show. ]', outlnum - mode_start) ]
+                                                endif
                                                 let mode_type = ''
                                         endif
                                 elseif mode_type == 'sig'
@@ -489,8 +553,10 @@ function! s:NM_cmd_show_parse(inlines)
                                         if (outlnum - mode_start) > g:notmuch_show_signature_lines_max
                                                 let mode_type = ''
                                         elseif part_end
-                                                let foldinfo = [ mode_type, mode_start, outlnum,
-                                                               \ printf('[ %d-line signature.  Press "s" to show. ]', outlnum - mode_start) ]
+                                                if mode_start != outlnum
+                                                        let foldinfo = [ mode_type, mode_start, outlnum-1,
+                                                                       \ printf('[ %d-line signature.  Press "s" to show. ]', outlnum - mode_start) ]
+                                                endif
                                                 let mode_type = ''
                                         endif
                                 endif
@@ -544,7 +610,7 @@ function! s:NM_cmd_show_parse(inlines)
                                         let hdr_start = msg['hdr_start']+1
                                         let hdr_end = len(info['disp'])
                                         let foldinfo = [ 'hdr', hdr_start, hdr_end,
-                                               \ printf('[ %d-line headers.  Press "h" to show. ]', hdr_end - hdr_start) ]
+                                               \ printf('[ %d-line headers.  Press "h" to show. ]', hdr_end + 1 - hdr_start) ]
                                         let msg['header'] = hdr
                                         let in_header = 0
                                         let hdr = {}
@@ -646,20 +712,28 @@ endfunction
 
 " --- notmuch helper functions {{{1
 
-function! s:NM_newBuffer(ft, content)
+function! s:NM_newBuffer(type, content)
         enew
         setlocal buftype=nofile readonly modifiable
         silent put=a:content
         keepjumps 0d
         setlocal nomodifiable
-        execute printf('set filetype=notmuch-%s', a:ft)
-        execute printf('set syntax=notmuch-%s', a:ft)
+        execute printf('set filetype=notmuch-%s', a:type)
+        execute printf('set syntax=notmuch-%s', a:type)
+        let b:nm_type = a:type
 endfunction
 
 function! s:NM_run(args)
         let cmd = g:notmuch_cmd . ' ' . join(a:args) . '< /dev/null'
+
+        let start = reltime()
         let out = system(cmd)
-        if v:shell_error
+        let err = v:shell_error
+        let delta = reltime(start)
+
+        echo printf('[%s] {%s} %s', reltimestr(delta), string(err), string(cmd))
+
+        if err
                 echohl Error
                 echo substitute(out, '\n*$', '', '')
                 echohl None
@@ -686,6 +760,31 @@ function! s:NM_kill_this_buffer()
         endif
 endfunction
 
+function! s:NM_add_remove_tags(prefix, tags)
+        let id = <SID>NM_search_find_thread_id()
+        if id == ''
+                echoe 'Eeek! I couldn''t find the thead id!'
+        endif
+        call map(a:tags, 'a:prefix . v:val')
+        " TODO: handle errors
+        call <SID>NM_run(['tag'] + a:tags + ['--', id])
+endfunction
+
+function! s:NM_add_remove_tags_on_screen(prefix, tags)
+        let online = ''
+        setlocal modifiable
+        if a:prefix == '-'
+                for tagname in a:tags
+                        exec printf('silent %ss/(\([^)]*\)\<%s\>\([^)]*\))$/(\1\2)/', online, tagname)
+                endfor
+        else
+                for tagname in a:tags
+                        exec printf('silent %ss/(\([^)]*\)\([^)]*\))$/(\1 %s)/', online, tagname)
+                endfor
+        endif
+        setlocal nomodifiable
+endfunction
+
 " --- process and set the defaults {{{1
 
 function! NM_set_defaults(force)
@@ -716,33 +815,47 @@ endif
 if !exists('g:notmuch_initial_search_words')
         let g:notmuch_initial_search_words = s:notmuch_initial_search_words_defaults
 endif
+if !exists('g:notmuch_folders')
+        let g:notmuch_folders = s:notmuch_folders_defaults
+endif
 
 
 " --- assign keymaps {{{1
 
 function! s:NM_set_map(maps)
+        nmapclear
         for [key, code] in items(a:maps)
                 exec printf('nnoremap <buffer> %s %s', key, code)
         endfor
+        " --- this is a hack for development :)
+        nnoremap ,nmr :source ~/.vim/plugin/notmuch.vim<CR>:call NotMuch('')<CR>
 endfunction
 
 " --- command handler {{{1
 
 function! NotMuch(args)
-        if !strlen(a:args)
-                if exists('b:nm_search_words')
+        let args = a:args
+        if !strlen(args)
+                let args = 'folders'
+        endif
+
+        let words = split(args)
+        if words[0] == 'folders'
+                let words = words[1:]
+                call <SID>NM_cmd_folders(words)
+        elseif words[0] == 'search'
+                if len(words) > 1
+                        let words = words[1:]
+                elseif exists('b:nm_search_words')
                         let words = b:nm_search_words
                 else
                         let words = g:notmuch_initial_search_words
                 endif
                 call <SID>NM_cmd_search(words)
-                return
-        endif
-
-        echo "blarg!"
 
-        let words = split(a:args)
-        " TODO: handle commands passed as arguments
+        elseif words[0] == 'show'
+                echoe 'show is not yet implemented.'
+        endif
 endfunction
 function! CompleteNotMuch(arg_lead, cmd_line, cursor_pos)
         return []
@@ -754,8 +867,4 @@ endfunction
 command! -nargs=* -complete=customlist,CompleteNotMuch NotMuch call NotMuch(<q-args>)
 cabbrev  notmuch <c-r>=(getcmdtype()==':' && getcmdpos()==1 ? 'NotMuch' : 'notmuch')<CR>
 
-" --- hacks, only for development :) {{{1
-
-nnoremap ,nmr :source ~/.vim/plugin/notmuch.vim<CR>:call NotMuch('')<CR>
-
 " vim: set ft=vim ts=8 sw=8 et foldmethod=marker :