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
|
if v:version < 700
finish
endif
if !exists("g:qb_hotkey") || g:qb_hotkey == ""
let g:qb_hotkey = "<F4>"
endif
exe "nnoremap <unique>" g:qb_hotkey " :cal <SID>init(1)<cr>:cal SBRun()<cr>"
exe "cnoremap <unique>" g:qb_hotkey "<Esc>"
if exists("g:qb_loaded") && g:qb_loaded
finish
endif
let g:qb_loaded = 1
let s:action2cmd = {"z": 'call <SID>switchbuf(#,"")', "!z": 'call <SID>switchbuf(#,"!")',
\"u": "hid b #|let s:cursel = (s:cursel+1) % s:blen",
\"s": "sb #",
\"d": 'call <SID>qbufdcmd(#,"")', "!d": 'call <SID>qbufdcmd(#,"!")',
\"w": "bw #", "!w": "bw! #",
\"l": "let s:unlisted = 1 - s:unlisted",
\"c": 'call <SID>closewindow(#,"")'}
function s:rebuild()
redir @y | silent ls! | redir END
let s:buflist = []
let s:blen = 0
for l:theline in split(@y,"\n")
if s:unlisted && l:theline[3] == "u" && (l:theline[6] != "-" || l:theline[5] != " ")
\ || !s:unlisted && l:theline[3] != "u"
if s:unlisted
let l:moreinfo = substitute(l:theline[5], "[ah]", " [+]", "")
else
let l:moreinfo = substitute(l:theline[7], "+", " [+]", "")
endif
let s:blen += 1
let l:fname = matchstr(l:theline, '"\zs[^"]*')
let l:bufnum = matchstr(l:theline, '^ *\zs\d*')
if l:bufnum == bufnr('')
let l:active = '* '
elseif bufwinnr(str2nr(l:bufnum)) > 0
let l:active = '= '
else
let l:active = ' '
endif
call add(s:buflist, s:blen . l:active
\.fnamemodify(l:fname,":t") . l:moreinfo
\." <" . l:bufnum . "> "
\.fnamemodify(l:fname,":h"))
endif
endfor
let l:alignsize = max(map(copy(s:buflist),'stridx(v:val,">")'))
call map(s:buflist, 'substitute(v:val, " <", repeat(" ",l:alignsize-stridx(v:val,">"))." <", "")')
call map(s:buflist, 'strpart(v:val, 0, &columns-3)')
endfunc
function SBRun()
if !exists("s:cursel") || (s:cursel >= s:blen) || (s:cursel < 0)
let s:cursel = s:blen-1
endif
if s:blen < 1
echoh WarningMsg | echo "No" s:unlisted ? "unlisted" : "listed" "buffer!" | echoh None
call s:init(0)
return
endif
for l:idx in range(s:blen)
if l:idx != s:cursel
echo " " . s:buflist[l:idx]
else
echoh DiffText | echo "> " . s:buflist[l:idx] | echoh None
endif
endfor
if s:unlisted
echoh WarningMsg
endif
let l:pkey = input(s:unlisted ? "UNLISTED ([+] loaded):" : "LISTED ([+] modified):" , " ")
if s:unlisted
echoh None
endif
if l:pkey =~ "j$"
let s:cursel = (s:cursel+1) % s:blen
elseif l:pkey =~ "k$"
if s:cursel == 0
let s:cursel = s:blen - 1
else
let s:cursel -= 1
endif
elseif s:update_buf(l:pkey)
call s:init(0)
return
endif
call s:setcmdh(s:blen+1)
endfunc
function s:init(onStart)
if a:onStart
set nolazyredraw
let s:unlisted = 1 - getbufvar("%", "&buflisted")
let s:cursorbg = synIDattr(hlID("Cursor"),"bg")
let s:cursorfg = synIDattr(hlID("Cursor"),"fg")
let s:cmdh = &cmdheight
hi Cursor guibg=NONE guifg=NONE
let s:klist = ["j", "k", "u", "d", "w", "l", "s", "c"]
for l:key in s:klist
exe "cnoremap ".l:key." ".l:key."<cr>:cal SBRun()<cr>"
endfor
cmap <up> k
cmap <down> j
call s:rebuild()
let s:cursel = match(s:buflist, '^\d*\*')
call s:setcmdh(s:blen+1)
else
call s:setcmdh(s:cmdh)
for l:key in s:klist
exe "cunmap ".l:key
endfor
cunmap <up>
cunmap <down>
exe "hi Cursor guibg=" . s:cursorbg . " guifg=".((s:cursorfg == "") ? "NONE" : s:cursorfg)
endif
endfunc
" return true to indicate termination
function s:update_buf(cmd)
if a:cmd != "" && a:cmd =~ '^ *\d*!\?\a\?$'
let l:bufidx = str2nr(a:cmd) - 1
if l:bufidx == -1
let l:bufidx = s:cursel
endif
let l:action = matchstr(a:cmd, '!\?\a\?$')
if l:action == "" || l:action == "!"
let l:action .= "z"
endif
if l:bufidx >= 0 && l:bufidx < s:blen && has_key(s:action2cmd, l:action)
try
exe substitute(s:action2cmd[l:action], "#", matchstr(s:buflist[l:bufidx], '<\zs\d\+\ze>'), "g")
if l:action[-1:] != "z"
call s:rebuild()
endif
catch
echoh ErrorMsg | echo "\rVIM" matchstr(v:exception, '^Vim(\a*):\zs.*') | echoh None
if l:action[-1:] != "z"
call inputsave() | call getchar() | call inputrestore()
endif
endtry
endif
endif
return index(s:klist, a:cmd[-1:]) == -1
endfunc
function s:setcmdh(height)
if a:height > &lines - winnr('$') * (&winminheight+1) - 1
call s:init(0)
echo "\r"|echoerr "QBuf E1: No room to display buffer list"
else
exe "set cmdheight=".a:height
endif
endfunc
function s:switchbuf(bno, mod)
if bufwinnr(a:bno) == -1
exe "b".a:mod a:bno
else
exe bufwinnr(a:bno) . "winc w"
endif
endfunc
function s:qbufdcmd(bno, mod)
if s:unlisted
call setbufvar(a:bno, "&buflisted", 1)
else
exe "bd" . a:mod a:bno
endif
endfunc
function s:closewindow(bno, mod)
if bufwinnr(a:bno) != -1
exe bufwinnr(a:bno) . "winc w|close" . a:mod
endif
endfunc
|