summaryrefslogtreecommitdiffstats
path: root/.vim/plugin/qname.vim
blob: e993e08f10672b973c94e043d5145465cfb894e5 (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
if v:version < 700
	finish
endif

if !exists("g:qname_hotkey") || g:qname_hotkey == ""
	let g:qname_hotkey = "<F3>"
endif
exe "nmap" g:qname_hotkey ":cal QNameInit(1)<cr>:~"
let s:qname_hotkey = eval('"\'.g:qname_hotkey.'"')

if exists("g:qname_loaded") && g:qname_loaded
	finish
endif
let g:qname_loaded = 1

function! QNameRun()
	cal s:colPrinter.print()
	echo "\rMatch" len(s:n)."/".len(s:ls) "names:" s:inp
	call inputsave()
	let _key = getchar()
	if !type(_key)
		let _key = nr2char(_key)
	endif

	if _key == "\<BS>"
		let s:inp = s:inp[:-2]
	elseif _key == "\<C-U>"
		let s:inp = ""
	elseif strlen(_key) == 1 && char2nr(_key) > 31
		let s:inp = s:inp._key
	endif
	if _key == "\<ESC>" || _key == "\<CR>" || _key == "\<S-CR>"
		let _sel = s:colPrinter.sel
		if _key != "\<ESC>" && _sel < len(s:n) && _sel >= 0
			if _key == "\<S-CR>"
				:split
			endif
			call s:swb(str2nr(matchstr(s:s[_sel], '<\zs\d\+\ze>')))
		endif
		cal QNameInit(0)
	elseif _key == "\<Up>"
		cal s:colPrinter.vert(-1)
	elseif _key == "\<Down>"
		cal s:colPrinter.vert(1)
	elseif _key == "\<Left>"
		cal s:colPrinter.horz(-1)
	elseif _key == "\<Right>"
		cal s:colPrinter.horz(1)
	elseif _key == s:qname_hotkey
		cal QNameInit(0)
	else
		cal s:build()
	endif
	redraws
	call inputrestore()
endfunc

function! QNameInit(start)
	if a:start
		cmap ~ cal QNameRun()<CR>:~
		let s:pro = "Prompt: "
		let s:cmdh = &cmdheight
		if a:start != -1
			let s:inp = ""
		endif
		call s:baselist()
		call s:build()
		exe "set cmdheight=".(s:colPrinter.trow+1)
	else
		cmap ~ exe "cunmap \x7E"<cr>
		exe "set cmdheight=".s:cmdh
	 endif
endfunc

function! s:build()
	let s:s = []
	let s:n = []
	let s:blen = 0
	let _cmp = tolower(tr(s:inp, '\', '/'))
	for _line in s:ls
		let _name = matchstr(_line, '^.\{-}\ze \+<')
		if s:fmatch(tolower(_name), _cmp)
			cal add(s:s, _line)
			cal add(s:n, _name)
		endif
	endfor
	if len(s:n) > s:colPrinter.trow
		cal s:colPrinter.put(s:n)
	else
		cal s:colPrinter.put(s:s)
	endif
endfunc

function! s:swb(bno)
	if bufwinnr(a:bno) == -1
		exe "hid b" a:bno
	else
		exe bufwinnr(a:bno) . "winc w"
	endif
endfunc 

function! s:fmatch(src,pat)
	let _si = strlen(a:src)-1
	let _pi = strlen(a:pat)-1
	while _si>=0 && _pi>=0
		if a:src[_si] == a:pat[_pi]
			let _pi -= 1
		endif
		let _si -= 1
	endwhile
	return _pi < 0
endfunc

function! s:baselist()
	let s:ls = []
	redir @y | silent ls! | redir END
	for _line in split(@y,"\n")
		if _line[3]!='u' || _line[6]!='-'
			let _bno = matchstr(_line, '^ *\zs\d*')+0
			let _fname = substitute(expand("#"._bno.":p"), '\', '/', 'g')
			if _fname == ""
				let _fname = "|".matchstr(_line, '"\[\zs[^\]]*')."|"
			endif
			let _name = fnamemodify(_fname,":t")
			cal add(s:ls, _name." <"._bno."> ".fnamemodify(_fname,":h"))
		endif
	endfor
	let _align = max(map(copy(s:ls),'stridx(v:val,">")'))
	call map(s:ls, 'substitute(v:val, " <", repeat(" ",_align-stridx(v:val,">"))." <", "")')
	cal sort(s:ls, 1)
endfunc

let s:colPrinter = {"trow": 4}
function! s:colPrinter.put(its) dict
	let _cols = []
	let _trow = self.trow

	let _its = copy(a:its)
	let _len = len(_its)
	let _i = 0
	while _i < _len
		if _i+_trow <= _len
			cal add(_cols, remove(_its,0,_trow-1))
		else
			cal add(_cols, _its)
		endif
		let _i += _trow
	endwhile

	let _cpos = [0]
	let _cw = []
	let _t = 0
	for _li in _cols
		let _w = max(map(copy(_li),'strlen(v:val)'))+4
		let _t += _w
		cal add(_cpos,_t)
		cal add(_cw,_w)
	endfor

	let _rows = []
	for _i in range(_trow)
		let _row = []
		for _j in range(len(_cols))
			if _j*_trow+_i < _len
				cal add(_row,_cols[_j][_i])
			endif
		endfor
		cal add(_rows, _row)
	endfor

	let self.cols = _cols
	let self.cw = _cw
	let self.rows = _rows
	let self.cpos = _cpos
	let self.len = _len
	let self.lcol = 0
	let self.sel = 0
endfunc

function! s:colPrinter.horz(mv) dict
	let _t = self.sel + a:mv*self.trow
	if _t >= 0 && _t < self.len
		let self.sel = _t
	endif
endfunc

function! s:colPrinter.vert(mv) dict
	let _t = self.sel + a:mv
	let _len = self.len
	if _t < 0 && _len > 0
		let self.sel = _len-1
	elseif _t >= _len
		let self.sel = 0
	else
		let self.sel = _t
	endif
endfunc

function! s:colPrinter.print() dict
	let _len = self.len
	let _trow = self.trow
	if !_len
		echo "  [...NO MATCH...]" repeat("\n",_trow)
		return
	endif
	let _sel = self.sel
	let _t = _sel/_trow
	let _cpos = self.cpos
	let _lcol = self.lcol
	let _tcol = &columns
	if _cpos[_lcol]+_tcol < _cpos[_t+1]
		let _rcol = _t
		let _pos = _cpos[_t+1]-_tcol-2
		while _cpos[_lcol] < _pos
			let _lcol += 1
		endwhile
		let _lcol -= _lcol > _t
	else
		if _t < _lcol
			let _lcol = _t
		endif
		let _rcol = len(_cpos)-1
		let _pos = _cpos[_lcol]+_tcol+2
		while _cpos[_rcol] > _pos
			let _rcol -= 1
		endwhile
		let _rcol -= _rcol > _lcol
	endif
	let _cw = self.cw
	let _pos = _cpos[_lcol]+_tcol
	let self.lcol = _lcol
	for _i in range(_trow)
		let _row = self.rows[_i]
		for _j in range(_lcol,_rcol)
			if _j*_trow+_i < _len
				let _txt = "  " . _row[_j]
				let _txt .= repeat(" ", _cw[_j] - strlen(_txt))
				let _txt = _txt[:_pos-_cpos[_j]-2]
				if _j*_trow + _i == _sel
					echoh Search|echon _txt|echoh None
				else
					echon _txt
				endif
			endif
		endfor
		echon "\n"
	endfor
endfunc