]> git.r.bdr.sh - rbdr/dotfiles/blame - vim/plugin/showmarks.vim
Add weechat, ack, git and nethack
[rbdr/dotfiles] / vim / plugin / showmarks.vim
CommitLineData
0d23b6e5
BB
1" ==============================================================================
2" Name: ShowMarks
3" Description: Visually displays the location of marks.
4" Authors: Anthony Kruize <trandor@labyrinth.net.au>
5" Michael Geddes <michaelrgeddes@optushome.com.au>
6" Version: 2.2
7" Modified: 17 August 2004
8" License: Released into the public domain.
9" ChangeLog: See :help showmarks-changelog
10"
11" Usage: Copy this file into the plugins directory so it will be
12" automatically sourced.
13"
14" Default keymappings are:
15" <Leader>mt - Toggles ShowMarks on and off.
16" <Leader>mo - Turns ShowMarks on, and displays marks.
17" <Leader>mh - Clears a mark.
18" <Leader>ma - Clears all marks.
19" <Leader>mm - Places the next available mark.
20"
21" Hiding a mark doesn't actually remove it, it simply moves it
22" to line 1 and hides it visually.
23"
24" Configuration: ***********************************************************
25" * PLEASE read the included help file(showmarks.txt) for a *
26" * more thorough explanation of how to use ShowMarks. *
27" ***********************************************************
28" The following options can be used to customize the behavior
29" of ShowMarks. Simply include them in your vimrc file with
30" the desired settings.
31"
32" showmarks_enable (Default: 1)
33" Defines whether ShowMarks is enabled by default.
34" Example: let g:showmarks_enable=0
35" showmarks_include (Default: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.'`^<>[]{}()\"")
36" Defines all marks, in precedence order (only the highest
37" precence will show on lines having more than one mark).
38" Can be buffer-specific (set b:showmarks_include)
39" showmarks_ignore_type (Default: "hq")
40" Defines the buffer types to be ignored.
41" Valid types are:
42" h - Help p - preview
43" q - quickfix r - readonly
44" m - non-modifiable
45" showmarks_textlower (Default: ">")
46" Defines how the mark is to be displayed.
47" A maximum of two characters can be displayed. To include
48" the mark in the text use a tab(\t) character. A single
49" character will display as the mark with the character
50" suffixed (same as "\t<character>")
51" Examples:
52" To display the mark with a > suffixed:
53" let g:showmarks_textlower="\t>"
54" or
55" let g:showmarks_textlower=">"
56" To display the mark with a ( prefixed:
57" let g:showmarks_textlower="(\t"
58" To display two > characters:
59" let g:showmarks_textlower=">>"
60" showmarks_textupper (Default: ">")
61" Same as above but for the marks A-Z.
62" Example: let g:showmarks_textupper="**"
63" showmarks_textother (Default: ">")
64" Same as above but for all other marks.
65" Example: let g:showmarks_textother="--"
66" showmarks_hlline_lower (Default: 0)
67" showmarks_hlline_upper (Default: 0)
68" showmarks_hlline_other (Default: 0)
69" Defines whether the entire line for a particular mark
70" should be highlighted.
71" Example: let g:showmarks_hlline_lower=1
72"
73" Setting Highlighting Colours
74" ShowMarks uses the following highlighting groups:
75" ShowMarksHLl - For marks a-z
76" ShowMarksHLu - For marks A-Z
77" ShowMarksHLo - For all other marks
78" ShowMarksHLm - For multiple marks on the same line.
79" (Highest precendece mark is shown)
80"
81" By default they are set to a bold blue on light blue.
82" Defining a highlight for each of these groups will
83" override the default highlighting.
84" See the VIM help for more information about highlighting.
85" ==============================================================================
86
87" Check if we should continue loading
88if exists( "loaded_showmarks" )
89 finish
90endif
91let loaded_showmarks = 1
92
93" Bail if Vim isn't compiled with signs support.
94if has( "signs" ) == 0
95 echohl ErrorMsg
96 echo "ShowMarks requires Vim to have +signs support."
97 echohl None
98 finish
99endif
100
101" Options: Set up some nice defaults
102if !exists('g:showmarks_enable' ) | let g:showmarks_enable = 1 | endif
103if !exists('g:showmarks_textlower' ) | let g:showmarks_textlower = ">" | endif
104if !exists('g:showmarks_textupper' ) | let g:showmarks_textupper = ">" | endif
105if !exists('g:showmarks_textother' ) | let g:showmarks_textother = ">" | endif
106if !exists('g:showmarks_ignore_type' ) | let g:showmarks_ignore_type = "hq" | endif
107if !exists('g:showmarks_ignore_name' ) | let g:showmarks_ignore_name = "" | endif
108if !exists('g:showmarks_hlline_lower') | let g:showmarks_hlline_lower = "0" | endif
109if !exists('g:showmarks_hlline_upper') | let g:showmarks_hlline_upper = "0" | endif
110if !exists('g:showmarks_hlline_other') | let g:showmarks_hlline_other = "0" | endif
111
112" This is the default, and used in ShowMarksSetup to set up info for any
113" possible mark (not just those specified in the possibly user-supplied list
114" of marks to show -- it can be changed on-the-fly).
115let s:all_marks = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.'`^<>[]{}()\""
116
117" Commands
118com! -nargs=0 ShowMarksToggle :call <sid>ShowMarksToggle()
119com! -nargs=0 ShowMarksOn :call <sid>ShowMarksOn()
120com! -nargs=0 ShowMarksClearMark :call <sid>ShowMarksClearMark()
121com! -nargs=0 ShowMarksClearAll :call <sid>ShowMarksClearAll()
122com! -nargs=0 ShowMarksPlaceMark :call <sid>ShowMarksPlaceMark()
123
124" Mappings (NOTE: Leave the '|'s immediately following the '<cr>' so the mapping does not contain any trailing spaces!)
125if !hasmapto( '<Plug>ShowmarksShowMarksToggle' ) | map <silent> <unique> <leader>mt :ShowMarksToggle<cr>| endif
126if !hasmapto( '<Plug>ShowmarksShowMarksOn' ) | map <silent> <unique> <leader>mo :ShowMarksOn<cr>| endif
127if !hasmapto( '<Plug>ShowmarksClearMark' ) | map <silent> <unique> <leader>mh :ShowMarksClearMark<cr>| endif
128if !hasmapto( '<Plug>ShowmarksClearAll' ) | map <silent> <unique> <leader>ma :ShowMarksClearAll<cr>| endif
129if !hasmapto( '<Plug>ShowmarksPlaceMark' ) | map <silent> <unique> <leader>mm :ShowMarksPlaceMark<cr>| endif
130noremap <unique> <script> \sm m
131noremap <silent> m :exe 'norm \sm'.nr2char(getchar())<bar>call <sid>ShowMarks()<CR>
132
133" AutoCommands: Only if ShowMarks is enabled
134if g:showmarks_enable == 1
135 aug ShowMarks
136 au!
137 autocmd CursorHold * call s:ShowMarks()
138 aug END
139endif
140
141" Highlighting: Setup some nice colours to show the mark positions.
142hi default ShowMarksHLl ctermfg=darkblue ctermbg=blue cterm=bold guifg=blue guibg=lightblue gui=bold
143hi default ShowMarksHLu ctermfg=darkblue ctermbg=blue cterm=bold guifg=blue guibg=lightblue gui=bold
144hi default ShowMarksHLo ctermfg=darkblue ctermbg=blue cterm=bold guifg=blue guibg=lightblue gui=bold
145hi default ShowMarksHLm ctermfg=darkblue ctermbg=blue cterm=bold guifg=blue guibg=lightblue gui=bold
146
147" Function: IncludeMarks()
148" Description: This function returns the list of marks (in priority order) to
149" show in this buffer. Each buffer, if not already set, inherits the global
150" setting; if the global include marks have not been set; that is set to the
151" default value.
152fun! s:IncludeMarks()
153 if exists('b:showmarks_include') && exists('b:showmarks_previous_include') && b:showmarks_include != b:showmarks_previous_include
154 " The user changed the marks to include; hide all marks; change the
155 " included mark list, then show all marks. Prevent infinite
156 " recursion during this switch.
157 if exists('s:use_previous_include')
158 " Recursive call from ShowMarksHideAll()
159 return b:showmarks_previous_include
160 elseif exists('s:use_new_include')
161 " Recursive call from ShowMarks()
162 return b:showmarks_include
163 else
164 let s:use_previous_include = 1
165 call <sid>ShowMarksHideAll()
166 unlet s:use_previous_include
167 let s:use_new_include = 1
168 call <sid>ShowMarks()
169 unlet s:use_new_include
170 endif
171 endif
172
173 if !exists('g:showmarks_include')
174 let g:showmarks_include = s:all_marks
175 endif
176 if !exists('b:showmarks_include')
177 let b:showmarks_include = g:showmarks_include
178 endif
179
180 " Save this include setting so we can detect if it was changed.
181 let b:showmarks_previous_include = b:showmarks_include
182
183 return b:showmarks_include
184endf
185
186" Function: NameOfMark()
187" Paramaters: mark - Specifies the mark to find the name of.
188" Description: Convert marks that cannot be used as part of a variable name to
189" something that can be. i.e. We cannot use [ as a variable-name suffix (as
190" in 'placed_['; this function will return something like 63, so the variable
191" will be something like 'placed_63').
192" 10 is added to the mark's index to avoid colliding with the numeric marks
193" 0-9 (since a non-word mark could be listed in showmarks_include in the
194" first 10 characters if the user overrides the default).
195" Returns: The name of the requested mark.
196fun! s:NameOfMark(mark)
197 let name = a:mark
198 if a:mark =~# '\W'
199 let name = stridx(s:all_marks, a:mark) + 10
200 endif
201 return name
202endf
203
204" Function: VerifyText()
205" Paramaters: which - Specifies the variable to verify.
206" Description: Verify the validity of a showmarks_text{upper,lower,other} setup variable.
207" Default to ">" if it is found to be invalid.
208fun! s:VerifyText(which)
209 if strlen(g:showmarks_text{a:which}) == 0 || strlen(g:showmarks_text{a:which}) > 2
210 echohl ErrorMsg
211 echo "ShowMarks: text".a:which." must contain only 1 or 2 characters."
212 echohl None
213 let g:showmarks_text{a:which}=">"
214 endif
215endf
216
217" Function: ShowMarksSetup()
218" Description: This function sets up the sign definitions for each mark.
219" It uses the showmarks_textlower, showmarks_textupper and showmarks_textother
220" variables to determine how to draw the mark.
221fun! s:ShowMarksSetup()
222 " Make sure the textlower, textupper, and textother options are valid.
223 call s:VerifyText('lower')
224 call s:VerifyText('upper')
225 call s:VerifyText('other')
226
227 let n = 0
228 let s:maxmarks = strlen(s:all_marks)
229 while n < s:maxmarks
230 let c = strpart(s:all_marks, n, 1)
231 let nm = s:NameOfMark(c)
232 let text = '>'.c
233 let lhltext = ''
234 if c =~# '[a-z]'
235 if strlen(g:showmarks_textlower) == 1
236 let text=c.g:showmarks_textlower
237 elseif strlen(g:showmarks_textlower) == 2
238 let t1 = strpart(g:showmarks_textlower,0,1)
239 let t2 = strpart(g:showmarks_textlower,1,1)
240 if t1 == "\t"
241 let text=c.t2
242 elseif t2 == "\t"
243 let text=t1.c
244 else
245 let text=g:showmarks_textlower
246 endif
247 endif
248 let s:ShowMarksDLink{nm} = 'ShowMarksHLl'
249 if g:showmarks_hlline_lower == 1
250 let lhltext = 'linehl='.s:ShowMarksDLink{nm}.nm
251 endif
252 elseif c =~# '[A-Z]'
253 if strlen(g:showmarks_textupper) == 1
254 let text=c.g:showmarks_textupper
255 elseif strlen(g:showmarks_textupper) == 2
256 let t1 = strpart(g:showmarks_textupper,0,1)
257 let t2 = strpart(g:showmarks_textupper,1,1)
258 if t1 == "\t"
259 let text=c.t2
260 elseif t2 == "\t"
261 let text=t1.c
262 else
263 let text=g:showmarks_textupper
264 endif
265 endif
266 let s:ShowMarksDLink{nm} = 'ShowMarksHLu'
267 if g:showmarks_hlline_upper == 1
268 let lhltext = 'linehl='.s:ShowMarksDLink{nm}.nm
269 endif
270 else " Other signs, like ', ., etc.
271 if strlen(g:showmarks_textother) == 1
272 let text=c.g:showmarks_textother
273 elseif strlen(g:showmarks_textother) == 2
274 let t1 = strpart(g:showmarks_textother,0,1)
275 let t2 = strpart(g:showmarks_textother,1,1)
276 if t1 == "\t"
277 let text=c.t2
278 elseif t2 == "\t"
279 let text=t1.c
280 else
281 let text=g:showmarks_textother
282 endif
283 endif
284 let s:ShowMarksDLink{nm} = 'ShowMarksHLo'
285 if g:showmarks_hlline_other == 1
286 let lhltext = 'linehl='.s:ShowMarksDLink{nm}.nm
287 endif
288 endif
289
290 " Define the sign with a unique highlight which will be linked when placed.
291 exe 'sign define ShowMark'.nm.' '.lhltext.' text='.text.' texthl='.s:ShowMarksDLink{nm}.nm
292 let b:ShowMarksLink{nm} = ''
293 let n = n + 1
294 endw
295endf
296
297" Set things up
298call s:ShowMarksSetup()
299
300" Function: ShowMarksOn
301" Description: Enable showmarks, and show them now.
302fun! s:ShowMarksOn()
303 if g:showmarks_enable == 0
304 call <sid>ShowMarksToggle()
305 else
306 call <sid>ShowMarks()
307 endif
308endf
309
310" Function: ShowMarksToggle()
311" Description: This function toggles whether marks are displayed or not.
312fun! s:ShowMarksToggle()
313 if g:showmarks_enable == 0
314 let g:showmarks_enable = 1
315 call <sid>ShowMarks()
316 aug ShowMarks
317 au!
318 autocmd CursorHold * call s:ShowMarks()
319 aug END
320 else
321 let g:showmarks_enable = 0
322 call <sid>ShowMarksHideAll()
323 aug ShowMarks
324 au!
325 autocmd BufEnter * call s:ShowMarksHideAll()
326 aug END
327 endif
328endf
329
330" Function: ShowMarks()
331" Description: This function runs through all the marks and displays or
332" removes signs as appropriate. It is called on the CursorHold autocommand.
333" We use the marked_{ln} variables (containing a timestamp) to track what marks
334" we've shown (placed) in this call to ShowMarks; to only actually place the
335" first mark on any particular line -- this forces only the first mark
336" (according to the order of showmarks_include) to be shown (i.e., letters
337" take precedence over marks like paragraph and sentence.)
338fun! s:ShowMarks()
339 if g:showmarks_enable == 0
340 return
341 endif
342
343 if ((match(g:showmarks_ignore_type, "[Hh]") > -1) && (&buftype == "help" ))
344 \ || ((match(g:showmarks_ignore_type, "[Qq]") > -1) && (&buftype == "quickfix"))
345 \ || ((match(g:showmarks_ignore_type, "[Pp]") > -1) && (&pvw == 1 ))
346 \ || ((match(g:showmarks_ignore_type, "[Rr]") > -1) && (&readonly == 1 ))
347 \ || ((match(g:showmarks_ignore_type, "[Mm]") > -1) && (&modifiable == 0 ))
348 return
349 endif
350
351 let n = 0
352 let s:maxmarks = strlen(s:IncludeMarks())
353 while n < s:maxmarks
354 let c = strpart(s:IncludeMarks(), n, 1)
355 let nm = s:NameOfMark(c)
356 let id = n + (s:maxmarks * winbufnr(0))
357 let ln = line("'".c)
358
359 if ln == 0 && (exists('b:placed_'.nm) && b:placed_{nm} != ln)
360 exe 'sign unplace '.id.' buffer='.winbufnr(0)
361 elseif ln > 1 || c !~ '[a-zA-Z]'
362 " Have we already placed a mark here in this call to ShowMarks?
363 if exists('mark_at'.ln)
364 " Already placed a mark, set the highlight to multiple
365 if c =~# '[a-zA-Z]' && b:ShowMarksLink{mark_at{ln}} != 'ShowMarksHLm'
366 let b:ShowMarksLink{mark_at{ln}} = 'ShowMarksHLm'
367 exe 'hi link '.s:ShowMarksDLink{mark_at{ln}}.mark_at{ln}.' '.b:ShowMarksLink{mark_at{ln}}
368 endif
369 else
370 if !exists('b:ShowMarksLink'.nm) || b:ShowMarksLink{nm} != s:ShowMarksDLink{nm}
371 let b:ShowMarksLink{nm} = s:ShowMarksDLink{nm}
372 exe 'hi link '.s:ShowMarksDLink{nm}.nm.' '.b:ShowMarksLink{nm}
373 endif
374 let mark_at{ln} = nm
375 if !exists('b:placed_'.nm) || b:placed_{nm} != ln
376 exe 'sign unplace '.id.' buffer='.winbufnr(0)
377 exe 'sign place '.id.' name=ShowMark'.nm.' line='.ln.' buffer='.winbufnr(0)
378 let b:placed_{nm} = ln
379 endif
380 endif
381 endif
382 let n = n + 1
383 endw
384endf
385
386" Function: ShowMarksClearMark()
387" Description: This function hides the mark at the current line.
388" It simply moves the mark to line 1 and removes the sign.
389" Only marks a-z and A-Z are supported.
390fun! s:ShowMarksClearMark()
391 let ln = line(".")
392 let n = 0
393 let s:maxmarks = strlen(s:IncludeMarks())
394 while n < s:maxmarks
395 let c = strpart(s:IncludeMarks(), n, 1)
396 if c =~# '[a-zA-Z]' && ln == line("'".c)
397 let nm = s:NameOfMark(c)
398 let id = n + (s:maxmarks * winbufnr(0))
399 exe 'sign unplace '.id.' buffer='.winbufnr(0)
400 exe '1 mark '.c
401 let b:placed_{nm} = 1
402 endif
403 let n = n + 1
404 endw
405endf
406
407" Function: ShowMarksClearAll()
408" Description: This function clears all marks in the buffer.
409" It simply moves the marks to line 1 and removes the signs.
410" Only marks a-z and A-Z are supported.
411fun! s:ShowMarksClearAll()
412 let n = 0
413 let s:maxmarks = strlen(s:IncludeMarks())
414 while n < s:maxmarks
415 let c = strpart(s:IncludeMarks(), n, 1)
416 if c =~# '[a-zA-Z]'
417 let nm = s:NameOfMark(c)
418 let id = n + (s:maxmarks * winbufnr(0))
419 exe 'sign unplace '.id.' buffer='.winbufnr(0)
420 exe '1 mark '.c
421 let b:placed_{nm} = 1
422 endif
423 let n = n + 1
424 endw
425endf
426
427" Function: ShowMarksHideAll()
428" Description: This function hides all marks in the buffer.
429" It simply removes the signs.
430fun! s:ShowMarksHideAll()
431 let n = 0
432 let s:maxmarks = strlen(s:IncludeMarks())
433 while n < s:maxmarks
434 let c = strpart(s:IncludeMarks(), n, 1)
435 let nm = s:NameOfMark(c)
436 if exists('b:placed_'.nm)
437 let id = n + (s:maxmarks * winbufnr(0))
438 exe 'sign unplace '.id.' buffer='.winbufnr(0)
439 unlet b:placed_{nm}
440 endif
441 let n = n + 1
442 endw
443endf
444
445" Function: ShowMarksPlaceMark()
446" Description: This function will place the next unplaced mark (in priority
447" order) to the current location. The idea here is to automate the placement
448" of marks so the user doesn't have to remember which marks are placed or not.
449" Hidden marks are considered to be unplaced.
450" Only marks a-z are supported.
451fun! s:ShowMarksPlaceMark()
452 " Find the first, next, and last [a-z] mark in showmarks_include (i.e.
453 " priority order), so we know where to "wrap".
454 let first_alpha_mark = -1
455 let last_alpha_mark = -1
456 let next_mark = -1
457
458 if !exists('b:previous_auto_mark')
459 let b:previous_auto_mark = -1
460 endif
461
462 " Find the next unused [a-z] mark (in priority order); if they're all
463 " used, find the next one after the previously auto-assigned mark.
464 let n = 0
465 let s:maxmarks = strlen(s:IncludeMarks())
466 while n < s:maxmarks
467 let c = strpart(s:IncludeMarks(), n, 1)
468 if c =~# '[a-z]'
469 if line("'".c) <= 1
470 " Found an unused [a-z] mark; we're done.
471 let next_mark = n
472 break
473 endif
474
475 if first_alpha_mark < 0
476 let first_alpha_mark = n
477 endif
478 let last_alpha_mark = n
479 if n > b:previous_auto_mark && next_mark == -1
480 let next_mark = n
481 endif
482 endif
483 let n = n + 1
484 endw
485
486 if next_mark == -1 && (b:previous_auto_mark == -1 || b:previous_auto_mark == last_alpha_mark)
487 " Didn't find an unused mark, and haven't placed any auto-chosen marks yet,
488 " or the previously placed auto-chosen mark was the last alpha mark --
489 " use the first alpha mark this time.
490 let next_mark = first_alpha_mark
491 endif
492
493 if (next_mark == -1)
494 echohl WarningMsg
495 echo 'No marks in [a-z] included! (No "next mark" to choose from)'
496 echohl None
497 return
498 endif
499
500 let c = strpart(s:IncludeMarks(), next_mark, 1)
501 let b:previous_auto_mark = next_mark
502 exe 'mark '.c
503 call <sid>ShowMarks()
504endf
505
506" -----------------------------------------------------------------------------
507" vim:ts=4:sw=4:noet