Load matchit plugin where available.
[profile.git] / .vim / plugin / compview.vim
1 "------------------------------------------------------------------------------
2 " Name Of File: compview.vim
3 "
4 "  Description: Vim plugin to search for a word and display a window with
5 "               matches.
6 "
7 "       Author: Juan Frias (juandfrias at gmail.com)
8 "
9 "  Last Change: 2007 Nov 10
10 "      Version: 1.01
11 "
12 "    Copyright: Permission is hereby granted to use and distribute this code,
13 "               with or without modifications, provided that this header
14 "               is included with it.
15 "
16 "               This script is to be distributed freely in the hope that it
17 "               will be useful, but is provided 'as is' and without warranties
18 "               as to performance of merchantability or any other warranties
19 "               whether expressed or implied. Because of the various hardware
20 "               and software environments into which this script may be put,
21 "               no warranty of fitness for a particular purpose is offered.
22 "
23 "               GOOD DATA PROCESSING PROCEDURE DICTATES THAT ANY SCRIPT BE
24 "               THOROUGHLY TESTED WITH NON-CRITICAL DATA BEFORE RELYING ON IT.
25 "
26 "               THE USER MUST ASSUME THE ENTIRE RISK OF USING THE SCRIPT.
27 "
28 "               The author does not retain any liability on any damage caused
29 "               through the use of this script.
30 "
31 "      Install: 1. Read the section titled 'Options'
32 "               2. Setup any variables need in your vimrc file
33 "               3. Copy 'compview.vim' to your plugin directory.
34 "
35 "  Mapped Keys: <Leader>v   Begin a search.
36 "
37 "        Usage: Start the script with the mapped key you'll be presented
38 "               with a prompt with the word under the cursor, press enter
39 "               to accept the word or type '\c' without the quotes to do a
40 "               case insensitive word or type in new word/expression to
41 "               search instead of current word.
42 "
43 "               Once the search is complete a new window appears with the
44 "               matches found moving around the window will also update the
45 "               position of the current document.
46 "
47 "               The following keys are mapped to the results window:
48 "
49 "                   q - Quit, and restore original cursor position.
50 "
51 "                   e - Exit, and keep results window open note that
52 "                       movements on the result window will no longer be
53 "                       updated.
54 "
55 "                <cr> - Quit and place the cursor on the selected line.
56 "
57 "------------------------------------------------------------------------------
58 " Please send me any bugs you find, so I can keep the script up to date.
59 "------------------------------------------------------------------------------
60
61 " History: {{{1
62 "------------------------------------------------------------------------------
63 " 1.01  Added open window position option cvWindowPosition.
64 "       Thanks to Bernhard Walle
65 "
66 " 1.00  Initial version.
67 "
68 " User Options: {{{1
69 "------------------------------------------------------------------------------
70 "
71 " <Leader>v
72 "       This is the default key map to start a search. Search for 'key' to
73 "       overwrite this key.
74 "
75 " g:cvWindowPosition
76 "       This is specifies the position of the window to be opened. By
77 "       default it will open at on top. To overwrite use:
78 "           let g:cvWindowPosition = 1
79 "       in your vimrc file, options are as follows:
80 "           0 = Open on top
81 "           1 = Open on the bottom
82 "
83
84 " Global variables: {{{1
85 "------------------------------------------------------------------------------
86
87 " Load script once
88 "------------------------------------------------------------------------------
89 if exists("loaded_compview") || &cp
90     finish
91 endif
92 let loaded_compview = 1
93
94 " Set where the window opens
95 "------------------------------------------------------------------------------
96 if !exists('g:cvWindowPosition')
97 "   0 = Open at top
98     let g:cvWindowPosition = 0
99 endif
100
101 " Function: Search file {{{1
102 "--------------------------------------------------------------------------
103 function! s:SearchFile(word)
104     " Add the name of the file to the top.
105     let @z = "File:".expand("%:p")."\n"
106
107     " Search at the beginning and keep adding them to the register
108     normal gg
109     while search(a:word, "W") > 0
110         if foldlevel(line(".")) != 0
111             normal 99zo
112         endif
113         normal 0
114         let @z = @z.line('.').':'
115         normal "Zy$
116         let @z = @z."\n"
117         normal $
118     endwhile
119
120     " Open results window and place items there.
121     if g:cvWindowPosition == 0
122       sp -SearchResults-
123     else
124       botright sp -SearchResults-
125     endif
126     set modifiable
127     normal "zPGddgg
128
129     " Resize line if too big.
130     let l:hits = line("$")
131     if l:hits < winheight(0)
132         sil! exe "resize ".l:hits
133     endif
134
135     " Clean up.
136     let @z = ""
137     set nomodified
138 endfunction
139
140 " Function: Get line number {{{1
141 "--------------------------------------------------------------------------
142 function! s:LineNumber()
143     let l:text = getline(".")
144     if strpart(l:text, 0, 5) == "File:"
145         return 0
146     endif
147     return strpart(l:text, 0, stridx(l:text, ":"))
148 endfunction
149
150 " Function: Update document position {{{1
151 "--------------------------------------------------------------------------
152 function! s:UpdateDoc()
153     let l:line_hit = <sid>LineNumber()
154     match
155     exe 'match Search /\%'.line(".").'l.*/'
156     if line(".") < (line("$") - (winheight(0) / 2)) + 1
157         normal zz
158     endif
159     execute bufwinnr(g:compview_buffer_name)." wincmd w"
160     match
161     if l:line_hit == 0
162         normal 1G
163     else
164         exe "normal ".l:line_hit."Gzz"
165         exe 'match Search /\%'.line(".").'l.*/'
166     endif
167     execute bufwinnr('-SearchResults-')." wincmd w"
168     redraw
169 endfunction
170
171 " Function: Clean up on exit {{{1
172 "--------------------------------------------------------------------------
173 function! s:Exit(key)
174
175     call <sid>UpdateDoc()
176     if a:key == -1
177         nunmap <buffer> e
178         nunmap <buffer> q
179         nunmap <buffer> <cr>
180         execute bufwinnr(g:compview_buffer_name)." wincmd w"
181     else
182         bd!
183     endif
184
185     if a:key == 0
186         exe "normal ".g:compview_original_line."G"
187     endif
188
189     match
190     normal zz
191
192     au! CursorHold
193     execute "set updatetime=".g:compview_old_updatetime
194
195     unlet g:compview_original_line
196     unlet g:compview_current_line
197     unlet g:compview_old_updatetime
198     unlet g:compview_buffer_name
199 endfunction
200
201 " Function: Check for screen update {{{1
202 "--------------------------------------------------------------------------
203 function! s:CheckForUpdate()
204     if expand("%:t") != "-SearchResults-"
205         return
206     endif
207     if g:compview_current_line != line(".")
208         call <sid>UpdateDoc()
209         let g:compview_current_line = line(".")
210     endif
211 endfunction
212
213 " Function: Start the search. {{{1
214 "--------------------------------------------------------------------------
215 function! s:CSearch()
216     let l:current_word = expand("<cword>")
217     let g:compview_buffer_name = expand("%")
218     let g:compview_original_line = line(".")
219
220     " Get the word {{{
221     " ----------------
222
223     " If the word is too big then blank it out
224     if strlen(l:current_word) > 30
225         let l:current_word = ""
226     endif
227
228     " Ask to verify the word
229     echohl Search
230     let l:search_word = input(l:current_word.",/")
231     echohl None
232
233     " If no new word was given use the one we picked up.
234     if strlen(l:search_word) == 0
235         let l:search_word = l:current_word
236     endif
237
238     " If only \c was passed then append it to the beginning
239     if l:search_word == "\\c"
240         let l:search_word = l:search_word.l:current_word
241     endif
242
243     " }}}
244
245     " Make sure we at least have one hit.
246     if !search(l:search_word, 'w')
247         echohl Search
248         echo "No matches found"
249         echohl None
250         return
251     endif
252
253     " Generate hit window
254     call s:SearchFile(l:search_word)
255
256     " Look for the next closest match
257     while <sid>LineNumber() < g:compview_original_line
258         normal j
259     endwhile
260
261     " Map exit keys
262     nnoremap <buffer> <silent> q :call <sid>Exit(0)<cr>
263     nnoremap <buffer> <silent> <cr> :call <sid>Exit(1)<cr>
264     nnoremap <buffer> <silent> e :call <sid>Exit(-1)<cr>
265
266     " Setup syntax highlight {{{
267     exe 'syntax match compviewSearchWord   /'.l:search_word.'/'
268     syntax match compviewFileDivider       /^File:.*$/
269     syntax match compviewLineNumber        /^\d\+:/
270
271     highlight def link compviewFileDivider  Title
272     highlight def link compviewLineNumber   LineNr
273     highlight def link compviewSearchWord   Search
274     " }}}
275
276     " Save globals and change updatetime
277     let g:compview_current_line = line(".")
278     let g:compview_old_updatetime = &updatetime
279     set updatetime=350
280
281     " update the doc and hook the CheckForUpdate function.
282     call <sid>UpdateDoc()
283     au! CursorHold -SearchResults- nested call <sid>CheckForUpdate()
284
285 endfunction
286 "}}}
287
288 map <silent> <Leader>v :call <sid>CSearch()<cr>
289
290 " vim:fdm=marker:tw=75: