From 7d70e30aae178efe2a25e815bf0ff903377f5403 Mon Sep 17 00:00:00 2001 From: David Beniamine Date: Wed, 18 Apr 2018 17:51:28 +0200 Subject: [PATCH] Add Possibility to fold on context or project Closes #30 Folds now works the following way: + At initialisation, if all completed tasks are at the end, folds are based on completed tasks only, else they are based on context + After a hierarchichal sort, folds are set by the first level between project and context + After a "normal" sort, folds are set only on completed tasks (as before) This work is greatly inspired from the snipped provided by @arecarn --- autoload/todo.vim | 2 ++ ftplugin/todo.vim | 51 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/autoload/todo.vim b/autoload/todo.vim index 69be5db..8b6c928 100644 --- a/autoload/todo.vim +++ b/autoload/todo.vim @@ -150,6 +150,7 @@ endfunction function! todo#Sort() " vim :sort is usually stable " we sort first on contexts, then on projects and then on priority + let g:Todo_fold_char='x' if expand('%')=~'[Dd]one.*.txt' " FIXME: Put some unit tests around this, and fix case sensitivity if ignorecase is set. silent! %s/\(x\s*\d\{4}\)-\(\d\{2}\)-\(\d\{2}\)/\1\2\3/g @@ -268,6 +269,7 @@ function! todo#HierarchicalSort(symbol, symbolsub, dolastsort) "Empty buffer do nothing return endif + let g:Todo_fold_char=a:symbol "if the sort modes doesn't start by '!' it must start with a space let l:sortmode=Todo_txt_InsertSpaceIfNeeded(g:Todo_txt_first_level_sort_mode) let l:sortmodesub=Todo_txt_InsertSpaceIfNeeded(g:Todo_txt_second_level_sort_mode) diff --git a/ftplugin/todo.vim b/ftplugin/todo.vim index a925f8b..8eb68fb 100644 --- a/ftplugin/todo.vim +++ b/ftplugin/todo.vim @@ -106,26 +106,57 @@ setlocal foldmethod=expr setlocal foldexpr=TodoFoldLevel(v:lnum) setlocal foldtext=TodoFoldText() +" Go to first completed task +let oldpos=getcurpos() +let g:Todo_fold_char='@' +let base_pos=search('^x\s', 'ce') +" Get next completed task +let first_incomplete = search('^\s*[^]') +if (first_incomplete < base_pos) + " Check if all tasks from + let g:Todo_fold_char='x' +else + " TODO detect if sorted on prjects + let g:Todo_fold_char='@' +endif +call setpos('.', oldpos) + +function! s:get_contextproject(line) abort "{{{2 + return matchstr(getline(a:line), g:Todo_fold_char.'[^ ]\+') +endfunction "}}}3 + " TodoFoldLevel(lnum) {{{2 function! TodoFoldLevel(lnum) - " The match function returns the index of the matching pattern or -1 if - " the pattern doesn't match. In this case, we always try to match a - " completed task from the beginning of the line so that the matching - " function will always return -1 if the pattern doesn't match or 0 if the - " pattern matches. Incrementing by one the value returned by the matching - " function we will return 1 for the completed tasks (they will be at the - " first folding level) while for the other lines 0 will be returned, - " indicating that they do not fold. - return match(getline(a:lnum),'\C^x\s') + 1 + let this_context = s:get_contextproject(a:lnum) + let next_context = s:get_contextproject(a:lnum - 1) + + if g:Todo_fold_char == 'x' + " fold on cmpleted task + return match(getline(a:lnum),'\C^x\s') + 1 + endif + + let fold_level = 0 + + if this_context ==# next_context + let fold_level = '1' + else + let fold_level = '>1' + endif + + return fold_level endfunction " TodoFoldText() {{{2 function! TodoFoldText() + let this_context = s:get_contextproject(v:foldstart) + if g:Todo_fold_char == 'x' + let this_context = 'Completed tasks' + endif " The text displayed at the fold is formatted as '+- N Completed tasks' " where N is the number of lines folded. return '+' . v:folddashes . ' ' \ . (v:foldend - v:foldstart + 1) - \ . ' Completed tasks ' + \ .' '. this_context endfunction " Restore context {{{1