"=============================================================================
" FILE: buffer.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" License: MIT license {{{
" Permission is hereby granted, free of charge, to any person obtaining
" a copy of this software and associated documentation files (the
" "Software"), to deal in the Software without restriction, including
" without limitation the rights to use, copy, modify, merge, publish,
" distribute, sublicense, and/or sell copies of the Software, and to
" permit persons to whom the Software is furnished to do so, subject to
" the following conditions:
"
" The above copyright notice and this permission notice shall be included
" in all copies or substantial portions of the Software.
"
" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
" IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
" CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
" TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
" SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
" }}}
"=============================================================================
let s:save_cpo = &cpo
set cpo&vim
" Variables "{{{
call unite#util#set_default(
\ 'g:unite_source_buffer_time_format',
\ '(%Y/%m/%d %H:%M:%S) ')
"}}}
function! unite#sources#buffer#define() abort "{{{
return [s:source_buffer_all, s:source_buffer_tab]
endfunction"}}}
let s:source_buffer_all = {
\ 'name' : 'buffer',
\ 'description' : 'candidates from buffer list',
\ 'syntax' : 'uniteSource__Buffer',
\ 'hooks' : {},
\ 'default_kind' : 'buffer',
\}
function! s:source_buffer_all.hooks.on_init(args, context) abort "{{{
let a:context.source__is_bang =
\ (get(a:args, 0, '') ==# '!')
let a:context.source__is_question =
\ (get(a:args, 0, '') ==# '?')
let a:context.source__is_plus =
\ (get(a:args, 0, '') ==# '+')
let a:context.source__is_minus =
\ (get(a:args, 0, '') ==# '-')
let a:context.source__is_terminal =
\ (get(a:args, 0, '') ==# 't')
let a:context.source__buffer_list =
\ s:get_buffer_list(a:context.source__is_bang,
\ a:context.source__is_question,
\ a:context.source__is_plus,
\ a:context.source__is_minus,
\ a:context.source__is_terminal)
endfunction"}}}
function! s:source_buffer_all.hooks.on_syntax(args, context) abort "{{{
syntax match uniteSource__Buffer_Name /[^/ \[\]]\+\s/
\ contained containedin=uniteSource__Buffer
highlight default link uniteSource__Buffer_Name Function
syntax match uniteSource__Buffer_Prefix /\d\+\s\%(\S\+\)\?/
\ contained containedin=uniteSource__Buffer
highlight default link uniteSource__Buffer_Prefix Constant
syntax match uniteSource__Buffer_Info /\[.\{-}\] /
\ contained containedin=uniteSource__Buffer
highlight default link uniteSource__Buffer_Info PreProc
syntax match uniteSource__Buffer_Modified /\[.\{-}+\]/
\ contained containedin=uniteSource__Buffer
highlight default link uniteSource__Buffer_Modified Statement
syntax match uniteSource__Buffer_NoFile /\[nofile\]/
\ contained containedin=uniteSource__Buffer
highlight default link uniteSource__Buffer_NoFile Function
syntax match uniteSource__Buffer_Time /(.\{-}) /
\ contained containedin=uniteSource__Buffer
highlight default link uniteSource__Buffer_Time Statement
endfunction"}}}
function! s:source_buffer_all.hooks.on_post_filter(args, context) abort "{{{
for candidate in a:context.candidates
let candidate.action__path =
\ unite#util#substitute_path_separator(
\ fnamemodify(s:make_word(candidate.action__buffer_nr), ':p'))
let candidate.action__directory =
\ unite#helper#get_buffer_directory(candidate.action__buffer_nr)
endfor
endfunction"}}}
function! s:source_buffer_all.gather_candidates(args, context) abort "{{{
if a:context.is_redraw
" Recaching.
let a:context.source__buffer_list =
\ s:get_buffer_list(a:context.source__is_bang,
\ a:context.source__is_question,
\ a:context.source__is_plus,
\ a:context.source__is_minus,
\ a:context.source__is_terminal)
endif
let candidates = map(a:context.source__buffer_list, "{
\ 'word' : unite#util#substitute_path_separator(
\ s:make_word(v:val.action__buffer_nr)),
\ 'abbr' : s:make_abbr(v:val.action__buffer_nr, v:val.source__flags)
\ . s:format_time(v:val.source__time),
\ 'action__buffer_nr' : v:val.action__buffer_nr,
\}")
return candidates
endfunction"}}}
function! s:source_buffer_all.complete(args, context, arglead, cmdline, cursorpos) abort "{{{
return ['!', '?', '+', '-', 't']
endfunction"}}}
let s:source_buffer_tab = deepcopy(s:source_buffer_all)
let s:source_buffer_tab.name = 'buffer_tab'
let s:source_buffer_tab.description =
\ 'candidates from buffer list in current tab'
function! s:source_buffer_tab.gather_candidates(args, context) abort "{{{
if a:context.is_redraw
" Recaching.
let a:context.source__buffer_list =
\ s:get_buffer_list(a:context.source__is_bang,
\ a:context.source__is_question,
\ a:context.source__is_plus,
\ a:context.source__is_minus,
\ a:context.source__is_terminal)
endif
if !exists('g:loaded_tabpagebuffer') && !exists('g:CtrlSpaceLoaded')
call unite#print_source_message(
\ 'tabpagebuffer or ctrlspace plugin is not installed.', self.name)
return []
endif
if exists('t:tabpagebuffer')
let bufferlist = t:tabpagebuffer
elseif exists('t:CtrlSpaceList')
let bufferlist = t:CtrlSpaceList
else
return []
endif
let list = filter(copy(a:context.source__buffer_list),
\ 'has_key(bufferlist, v:val.action__buffer_nr)')
let candidates = map(list, "{
\ 'word' : unite#util#substitute_path_separator(
\ fnamemodify(s:make_word(v:val.action__buffer_nr), ':p')),
\ 'abbr' : s:make_abbr(v:val.action__buffer_nr, v:val.source__flags)
\ . s:format_time(v:val.source__time),
\ 'action__buffer_nr' : v:val.action__buffer_nr,
\}")
return candidates
endfunction"}}}
" Misc
function! s:make_word(bufnr) abort "{{{
let filetype = getbufvar(a:bufnr, '&filetype')
if filetype ==# 'vimfiler'
let path = unite#util#substitute_path_separator(
\ simplify(getbufvar(a:bufnr, 'vimfiler').current_dir))
let path = unite#util#substitute_path_separator(
\ simplify(bufname(a:bufnr))) . ' ' . path . '/'
elseif filetype ==# 'vimshell'
let path = unite#util#substitute_path_separator(
\ simplify(getbufvar(a:bufnr, 'vimshell').current_dir))
let path = unite#util#substitute_path_separator(
\ simplify(bufname(a:bufnr))) . ' ' . path . '/'
else
let path = unite#util#substitute_path_separator(
\ simplify(bufname(a:bufnr)))
endif
return path
endfunction"}}}
function! s:make_abbr(bufnr, flags) abort "{{{
let bufname = fnamemodify(bufname(a:bufnr), ':t')
if bufname == ''
let bufname = bufname(a:bufnr)
endif
let filetype = getbufvar(a:bufnr, '&filetype')
if filetype ==# 'vimfiler' || filetype ==# 'vimshell'
if filetype ==# 'vimfiler'
let vimfiler = getbufvar(a:bufnr, 'vimfiler')
let path = vimfiler.current_dir
if vimfiler.source !=# 'file'
let path = vimfiler.source . ':' . path
endif
else
let path = simplify(getbufvar(a:bufnr, 'vimshell').current_dir)
endif
let path = printf('%s [%s : %s]', bufname, path, filetype)
else
let path = bufname(a:bufnr) == '' ? 'No Name' :
\ simplify(fnamemodify(bufname(a:bufnr), ':~:.'))
if a:flags != ''
" Format flags so that buffer numbers are aligned on the left.
" example: '42 a% +' => '42 a%+ '
" '3 h +' => ' 3 h+ '
let nowhitespace = substitute(a:flags, '\s*', '', 'g')
let path = substitute(nowhitespace, '\(\d\+\)\(.*\)',
\ '\=printf("%*s %-*s", len(bufnr("$")),
\ submatch(1), 4, submatch(2))', 'g') . path
endif
if filetype != ''
let path .= ' [' . filetype . ']'
endif
endif
return (getbufvar(a:bufnr, '&buftype') =~# 'nofile' ? '[nofile] ' : '' ) .
\ unite#util#substitute_path_separator(path) . ' '
endfunction"}}}
function! s:compare(candidate_a, candidate_b) abort "{{{
return a:candidate_a.action__buffer_nr == unite#get_current_unite().prev_bufnr ? 1 :
\ (a:candidate_b.action__buffer_nr == unite#get_current_unite().prev_bufnr ? -1 :
\ a:candidate_b.source__time - a:candidate_a.source__time)
endfunction"}}}
function! s:get_buffer_list(is_bang, is_question, is_plus, is_minus, is_terminal) abort "{{{
" Get :ls flags.
let flag_dict = {}
for out in map(split(unite#util#redir('ls'), '\n'), 'split(v:val)')
let flag_dict[out[0]] = matchstr(join(out), '^.*\ze\s\+"')
endfor
" Make buffer list.
let list = []
let bufnr = 1
let buffer_list = unite#sources#buffer#variables#get_buffer_list()
while bufnr <= bufnr('$')
if s:is_listed(a:is_bang, a:is_question, a:is_plus, a:is_minus, a:is_terminal, bufnr)
let dict = get(buffer_list, bufnr, {
\ 'action__buffer_nr' : bufnr,
\ 'source__time' : 0,
\ })
let dict.source__flags = get(flag_dict, bufnr, '')
call add(list, dict)
endif
let bufnr += 1
endwhile
call sort(list, 's:compare')
return list
endfunction"}}}
function! s:is_listed(is_bang, is_question, is_plus, is_minus, is_terminal, bufnr) abort "{{{
let bufname = bufname(a:bufnr)
let buftype = getbufvar(a:bufnr, '&buftype')
return bufexists(a:bufnr) &&
\ (a:is_question ? !buflisted(a:bufnr) :
\ (a:is_bang || buflisted(a:bufnr)))
\ && (!a:is_plus || getbufvar(a:bufnr, '&mod'))
\ && (!a:is_minus || buftype == ''
\ && bufname != ''
\ && !isdirectory(bufname))
\ && (!a:is_terminal || buftype ==# 'terminal' )
\ && (getbufvar(a:bufnr, '&filetype') !=# 'unite'
\ || getbufvar(a:bufnr, 'unite').buffer_name !=#
\ unite#get_current_unite().buffer_name)
endfunction"}}}
function! s:format_time(time) abort "{{{
if empty(a:time)
return ''
endif
return strftime(g:unite_source_buffer_time_format, a:time)
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker