376 lines
11 KiB
VimL
376 lines
11 KiB
VimL
|
"------------------------------------------------------------------------------
|
||
|
" Name Of File: tasklist.vim
|
||
|
"
|
||
|
" Description: Vim plugin to search for a list of tokens and display a
|
||
|
" window with matches.
|
||
|
"
|
||
|
" Author: Juan Frias (juandfrias at gmail.com)
|
||
|
"
|
||
|
" Last Change: 2009 Apr 11
|
||
|
" Version: 1.0.1
|
||
|
"
|
||
|
" Copyright: Permission is hereby granted to use and distribute this code,
|
||
|
" with or without modifications, provided that this header
|
||
|
" is included with it.
|
||
|
"
|
||
|
" This script is to be distributed freely in the hope that it
|
||
|
" will be useful, but is provided 'as is' and without warranties
|
||
|
" as to performance of merchantability or any other warranties
|
||
|
" whether expressed or implied. Because of the various hardware
|
||
|
" and software environments into which this script may be put,
|
||
|
" no warranty of fitness for a particular purpose is offered.
|
||
|
"
|
||
|
" GOOD DATA PROCESSING PROCEDURE DICTATES THAT ANY SCRIPT BE
|
||
|
" THOROUGHLY TESTED WITH NON-CRITICAL DATA BEFORE RELYING ON IT.
|
||
|
"
|
||
|
" THE USER MUST ASSUME THE ENTIRE RISK OF USING THE SCRIPT.
|
||
|
"
|
||
|
" The author does not retain any liability on any damage caused
|
||
|
" through the use of this script.
|
||
|
"
|
||
|
" Install: 1. Read the section titled 'Options'
|
||
|
" 2. Setup any variables need in your vimrc file
|
||
|
" 3. Copy 'tasklist.vim' to your plugin directory.
|
||
|
"
|
||
|
" Mapped Keys: <Leader>t Display list.
|
||
|
"
|
||
|
" Usage: Start the script with the mapped key, a new window appears
|
||
|
" with the matches found, moving around the window will also
|
||
|
" update the position of the current document.
|
||
|
"
|
||
|
" The following keys are mapped to the results window:
|
||
|
"
|
||
|
" q - Quit, and restore original cursor position.
|
||
|
"
|
||
|
" e - Exit, and keep results window open note that
|
||
|
" movements on the result window will no longer be
|
||
|
" updated.
|
||
|
"
|
||
|
" <cr> - Quit and place the cursor on the selected line.
|
||
|
"
|
||
|
" Aknowledgments: Many thanks to Zhang Shuhan for taking the time to beta
|
||
|
" test and suggest many of the improvements and features
|
||
|
" found in the script. I don't think I would have
|
||
|
" implemented it wihout his help. Thanks!
|
||
|
"
|
||
|
"------------------------------------------------------------------------------
|
||
|
" Please send me any bugs you find, so I can keep the script up to date.
|
||
|
"------------------------------------------------------------------------------
|
||
|
|
||
|
" History: {{{1
|
||
|
"------------------------------------------------------------------------------
|
||
|
"
|
||
|
" 1.00 Initial version.
|
||
|
"
|
||
|
" User Options: {{{1
|
||
|
"------------------------------------------------------------------------------
|
||
|
"
|
||
|
" <Leader>t
|
||
|
" This is the default key map to view the task list.
|
||
|
" to overwrite use something like:
|
||
|
" map <leader>v <Plug>TaskList
|
||
|
" in your vimrc file
|
||
|
"
|
||
|
" g:tlWindowPosition
|
||
|
" This is specifies the position of the window to be opened. By
|
||
|
" default it will open at on top. To overwrite use:
|
||
|
" let g:tlWindowPosition = 1
|
||
|
" in your vimrc file, options are as follows:
|
||
|
" 0 = Open on top
|
||
|
" 1 = Open on the bottom
|
||
|
"
|
||
|
" g:tlTokenList
|
||
|
" This is the list of tokens to search for default is
|
||
|
" 'FIXME TODO XXX'. The results are groupped and displayed in the
|
||
|
" order that they appear. to overwrite use:
|
||
|
" let g:tlTokenList = ['TOKEN1', 'TOKEN2', 'TOKEN3']
|
||
|
" in your vimrc file
|
||
|
"
|
||
|
" g:tlRememberPosition
|
||
|
" If this is set to 1 then the script will try to get back to the
|
||
|
" position where it last was closed. By default it will find the line
|
||
|
" closest to the current cursor position.
|
||
|
" to overwrite use:
|
||
|
" let g:tlRememberPosition = 1
|
||
|
" in your vimrc file
|
||
|
"
|
||
|
|
||
|
" Global variables: {{{1
|
||
|
"------------------------------------------------------------------------------
|
||
|
|
||
|
" Load script once
|
||
|
"------------------------------------------------------------------------------
|
||
|
if exists("g:loaded_tasklist") || &cp
|
||
|
finish
|
||
|
endif
|
||
|
let g:loaded_tasklist = 1
|
||
|
|
||
|
" Set where the window opens
|
||
|
"------------------------------------------------------------------------------
|
||
|
if !exists('g:tlWindowPosition')
|
||
|
" 0 = Open at top
|
||
|
let g:tlWindowPosition = 0
|
||
|
endif
|
||
|
|
||
|
" Set the token list
|
||
|
"------------------------------------------------------------------------------
|
||
|
if !exists('g:tlTokenList')
|
||
|
" default list of tokens
|
||
|
let g:tlTokenList = ["FIXME", "TODO", "XXX"]
|
||
|
endif
|
||
|
|
||
|
" Remember position
|
||
|
"------------------------------------------------------------------------------
|
||
|
if !exists('g:tlRememberPosition')
|
||
|
" 0 = Donot remember, find closest match
|
||
|
let g:tlRememberPosition = 0
|
||
|
endif
|
||
|
|
||
|
" Script variables: {{{1
|
||
|
"------------------------------------------------------------------------------
|
||
|
|
||
|
" Function: Open Window {{{1
|
||
|
"--------------------------------------------------------------------------
|
||
|
function! s:OpenWindow(buffnr, lineno)
|
||
|
" Open results window and place items there.
|
||
|
if g:tlWindowPosition == 0
|
||
|
execute 'sp -TaskList_'.a:buffnr.'-'
|
||
|
else
|
||
|
execute 'botright sp -TaskList_'.a:buffnr.'-'
|
||
|
endif
|
||
|
|
||
|
let b:original_buffnr = a:buffnr
|
||
|
let b:original_line = a:lineno
|
||
|
|
||
|
set noswapfile
|
||
|
set modifiable
|
||
|
normal! "zPGddgg
|
||
|
set fde=getline(v:lnum)[0]=='L'
|
||
|
set foldmethod=expr
|
||
|
set foldlevel=0
|
||
|
normal! zR
|
||
|
|
||
|
" Resize line if too big.
|
||
|
let l:hits = line("$")
|
||
|
if l:hits < winheight(0)
|
||
|
sil! exe "resize ".l:hits
|
||
|
endif
|
||
|
|
||
|
" Clean up.
|
||
|
let @z = ""
|
||
|
set nomodified
|
||
|
endfunction
|
||
|
|
||
|
" Function: Search file {{{1
|
||
|
"--------------------------------------------------------------------------
|
||
|
function! s:SearchFile(hits, word)
|
||
|
" Search at the beginning and keep adding them to the register
|
||
|
let l:match_count = 0
|
||
|
normal! gg0
|
||
|
let l:max = strlen(line('$'))
|
||
|
let l:last_match = -1
|
||
|
let l:div = 0
|
||
|
while search(a:word, "Wc") > 0
|
||
|
let l:curr_line = line('.')
|
||
|
if l:last_match == l:curr_line
|
||
|
if l:curr_line == line('$')
|
||
|
break
|
||
|
endif
|
||
|
normal! j0
|
||
|
continue
|
||
|
endif
|
||
|
let l:last_match = l:curr_line
|
||
|
if foldlevel(l:curr_line) != 0
|
||
|
normal! 99zo
|
||
|
endif
|
||
|
if l:div == 0
|
||
|
if a:hits != 0
|
||
|
let @z = @z."\n"
|
||
|
endif
|
||
|
let l:div = 1
|
||
|
endif
|
||
|
normal! 0
|
||
|
let l:lineno = ' '.l:curr_line
|
||
|
let @z = @z.'Ln '.strpart(l:lineno, strlen(l:lineno) - l:max).': '
|
||
|
let l:text = getline(".")
|
||
|
let @z = @z.strpart(l:text, stridx(l:text, a:word))
|
||
|
let @z = @z."\n"
|
||
|
normal! $
|
||
|
let l:match_count = l:match_count + 1
|
||
|
endwhile
|
||
|
return l:match_count
|
||
|
endfunction
|
||
|
|
||
|
" Function: Get line number {{{1
|
||
|
"--------------------------------------------------------------------------
|
||
|
function! s:LineNumber()
|
||
|
let l:text = getline(".")
|
||
|
if strpart(l:text, 0, 5) == "File:"
|
||
|
return 0
|
||
|
endif
|
||
|
if strlen(l:text) == 0
|
||
|
return -1
|
||
|
endif
|
||
|
let l:num = matchstr(l:text, '[0-9]\+')
|
||
|
if l:num == ''
|
||
|
return -1
|
||
|
endif
|
||
|
return l:num
|
||
|
endfunction
|
||
|
|
||
|
" Function: Update document position {{{1
|
||
|
"--------------------------------------------------------------------------
|
||
|
function! s:UpdateDoc()
|
||
|
let l:line_hit = <sid>LineNumber()
|
||
|
|
||
|
match none
|
||
|
if l:line_hit == -1
|
||
|
redraw
|
||
|
return
|
||
|
endif
|
||
|
|
||
|
let l:buffnr = b:original_buffnr
|
||
|
exe 'match Search /\%'.line(".").'l.*/'
|
||
|
if line(".") < (line("$") - (winheight(0) / 2)) + 1
|
||
|
normal! zz
|
||
|
endif
|
||
|
execute bufwinnr(l:buffnr)." wincmd w"
|
||
|
match none
|
||
|
if l:line_hit == 0
|
||
|
normal! 1G
|
||
|
else
|
||
|
exe "normal! ".l:line_hit."Gzz"
|
||
|
exe 'match Search /\%'.line(".").'l.*/'
|
||
|
endif
|
||
|
execute bufwinnr('-TaskList_'.l:buffnr.'-')." wincmd w"
|
||
|
redraw
|
||
|
endfunction
|
||
|
|
||
|
" Function: Clean up on exit {{{1
|
||
|
"--------------------------------------------------------------------------
|
||
|
function! s:Exit(key)
|
||
|
|
||
|
call <sid>UpdateDoc()
|
||
|
match none
|
||
|
|
||
|
let l:original_line = b:original_line
|
||
|
let l:last_position = line('.')
|
||
|
|
||
|
if a:key == -1
|
||
|
nunmap <buffer> e
|
||
|
nunmap <buffer> q
|
||
|
nunmap <buffer> <cr>
|
||
|
execute bufwinnr(b:original_buffnr)." wincmd w"
|
||
|
else
|
||
|
bd!
|
||
|
endif
|
||
|
|
||
|
let b:last_position = l:last_position
|
||
|
|
||
|
if a:key == 0
|
||
|
exe "normal! ".l:original_line."G"
|
||
|
endif
|
||
|
|
||
|
match none
|
||
|
normal! zz
|
||
|
|
||
|
execute "set updatetime=".s:old_updatetime
|
||
|
endfunction
|
||
|
|
||
|
" Function: Check for screen update {{{1
|
||
|
"--------------------------------------------------------------------------
|
||
|
function! s:CheckForUpdate()
|
||
|
if stridx(expand("%:t"), '-TaskList_') == -1
|
||
|
return
|
||
|
endif
|
||
|
if b:selected_line != line(".")
|
||
|
call <sid>UpdateDoc()
|
||
|
let b:selected_line = line(".")
|
||
|
endif
|
||
|
endfunction
|
||
|
|
||
|
" Function: Start the search. {{{1
|
||
|
"--------------------------------------------------------------------------
|
||
|
function! s:TaskList()
|
||
|
let l:original_buffnr = bufnr('%')
|
||
|
let l:original_line = line(".")
|
||
|
|
||
|
" last position
|
||
|
if !exists('b:last_position')
|
||
|
let b:last_position = 1
|
||
|
endif
|
||
|
let l:last_position = b:last_position
|
||
|
|
||
|
|
||
|
" get file name
|
||
|
let @z = "File:".expand("%:p")."\n\n"
|
||
|
|
||
|
" search file
|
||
|
let l:index = 0
|
||
|
let l:count = 0
|
||
|
let l:hits = 0
|
||
|
while l:index < len(g:tlTokenList)
|
||
|
let l:search_word = g:tlTokenList[l:index]
|
||
|
let l:hits = s:SearchFile(l:hits, l:search_word)
|
||
|
let l:count = l:count + l:hits
|
||
|
let l:index = l:index + 1
|
||
|
endwhile
|
||
|
|
||
|
" Make sure we at least have one hit.
|
||
|
if l:count == 0
|
||
|
echohl Search
|
||
|
echo "tasklist.vim: No task information found."
|
||
|
echohl None
|
||
|
execute 'normal! '.l:original_line.'G'
|
||
|
return
|
||
|
endif
|
||
|
|
||
|
" display window
|
||
|
call s:OpenWindow(l:original_buffnr, l:original_line)
|
||
|
|
||
|
" restore the cursor position
|
||
|
if g:tlRememberPosition != 0
|
||
|
exec 'normal! '.l:last_position.'G'
|
||
|
else
|
||
|
normal! gg
|
||
|
endif
|
||
|
|
||
|
" Map exit keys
|
||
|
nnoremap <buffer> <silent> q :call <sid>Exit(0)<cr>
|
||
|
nnoremap <buffer> <silent> <cr> :call <sid>Exit(1)<cr>
|
||
|
nnoremap <buffer> <silent> e :call <sid>Exit(-1)<cr>
|
||
|
|
||
|
" Setup syntax highlight {{{
|
||
|
syntax match tasklistFileDivider /^File:.*$/
|
||
|
syntax match tasklistLineNumber /^Ln\s\+\d\+:/
|
||
|
|
||
|
highlight def link tasklistFileDivider Title
|
||
|
highlight def link tasklistLineNumber LineNr
|
||
|
highlight def link tasklistSearchWord Search
|
||
|
" }}}
|
||
|
|
||
|
" Save globals and change updatetime
|
||
|
let b:selected_line = line(".")
|
||
|
let s:old_updatetime = &updatetime
|
||
|
set updatetime=350
|
||
|
|
||
|
" update the doc and hook the CheckForUpdate function.
|
||
|
call <sid>UpdateDoc()
|
||
|
au! CursorHold <buffer> nested call <sid>CheckForUpdate()
|
||
|
|
||
|
endfunction
|
||
|
"}}}
|
||
|
|
||
|
" Command
|
||
|
command! TaskList call s:TaskList()
|
||
|
|
||
|
" Default key map
|
||
|
if !hasmapto('<Plug>TaskList')
|
||
|
map <unique> <Leader>t <Plug>TaskList
|
||
|
endif
|
||
|
|
||
|
" Key map to Command
|
||
|
nnoremap <unique> <script> <Plug>TaskList :TaskList<CR>
|
||
|
|
||
|
" vim:fdm=marker:tw=75:ff=unix:
|