Subversion Repositories programming

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
160 ira 1
"=== VIM BUFFER LIST SCRIPT 1.2 ================================================
2
"= Copyright(c) 2005, Robert Lillack <rob@lillack.de>                          =
3
"= Redistribution in any form with or without modification permitted.          =
4
"=                                                                             =
5
"= INFORMATION =================================================================
6
"= Upon keypress this script display a nice list of buffers on the left, which =
7
"= can be selected with mouse or keyboard. As soon as a buffer is selected     =
8
"= (Return, double click) the list disappears.                                 =
9
"= The selection can be cancelled with the same key that is configured to open =
10
"= the list or by pressing 'q'. Movement key and mouse (wheel) should work as  =
11
"= one expects.                                                                =
12
"= Buffers that are visible (in any window) are marked with '*', ones that are =
13
"= Modified are marked with '+'                                                =
14
"=                                                                             =
15
"= USAGE =======================================================================
16
"= Put this file into you ~/.vim/plugin directory and set up up like this in   =
17
"= your ~/.vimrc:                                                              =
18
"=                                                                             =
19
"= NEEDED:                                                                     =
20
"=     map <silent> <F3> :call BufferList()<CR>                                =
21
"= OPTIONAL:                                                                   =
22
"=     let g:BufferListWidth = 25                                              =
23
"=     let g:BufferListMaxWidth = 50                                           =
24
"=     hi BufferSelected term=reverse ctermfg=white ctermbg=red cterm=bold     =
25
"=     hi BufferNormal term=NONE ctermfg=black ctermbg=darkcyan cterm=NONE     =
26
"===============================================================================
27
 
28
if exists('g:BufferListLoaded')
29
  finish
30
endif
31
let g:BufferListLoaded = 1
32
 
33
if !exists('g:BufferListWidth')
34
  let g:BufferListWidth = 20
35
endif
36
 
37
if !exists('g:BufferListMaxWidth')
38
  let g:BufferListMaxWidth = 40
39
endif
40
 
41
" toggled the buffer list on/off
42
function! BufferList()
43
  " if we get called and the list is open --> close it
44
  if bufexists(bufnr("__BUFFERLIST__"))
45
    exec ':' . bufnr("__BUFFERLIST__") . 'bwipeout'
46
    return
47
  endif
48
 
49
  let l:bufcount = bufnr('$')
50
  let l:displayedbufs = 0
51
  let l:activebuf = bufnr('')
52
  let l:activebufline = 0
53
  let l:buflist = ''
54
  let l:bufnumbers = ''
55
  let l:width = g:BufferListWidth
56
 
57
  " iterate through the buffers
58
  let l:i = 0 | while l:i <= l:bufcount | let l:i = l:i + 1
59
    let l:bufname = bufname(l:i)
60
    if strlen(l:bufname)
61
      \&& getbufvar(l:i, '&modifiable')
62
      \&& getbufvar(l:i, '&buflisted')
63
 
64
      " adapt width and/or buffer name
65
      if l:width < (strlen(l:bufname) + 5)
66
        if strlen(l:bufname) + 5 < g:BufferListMaxWidth
67
          let l:width = strlen(l:bufname) + 5
68
        else
69
          let l:width = g:BufferListMaxWidth
70
          let l:bufname = '...' . strpart(l:bufname, strlen(l:bufname) - g:BufferListMaxWidth + 8)
71
        endif
72
      endif
73
 
74
      if bufwinnr(l:i) != -1
75
        let l:bufname = l:bufname . '*'
76
      endif
77
      if getbufvar(l:i, '&modified')
78
        let l:bufname = l:bufname . '+'
79
      endif
80
      " count displayed buffers
81
      let l:displayedbufs = l:displayedbufs + 1
82
      " remember buffer numbers
83
      let l:bufnumbers = l:bufnumbers . l:i . ':'
84
      " remember the buffer that was active BEFORE showing the list
85
      if l:activebuf == l:i
86
        let l:activebufline = l:displayedbufs
87
      endif
88
      " fill the name with spaces --> gives a nice selection bar
89
      " use MAX width here, because the width may change inside of this 'for' loop
90
      while strlen(l:bufname) < g:BufferListMaxWidth
91
        let l:bufname = l:bufname . ' '
92
      endwhile
93
      " add the name to the list
94
      let l:buflist = l:buflist . '  ' .l:bufname . "\n"
95
    endif
96
  endwhile
97
 
98
  " generate a variable to fill the buffer afterwards
99
  " (we need this for "full window" color :)
100
  let l:fill = "\n"
101
  let l:i = 0 | while l:i < l:width | let l:i = l:i + 1
102
    let l:fill = ' ' . l:fill
103
  endwhile
104
 
105
  " now, create the buffer & set it up
106
  exec 'silent! ' . l:width . 'vne __BUFFERLIST__'
107
  setlocal noshowcmd
108
  setlocal noswapfile
109
  setlocal buftype=nofile
110
  setlocal bufhidden=delete
111
  setlocal nobuflisted
112
  setlocal nomodifiable
113
  setlocal nowrap
114
  setlocal nonumber
115
 
116
  " set up syntax highlighting
117
  if has("syntax")
118
    syn clear
119
    syn match BufferNormal /  .*/
120
    syn match BufferSelected /> .*/hs=s+1
121
    hi def BufferNormal ctermfg=black ctermbg=white
122
    hi def BufferSelected ctermfg=white ctermbg=black
123
  endif
124
 
125
  setlocal modifiable
126
  if l:displayedbufs > 0
127
    " input the buffer list, delete the trailing newline, & fill with blank lines
128
    put! =l:buflist
129
    " is there any way to NOT delete into a register? bummer...
130
    "norm Gdd$
131
    norm GkJ
132
    while winheight(0) > line(".")
133
      put =l:fill
134
    endwhile
135
  else
136
    let l:i = 0 | while l:i < winheight(0) | let l:i = l:i + 1
137
      put! =l:fill
138
    endwhile
139
    norm 0
140
  endif
141
  setlocal nomodifiable
142
 
143
  " set up the keymap
144
  noremap <silent> <buffer> <CR> :call LoadBuffer()<CR>
145
  map <silent> <buffer> q :bwipeout<CR> 
146
  map <silent> <buffer> j :call BufferListMove("down")<CR>
147
  map <silent> <buffer> k :call BufferListMove("up")<CR>
148
  map <silent> <buffer> <MouseDown> :call BufferListMove("up")<CR>
149
  map <silent> <buffer> <MouseUp> :call BufferListMove("down")<CR>
150
  map <silent> <buffer> <LeftDrag> <Nop>
151
  map <silent> <buffer> <LeftRelease> :call BufferListMove("mouse")<CR>
152
  map <silent> <buffer> <2-LeftMouse> :call BufferListMove("mouse")<CR>
153
    \:call LoadBuffer()<CR>
154
  map <silent> <buffer> <Down> j
155
  map <silent> <buffer> <Up> k
156
  map <buffer> h <Nop>
157
  map <buffer> l <Nop>
158
  map <buffer> <Left> <Nop>
159
  map <buffer> <Right> <Nop>
160
  map <buffer> i <Nop>
161
  map <buffer> a <Nop>
162
  map <buffer> I <Nop>
163
  map <buffer> A <Nop>
164
  map <buffer> o <Nop>
165
  map <buffer> O <Nop>
166
  map <silent> <buffer> <Home> :call BufferListMove(1)<CR>
167
  map <silent> <buffer> <End> :call BufferListMove(line("$"))<CR>
168
 
169
  " make the buffer count & the buffer numbers available
170
  " for our other functions
171
  let b:bufnumbers = l:bufnumbers
172
  let b:bufcount = l:displayedbufs
173
 
174
  " go to the correct line
175
  call BufferListMove(l:activebufline)
176
endfunction
177
 
178
" move the selection bar of the list:
179
" where can be "up"/"down"/"mouse" or
180
" a line number
181
function! BufferListMove(where)
182
  if b:bufcount < 1
183
    return
184
  endif
185
  let l:newpos = 0
186
  if !exists('b:lastline')
187
    let b:lastline = 0
188
  endif
189
  setlocal modifiable
190
 
191
  " the mouse was pressed: remember which line
192
  " and go back to the original location for now
193
  if a:where == "mouse"
194
    let l:newpos = line(".")
195
    call BufferListGoto(b:lastline)
196
  endif
197
 
198
  " exchange the first char (>) with a space
199
  call setline(line("."), " ".strpart(getline(line(".")), 1))
200
 
201
  " go where the user want's us to go
202
  if a:where == "up"
203
    call BufferListGoto(line(".")-1)
204
  elseif a:where == "down"
205
    call BufferListGoto(line(".")+1)
206
  elseif a:where == "mouse"
207
    call BufferListGoto(l:newpos)
208
  else
209
    call BufferListGoto(a:where)
210
  endif
211
 
212
  " and mark this line with a >
213
  call setline(line("."), ">".strpart(getline(line(".")), 1))
214
 
215
  " remember this line, in case the mouse is clicked
216
  " (which automatically moves the cursor there)
217
  let b:lastline = line(".")
218
 
219
  setlocal nomodifiable
220
endfunction
221
 
222
" tries to set the cursor to a line of the buffer list
223
function! BufferListGoto(line)
224
  if b:bufcount < 1 | return | endif
225
  if a:line < 1
226
    call cursor(1, 1)
227
  elseif a:line > b:bufcount
228
    call cursor(b:bufcount, 1)
229
  else
230
    call cursor(a:line, 1)
231
  endif
232
endfunction
233
 
234
" loads the selected buffer
235
function! LoadBuffer()
236
  " this is our string containing the buffer numbers in
237
  " the order of the list (separated by ':')
238
  let l:str = b:bufnumbers
239
 
240
  " remove all numbers BEFORE the one we want
241
  let l:i = 1 | while l:i < line(".") | let l:i = l:i + 1
242
    let l:str = strpart(l:str, stridx(l:str, ':') + 1)
243
  endwhile
244
 
245
  " and everything AFTER
246
  let l:str = strpart(l:str, 0, stridx(l:str, ':'))
247
 
248
  " kill the buffer list
249
  bwipeout
250
 
251
  " ...and switch to the buffer number
252
  exec ":b " . l:str
253
endfunction
254