1"
2" cream-menu-window-buffer.vim
3"
4" Cream -- An easy-to-use configuration of the famous Vim text editor
5" [ http://cream.sourceforge.net ] Copyright (C) 2001-2011 Steve Hall
6"
7" License:
8" This program is free software; you can redistribute it and/or modify
9" it under the terms of the GNU General Public License as published by
10" the Free Software Foundation; either version 3 of the License, or
11" (at your option) any later version.
12" [ http://www.gnu.org/licenses/gpl.html ]
13"
14" This program is distributed in the hope that it will be useful, but
15" WITHOUT ANY WARRANTY; without even the implied warranty of
16" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17" General Public License for more details.
18"
19" You should have received a copy of the GNU General Public License
20" along with this program; if not, write to the Free Software
21" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22" 02111-1307, USA.
23"
24" Source:
25" o Origin: Extracted and modifified from the Vim 6.0 menu.vim
26"   buffers.
27" o 2002-08-28: Verified against Vim 6.1, no changes.
28" o 2002-09-19: Removed all cruft and abandoned hope of ever
29"   syncronizing with Vim's buffer menu again. (That's a good thing ;)
30
31
32" wait with building the menu until after loading 'session' files.
33" Makes startup faster.
34let s:bmenu_wait = 1
35
36" always reset
37let g:bmenu_priority = '80.900'
38
39" Truncate a long path to fit it in a menu item.
40if !exists("g:bmenu_max_pathlen")
41	let g:bmenu_max_pathlen = 35
42endif
43
44" BMShow() {{{1
45function! BMShow(...)
46" Create the buffer menu (delete an existing one first).
47
48	let s:bmenu_wait = 1
49	"let s:bmenu_short = 0
50	let s:bmenu_count = 0
51	" do not show actual buffer numbers, we don't care. Instead, number consecutively.
52	let s:mynum = 0
53
54	" remove the entire Window menu, restore, THEN add buffers
55	silent! unmenu &Window
56	silent! unmenu! &Window
57
58	" replace existing window menu (non-buffer portion)
59	call Cream_menu_window()
60
61	" figure out how many buffers there are
62	"" TODO: don't force short style, need to count and determine prior
63	"let s:bmenu_short = 0
64	" count from 1
65	let buf = 1
66	let i = 0
67	while buf <= bufnr('$')
68		"let buf = buf + 1
69		let i = i + 1
70		if  bufexists(buf)
71		\&& !isdirectory(bufname(buf))
72		\&& Cream_buffer_isspecial() == 0
73		" allow unlisted to pass through so we can call it '(Untitled)' if modified
74		"\&& buflisted(bufname(buf)) != 0
75			let s:bmenu_count = s:bmenu_count + 1
76			call s:BMFilename(bufname(buf), i)
77			"call <SID>BMFilename(Cream_path_fullsystem(bufname(buf)), i)
78		endif
79		let buf = buf + 1
80	endwhile
81	"if s:bmenu_count <= &menuitems
82	"    let s:bmenu_short = 0
83	"endif
84	let s:bmenu_wait = 0
85
86	" TODO: moved to cream-autocmd 2006-02-14
87	"augroup buffer_list
88	"    autocmd!
89	"    "autocmd BufCreate,BufFilePost * call <SID>BMAdd()
90	"    " necessary to recount menu items and refresh indicated status
91	"    "autocmd BufWinEnter * call BMShow()
92	"    " TODO: why isn't this in cream-autocmd ?
93	"    autocmd BufWinEnter,BufEnter,BufNew,WinEnter * call BMShow()
94	"augroup END
95
96endfunction
97
98"" s:BMAdd() {{{1
99"function! s:BMAdd()
100"    if s:bmenu_wait == 0
101"        " when adding too many buffers, redraw in short format
102"        if  s:bmenu_count == &menuitems
103"        "\ && s:bmenu_short == 0
104"            call BMShow()
105"        else
106"            call s:BMFilename(expand("<afile>"), expand("<abuf>"))
107"            let s:bmenu_count = s:bmenu_count + 1
108"        endif
109"    endif
110"endfunction
111
112" s:BMHash() {{{1
113function! s:BMHash(name)
114" Make name all upper case, so that chars are between 32 and 96
115	let nm = substitute(a:name, ".*", '\U\0', "")
116	if has("ebcdic")
117		" HACK: Replace all non alphabetics with 'Z' just to make it work for now.
118		let nm = substitute(nm, "[^A-Z]", 'Z', "g")
119		let sp = char2nr('A') - 1
120	else
121		let sp = char2nr(' ')
122	endif
123	" convert first six chars into a number for sorting:
124	return (char2nr(nm[0]) - sp) * 0x800000 + (char2nr(nm[1]) - sp) * 0x20000 + (char2nr(nm[2]) - sp) * 0x1000 + (char2nr(nm[3]) - sp) * 0x80 + (char2nr(nm[4]) - sp) * 0x20 + (char2nr(nm[5]) - sp)
125endfunction
126
127"" s:BMHash2() {{{1
128"function! s:BMHash2(name)
129"" list overload alphabetization scheme
130"" * Only called if s:bmenu_short != 0
131"
132"    let nm = substitute(a:name, ".", '\L\0', "")
133"    " Not exactly right for EBCDIC...
134"    if nm[0] < 'a' || nm[0] > 'z'
135"        return '&others.'
136"    elseif nm[0] <= 'd'
137"        return '&abcd.'
138"    elseif nm[0] <= 'h'
139"        return '&efgh.'
140"    elseif nm[0] <= 'l'
141"        return '&ijkl.'
142"    elseif nm[0] <= 'p'
143"        return '&mnop.'
144"    elseif nm[0] <= 't'
145"        return '&qrst.'
146"    else
147"        return '&u-z.'
148"    endif
149"endfunction
150
151" s:BMFilename() {{{1
152function! s:BMFilename(bufname, bufnum)
153" insert a buffer name into the buffer menu
154
155	" can't use "a:" arg in "if" statement for some reason
156	let mybufname = a:bufname
157	let mybufnum = a:bufnum
158
159	" test if we want to list it
160	if s:Cream_buffer_islistable(mybufname, mybufnum) == "0"
161		return
162	endif
163
164	let munge = s:BMMunge(mybufname, mybufnum)
165	let hash = s:BMHash(munge)
166
167	" consecutively number buffers
168
169	" indicate modified buffers
170	if getbufvar(mybufnum, "&modified") == 1
171		let mymod = "*"
172	else
173		let mymod = '\ \ '
174	endif
175
176	" indicate current buffer
177	let curbufnr = bufnr("%")
178	if has("win32")
179		if curbufnr == mybufnum
180			let mycurrent = nr2char(187)   " requires 2 spaces (in else) to balance
181		else
182			let mycurrent = '\ \ '
183		endif
184	elseif   &encoding == "latin1"
185		\ || &encoding == "utf-8"
186		if curbufnr == mybufnum
187			let mycurrent = nr2char(187)   " requires 2 spaces (in else) to balance
188		else
189			let mycurrent = '\ \ '
190		endif
191	else
192		if curbufnr == mybufnum
193			let mycurrent = '>' 	       " requires 5 spaces (in else) to balance
194		else
195			let mycurrent = '\ \ '
196		endif
197	endif
198
199	" if unnamed and modified, name '(Untitled)'
200	if  munge == ""
201	\&& getbufvar(mybufnum, "&modified") == 1
202		let munge = '[untitled]'
203	endif
204
205	if munge != ""
206		" use false count number, not actual buffer number
207		let s:mynum = s:mynum + 1
208		" put space before single digits (to align with two-digit numbers)
209		if s:mynum < 10
210			let mymenunum = mycurrent . '\ \ &' . s:mynum . mymod
211		else
212			let mymenunum = mycurrent . '' . s:mynum . mymod
213		endif
214		"if s:bmenu_short == 0
215			let name = 'anoremenu <silent> ' . g:bmenu_priority . '.' . s:mynum . ' &Window.' . mymenunum . munge
216		"else
217		"    let name = 'anoremenu <silent> ' . g:bmenu_priority . '.' . s:mynum . ' &Window.' . mymenunum . s:BMHash2(munge) . munge
218		"endif
219		" add menu name to edit command, check not in special
220		execute name . ' :call Cream_buffer_edit(' . mybufnum . ')<CR>'
221	else
222		" do nothing (don't add menu and don't increment)
223	endif
224
225	" set 'cpo' to include the <CR>
226	let cpo_save = &cpo
227	set cpo&vim
228
229endfunction
230
231" s:Cream_buffer_islistable() {{{1
232function! s:Cream_buffer_islistable(bufname, bufnr)
233" return 0 if we don't want to list the buffer name
234
235	" TODO: Don't we have another function to do this?
236
237	" can't use "a:" arg in "if" statement for some reason
238	let myname = a:bufname
239	let mynr = a:bufnr
240
241	" ignore unlisted, unmodified buffer
242	if !buflisted(bufname(myname))
243	\&& getbufvar(mynr, "&modified") == 0
244		return 0
245	endif
246
247	"" ignore help file
248	"if getbufvar(bufname(myname), "&buftype") == "help"
249	"    return 0
250	"endif
251	"
252	"" OBSOLETE
253	""" ignore if a directory (explorer)
254	""if isdirectory(myname)
255	""    return 0
256	""endif
257	"
258	"" ignore opsplorer
259	"let tempname = fnamemodify(myname, ":t")
260	"if myname == "_opsplorer"
261	"    return 0
262	"endif
263	"
264	"" ignore calendar
265	"if myname == "__Calendar"
266	"    return 0
267	"endif
268	"
269	"" ignore calendar
270	"if myname == "__Tag_List__"
271	"    return 0
272	"endif
273	"
274	"" ignore calendar
275	"if myname == "-- EasyHtml --"
276	"    return 0
277	"endif
278	if Cream_buffer_isspecial(mynr)
279		return 0
280	endif
281
282	return myname
283
284endfunction
285
286" s:BMMunge() {{{1
287function! s:BMMunge(fname, bnum)
288" Return menu item name for given buffer
289	let name = a:fname
290	if name == ''
291		return ""
292	else
293		" TODO: why do this?
294		" change to relative to home directory if possible
295		let name = Cream_path_fullsystem(name)
296		let name = fnamemodify(name, ':p:~')
297	endif
298	" get file name alone
299	let name2 = fnamemodify(name, ':t')
300	let name = name2 . "\t" . s:BMTruncName(fnamemodify(name,':h'))
301	let name = escape(name, "\\. \t|")
302	let name = substitute(name, "\n", "^@", "g")
303	return name
304endfunction
305
306" s:BMTruncName() {{{1
307function! s:BMTruncName(fname)
308	let name = a:fname
309	if g:bmenu_max_pathlen < 5
310		let name = ""
311	else
312		let len = strlen(name)
313		if len > g:bmenu_max_pathlen
314			let amount = (g:bmenu_max_pathlen / 2) - 2
315			let left = strpart(name, 0, amount)
316			let amount = g:bmenu_max_pathlen - amount - 3
317			let right = strpart(name, len - amount, amount)
318			let name = left . '...' . right
319		endif
320	endif
321	return name
322endfunction
323
324" 1}}}
325" vim:foldmethod=marker
326