diff --git a/plugin/todo-txt.vim b/plugin/todo-txt.vim index b5fd74e..2faaabe 100644 --- a/plugin/todo-txt.vim +++ b/plugin/todo-txt.vim @@ -1,74 +1,121 @@ " File: todo.txt.vim " Description: Todo.txt sorting plugin -" Author: Leandro Freitas +" Author: David Beniamine " Licence: Vim licence " Website: http://github.com/dbeniamine/todo.txt.vim " Version: 0.3 +" vim: ts=4 sw=4 :help tw=78 cc=80 -" These two variables are parameters for the first and second call to the vim -" sort function +" These two variables are parameters for the successive calls the vim sort " '' means no flags " '! i' means reverse and ignore case " for more information on flags, see :help sort if (! exists("g:Todo_txt_first_level_sort_mode")) - let g:Todo_txt_first_level_sort_mode="i" + let g:Todo_txt_first_level_sort_mode='i' endif if (! exists("g:Todo_txt_second_level_sort_mode")) - let g:Todo_txt_second_level_sort_mode="i" + let g:Todo_txt_second_level_sort_mode='i' +endif +if (! exists("g:Todo_txt_third_level_sort_mode")) + let g:Todo_txt_third_level_sort_mode='i' endif " Sort todo by (first) context -noremap sc :call Todo_txt_TwoLevelsSort('@') +noremap sc :call Todo_txt_HierarchicalSort('@', '', 1) +noremap scp :call Todo_txt_HierarchicalSort('@', '+', 1) " Sort todo by (first) project -noremap sp :call Todo_txt_TwoLevelsSort('+') +noremap sp :call Todo_txt_HierarchicalSort('+', '',1) +noremap spc :call Todo_txt_HierarchicalSort('+', '@',0) -" This is a two level sort designed for todo.txt todo lists +" This is a Hierarchical sort designed for todo.txt todo lists, however it +" might be used for other files types " At the first level, lines are sorted by the word right after the first " occurence of a:symbol, there must be no space between the symbol and the -" word. Therefore, according to todo.txt syntaxt, if +" word. At the second level, the same kind of sort is done based on +" a:symbolsub, is a:symbol==' ', the second sort doesn't occurs +" Therefore, according to todo.txt syntaxt, if " a:symbol is a '+' it sort by the first project " a:symbol is an '@' it sort by the first context -" The second level of sort is done direcetly on the line, so according to -" todo.txt syntax, it means sort by priority -function! Todo_txt_TwoLevelsSort(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:sortmode2=Todo_txt_InsertSpaceIfNeeded(g:Todo_txt_second_level_sort_mode) - - " Count the number of lines - let l:position= getpos(".") - execute "silent normal g\" +" The last level of sort is done directly on the line, so according to +" todo.txt syntax, it means by priority. This sort is done if and only if the +" las argument is not 0 +function! Todo_txt_HierarchicalSort(symbol, symbolsub, dolastsort) if v:statusmsg =~ '--No lines in buffer--' "Empty buffer do nothing return endif + "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) + let l:sortmodefinal=Todo_txt_InsertSpaceIfNeeded(g:Todo_txt_third_level_sort_mode) + + " Count the number of lines + let l:position= getpos(".") + execute "silent normal g\" let l:linecount=str2nr(split(v:statusmsg)[7]) " Get all the groups names - let l:curline=0 + let l:groups=GetGroups(a:symbol,0,l:linecount) + + " Sort by groups + execute 'sort'.l:sortmode.' /.\{-}\ze'.a:symbol.'/' + for l:g in l:groups + " Find the beginning of the group + execute '/'.a:symbol.l:g.'.*$' + let l:groupBegin=getpos(".")[1] + " Find the end of the group + silent normal N + let l:groupEnd=getpos(".")[1] + + " I'm too lazy to sort one groups of one line + if(l:groupEnd==l:groupBegin) + continue + endif + if( a:symbolsub!='') + " Sort by subgroups + let l:subgroups=GetGroups(a:symbolsub,l:groupBegin,l:groupEnd) + " Go before the first line of the group + " Sort the group using the second symbol + for l:sg in l:subgroups + " Find the beginning of the subgroup + execute '/'.a:symbol.l:g.'.*'.a:symbolsub.l:sg.'.*$\|'.a:symbolsub.l:sg.'.*'.a:symbol.l:g.'.*$' + let l:subgroupBegin=getpos(".")[1] + " Find the end of the subgroup + silent normal N + let l:subgroupEnd=getpos(".")[1] + " Sort by priority + if a:dolastsort + execute l:subgroupBegin.','.l:subgroupEnd.'sort'.l:sortmodefinal + endif + endfor + else + " Sort by priority + if a:dolastsort + execute l:groupBegin.','.l:groupEnd.'sort'.l:sortmodefinal + endif + endif + endfor + " Restore the cursor position + call setpos('.', position) +endfunction + +" Returns the list of groups starting by a:symbol between lines a:begin and +" a:end +function GetGroups(symbol,begin, end) + let l:curline=a:begin let l:groups=[] - while l:curline <= l:linecount + while l:curline <= a:end let l:curproj=strpart(matchstr(getline(l:curline),a:symbol.'\a*'),1) if l:curproj != "" && index(l:groups,l:curproj) == -1 let l:groups=add(l:groups , l:curproj) endif let l:curline += 1 endwhile - - " Sort by groups - execute 'sort'.l:sortmode.' /.\{-}\ze'.a:symbol.'/' - for l:p in l:groups - execute '/^.\{-}'.a:symbol.l:p.'.*$' - normal ma - normal G - execute '?^.\{-}'.a:symbol.l:p.'.*$' - normal mb - execute "'a,'b sort".l:sortmode2 - endfor - " Restore the cursor position - call setpos('.', position) + return l:groups endfunction +" Insert a space if needed (the first char isn't '!' or ' ') in front of +" sort parameters function! Todo_txt_InsertSpaceIfNeeded(str) let l:c=strpart(a:str,1,1) if( l:c != '!' && l:c !=' ')