diff --git a/README b/README index e0e9386..0187f28 100644 --- a/README +++ b/README @@ -82,8 +82,10 @@ The plugin defines some new mappings: \tD Archive @done items \tX Show tasks marked as cancelled \tT Show tasks marked as today + \to Show tasks that are due today or overdue \t/ Search for items including keyword \ts Search for items including tag + \tr Search for items with a tag parameter in a range (literal) \tp Fold all projects \t. Fold all notes \tP Focus on the current project @@ -103,6 +105,14 @@ search. If you use the `\ts` command over the desired context tag, the tag name is set as default value. This will fold all the irrelevant tasks leaving only the tasks in the current context visible. +To show all tasks with a particular context tag parameter +(e.g. `@due(2013-07-26)`) being in a certain range, type `\tr` and a tag name, +a minimum and a maximum. This will fold all irrelevant tasks, leaving +only the tasks that have their parameter being inside the specified range. +This is useful, for example, to show all tasks that have a specific due date. +Not that the comparison is done based on string literals, i.e. "12" is less than "20". +This is no problem for dates in ISO format (e.g. "2013-07-13"). + To fold all top-level projects leaving only the headings visible use the `\tp` command. Standard fold commands can be used to open (`zo`) and close (`zc`) individual projects. diff --git a/autoload/taskpaper.vim b/autoload/taskpaper.vim index d9b7a93..64e464e 100644 --- a/autoload/taskpaper.vim +++ b/autoload/taskpaper.vim @@ -327,7 +327,7 @@ function! taskpaper#update_project() for linenr in range(line('.'), 1, -1) let line = getline(linenr) - let ml = matchlist(line, '\v^\t{0,' . depth . '}([^\t:]+):') + let ml = matchlist(line, '\v^\t{0,' . depth . '}([^\t:]+):$') if empty(ml) continue endif @@ -349,6 +349,8 @@ function! taskpaper#update_project() endfunction function! taskpaper#archive_done() + + " Search for the beginning of the archive section let archive_start = search('^' . g:task_paper_archive_project . ':', 'cw') if archive_start == 0 call append('$', g:task_paper_archive_project . ':') @@ -366,6 +368,7 @@ function! taskpaper#archive_done() call cursor(1, 1) let deleted = 0 + " Search for @done tasks while 1 let lnum = search('@done', 'W', archive_start - deleted) if lnum == 0 @@ -375,7 +378,7 @@ function! taskpaper#archive_done() call taskpaper#update_project() let deleted += taskpaper#delete(lnum, 'A', 1) endwhile - + " Also search after the archive if archive_end != 0 call cursor(archive_end, 1) @@ -402,6 +405,43 @@ function! taskpaper#archive_done() return deleted endfunction +function! taskpaper#fold_tag_range(lnum, tag, min, max) + " Fold lines based on the parameter of a tag, i.e. tag(param) + " and show only lines for which min <= param <= max + let line = getline(a:lnum) + let level = foldlevel(a:lnum) + + let rex = a:tag.'(\(.*\))' + let params = matchlist(line, rex) + if len(params) > 0 + let parameter = params[1] + if (parameter >= a:min) && (parameter <= a:max) + return 0 + endif + " default behavior + elseif synIDattr(synID(a:lnum, 1, 1), "name") != 'taskpaperProject' + return 1 + elseif level != -1 + return level + endif + + " TODO What happens here? + let depth = len(matchstr(getline(a:lnum), '^\t*')) + + for lnum in range(a:lnum + 1, line('$')) + let line = getline(lnum) + + if depth >= len(matchstr(line, '^\t*')) + break + endif + + if line =~? a:pat && (a:ipat == '' || line !~? a:ipat) + return 0 + endif + endfor + return 1 +endfunction + function! taskpaper#fold(lnum, pat, ipat) let line = getline(a:lnum) let level = foldlevel(a:lnum) @@ -442,6 +482,29 @@ function! taskpaper#search(...) setlocal foldmethod=expr foldlevel=0 foldenable endfunction +function! taskpaper#search_tag_range(...) + " Start a search (using folds to filter non-matching lines) + " based on the parameter of a tag, i.e. tag(param) + " and show only lines for which min <= param <= max + if a:0 > 0 + let tag = a:1 + else + let cword = expand('') + let tag = input('Tag: ', cword =~ '@\k\+' ? cword[1:] : '') + endif + let min = a:0 > 1 ? a:2 : input('Min: ') + let max = a:0 > 2 ? a:3 : input('Max: ') + if tag == '' + return + endif + " set min and max to ASCII 0 and 255 if nothing is set + let min = min == '' ? ' ' : min + let max = max == '' ? '~' : max + + setlocal foldexpr=taskpaper#fold_tag_range(v:lnum,tag,min,max) + setlocal foldminlines=0 foldtext='' + setlocal foldmethod=expr foldlevel=0 foldenable +endfunction function! taskpaper#fold_except_range(lnum, begin, end) if a:lnum > a:end return 1 diff --git a/doc/taskpaper.txt b/doc/taskpaper.txt index 8993019..a1cd26d 100644 --- a/doc/taskpaper.txt +++ b/doc/taskpaper.txt @@ -87,8 +87,10 @@ The plugin defines some new mappings: \tD Archive @done items \tX Show tasks marked as cancelled \tT Show tasks marked as today + \to Show tasks that are due today or overdue \t/ Search for items including keyword \ts Search for items including tag + \tr Search for items with a tag parameter in a range (literal) \tp Fold all projects \t. Fold all notes \tP Focus on the current project @@ -108,6 +110,14 @@ search. If you use the `\ts` command over the desired context tag, the tag name is set as default value. This will fold all the irrelevant tasks leaving only the tasks in the current context visible. +To show all tasks with a particular context tag parameter +(e.g. `@due(2013-07-26)`) being in a certain range, type `\tr` and a tag name, +a minimum and a maximum. This will fold all irrelevant tasks, leaving +only the tasks that have their parameter being inside the specified range. +This is useful, for example, to show all tasks that have a specific due date. +Not that the comparison is done based on string literals, i.e. "12" is less than "20". +This is no problem for dates in ISO format (e.g. "2013-07-13"). + To fold all top-level projects leaving only the headings visible use the `\tp` command. Standard fold commands can be used to open (`zo`) and close (`zc`) individual projects. diff --git a/ftplugin/taskpaper.vim b/ftplugin/taskpaper.vim index ea66fcb..aaf58d3 100644 --- a/ftplugin/taskpaper.vim +++ b/ftplugin/taskpaper.vim @@ -59,6 +59,10 @@ if !exists("no_plugin_maps") && !exists("no_taskpaper_maps") \ :call taskpaper#search() nnoremap TaskPaperSearchTag \ :call taskpaper#search_tag() + nnoremap TaskPaperSearchRange + \ :call taskpaper#search_tag_range() + nnoremap TaskPaperShowDueToday + \ :call taskpaper#search_tag_range('due','',strftime('%Y-%m-%d')) nnoremap TaskPaperGoToProject \ :call taskpaper#go_to_project() @@ -93,6 +97,8 @@ if !exists("no_plugin_maps") && !exists("no_taskpaper_maps") nmap t/ TaskPaperSearchKeyword nmap ts TaskPaperSearchTag + nmap tr TaskPaperSearchRange + nmap to TaskPaperShowDueToday nmap tg TaskPaperGoToProject nmap tj TaskPaperNextProject