summaryrefslogtreecommitdiffstats
path: root/.vim/plugin/buftabs.vim
blob: 30edea98fc2ca87e97cdb820e4415fc85a2a4c78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" buftabs (C) 2006 Ico Doornekamp
"
" 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 2 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.
"
" Introduction
" ------------
"
" This is a simple script that shows a tabs-like list of buffers in the bottom
" of the window. The biggest advantage of this script over various others is
" that it does not take any lines away from your terminal, leaving more space
" for the document you're editing. The tabs are only visible when you need
" them - when you are switchin between buffers.
"
" Usage
" -----
" 
" This script draws buffer tabs on vim startup, when a new buffer is created
" and when switching between buffers.
"
" It might be handy to create a few maps for easy switching of buffers in your
" .vimrc file. For example, using F1 and F2 keys:
"
"   noremap <f1> :bprev<CR> 
"   noremap <f2> :bnext<CR>
"
" or using control-left and control-right keys:
"
"   :noremap <C-left> :bprev<CR>
"   :noremap <C-right> :bnext<CR>
"
"
" The following extra configuration variables are availabe:
" 
" * g:buftabs_only_basename
"
"   Define this variable to make buftabs only print the filename of each buffer,
"   omitting the preceding directory name. Add to your .vimrc:
"
"   :let g:buftabs_only_basename=1
"
"
" * g:buftabs_in_statusline
"
"   Define this variable to make the plugin show the buftabs in the statusline
"   instead of the command line. It is a good idea to configure vim to show
"   the statusline as well when only one window is open. Add to your .vimrc:
"
"   set laststatus=2
"   :let g:buftabs_in_statusline=1
"    
"
" * g:buftabs_active_highlight_group
" * g:buftabs_inactive_highlight_group
"
"   The name of a highlight group (:help highligh-groups) which is used to
"   show the name of the current active buffer and of all other inactive
"   buffers. If these variables are not defined, no highlighting is used.
"   (Highlighting is only functional when g:buftabs_in_statusline is enabled)
"
"   :let g:buftabs_active_highlight_group="Visual"
"
"
" * g:buftabs_marker_start   [
" * g:buftabs_marker_end     ]
" * g:buftabs_separator      -
"
"   These strings are drawn around each tab as separators.
"
"   :let g:buftabs_separator = "."  
"   :let g:buftabs_marker_start = "("
"   :let g:buftabs_marker_end = ")"       
"
"
" Changelog
" ---------
" 
" 0.1  2006-09-22  Initial version 
"
" 0.2  2006-09-22  Better handling when the list of buffers is longer then the
"                  window width.
"
" 0.3  2006-09-27  Some cleanups, set 'hidden' mode by default
"
" 0.4  2007-02-26  Don't draw buftabs until VimEnter event to avoid clutter at
"                  startup in some circumstances
"
" 0.5  2007-02-26  Added option for showing only filenames without directories
"                  in tabs
"
" 0.6  2007-03-04  'only_basename' changed to a global variable.  Removed
"                  functions and add event handlers instead.  'hidden' mode 
"                  broke some things, so is disabled now. Fixed documentation
"
" 0.7  2007-03-07  Added configuration option to show tabs in statusline
"                  instead of cmdline
"
" 0.8  2007-04-02  Update buftabs when leaving insertmode
"
" 0.9  2007-08-22  Now compatible with older Vim versions < 7.0
"
" 0.10 2008-01-26  Added GPL license
"
" 0.11 2008-02-29  Added optional syntax highlighting to active buffer name
"
" 0.12 2009-03-18  Fixed support for split windows
"
" 0.13 2009-05-07  Store and reuse right-aligned part of original statusline
"
" 0.14 2010-01-28  Fixed bug that caused buftabs in command line being
"                  overwritten when 'hidden' mode is enabled.
" 
" 0.15 2010-02-16  Fixed window width handling bug which caused strange
"                  behaviour in combination with the bufferlist plugin.
"									 Fixed wrong buffer display when deleting last window.
"									 Added extra options for tabs style and highlighting.
"
"	0.16 2010-02-28  Fixed bug causing errors when using buftabs in vim
"                  diff mode.
"
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

let w:buftabs_enabled = 0
let w:original_statusline = matchstr(&statusline, "%=.*")

"
" Don't bother when in diff mode
"

if &diff                                      
	finish
endif     


"
" Called on VimEnter event
"

function! Buftabs_enable()
	let w:buftabs_enabled = 1
endfunction


"
" Persistent echo to avoid overwriting of status line when 'hidden' is enabled
" 

function! Pecho(msg)
	let s:hold_ut=&ut|let &ut=1
	let s:Pecho=a:msg
	aug Pecho
		au CursorHold * ec s:Pecho
					\|let &ut=s:hold_ut
					\|aug Pecho|exe 'au!'|aug END|aug! Pecho
	aug END
endf


"
" Draw the buftabs
"

function! Buftabs_show(deleted_buf)

	let l:i = 1
	let l:list = ''
	let l:start = 0
	let l:end = 0
	if ! exists("w:from") 
		let w:from = 0
	endif

	if ! exists("w:buftabs_enabled")
		return
	endif

	" Walk the list of buffers

	while(l:i <= bufnr('$'))

		" Only show buffers in the list, and omit help screens
	
		if buflisted(l:i) && getbufvar(l:i, "&modifiable") && a:deleted_buf != l:i

			" Get the name of the current buffer, and escape characters that might
			" mess up the statusline

			if exists("g:buftabs_only_basename")
				let l:name = fnamemodify(bufname(l:i), ":t")
			else
				let l:name = bufname(l:i)
			endif
			let l:name = substitute(l:name, "%", "%%", "g")
			
			" Append the current buffer number and name to the list. If the buffer
			" is the active buffer, enclose it in some magick characters which will
			" be replaced by markers later. If it is modified, it is appended with
			" an exclaimation mark

			if winbufnr(winnr()) == l:i
				let l:start = strlen(l:list)
				let l:list = l:list . "\x01"
			else
				let l:list = l:list . ' '
			endif
				
      let l:buftabs_separator = "-"
      if exists("g:buftabs_separator")
        let l:buftabs_separator = g:buftabs_separator
      endif

			let l:list = l:list . l:i . l:buftabs_separator
			let l:list = l:list . l:name

			if getbufvar(l:i, "&modified") == 1
				let l:list = l:list . "!"
			endif
			
			if winbufnr(winnr()) == l:i
				let l:list = l:list . "\x02"
				let l:end = strlen(l:list)
			else
				let l:list = l:list . ' '
			endif
		end

		let l:i = l:i + 1
	endwhile

	" If the resulting list is too long to fit on the screen, chop
	" out the appropriate part

	let l:width = winwidth(0) - 12

	if(l:start < w:from) 
		let w:from = l:start - 1
	endif
	if l:end > w:from + l:width
		let w:from = l:end - l:width 
	endif
		
	let l:list = strpart(l:list, w:from, l:width)

	" Replace the magic characters by visible markers for highlighting the
	" current buffer. The markers can be simple characters like square brackets,
	" but can also be special codes with highlight groups

	let l:buftabs_marker_start = "["
  if exists("g:buftabs_marker_start")
    let l:buftabs_marker_start = g:buftabs_marker_start
  endif

	let l:buftabs_marker_end = "]"
  if exists("g:buftabs_marker_end")
    let l:buftabs_marker_end = g:buftabs_marker_end
  endif
  
	if exists("g:buftabs_active_highlight_group")
		if exists("g:buftabs_in_statusline")
			let l:buftabs_marker_start = "%#" . g:buftabs_active_highlight_group . "#" . l:buftabs_marker_start
			let l:buftabs_marker_end = l:buftabs_marker_end . "%##"
		end
	end

	if exists("g:buftabs_inactive_highlight_group")
		if exists("g:buftabs_in_statusline")
			let l:list = '%#' . g:buftabs_inactive_highlight_group . '#' . l:list
			let l:list .= '%##'
			let l:buftabs_marker_end = l:buftabs_marker_end . '%#' . g:buftabs_inactive_highlight_group . '#'
		end
	end

	let l:list = substitute(l:list, "\x01", l:buftabs_marker_start, 'g')
	let l:list = substitute(l:list, "\x02", l:buftabs_marker_end, 'g')

	" Show the list. The buftabs_in_statusline variable determines of the list
	" is displayed in the command line (volatile) or in the statusline
	" (persistent)

	if exists("g:buftabs_in_statusline")
		let &l:statusline = l:list . w:original_statusline
	else
		redraw
		call Pecho(l:list)
	end

endfunction


" Hook to events to show buftabs at startup, when creating and when switching
" buffers

autocmd VimEnter * call Buftabs_enable()
autocmd VimEnter,BufNew,BufEnter,BufWritePost * call Buftabs_show(-1)
autocmd BufDelete * call Buftabs_show(expand('<abuf>'))
if version >= 700
	autocmd InsertLeave,VimResized * call Buftabs_show(-1)
end

" vi: ts=2 sw=2