mirror of
https://github.com/gryf/.vim.git
synced 2025-12-17 19:40:29 +01:00
548 lines
16 KiB
VimL
548 lines
16 KiB
VimL
" ============================================================================
|
|
" File: buffers.vim
|
|
" Description: vim plugin that provides buffers helpers. Almost all of parts
|
|
" are taken from Eclim project <http://eclim.sourceforge.net>
|
|
" Maintainer: Roman 'gryf' Dobosz <gryf73@gmail.com>
|
|
" Last Change: 2011-07-16
|
|
" License: This program is free software: you can redistribute it and/or
|
|
" modify it under the terms of the GNU General Public License as
|
|
" published by the Free Software Foundation, either version 3 of
|
|
" the License, or (at your option) any later version.
|
|
"
|
|
" This program is distributed in the hope that it will be useful,
|
|
" but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
" GNU General Public License for more details.
|
|
"
|
|
" You should have received a copy of the GNU General Public
|
|
" License along with this program. If not, see
|
|
" <http://www.gnu.org/licenses/>.
|
|
" ============================================================================
|
|
let s:Eclim_ver = '1.7.1'
|
|
|
|
" Eclim: {{{1
|
|
" files:
|
|
" - plugin/eclim.vim (global vars)
|
|
" - plugin/common.vim (commands)
|
|
|
|
" Global Variables {{{2
|
|
|
|
if has("signs")
|
|
if !exists("g:EclimSignLevel")
|
|
let g:EclimSignLevel = 5
|
|
endif
|
|
else
|
|
let g:EclimSignLevel = 0
|
|
endif
|
|
|
|
if !exists("g:EclimInfoHighlight")
|
|
let g:EclimInfoHighlight = "Statement"
|
|
endif
|
|
|
|
if !exists("g:EclimLogLevel")
|
|
let g:EclimLogLevel = 4
|
|
endif
|
|
|
|
if !exists("g:EclimTraceHighlight")
|
|
let g:EclimTraceHighlight = "Normal"
|
|
endif
|
|
if !exists("g:EclimDebugHighlight")
|
|
let g:EclimDebugHighlight = "Normal"
|
|
endif
|
|
if !exists("g:EclimInfoHighlight")
|
|
let g:EclimInfoHighlight = "Statement"
|
|
endif
|
|
if !exists("g:EclimWarningHighlight")
|
|
let g:EclimWarningHighlight = "WarningMsg"
|
|
endif
|
|
if !exists("g:EclimErrorHighlight")
|
|
let g:EclimErrorHighlight = "Error"
|
|
endif
|
|
if !exists("g:EclimFatalHighlight")
|
|
let g:EclimFatalHighlight = "Error"
|
|
endif
|
|
|
|
if !exists("g:EclimShowCurrentError")
|
|
let g:EclimShowCurrentError = 1
|
|
endif
|
|
|
|
if !exists("g:EclimShowCurrentErrorBalloon")
|
|
let g:EclimShowCurrentErrorBalloon = 1
|
|
endif
|
|
|
|
if !exists("g:EclimOpenQFLists")
|
|
let g:EclimOpenQFLists = 1
|
|
endif
|
|
|
|
" }}}
|
|
|
|
" Command Declarations {{{2
|
|
|
|
if !exists(":Buffers")
|
|
command Buffers :call s:Buffers()
|
|
endif
|
|
|
|
" }}}
|
|
|
|
" End Eclim: }}}
|
|
|
|
" Common Buffers: {{{1
|
|
|
|
" Global Variables {{{2
|
|
if !exists('g:EclimBuffersSort')
|
|
let g:EclimBuffersSort = 'file'
|
|
endif
|
|
if !exists('g:EclimBuffersSortDirection')
|
|
let g:EclimBuffersSortDirection = 'asc'
|
|
endif
|
|
if !exists('g:EclimBuffersDefaultAction')
|
|
let g:EclimBuffersDefaultAction = 'edit'
|
|
endif
|
|
" }}}
|
|
|
|
" Buffers() eclim/autoload/eclim/common/buffers.vim {{{2
|
|
" Like, :buffers, but opens a temporary buffer.
|
|
function! s:Buffers()
|
|
redir => list
|
|
silent exec 'buffers'
|
|
redir END
|
|
|
|
let buffers = []
|
|
let filelength = 0
|
|
for entry in split(list, '\n')
|
|
let buffer = {}
|
|
let buffer.status = substitute(entry, '\s*[0-9]\+\s\+\(.\{-}\)\s\+".*', '\1', '')
|
|
let buffer.path = substitute(entry, '.\{-}"\(.\{-}\)".*', '\1', '')
|
|
let buffer.path = fnamemodify(buffer.path, ':p')
|
|
let buffer.file = fnamemodify(buffer.path, ':p:t')
|
|
let buffer.dir = fnamemodify(buffer.path, ':p:h')
|
|
exec 'let buffer.bufnr = ' . substitute(entry, '\s*\([0-9]\+\).*', '\1', '')
|
|
exec 'let buffer.lnum = ' .
|
|
\ substitute(entry, '.*"\s\+line\s\+\([0-9]\+\).*', '\1', '')
|
|
call add(buffers, buffer)
|
|
|
|
if len(buffer.file) > filelength
|
|
let filelength = len(buffer.file)
|
|
endif
|
|
endfor
|
|
|
|
if g:EclimBuffersSort != ''
|
|
call sort(buffers, 'BufferCompare')
|
|
endif
|
|
|
|
let lines = []
|
|
for buffer in buffers
|
|
call add(lines, s:BufferEntryToLine(buffer, filelength))
|
|
endfor
|
|
|
|
call TempWindow('[buffers]', lines)
|
|
|
|
setlocal modifiable noreadonly
|
|
call append(line('$'), ['', '" use ? to view help'])
|
|
setlocal nomodifiable readonly
|
|
|
|
let b:eclim_buffers = buffers
|
|
|
|
" syntax
|
|
set ft=eclim_buffers
|
|
hi link BufferActive Special
|
|
hi link BufferHidden Comment
|
|
syntax match BufferActive /+\?active\s\+\(\[RO\]\)\?/
|
|
syntax match BufferHidden /+\?hidden\s\+\(\[RO\]\)\?/
|
|
syntax match Comment /^".*/
|
|
|
|
" mappings
|
|
nnoremap <silent> <buffer> <cr> :call <SID>BufferOpen2(g:EclimBuffersDefaultAction)<cr>
|
|
nnoremap <silent> <buffer> E :call <SID>BufferOpen2('edit')<cr>
|
|
nnoremap <silent> <buffer> S :call <SID>BufferOpen2('split')<cr>
|
|
nnoremap <silent> <buffer> T :call <SID>BufferOpen('tablast \| tabnew')<cr>
|
|
nnoremap <silent> <buffer> D :call <SID>BufferDelete()<cr>
|
|
nnoremap <silent> <buffer> R :Buffers<cr>
|
|
|
|
" assign to buffer var to get around weird vim issue passing list containing
|
|
" a string w/ a '<' in it on execution of mapping.
|
|
let b:buffers_help = [
|
|
\ '<cr> - open buffer with default action',
|
|
\ 'E - open with :edit',
|
|
\ 'S - open in a new split window',
|
|
\ 'T - open in a new tab',
|
|
\ 'D - delete the buffer',
|
|
\ 'R - refresh the buffer list',
|
|
\ ]
|
|
nnoremap <buffer> <silent> ?
|
|
\ :call BufferHelp(b:buffers_help, 'vertical', 40)<cr>
|
|
|
|
"augroup eclim_buffers
|
|
" autocmd!
|
|
" autocmd BufAdd,BufWinEnter,BufDelete,BufWinLeave *
|
|
" \ call eclim#common#buffers#BuffersUpdate()
|
|
" autocmd BufUnload <buffer> autocmd! eclim_buffers
|
|
"augroup END
|
|
endfunction " }}}
|
|
|
|
" BufferCompare(buffer1, buffer2) eclim/autoload/eclim/common/buffers.vim {{{2
|
|
function! BufferCompare(buffer1, buffer2)
|
|
exec 'let attr1 = a:buffer1.' . g:EclimBuffersSort
|
|
exec 'let attr2 = a:buffer2.' . g:EclimBuffersSort
|
|
let compare = attr1 == attr2 ? 0 : attr1 > attr2 ? 1 : -1
|
|
if g:EclimBuffersSortDirection == 'desc'
|
|
let compare = 0 - compare
|
|
endif
|
|
return compare
|
|
endfunction " }}}
|
|
|
|
" s:BufferDelete() {{{2
|
|
function! s:BufferDelete()
|
|
let line = line('.')
|
|
if line > len(b:eclim_buffers)
|
|
return
|
|
endif
|
|
|
|
let index = line - 1
|
|
setlocal modifiable
|
|
setlocal noreadonly
|
|
exec line . ',' . line . 'delete _'
|
|
setlocal nomodifiable
|
|
setlocal readonly
|
|
let buffer = b:eclim_buffers[index]
|
|
call remove(b:eclim_buffers, index)
|
|
|
|
let winnr = bufwinnr(buffer.bufnr)
|
|
if winnr != -1
|
|
" if active in a window, go to the window to delete the buffer since that
|
|
" keeps eclim's prevention of closing the last non-utility window working
|
|
" properly.
|
|
let curwin = winnr()
|
|
exec winnr . 'winc w'
|
|
bdelete
|
|
exec curwin . 'winc w'
|
|
else
|
|
exec 'bd ' . buffer.bufnr
|
|
endif
|
|
endfunction " }}}
|
|
|
|
" s:BufferEntryToLine(buffer, filelength) eclim/autoload/eclim/common/buffers.vim {{{2
|
|
function! s:BufferEntryToLine(buffer, filelength)
|
|
let line = ''
|
|
let line .= a:buffer.status =~ '+' ? '+' : ' '
|
|
let line .= a:buffer.status =~ 'a' ? 'active' : 'hidden'
|
|
let line .= a:buffer.status =~ '[-=]' ? ' [RO] ' : ' '
|
|
let line .= a:buffer.file
|
|
|
|
let pad = a:filelength - len(a:buffer.file) + 2
|
|
while pad > 0
|
|
let line .= ' '
|
|
let pad -= 1
|
|
endwhile
|
|
|
|
let line .= a:buffer.dir
|
|
return line
|
|
endfunction " }}}
|
|
|
|
" s:BufferOpen(cmd) eclim/autoload/eclim/common/buffers.vim {{{2
|
|
function! s:BufferOpen(cmd)
|
|
let line = line('.')
|
|
if line > len(b:eclim_buffers)
|
|
return
|
|
endif
|
|
|
|
let file = bufname(b:eclim_buffers[line - 1].bufnr)
|
|
let winnr = b:winnr
|
|
close
|
|
exec winnr . 'winc w'
|
|
call GoToBufferWindowOrOpen(file, a:cmd)
|
|
endfunction " }}}
|
|
|
|
" End Common Buffers: }}}
|
|
|
|
" Util: {{{1
|
|
|
|
" Script Variables eclim/autoload/eclim/util.vim {{{2
|
|
let s:buffer_write_closing_commands = '^\s*\(' .
|
|
\ 'wq\|xa\|' .
|
|
\ '\d*w[nN]\|\d*wp\|' .
|
|
\ 'ZZ' .
|
|
\ '\)'
|
|
|
|
let s:bourne_shells = ['sh', 'bash', 'dash', 'ksh', 'zsh']
|
|
let s:c_shells = ['csh', 'tcsh']
|
|
|
|
let s:show_current_error_displaying = 0
|
|
" }}}
|
|
|
|
" DelayedCommand(command, [delay]) eclim/autoload/eclim/util.vim {{{2
|
|
" Executes a delayed command. Useful in cases where one would expect an
|
|
" autocommand event (WinEnter, etc) to fire, but doesn't, or you need a
|
|
" command to execute after other autocommands have finished.
|
|
" Note: Nesting is not supported. A delayed command cannot be invoke off
|
|
" another delayed command.
|
|
function! DelayedCommand(command, ...)
|
|
let uid = fnamemodify(tempname(), ':t:r')
|
|
if &updatetime > 1
|
|
exec 'let g:eclim_updatetime_save' . uid . ' = &updatetime'
|
|
endif
|
|
exec 'let g:eclim_delayed_command' . uid . ' = a:command'
|
|
let &updatetime = len(a:000) ? a:000[0] : 1
|
|
exec 'augroup delayed_command' . uid
|
|
exec 'autocmd CursorHold * ' .
|
|
\ ' if exists("g:eclim_updatetime_save' . uid . '") | ' .
|
|
\ ' let &updatetime = g:eclim_updatetime_save' . uid . ' | ' .
|
|
\ ' unlet g:eclim_updatetime_save' . uid . ' | ' .
|
|
\ ' endif | ' .
|
|
\ ' exec g:eclim_delayed_command' . uid . ' | ' .
|
|
\ ' unlet g:eclim_delayed_command' . uid . ' | ' .
|
|
\ ' autocmd! delayed_command' . uid
|
|
exec 'augroup END'
|
|
endfunction " }}}
|
|
|
|
" EscapeBufferName(name) eclim/autoload/eclim/util.vim {{{2
|
|
" Escapes the supplied buffer name so that it can be safely used by buf*
|
|
" functions.
|
|
function! EscapeBufferName(name)
|
|
let name = a:name
|
|
" escaping the space in cygwin could lead to the dos path error message that
|
|
" cygwin throws when a dos path is referenced.
|
|
if !has('win32unix')
|
|
let name = escape(a:name, ' ')
|
|
endif
|
|
return substitute(name, '\(.\{-}\)\[\(.\{-}\)\]\(.\{-}\)', '\1[[]\2[]]\3', 'g')
|
|
endfunction " }}}
|
|
|
|
" GoToBufferWindow(buf) eclim/autoload/eclim/util.vim {{{2
|
|
" Focuses the window containing the supplied buffer name or buffer number.
|
|
" Returns 1 if the window was found, 0 otherwise.
|
|
function! GoToBufferWindow(buf)
|
|
if type(a:buf) == 0
|
|
let winnr = bufwinnr(a:buf)
|
|
else
|
|
let name = EscapeBufferName(a:buf)
|
|
let winnr = bufwinnr(bufnr('^' . name . '$'))
|
|
endif
|
|
if winnr != -1
|
|
exec winnr . "winc w"
|
|
call DelayedCommand('doautocmd WinEnter')
|
|
return 1
|
|
endif
|
|
return 0
|
|
endfunction " }}}
|
|
|
|
" GoToBufferWindowOrOpen(name, cmd) eclim/autoload/eclim/util.vim {{{2
|
|
" Gives focus to the window containing the buffer for the supplied file, or if
|
|
" none, opens the file using the supplied command.
|
|
function! GoToBufferWindowOrOpen(name, cmd)
|
|
let name = EscapeBufferName(a:name)
|
|
let winnr = bufwinnr(bufnr('^' . name))
|
|
if winnr != -1
|
|
exec winnr . "winc w"
|
|
call DelayedCommand('doautocmd WinEnter')
|
|
else
|
|
let cmd = a:cmd
|
|
" if splitting and the buffer is a unamed empty buffer, then switch to an
|
|
" edit.
|
|
if cmd == 'split' && expand('%') == '' &&
|
|
\ !&modified && line('$') == 1 && getline(1) == ''
|
|
let cmd = 'edit'
|
|
endif
|
|
silent exec cmd . ' ' . escape(Simplify(a:name), ' ')
|
|
endif
|
|
endfunction " }}}
|
|
|
|
|
|
" GoToBufferWindowRegister(buf) eclim/autoload/eclim/util.vim {{{2
|
|
" Registers the autocmd for returning the user to the supplied buffer when the
|
|
" current buffer is closed.
|
|
function! GoToBufferWindowRegister(buf)
|
|
exec 'autocmd BufWinLeave <buffer> ' .
|
|
\ 'call GoToBufferWindow("' . escape(a:buf, '\') . '") | ' .
|
|
\ 'doautocmd BufEnter'
|
|
endfunction " }}}
|
|
|
|
" Simplify(file) eclim/autoload/eclim/util.vim {{{2
|
|
" Simply the supplied file to the shortest valid name.
|
|
function! Simplify(file)
|
|
let file = a:file
|
|
|
|
" Don't run simplify on url files, it will screw them up.
|
|
if file !~ '://'
|
|
let file = simplify(file)
|
|
endif
|
|
|
|
" replace all '\' chars with '/' except those escaping spaces.
|
|
let file = substitute(file, '\\\([^[:space:]]\)', '/\1', 'g')
|
|
let cwd = substitute(getcwd(), '\', '/', 'g')
|
|
if cwd !~ '/$'
|
|
let cwd .= '/'
|
|
endif
|
|
|
|
if file =~ '^' . cwd
|
|
let file = substitute(file, '^' . cwd, '', '')
|
|
endif
|
|
|
|
return file
|
|
endfunction " }}}
|
|
|
|
" TempWindow(name, lines, [readonly]) eclim/autoload/eclim/util.vim {{{2
|
|
" Opens a temp window w/ the given name and contents which is readonly unless
|
|
" specified otherwise.
|
|
function! TempWindow(name, lines, ...)
|
|
let filename = expand('%:p')
|
|
let winnr = winnr()
|
|
|
|
call TempWindowClear(a:name)
|
|
let name = EscapeBufferName(a:name)
|
|
|
|
if bufwinnr(name) == -1
|
|
silent! noautocmd exec "botright 10sview " . escape(a:name, ' []')
|
|
setlocal nowrap
|
|
setlocal winfixheight
|
|
setlocal noswapfile
|
|
setlocal nobuflisted
|
|
setlocal buftype=nofile
|
|
setlocal bufhidden=delete
|
|
silent doautocmd WinEnter
|
|
else
|
|
let temp_winnr = bufwinnr(name)
|
|
if temp_winnr != winnr()
|
|
exec temp_winnr . 'winc w'
|
|
silent doautocmd WinEnter
|
|
endif
|
|
endif
|
|
|
|
setlocal modifiable
|
|
setlocal noreadonly
|
|
call append(1, a:lines)
|
|
retab
|
|
silent 1,1delete _
|
|
|
|
if len(a:000) == 0 || a:000[0]
|
|
setlocal nomodified
|
|
setlocal nomodifiable
|
|
setlocal readonly
|
|
endif
|
|
|
|
silent doautocmd BufEnter
|
|
|
|
" Store filename and window number so that plugins can use it if necessary.
|
|
if filename != expand('%:p')
|
|
let b:filename = filename
|
|
let b:winnr = winnr
|
|
|
|
augroup eclim_temp_window
|
|
autocmd! BufWinLeave <buffer>
|
|
call GoToBufferWindowRegister(b:filename)
|
|
augroup END
|
|
endif
|
|
endfunction " }}}
|
|
|
|
" TempWindowClear(name) eclim/autoload/eclim/util.vim {{{2
|
|
" Clears the contents of the temp window with the given name.
|
|
function! TempWindowClear(name)
|
|
let name = EscapeBufferName(a:name)
|
|
if bufwinnr(name) != -1
|
|
let curwinnr = winnr()
|
|
exec bufwinnr(name) . "winc w"
|
|
setlocal modifiable
|
|
setlocal noreadonly
|
|
silent 1,$delete _
|
|
exec curwinnr . "winc w"
|
|
endif
|
|
endfunction " }}}
|
|
|
|
" End Util: }}}
|
|
|
|
" Eclim Help: {{{1
|
|
|
|
" BufferHelp(lines, orientation, size) eclim/autoload/eclim/help.vim {{{
|
|
" Function to display a help window for the current buffer.
|
|
function! BufferHelp(lines, orientation, size)
|
|
let orig_bufnr = bufnr('%')
|
|
let name = expand('%')
|
|
if name =~ '^\W.*\W$'
|
|
let name = name[:-2] . ' Help' . name[len(name) - 1]
|
|
else
|
|
let name .= ' Help'
|
|
endif
|
|
|
|
let bname = EscapeBufferName(name)
|
|
|
|
let orient = a:orientation == 'vertical' ? 'v' : ''
|
|
if bufwinnr(bname) != -1
|
|
exec 'bd ' . bufnr(bname)
|
|
return
|
|
endif
|
|
|
|
silent! noautocmd exec a:size . orient . "new " . escape(name, ' ')
|
|
if a:orientation == 'vertical'
|
|
setlocal winfixwidth
|
|
else
|
|
setlocal winfixheight
|
|
endif
|
|
setlocal nowrap
|
|
setlocal noswapfile nobuflisted nonumber
|
|
setlocal buftype=nofile bufhidden=delete
|
|
nnoremap <buffer> <silent> ? :bd<cr>
|
|
nnoremap <buffer> <silent> q :bd<cr>
|
|
|
|
setlocal modifiable noreadonly
|
|
silent 1,$delete _
|
|
call append(1, a:lines)
|
|
retab
|
|
silent 1,1delete _
|
|
|
|
if len(a:000) == 0 || a:000[0]
|
|
setlocal nomodified nomodifiable readonly
|
|
endif
|
|
|
|
let help_bufnr = bufnr('%')
|
|
augroup eclim_help_buffer
|
|
autocmd! BufWinLeave <buffer>
|
|
autocmd BufWinLeave <buffer> nested autocmd! eclim_help_buffer * <buffer>
|
|
exec 'autocmd BufWinLeave <buffer> nested ' .
|
|
\ 'autocmd! eclim_help_buffer * <buffer=' . orig_bufnr . '>'
|
|
exec 'autocmd! BufWinLeave <buffer=' . orig_bufnr . '>'
|
|
exec 'autocmd BufWinLeave <buffer=' . orig_bufnr . '> nested bd ' . help_bufnr
|
|
augroup END
|
|
|
|
return help_bufnr
|
|
endfunction " }}}
|
|
|
|
" }}}
|
|
|
|
" Gryfs Mods: {{{
|
|
|
|
" s:BufferOpen2(cmd) (gryf) {{{2
|
|
function! s:BufferOpen2(cmd)
|
|
let line = line('.')
|
|
if line > len(b:eclim_buffers)
|
|
return
|
|
endif
|
|
|
|
let bufnr = b:eclim_buffers[line - 1].bufnr
|
|
let winnr = b:winnr
|
|
close
|
|
exec winnr . 'winc w'
|
|
call s:GoToBufferWindowOrOpen2(bufnr, a:cmd)
|
|
endfunction " }}}
|
|
|
|
" GoToBufferWindowOrOpen2(nr, cmd) (gryf) {{{2
|
|
" modified function GoToBufferWindowOrOpen. instead of buffer name it accepts
|
|
" buffer number.
|
|
function! s:GoToBufferWindowOrOpen2(nr, cmd)
|
|
let winnr = bufwinnr(a:nr)
|
|
if winnr != -1
|
|
exec winnr . "winc w"
|
|
call DelayedCommand('doautocmd WinEnter')
|
|
else
|
|
if a:cmd == 'edit'
|
|
silent exec 'buffer ' . a:nr
|
|
elseif a:cmd == 'split'
|
|
silent exec 'sbuffer ' . a:nr
|
|
endif
|
|
endif
|
|
endfunction " }}}
|
|
|
|
" End Gryfs Mods: }}}
|
|
|
|
" vim:ft=vim:fdm=marker
|
|
|