mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-03-23 09:39:58 +08:00
208 lines
6.0 KiB
VimL
208 lines
6.0 KiB
VimL
"=============================================================================
|
|
" todo.vim --- todo manager for SpaceVim
|
|
" Copyright (c) 2016-2023 Wang Shidong & Contributors
|
|
" Author: Wang Shidong < wsdjeg@outlook.com >
|
|
" URL: https://spacevim.org
|
|
" License: GPLv3
|
|
"=============================================================================
|
|
|
|
""
|
|
" @section todo manager, plugins-todomanager
|
|
" @parentsection plugins
|
|
" The `todomanager` plugin provides todo manager support for SpaceVim.
|
|
"
|
|
" @subsection Key bindings
|
|
" >
|
|
" Key binding Description
|
|
" SPC a o open todo manager windows
|
|
" <
|
|
"
|
|
" @subsection Configuration
|
|
"
|
|
" The todo manager labels can be set via @section(options-todo_labels)
|
|
|
|
let s:JOB = SpaceVim#api#import('job')
|
|
let s:BUFFER = SpaceVim#api#import('vim#buffer')
|
|
let s:SYS = SpaceVim#api#import('system')
|
|
let s:LOG = SpaceVim#logger#derive('todo')
|
|
let s:REG = SpaceVim#api#import('vim#regex')
|
|
|
|
|
|
let [
|
|
\ s:grep_default_exe,
|
|
\ s:grep_default_opt,
|
|
\ s:grep_default_ropt,
|
|
\ s:grep_default_expr_opt,
|
|
\ s:grep_default_fix_string_opt,
|
|
\ s:grep_default_ignore_case,
|
|
\ s:grep_default_smart_case
|
|
\ ] = SpaceVim#mapping#search#default_tool()
|
|
|
|
function! SpaceVim#plugins#todo#list() abort
|
|
call s:open_win()
|
|
endfunction
|
|
|
|
let s:bufnr = -1
|
|
let s:todo_jobid = -1
|
|
|
|
function! s:open_win() abort
|
|
if s:bufnr != 0 && bufexists(s:bufnr)
|
|
exe 'bd ' . s:bufnr
|
|
endif
|
|
botright split __todo_manager__
|
|
" @todo add win_getid api
|
|
let s:winnr = winnr('#')
|
|
let lines = &lines * 30 / 100
|
|
exe 'resize ' . lines
|
|
setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline nospell nonu norelativenumber winfixheight nomodifiable
|
|
set filetype=SpaceVimTodoManager
|
|
let s:bufnr = bufnr('%')
|
|
call s:update_todo_content()
|
|
augroup spacevim_plugin_todo
|
|
autocmd! * <buffer>
|
|
autocmd WinEnter <buffer> call s:WinEnter()
|
|
augroup END
|
|
nnoremap <buffer><silent> <Enter> :call <SID>open_todo()<cr>
|
|
endfunction
|
|
|
|
function! s:WinEnter() abort
|
|
" @todo add win_getid api
|
|
let s:winnr = winnr('#')
|
|
endfunction
|
|
|
|
" @todo Improve todo manager
|
|
function! s:update_todo_content() abort
|
|
if exists('g:spacevim_todo_labels')
|
|
\ && type(g:spacevim_todo_labels) == type([])
|
|
\ && !empty(g:spacevim_todo_labels)
|
|
let s:labels = g:spacevim_todo_labels
|
|
let s:prefix = g:spacevim_todo_prefix
|
|
else
|
|
let s:labels = ['fixme', 'question', 'todo', 'idea']
|
|
let s:prefix = '@'
|
|
endif
|
|
|
|
let s:todos = []
|
|
let s:todo = {}
|
|
let s:labels_regex = s:get_labels_regex()
|
|
let s:labels_partten = s:get_labels_pattern()
|
|
let argv = [s:grep_default_exe] +
|
|
\ s:grep_default_opt +
|
|
\ s:grep_default_expr_opt
|
|
let argv += [s:labels_regex]
|
|
if s:SYS.isWindows && (s:grep_default_exe ==# 'rg' || s:grep_default_exe ==# 'ag' || s:grep_default_exe ==# 'pt' )
|
|
let argv += ['.']
|
|
elseif s:SYS.isWindows && s:grep_default_exe ==# 'findstr'
|
|
let argv += ['*.*']
|
|
elseif !s:SYS.isWindows && s:grep_default_exe ==# 'rg'
|
|
let argv += ['./']
|
|
endif
|
|
let argv += s:grep_default_ropt
|
|
call s:LOG.info('cmd: ' . string(argv))
|
|
call s:LOG.info(' labels_partten: ' . s:labels_partten)
|
|
let s:todo_jobid = s:JOB.start(argv, {
|
|
\ 'on_stdout' : function('s:stdout'),
|
|
\ 'on_stderr' : function('s:stderr'),
|
|
\ 'on_exit' : function('s:exit'),
|
|
\ })
|
|
call s:LOG.info('jobid: ' . string(s:todo_jobid))
|
|
endfunction
|
|
|
|
function! s:stdout(id, data, event) abort
|
|
if a:id !=# s:todo_jobid
|
|
return
|
|
endif
|
|
for data in a:data
|
|
call s:LOG.info('stdout: ' . data)
|
|
if !empty(data)
|
|
let file = fnameescape(split(data, ':\d\+:')[0])
|
|
let line = matchstr(data, ':\d\+:')[1:-2]
|
|
let column = matchstr(data, '\(:\d\+\)\@<=:\d\+:')[1:-2]
|
|
let label = matchstr(data, s:labels_partten)
|
|
let title = get(split(data, label), 1, '')
|
|
" @todo add time tag
|
|
call add(s:todos,
|
|
\ {
|
|
\ 'file' : file,
|
|
\ 'line' : line,
|
|
\ 'column' : column,
|
|
\ 'title' : title,
|
|
\ 'label' : label,
|
|
\ }
|
|
\ )
|
|
endif
|
|
endfor
|
|
endfunction
|
|
|
|
function! s:stderr(id, data, event) abort
|
|
if a:id !=# s:todo_jobid
|
|
return
|
|
endif
|
|
for date in a:data
|
|
call s:LOG.info('stderr: ' . string(a:data))
|
|
endfor
|
|
endfunction
|
|
|
|
function! s:exit(id, data, event ) abort
|
|
if a:id !=# s:todo_jobid
|
|
return
|
|
endif
|
|
call s:LOG.info('todomanager exit: ' . string(a:data))
|
|
let s:todos = sort(s:todos, function('s:compare_todo'))
|
|
let label_w = max(map(deepcopy(s:todos), 'strlen(v:val.label)'))
|
|
let file_w = max(map(deepcopy(s:todos), 'strlen(v:val.file)'))
|
|
let expr = "v:val.label . repeat(' ', label_w - strlen(v:val.label)) . ' ' ."
|
|
\ . "SpaceVim#api#import('file').unify_path(v:val.file, ':.') . repeat(' ', file_w - strlen(v:val.file)) . ' ' ."
|
|
\ . "v:val.title"
|
|
let lines = map(deepcopy(s:todos),expr)
|
|
call s:BUFFER.buf_set_lines(s:bufnr, 0 , -1, 0, lines)
|
|
endfunction
|
|
|
|
function! s:compare_todo(a, b) abort
|
|
let a = index(s:labels, a:a.label)
|
|
let b = index(s:labels, a:b.label)
|
|
return a == b ? 0 : a > b ? 1 : -1
|
|
endfunction
|
|
|
|
function! s:open_todo() abort
|
|
let todo = s:todos[line('.') - 1]
|
|
if g:spacevim_todo_close_list
|
|
try
|
|
close
|
|
catch
|
|
endtry
|
|
endif
|
|
exe s:winnr . 'wincmd w'
|
|
exe 'e ' . todo.file
|
|
call cursor(todo.line, todo.column)
|
|
noautocmd normal! :
|
|
endfunction
|
|
|
|
" @fixme expr for different tools
|
|
" when using rg, [join(s:labels, '|')]
|
|
" when using grep, [join(s:labels, '\|')]
|
|
function! s:get_labels_regex()
|
|
if s:grep_default_exe ==# 'rg'
|
|
let separator = '|'
|
|
elseif s:grep_default_exe ==# 'grep'
|
|
let separator = '\|'
|
|
elseif s:grep_default_exe ==# 'findstr'
|
|
let separator = ' '
|
|
else
|
|
let separator = '|'
|
|
endif
|
|
|
|
return join(map(copy(s:labels), "s:prefix . v:val . '\\b'"),
|
|
\ separator)
|
|
endfunc
|
|
|
|
function! s:get_labels_pattern()
|
|
return s:REG.parser(s:get_labels_regex(), 0)
|
|
endfunc
|
|
|
|
|
|
" @todo fuzzy find todo list
|
|
" after open todo manager buffer, we should be able to fuzzy find the item we
|
|
" need.
|
|
|