Update 2024-02-14 16:20 Linux/x86_64-ld5587

This commit is contained in:
c0dev0id
2024-02-14 16:20:07 +01:00
parent 35ed2c3d92
commit 8d78a17efb
19 changed files with 2058 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
function! airline#extensions#taskwarrior#apply(...)
if &ft == 'taskreport'
call a:1.add_section('airline_a', ' Taskwarrior ')
call a:1.add_section('airline_b', ' %{b:command} %{&readonly ? g:airline_symbols.readonly : ""}')
call a:1.add_section('airline_b', ' @%{b:context} ')
call a:1.add_section('airline_b', g:task_left_arrow.' %{b:hist > 1 ? g:task_right_arrow : ""}')
call a:1.add_section('airline_c', ' %{b:filter} ')
call a:1.add_section('airline_c', ' %{b:sstring} ')
call a:1.split()
call a:1.add_section('airline_x', ' %{b:now} ')
call a:1.add_section('airline_x', ' %{b:task_report_columns[taskwarrior#data#current_index()]} ')
call a:1.add_section('airline_y', ' %{b:sort} ')
if b:active != '0'
call airline#parts#define_text('active', ' '.b:active.' ')
call airline#parts#define_accent('active', 'orange')
call a:1.add_section('airline_z', airline#section#create(['active']))
endif
call a:1.add_section('airline_z', ' %{b:summary[0]} ')
call airline#parts#define_text('completed', ' '.b:summary[1].' ')
call airline#parts#define_accent('completed', 'green')
call a:1.add_section('airline_z', airline#section#create(['completed']))
call a:1.add_section('airline_z', ' %{b:summary[2]} ')
return 1
elseif &ft == 'taskinfo'
call a:1.add_section('airline_a', ' Taskinfo ')
call a:1.add_section('airline_b', ' %{b:command." ".g:airline_symbols.readonly }')
call a:1.add_section('airline_c', ' %{b:filter} ')
call a:1.split()
return 1
endif
endfunction
function s:context()
let con = split(system('task context show'), '\n')
let con = con =~ 'No context' ? 'none' : con
return con
endfunction
function! airline#extensions#taskwarrior#init(ext)
call a:ext.add_statusline_func('airline#extensions#taskwarrior#apply')
endfunction

View File

@@ -0,0 +1,44 @@
function! taskinfo#init(command, filter, info)
if exists('g:task_info')
call taskinfo#quit()
endif
if a:command != 'info'
\ && exists('g:task_info_arg')
\ && g:task_info_arg == [a:command, a:filter]
unlet g:task_info_arg
return
endif
execute g:task_info_position.' '.g:task_info_size.
\ (g:task_info_vsplit ? 'v' : '').'split'
edit taskinfo
let g:task_info = bufnr('%')
let g:task_info_arg = [a:command, a:filter]
setlocal noswapfile
setlocal modifiable
call append(0, a:info)
silent global/^[\t ]*$/delete
silent global/^[ -]\+$/delete
setlocal readonly
setlocal nomodifiable
setlocal buftype=nofile
setlocal nowrap
setlocal filetype=taskinfo
1
let b:command = a:command
let b:filter = a:filter
nnoremap <silent> <buffer> q :call taskinfo#quit()<CR>
nnoremap <silent> <buffer> <enter> :call taskinfo#quit()<CR>
if a:command != 'info'
wincmd W
endif
endfunction
function! taskinfo#quit()
silent! execute g:task_info.'bd!'
unlet g:task_info
endfunction

View File

@@ -0,0 +1,221 @@
function! taskwarrior#list(...) abort
setlocal noreadonly
setlocal modifiable
let pos = getpos('.')
%delete
call taskwarrior#buffer_var_init()
let b:command = get(a:, 1, b:command)
let b:filter = get(a:, 2, b:filter)
let b:type = get(a:, 3, b:type)
let b:rc = get(a:, 4, b:rc). ' rc.defaultheight=0'
let b:rc .= ' '.join(filter(split(b:filter, ' '), "v:val =~ '^rc\..*'"))
let b:filter = join(filter(split(b:filter, ' '), "v:val !~ '^rc\..*'"))
let rcs = split(b:rc, ' ')
let b:rc = join(filter(copy(rcs), "match(rcs, matchstr(v:val, '^[^=:]*'), v:key+1) == -1"), ' ')
if b:type == 'special'
setlocal buftype=nofile
call append(0, split(system('task '.b:rc.' '.b:filter.' '.b:command), '\n'))
silent global/^[\t ]*$/delete
execute 'setlocal filetype=task_'.b:command
nnoremap <buffer> q :call taskwarrior#Bclose(bufnr('%'))<CR>
call setpos('.', pos)
return
endif
let b:hist = get(b:, 'hist', 1)
call taskwarrior#log#history('write')
let rcc = matchstr(b:rc, 'rc\.report\.'.b:command.'\.columns.\zs\S*')
let rcl = matchstr(b:rc, 'rc\.report\.'.b:command.'\.labels.\zs\S*')
" let b:task_report_columns = rcc == '' ? split(system("task _get -- rc.report.".b:command.".columns")[0:-2], ',') : split(rcc, ',')
" let b:task_report_labels = rcl == '' ? split(system("task _get -- rc.report.".b:command.".labels")[0:-2], ',') : split(rcl, ',')
let b:task_report_columns = rcc == '' ? split(matchstr(system("task show |grep report.".b:command.".columns")[0:-2], '\S*$'), ',') : split(rcc, ',')
let b:task_report_labels = rcl == '' ? split(matchstr(system("task show |grep report.".b:command.".labels")[0:-2], '\S*$'), ',') : split(rcl, ',')
let line1 = join(b:task_report_labels, ' ')
let context = split(substitute(
\ system('task '.b:rc.' '.b:filter.' '.b:command),
\ '\[[0-9;]\+m',
\ '', 'g'),
\ '\n')
let split_lineno = match(context, '^[ -]\+$')
if split_lineno == -1
call append(0, line1)
else
let end = len(context)-match(reverse(copy(context)), '^$')
call append(0, context[split_lineno-1:end-1])
silent global/^[\t ]*$/delete
silent global/^[ -]\+$/delete
endif
call filter(b:task_report_columns, "index(split(getline(1), ' '), b:task_report_labels[v:key]) != -1")
call filter(b:task_report_labels, "index(split(getline(1), ' '), v:val) != -1")
let b:task_columns = []
let ci = 0
1
while ci != -1
let b:task_columns += [ci]
let ci = search('\s\S', 'W', 1)
let ci = ci > 0 ? virtcol('.') : -1
endwhile
let b:task_columns += [999]
let b:summary = taskwarrior#data#global_stats()
let b:sort = taskwarrior#sort#order_list()[0]
let a_tasks = split(system('task active limit:1 rc.verbose:nothing
\ rc.report.active.sort=start-
\ rc.report.active.columns=start.active,start.age,id,description.desc
\ rc.report.active.labels=A,Age,ID,Description'), '\n')
let b:now = len(a_tasks) > 0 ? a_tasks[-1] : ''
let b:active = split(system('task start.any: count'), '\n')[0]
let b:selected = []
let b:sline = []
let b:sstring = ''
let con = split(system('task context show'), '\n')[0]
let b:context = con =~ 'No context' ? 'none' :
\ matchstr(con, 'Context .\zs\S*\ze. ')
setlocal filetype=taskreport
if exists('b:ct')
for l in range(line('$'))
if taskwarrior#data#get_uuid(l) == b:ct
let pos[1] = l
break
endif
endfor
endif
call setpos('.', pos)
endfunction
function! taskwarrior#buffer_var_init()
let b:command = get(b:, 'command', g:task_report_name)
let b:filter = get(b:, 'filter', '')
let b:type = get(b:, 'type', 'report')
let b:rc = get(b:, 'rc', g:task_rc_override)
endfunction
function! taskwarrior#init(...)
if exists(':TagbarClose')
TagbarClose
endif
let argstring = join(a:000, ' ')
let [command, filter, type] = taskwarrior#command_type(argstring)
let rc = g:task_rc_override
if type == 'interactive'
if !g:task_readonly
execute '!task '.argstring
call taskwarrior#refresh()
endif
return
endif
execute 'edit task\ '.command.'\ '.type
if exists('g:task_view')
let g:task_view += [bufnr('%')]
else
let g:task_view = [bufnr('%')]
endif
setlocal noswapfile
call taskwarrior#list(command, filter, type, rc)
endfunction
function! taskwarrior#refresh()
if exists('g:task_view')
for bufn in g:task_view
execute bufn.'buffer'
call taskwarrior#list()
endfor
else
call taskwarrior#init()
endif
endfunction
function! taskwarrior#Bclose(buffer)
if a:buffer =~ '^\d\+$'
let btarget = bufnr(str2nr(a:buffer))
else
let btarget = bufnr(a:buffer)
endif
if bufname(btarget) == ''
bdelete
return
endif
" Numbers of windows that view target buffer which we will delete.
let wnums = filter(range(1, winnr('$')), 'winbufnr(v:val) == btarget')
let wcurrent = winnr()
for w in wnums
execute w.'wincmd w'
let prevbuf = bufnr('#')
if prevbuf > 0 && buflisted(prevbuf) && prevbuf != w
buffer #
else
bprevious
endif
if btarget == bufnr('%')
" Numbers of listed buffers which are not the target to be deleted.
let blisted = filter(range(1, bufnr('$')), 'buflisted(v:val) && v:val != btarget')
" Listed, not target, and not displayed.
let bhidden = filter(copy(blisted), 'bufwinnr(v:val) < 0')
" Take the first buffer, if any (could be more intelligent).
let bjump = (bhidden + blisted + [-1])[0]
if bjump > 0
execute 'buffer '.bjump
else
enew
endif
endif
endfor
execute 'silent! bdelete '.btarget
execute wcurrent.'wincmd w'
endfunction
function! taskwarrior#hi_field()
silent! syntax clear taskwarrior_field
let index = taskwarrior#data#current_index()
execute 'syntax match taskwarrior_field /\%>1l\%'.line('.').'l\%'.(b:task_columns[index]+1).'v.*\%<'.(b:task_columns[index+1]+1).'v/'
endfunction
function! taskwarrior#quit()
call taskwarrior#Bclose(bufnr('%'))
call remove(g:task_view, index(g:task_view, bufnr('%')))
endfunction
function! taskwarrior#quit_all()
for bufn in g:task_view
call taskwarrior#Bclose(bufn)
endfor
let g:task_view = []
endfunction
function! taskwarrior#system_call(filter, command, args, mode)
if a:mode == 'silent'
call system('task '.a:filter.' '.a:command.' '.a:args)
elseif a:mode == 'echo'
echo "\n----------------\n"
echo system('task '.a:filter.' '.a:command.' '.a:args)
else
execute '!task '.a:filter.' '.a:command.' '.a:args
endif
call taskwarrior#refresh()
endfunction
function! taskwarrior#command_type(string)
for sub in split(a:string, ' ')
if index(g:task_report_command, sub) != -1
return [ sub, substitute(' '.a:string, ' '.sub, '', ''), 'report' ]
elseif index(g:task_interactive_command, sub) != -1
return [ sub, substitute(' '.a:string, ' '.sub, '', ''), 'interactive' ]
elseif index(g:task_all_commands, sub) != -1
return [ sub, substitute(' '.a:string, ' '.sub, '', ''), 'special' ]
endif
endfor
return [ g:task_report_name, a:string, 'report' ]
endfunction

View File

@@ -0,0 +1,370 @@
function! taskwarrior#action#new()
call taskwarrior#system_call('', 'add', taskwarrior#data#get_args('add'), 'echo')
endfunction
function! taskwarrior#action#set_done()
call taskwarrior#system_call(taskwarrior#data#get_uuid(), ' done', '', 'silent')
endfunction
function! taskwarrior#action#urgency() abort
let cc = taskwarrior#data#current_column()
let udas = split(system('task _udas'), '\n')
let cmap = { 'start' : 'active',
\ 'entry' : 'age',
\ 'depends' : 'blocked',
\ 'parent' : 'blocking',
\ 'wait' : 'waiting',
\ 'description' : 'annotations'
\ }
let isuda = 0
if has_key(cmap, cc)
let cc = cmap[cc]
elseif index(['due', 'priority', 'project', 'tags', 'scheduled']
\ , cc) == -1
if index(udas, cc) == -1
call taskwarrior#sort#by_arg('urgency-')
return
else
let isuda = 1
endif
endif
let rcfile = $HOME.'/.taskrc'
if filereadable(rcfile)
let cv = taskwarrior#data#get_value_by_column(line('.'), cc)
let option = isuda ? 'urgency.uda.'.cc.'.coefficient' :
\ 'urgency.'.cc.'.coefficient'
if len(cv)
let ctag = expand('<cword>')
if cc == 'tags' && index(split(cv), ctag) != -1
let option = 'urgency.user.tag.'.ctag.'.coefficient'
elseif cc == 'project' && cv =~ '^[^ \t%\\*]\+$'
let pl = split(cv, '\.')
let idx = index(pl, expand('<cword>'))
let option = 'urgency.user.project.'.
\ join(pl[0:idx], '.').'.coefficient'
elseif isuda && cv =~ '^\w\+$'
let option = 'urgency.uda.'.cc.'.'.cv.'.coefficient'
endif
endif
let default_raw = split(system('task _get rc.'.option), '\n')
let default = len(default_raw) ? default_raw[0] : '0'
let new = input(option.' : ', default)
let lines = readfile(rcfile)
let index = match(lines, option)
if str2float(new) == str2float(default)
elseif str2float(new) == 0
call filter(lines, 'v:val !~ option')
elseif index == -1
call add(lines, option.'='.new)
else
let lines[index] = option.'='.new
endif
call writefile(lines, rcfile)
endif
call taskwarrior#sort#by_arg('urgency-')
execute 'normal! :\<Esc>'
endfunction
function! taskwarrior#action#modify(mode)
let uuid = taskwarrior#data#get_uuid()
if uuid == ''
return
endif
if a:mode == 'current'
let field = taskwarrior#data#current_column()
if index(['id', 'uuid', 'status', 'urgency'], field) != -1
return
elseif field == 'description'
call taskwarrior#system_call(uuid, 'modify', taskwarrior#data#get_args('modify', [field]), 'external')
else
call taskwarrior#system_call(uuid, 'modify', taskwarrior#data#get_args('modify', [field]), 'silent')
endif
else
call taskwarrior#system_call(uuid, 'modify', taskwarrior#data#get_args('modify'), 'external')
endif
endfunction
function! taskwarrior#action#delete()
let uuid = taskwarrior#data#get_uuid()
if uuid == ''
call taskwarrior#action#annotate('del')
else
let ccol = taskwarrior#data#current_column()
if index(['project', 'tags', 'due', 'priority', 'start', 'depends'], ccol) != -1
call taskwarrior#system_call(uuid, 'modify', ccol.':', 'silent')
else
execute '!task '.uuid.' delete'
endif
endif
call taskwarrior#refresh()
endfunction
function! taskwarrior#action#remove()
execute '!task '.taskwarrior#data#get_uuid().' delete'
call taskwarrior#list()
endfunction
function! taskwarrior#action#annotate(op)
let ln = line('.')
let offset = -1
while ln > 1 && taskwarrior#data#get_uuid(ln) == ''
let ln -= 1
let offset += 1
endwhile
let uuid = taskwarrior#data#get_uuid(ln)
if uuid == ''
return
endif
if a:op == 'add'
let annotation = input('new annotation:', '', 'file')
call taskwarrior#system_call(uuid, ' annotate ', annotation, 'silent')
elseif a:op == 'del'
let annotation = input('annotation pattern to delete:')
call taskwarrior#system_call(uuid, ' denotate ', annotation, 'silent')
elseif offset >= 0
let taskobj = taskwarrior#data#get_query(uuid)
if exists('taskobj.annotations[offset].description')
let file = substitute(taskobj.annotations[offset].description, '\s*\/\s*', '/', 'g')
let file = escape(file, ' ')
let ft = 'text'
if executable('file')
let ft = system('file '.file)[:-2]
endif
if ft =~ 'text$'
execute 'e '.file
elseif ft !~ '(No such file or directory)' || file =~ '[a-z]*:\/\/[^ >,;]*'
if executable('xdg-open')
call system('xdg-open '.file.'&')
elseif executable('open')
call system('open '.file.'&')
endif
endif
endif
endif
endfunction
function! taskwarrior#action#filter()
let column = taskwarrior#data#current_column()
if index(['project', 'tags', 'status', 'priority'], column) != -1 && line('.') > 1
let filter = substitute(substitute(taskwarrior#data#get_args('modify', [column]), 'tags:', '+', ''), '\v^\s*\+(\s|$)', '', '')
elseif column =~ '\v^(entry|end|due)$'
let filter = column.'.before:'.input(column.'.before:', taskwarrior#data#get_value_by_column('.', column))
elseif column == 'description'
let filter = 'description:'.input('description:', taskwarrior#data#get_value_by_column('.', column) )
else
let filter = input('new filter:', b:filter, 'customlist,taskwarrior#complete#filter')
endif
let filter = substitute(filter, 'status:\(\s\|$\)', 'status.any: ', 'g')
if filter != b:filter
let b:filter = filter
let b:hist = 1
call taskwarrior#list()
endif
endfunction
function! taskwarrior#action#command()
if len(b:selected) == 0
let filter = taskwarrior#data#get_uuid()
else
let filter = join(b:selected, ',')
endif
let command = input('task '.filter.':', '', 'customlist,taskwarrior#complete#command')
if index(g:task_all_commands, b:command) == -1
return
endif
call taskwarrior#system_call(filter, command, '', 'interactive')
endfunction
function! taskwarrior#action#report()
let command = input('new report:', g:task_report_name, 'customlist,taskwarrior#complete#report')
if index(g:task_report_command, command) != -1 && command != b:command
let b:command = command
let b:hist = 1
call taskwarrior#list()
endif
endfunction
function! taskwarrior#action#paste()
if len(b:selected) == 0
return
elseif len(b:selected) < 3
call taskwarrior#system_call(join(b:selected, ','), 'duplicate', '', 'echo')
else
call taskwarrior#system_call(join(b:selected, ','), 'duplicate', '', 'interactive')
endif
endfunction
function! taskwarrior#action#columns_format_change(direction)
let ccol = taskwarrior#data#current_column()
if !exists('g:task_columns_format[ccol]')
return
endif
let clist = g:task_columns_format[ccol]
if len(clist) == 1
return
endif
let ccol_ful = b:task_report_columns[taskwarrior#data#current_index()]
let ccol_sub = matchstr(ccol_ful, '\.\zs.*')
let rcl = matchstr(b:rc, 'rc\.report\.'.b:command.'\.columns.\zs\S*')
" let dfl = system('task _get -- rc.report.'.b:command.'.columns')[0:-2]
let dfl = matchstr(system('task show | grep report.'.b:command.'.columns')[0:-2], '\S*$')
let index = index(clist, ccol_sub)
let index = index == -1 ? 0 : index
if a:direction == 'left'
let index -= 1
else
let index += 1
if index == len(clist)
let index = 0
endif
endif
let newsub = index == 0 ? '' : '.'.clist[index]
let b:rc .= ' rc.report.'.b:command.'.columns:'.
\ substitute(
\ rcl == '' ? dfl : rcl,
\ '[=:,]\zs'.ccol_ful.'\ze\(,\|$\)',
\ ccol.newsub, ''
\ )
let b:hist = 1
call taskwarrior#list()
endfunction
function! taskwarrior#action#date(count)
let ccol = taskwarrior#data#current_column()
if index(['due', 'end', 'entry'], ccol) == -1
return
endif
setlocal modifiable
if exists('g:loaded_speeddating')
call speeddating#increment(a:count)
elseif a:count > 0
execute 'normal! '.a:count.''
else
execute 'normal! '.-a:count.''
endif
let b:ct = taskwarrior#data#get_uuid()
call taskwarrior#system_call(b:ct, 'modify', ccol.':'.taskwarrior#data#get_value_by_column('.', ccol, 'temp'), 'silent')
endfunction
function! taskwarrior#action#visual(action) range
let line1 = getpos("'<")[1]
let line2 = getpos("'>")[1]
let fil = []
let lin = []
for l in range(line1, line2)
let uuid = taskwarrior#data#get_uuid(l)
if uuid !~ '^\s*$'
let fil += [uuid]
let lin += [l]
endif
endfor
let filter = join(fil, ',')
if a:action == 'done'
call taskwarrior#system_call(filter, 'done', '', 'interactive')
elseif a:action == 'delete'
call taskwarrior#system_call(filter, 'delete', '', 'interactive')
elseif a:action == 'info'
call taskinfo#init('information', filter, split(system('task rc.color=no information '.filter), '\n'))
elseif a:action == 'select'
for var in fil
let index = index(b:selected, var)
if index == -1
let b:selected += [var]
let b:sline += [lin[index(fil, var)]]
else
call remove(b:selected, index)
call remove(b:sline, index)
endif
endfor
let b:sstring = join(b:selected, ' ')
setlocal syntax=taskreport
endif
endfunction
function! taskwarrior#action#move_cursor(direction, mode)
let ci = taskwarrior#data#current_index()
if ci == -1 || (ci == 0 && a:direction == 'left') || (ci == len(b:task_columns)-1 && a:direction == 'right')
return
endif
if a:direction == 'left'
call search('\%'.(b:task_columns[ci-1]+1).'v', 'be')
else
call search('\%'.(b:task_columns[ci+1]+1).'v', 'e')
endif
if a:mode == 'skip' && taskwarrior#data#get_value_by_index('.', taskwarrior#data#current_index()) =~ '^\s*$'
call taskwarrior#action#move_cursor(a:direction, 'skip')
endif
endfunction
function! taskwarrior#action#undo()
if has("gui_running")
if exists('g:task_gui_term') && g:task_gui_term == 1
!task rc.color=off undo
elseif executable('xterm')
silent !xterm -e 'task undo'
elseif executable('urxvt')
silent !urxvt -e task undo
elseif executable('gnome-terminal')
silent !gnome-terminal -e 'task undo'
endif
else
sil !clear
!task undo
endif
call taskwarrior#refresh()
endfunction
function! taskwarrior#action#clear_completed()
!task status:completed delete
call taskwarrior#refresh()
endfunction
function! taskwarrior#action#sync(action)
execute '!task '.a:action.' '
call taskwarrior#refresh()
endfunction
function! taskwarrior#action#select()
let uuid = taskwarrior#data#get_uuid()
if uuid == ''
return
endif
let index = index(b:selected, uuid)
if index == -1
let b:selected += [uuid]
let b:sline += [line('.')]
else
call remove(b:selected, index)
call remove(b:sline, index)
endif
let b:sstring = join(b:selected, ' ')
setlocal syntax=taskreport
endfunction
function! taskwarrior#action#show_info(...)
if a:0 > 0
let command = 'info'
let filter = a:1
else
let ccol = taskwarrior#data#current_column()
let dict = { 'project': 'projects',
\ 'tags': 'tags',
\ 'id': 'stats',
\ 'depends': 'blocking',
\ 'recur': 'recurring',
\ 'due': 'overdue',
\ 'wait': 'waiting',
\ 'urgency': 'ready',
\ 'entry': 'history.monthly',
\ 'end': 'history.monthly'}
let command = get(dict, ccol, 'summary')
let uuid = taskwarrior#data#get_uuid()
if uuid !~ '^\s*$'
let command = substitute(command, '\v(summary|stats)', 'information', '')
let filter = taskwarrior#data#get_uuid()
else
let filter = b:filter
endif
endif
call taskinfo#init(command, filter, split(system('task rc.color=no '.command.' '.filter), '\n'))
endfunction

View File

@@ -0,0 +1,54 @@
function! taskwarrior#complete#TW(A, L, P)
let command = copy(g:task_all_commands)
let filter = copy(g:task_filter)
let config = copy(g:task_all_configurations)
let contexts = split(system('task _context'), '\n')
let context_cmd = ['define', 'show', 'list', 'delete']
let words = split(a:L, ' ')
if len(words) > 1 && words[1] == 'context'
if len(words) == 2 || index(context_cmd, words[2]) == -1
return filter(context_cmd + contexts + ['none'],
\ 'match(v:val, a:A) != -1')
elseif words[2] == 'delete'
return filter(contexts, 'match(v:val, a:A) != -1')
else
return []
endif
endif
for ph in words
if ph == 'config' || ph == 'show'
return filter(config, 'match(v:val, a:A) != -1')
elseif ph =~ '^rc\..*'
return map(filter(config, 'match(v:val, a:A[3:]) != -1'),
\ "'rc.'.v:val")
elseif index(command, ph) != -1
return filter(filter, 'match(v:val, a:A) != -1')
endif
endfor
return filter(command+filter, 'match(v:val, a:A) != -1')
endfunction
function! taskwarrior#complete#sort(A, L, P)
let cols = map(split(system('task _columns'), '\n'),
\ 'matchstr(v:val, "^\\w*")')
return filter(cols, 'match(v:val, a:A) != -1')
endfunction
function! taskwarrior#complete#filter(A, L, P)
let lead = matchstr(a:A, '\S*$')
let lead = lead == '' ? '.*' : lead
let dict = copy(g:task_filter)
for ph in split(a:L, ' ')
call remove(dict, index(dict, matchstr(ph, '.*:\ze')))
endfor
return map(filter(dict, 'match(v:val, lead) != -1'),
\ "matchstr(a:L, '.*\\ze\\s\\+\\S*').' '.v:val")
endfunction
function! taskwarrior#complete#command(A, L, P)
return filter(copy(g:task_all_commands), 'match(v:val, a:A) != -1')
endfunction
function! taskwarrior#complete#report(A, L, P)
return filter(copy(g:task_report_command), 'match(v:val, a:A) != -1')
endfunction

View File

@@ -0,0 +1,132 @@
function! taskwarrior#data#get_uuid(...)
let line = a:0 == 0 ? '.' : a:1
let vol = taskwarrior#data#get_value_by_column(line, 'uuid')
let vol = vol =~ '[0-9a-f]\{8}\(-[0-9a-f]\{4}\)\{3}-[0-9a-f]\{12}' ?
\ vol : taskwarrior#data#get_value_by_column(line, 'id')
return vol =~ '^\s*-*\s*$' ? '' : vol
endfunction
function! taskwarrior#data#get_args(...)
if a:0 == 0
return
elseif a:0 == 1
return taskwarrior#data#get_args(a:1, g:task_default_prompt)
endif
let arg = ' '
for key in a:2
let default = a:1 == 'modify' ?
\ taskwarrior#data#get_value_by_column('.', key)
\ : ''
let temp = shellescape(input(key.":", default), 1)
if key == 'description'
let arg .= ' '.temp
elseif temp !~ '^[ \t]*$' || a:1 == 'modify'
let arg .= ' '.key.':'.temp
endif
endfor
echom arg
return arg
endfunction
function! taskwarrior#data#get_value_by_column(line, column, ...)
if a:line == 1 || (a:line == '.' && line('.') == 1)
return ''
endif
if a:column == 'id' || a:column == 'uuid' || exists('a:1')
let index = match(b:task_report_columns, '^'.a:column.'.*')
return taskwarrior#data#get_value_by_index(a:line, index(b:task_report_columns, a:column))
else
let dict = taskwarrior#data#get_query()
let val = get(dict, a:column, '')
if type(val) == type('')
return val
elseif type(val) == type([])
return join(val, ' ')
else
return string(val)
endif
endif
endfunction
function! taskwarrior#data#get_value_by_index(line, index)
if exists('b:task_columns[a:index]')
return substitute(getline(a:line)[b:task_columns[a:index]:b:task_columns[a:index+1]-1], '\(\s*$\|^\s*\)', '', 'g')
endif
return ''
endfunction
function! taskwarrior#data#current_index()
let i = 0
while i < len(b:task_columns) && virtcol('.') >= b:task_columns[i]
let i += 1
endwhile
return i-1
endfunction
function! taskwarrior#data#current_column()
return matchstr(b:task_report_columns[taskwarrior#data#current_index()], '^\w\+')
endfunction
function! taskwarrior#data#get_stats(method)
let dict = {}
if a:method != 'current'
let stat = split(system('task '.a:method.' stats'), '\n')
else
let uuid = taskwarrior#data#get_uuid()
let stat = split(system('task '.taskwarrior#data#get_uuid().' stats'), '\n')
if uuid == '' || len(stat) < 5
return {}
endif
endif
for line in stat[2:-1]
if line !~ '^\W*$'
let dict[split(line, '\s\s')[0]] = substitute(split(line, '\s\s')[-1], '^\s*', '', '')
endif
endfor
return dict
endfunction
function! taskwarrior#data#get_query(...)
let uuid = get(a:, 1, taskwarrior#data#get_uuid())
if uuid == ''
return {}
endif
let obj = webapi#json#decode(substitute(system(
\ 'task rc.verbose=off '.uuid.' export'),
\ '\nConfiguration.*', '', ''))
return type(obj) == 3 ? obj[0] : obj
endfunction
function! taskwarrior#data#global_stats()
let dict = taskwarrior#data#get_stats(b:filter)
return [
\ get(dict, 'Pending', 0),
\ get(dict, 'Completed', 0),
\ get(taskwarrior#data#get_stats(''), 'Pending', 0)
\ ]
endfunction
function! taskwarrior#data#category()
let dict = {}
let dict.Pending = []
let dict.Waiting = []
let dict.Recurring = []
let dict.Completed = []
for i in range(2, line('$'))
let uuid = taskwarrior#data#get_uuid(i)
if uuid == ''
continue
endif
let subdict = taskwarrior#data#get_stats(uuid)
if subdict.Pending == '1'
let dict.Pending += [i]
elseif subdict.Waiting == '1'
let dict.Waiting += [i]
elseif subdict.Recurring == '1'
let dict.Recurring += [i]
elseif subdict.Completed == '1'
let dict.Completed += [i]
endif
endfor
return dict
endfunction

View File

@@ -0,0 +1,68 @@
if !isdirectory(expand(g:task_log_directory))
call mkdir(expand(g:task_log_directory), 'p')
endif
let s:history_file = expand(g:task_log_directory.'/.vim_tw.history')
let s:bookmark_file = expand(g:task_log_directory.'/.vim_tw.bookmark')
function! taskwarrior#log#history(action)
if findfile(s:history_file) == ''
call writefile([], s:history_file)
endif
if a:action == 'write' && filewritable(s:history_file) && b:hist == 1
let fl = readfile(s:history_file)
let numb = len(fl)
let last = numb ? substitute(fl[-1], '\v($|\n|\t|\s)', '', 'g') : ''
let current = join([b:command, b:filter, b:rc], ' ')
if last == substitute(current, '[\t ]', '', 'g')
return
endif
call add(fl, current)
if numb >= g:task_log_max
call remove(fl, 0)
endif
call writefile(fl, s:history_file)
elseif a:action == 'read' && filereadable(s:history_file)
call taskwarrior#init(join(split(readfile(s:history_file)[-1], ' '), ' '))
elseif a:action == 'clear'
call writefile([], s:history_file)
elseif a:action != 'write'
let hists = readfile(s:history_file)
if a:action == 'previous'
if b:hist >= len(hists)
return
endif
let b:hist += 1
elseif a:action == 'next'
if b:hist == 1
return
endif
let b:hist -= 1
endif
let hlist = split(substitute(hists[-b:hist], '\v($|\n)', ' ', ''), ' ')
if len(hlist) != 3
return
endif
let [b:command, b:filter, b:rc] = hlist
call taskwarrior#list()
endif
endfunction
function! taskwarrior#log#bookmark(action)
if findfile(s:bookmark_file) == ''
call writefile([], s:bookmark_file)
endif
if a:action == 'new' && filewritable(s:bookmark_file)
let now = b:command.' '.b:filter.' '.b:rc
let ext = readfile(s:bookmark_file)
if index(ext, now) == -1
execute 'redir >> '.s:bookmark_file
silent! echo now
redir END
echohl String
echomsg 'New bookmark added.'
echohl None
endif
elseif a:action == 'clear'
call writefile([], s:bookmark_file)
endif
endfunction

View File

@@ -0,0 +1,88 @@
function! taskwarrior#sort#by_arg(...)
let args = substitute(join(a:000, ' '), '\s\+', ',', 'g')
let args = substitute(args, '\w\zs,', '-,', 'g')
let args = substitute(args, '\w\zs$', '-', '')
if args =~ '^\s*$'
let b:rc = substitute(b:rc, 'rc.report.'.b:command.'.sort[:=]\S*', '', 'g')
else
let b:rc .= args == '' ? '' : ' rc.report.'.b:command.'.sort:'.args
endif
let b:hist = 1
call taskwarrior#list()
endfunction
function! taskwarrior#sort#by_column(polarity, column)
let fromrc = matchstr(b:rc, 'rc\.report\.'.b:command.'\.sort.\zs\S*')
" let default = system('task _get -- rc.report.'.b:command.'.sort')[0:-2]
let default = matchstr(system('task show | grep report.'.b:command.'.sort')[0:-2], '\S*$')
let colshort = map(copy(b:task_report_columns), 'matchstr(v:val, "^\\w*")')
let ccol = index(colshort, a:column) == -1 ?
\ taskwarrior#data#current_column() :
\ a:column
let list = split(fromrc, ',')
let ind = index(split(fromrc, '[-+],\='), ccol)
let dlist = split(default, ',')
let dind = index(split(default, '[-+],\='), ccol)
if fromrc == ''
if dind != -1
if a:polarity == 'm'
if dind == 0
let dlist[0] = dlist[0][0:-2].(dlist[0][-1:-1] == '+' ? '-' : '+')
endif
call insert(dlist, remove(dlist, dind))
elseif dlist[dind] == ccol.a:polarity
return
else
let dlist[dind] = ccol.a:polarity
endif
let b:rc .= ' rc.report.'.b:command.'.sort:'.join(dlist, ',')
else
let polarity = a:polarity == 'm' ? '-' : a:polarity
let b:rc .= ' rc.report.'.b:command.'.sort:'.ccol.polarity.','.default
endif
elseif ind != -1
if a:polarity == 'm'
if ind == 0
let list[0] = list[0][0:-2].(list[0][-1:-1] == '+' ? '-' : '+')
else
call insert(list, remove(list, ind))
endif
elseif list[ind] == ccol.a:polarity
if a:polarity == '+'
call insert(list, remove(list, ind), ind > 1 ? ind-1 : 0)
else
if ind > len(list)-3
call add(list, remove(list, ind))
else
call insert(list, remove(list, ind), ind+1)
endif
endif
else
let list[ind] = ccol.a:polarity
endif
let g:listabc = list
let b:rc = substitute(b:rc, 'report\.'.b:command.'\.sort.'.fromrc, 'report.'.b:command.'.sort:'.join(list, ','), '')
else
let polarity = a:polarity == 'm' ? '-' : a:polarity
let b:rc = substitute(b:rc, 'report\.'.b:command.'\.sort.', 'report.'.b:command.'.sort:'.ccol.polarity.',', '')
endif
let b:hist = 1
call taskwarrior#list()
endfunction
function! taskwarrior#sort#order_list()
let fromrc = matchstr(b:rc, 'rc\.report\.'.b:command.'\.sort.\zs\S*')
if fromrc == ''
" let list = split(system('task _get -- rc.report.'.b:command.'.sort')[0:-2], ',')
let list = split(matchstr(system('task show | grep report.'.b:command.'.sort')[0:-2], '\S*$'), ',')
else
let list = split(fromrc, ',')
endif
while exists('list[0]') && match(b:task_report_columns, list[0][0:-2]) == -1 && system('task count '.list[0][0:-2].'.any:')[0] == '0'
call remove(list, 0)
endwhile
if len(list) == 0
let list = ['status-']
endif
return list
endfunction

View File

@@ -0,0 +1,23 @@
let s:save_cpo = &cpo
set cpo&vim
function! unite#kinds#task#define()
return s:kind
endfunction
let s:kind = {
\ 'name' : 'task',
\ 'default_action' : 'show',
\ 'action_table': {},
\}
let s:kind.action_table.show = {
\ 'description' : 'Show report',
\ }
function! s:kind.action_table.show.func(candidate)
call taskwarrior#init(join(split(a:candidate.word, '[ \t]'), ' '))
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@@ -0,0 +1,68 @@
let s:save_cpo = &cpo
set cpo&vim
let s:template = {
\ 'name' : 'task/',
\ 'description' : 'vim-taskwarrior ',
\ 'filters' : ['matcher_regexp'],
\ 'action_table': {},
\ 'hooks' : {},
\ }
let s:bookmark = {
\ 'name' : 'bookmark',
\ 'logfile' : expand(g:task_log_directory.'/.vim_tw.bookmark')
\ }
let s:history = {
\ 'name' : 'history',
\ 'logfile' : expand(g:task_log_directory.'/.vim_tw.history')
\ }
function! s:make_source(dict)
let source = deepcopy(s:template)
let source.name .= a:dict.name
let source.description .= a:dict.name
let source.logfile = a:dict.logfile
function! source.hooks.on_syntax(args, context)
syntax match uniteSource__task_rc /rc.*/ contained containedin=ALL contains=uniteCandidateInputKeyword
syntax match uniteSource__task_report /\w\+\ze[ \t]\+/ contained containedin=ALL
highlight default link uniteSource__task_rc String
highlight default link uniteSource__task_report Keyword
endfunction
function! source.gather_candidates(args, context)
if findfile(self.logfile) == ''
call writefile([], self.logfile)
endif
return map(reverse(readfile(self.logfile)),
\ '{"word": v:val,
\ "kind": "task",
\ "source": "task/" . self.name,
\ }')
endfunction
let source.action_table.delete = {
\ 'description' : 'remove the item',
\ }
function! source.action_table.delete.func(candidate)
let current = substitute(a:candidate.word, '\s', '', 'g')
let lfile = g:task_log_directory.'/.vim_tw.bookmark'
let all = readfile(lfile)
let allns = map(copy(all), "substitute(v:val, '[ \t]', '', 'g')")
call remove(all, index(allns, current))
call writefile(all, lfile)
endfunction
return source
endfunction
function! unite#sources#task#define()
return map([s:bookmark, s:history], 's:make_source(v:val)')
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo

View File

@@ -0,0 +1,135 @@
" json
" Last Change: 2012-03-08
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
" License: This file is placed in the public domain.
" Reference:
"
let s:save_cpo = &cpo
set cpo&vim
function! webapi#json#null()
return 0
endfunction
function! webapi#json#true()
return 1
endfunction
function! webapi#json#false()
return 0
endfunction
function! s:nr2byte(nr)
if a:nr < 0x80
return nr2char(a:nr)
elseif a:nr < 0x800
return nr2char(a:nr/64+192).nr2char(a:nr%64+128)
else
return nr2char(a:nr/4096%16+224).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
endif
endfunction
function! s:nr2enc_char(charcode)
if &encoding == 'utf-8'
return nr2char(a:charcode)
endif
let char = s:nr2byte(a:charcode)
if strlen(char) > 1
let char = strtrans(iconv(char, 'utf-8', &encoding))
endif
return char
endfunction
function! s:fixup(val, tmp)
if type(a:val) == 0
return a:val
elseif type(a:val) == 1
if a:val == a:tmp.'null'
return function('webapi#json#null')
elseif a:val == a:tmp.'true'
return function('webapi#json#true')
elseif a:val == a:tmp.'false'
return function('webapi#json#false')
endif
return a:val
elseif type(a:val) == 2
return a:val
elseif type(a:val) == 3
return map(a:val, 's:fixup(v:val, a:tmp)')
elseif type(a:val) == 4
return map(a:val, 's:fixup(v:val, a:tmp)')
else
return string(a:val)
endif
endfunction
function! webapi#json#decode(json)
let json = iconv(a:json, "utf-8", &encoding)
if get(g:, 'webapi#json#parse_strict', 1) == 1 && substitute(substitute(substitute(
\ json,
\ '\\\%(["\\/bfnrt]\|u[0-9a-fA-F]\{4}\)', '\@', 'g'),
\ '"[^\"\\\n\r]*\"\|true\|false\|null\|-\?\d\+'
\ . '\%(\.\d*\)\?\%([eE][+\-]\{-}\d\+\)\?', ']', 'g'),
\ '\%(^\|:\|,\)\%(\s*\[\)\+', '', 'g') !~ '^[\],:{} \t\n]*$'
throw json
endif
let json = substitute(json, '\n', '', 'g')
let json = substitute(json, '\\u34;', '\\"', 'g')
if v:version >= 703 && has('patch780')
let json = substitute(json, '\\u\(\x\x\x\x\)', '\=iconv(nr2char(str2nr(submatch(1), 16), 1), "utf-8", &encoding)', 'g')
else
let json = substitute(json, '\\u\(\x\x\x\x\)', '\=s:nr2enc_char("0x".submatch(1))', 'g')
endif
if get(g:, 'webapi#json#allow_nil', 0) != 0
let tmp = '__WEBAPI_JSON__'
while 1
if stridx(json, tmp) == -1
break
endif
let tmp .= '_'
endwhile
let [null,true,false] = [
\ tmp.'null',
\ tmp.'true',
\ tmp.'false']
sandbox let ret = eval(json)
call s:fixup(ret, tmp)
else
let [null,true,false] = [0,1,0]
sandbox let ret = eval(json)
endif
return ret
endfunction
function! webapi#json#encode(val)
if type(a:val) == 0
return a:val
elseif type(a:val) == 1
let json = '"' . escape(a:val, '\"') . '"'
let json = substitute(json, "\r", '\\r', 'g')
let json = substitute(json, "\n", '\\n', 'g')
let json = substitute(json, "\t", '\\t', 'g')
let json = substitute(json, '\([[:cntrl:]]\)', '\=printf("\x%02d", char2nr(submatch(1)))', 'g')
return iconv(json, &encoding, "utf-8")
elseif type(a:val) == 2
let s = string(a:val)
if s == "function('webapi#json#null')"
return 'null'
elseif s == "function('webapi#json#true')"
return 'true'
elseif s == "function('webapi#json#false')"
return 'false'
endif
elseif type(a:val) == 3
return '[' . join(map(copy(a:val), 'webapi#json#encode(v:val)'), ',') . ']'
elseif type(a:val) == 4
return '{' . join(map(keys(a:val), 'webapi#json#encode(v:val).":".webapi#json#encode(a:val[v:val])'), ',') . '}'
else
return string(a:val)
endif
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim:set et: