1 " Script Name: mark.vim
2 " Description: Highlight several words in different colors simultaneously.
4 " Copyright: (C) 2005-2008 by Yuheng Xie
5 " (C) 2008-2009 by Ingo Karkat
6 " The VIM LICENSE applies to this script; see ':help copyright'.
8 " Maintainer: Ingo Karkat <ingo@karkat.de>
9 " Orig Author: Yuheng Xie <elephant@linux.net.cn>
10 " Contributors:Luc Hermitte, Ingo Karkat
13 " - Requires Vim 7.1 with "matchadd()", or Vim 7.2 or higher.
14 " - mark.vim autoload script.
18 " 17-Nov-2009, Ingo Karkat
19 " - Replaced the (overly) generic mark#GetVisualSelectionEscaped() with
20 " mark#GetVisualSelectionAsRegexp() and
21 " mark#GetVisualSelectionAsLiteralPattern().
23 " 04-Jul-2009, Ingo Karkat
24 " - A [count] before any mapping either caused "No range allowed" error or just
25 " repeated the :call [count] times, resulting in the current search pattern
26 " echoed [count] times and a hit-enter prompt. Now suppressing [count] via
27 " <C-u> and handling it inside the implementation.
28 " - Now passing isBackward (0/1) instead of optional 'b' flag into functions.
29 " Also passing empty regexp to mark#MarkRegex() to avoid any optional
32 " 02-Jul-2009, Ingo Karkat
33 " - Split off functions into autoload script.
34 " - Removed g:force_reload_mark.
35 " - Initialization of global variables and autocommands is now done lazily on
36 " the first use, not during loading of the plugin. This reduces Vim startup
37 " time and footprint as long as the functionality isn't yet used.
39 " 6-Jun-2009, Ingo Karkat
40 " 1. Somehow s:WrapMessage() needs a redraw before the :echo to avoid that a
41 " later Vim redraw clears the wrap message. This happened when there's no
42 " statusline and thus :echo'ing into the ruler.
43 " 2. Removed line-continuations and ':set cpo=...'. Upper-cased <SID> and <CR>.
44 " 3. Added default highlighting for the special search type.
46 " 2-Jun-2009, Ingo Karkat
47 " 1. Replaced highlighting via :syntax with matchadd() / matchdelete(). This
48 " requires Vim 7.2 / 7.1 with patches. This method is faster, there are no
49 " more clashes with syntax highlighting (:match always has preference), and
50 " the background highlighting does not disappear under 'cursorline'.
51 " 2. Factored :windo application out into s:MarkScope().
52 " 3. Using winrestcmd() to fix effects of :windo: By entering a window, its
53 " height is potentially increased from 0 to 1.
54 " 4. Handling multiple tabs by calling s:UpdateScope() on the TabEnter event.
56 " 1-Jun-2009, Ingo Karkat
57 " 1. Now using Vim List for g:mwWord and thus requiring Vim 7. g:mwCycle is now
58 " zero-based, but the syntax groups "MarkWordx" are still one-based.
59 " 2. Added missing setter for re-inclusion guard.
60 " 3. Factored :syntax operations out of s:DoMark() and s:UpdateMark() so that
61 " they can all be done in a single :windo.
62 " 4. Normal mode <Plug>MarkSet now has the same semantics as its visual mode
63 " cousin: If the cursor is on an existing mark, the mark is removed.
64 " Beforehand, one could only remove a visually selected mark via again
65 " selecting it. Now, one simply can invoke the mapping when on such a mark.
66 " 5. Highlighting can now actually be overridden in the vimrc (anywhere
67 " _before_ sourcing this script) by using ':hi def'.
69 " 31-May-2009, Ingo Karkat
70 " 1. Refactored s:Search() to optionally take advantage of SearchSpecial.vim
71 " autoload functionality for echoing of search pattern, wrap and error
73 " 2. Now prepending search type ("any-mark", "same-mark", "new-mark") for
74 " better identification.
75 " 3. Retired the algorithm in s:PrevWord in favor of simply using <cword>,
76 " which makes mark.vim work like the * command. At the end of a line,
77 " non-keyword characters may now be marked; the previous algorithm prefered
79 " 4. BF: If 'iskeyword' contains characters that have a special meaning in a
80 " regex (e.g. [.*]), these are now escaped properly.
82 " 01-Sep-2008, Ingo Karkat: bugfixes and enhancements
83 " 1. Added <Plug>MarkAllClear (without a default mapping), which clears all
84 " marks, even when the cursor is on a mark.
85 " 2. Added <Plug>... mappings for hard-coded \*, \#, \/, \?, * and #, to allow
86 " re-mapping and disabling. Beforehand, there were some <Plug>... mappings
87 " and hard-coded ones; now, everything can be customized.
88 " 3. Bugfix: Using :autocmd without <bang> to avoid removing _all_ autocmds for
89 " the BufWinEnter event. (Using a custom :augroup would be even better.)
90 " 4. Bugfix: Explicitly defining s:current_mark_position; some execution paths
91 " left it undefined, causing errors.
92 " 5. Refactoring: Instead of calling s:InitMarkVariables() at the beginning of
93 " several functions, just calling it once when sourcing the script.
94 " 6. Refactoring: Moved multiple 'let lastwinnr = winnr()' to a single one at the
96 " 7. ENH: Make the match according to the 'ignorecase' setting, like the star
98 " 8. The jumps to the next/prev occurrence now print 'search hit BOTTOM,
99 " continuing at TOP" and "Pattern not found:..." messages, like the * and
100 " n/N Vim search commands.
101 " 9. Jumps now open folds if the occurrence is inside a closed fold, just like n/N
104 " 10th Mar 2006, Yuheng Xie: jump to ANY mark
105 " (*) added \* \# \/ \? for the ability of jumping to ANY mark, even when the
106 " cursor is not currently over any mark
108 " 20th Sep 2005, Yuheng Xie: minor modifications
109 " (*) merged MarkRegexVisual into MarkRegex
110 " (*) added GetVisualSelectionEscaped for multi-lines visual selection and
111 " visual selection contains ^, $, etc.
112 " (*) changed the name ThisMark to CurrentMark
113 " (*) added SearchCurrentMark and re-used raw map (instead of Vim function) to
116 " 14th Sep 2005, Luc Hermitte: modifications done on v1.1.4
117 " (*) anti-reinclusion guards. They do not guard colors definitions in case
118 " this script must be reloaded after .gvimrc
119 " (*) Protection against disabled |line-continuation|s.
120 " (*) Script-local functions
121 " (*) Default keybindings
122 " (*) \r for visual mode
123 " (*) uses <Leader> instead of "\"
124 " (*) do not mess with global variable g:w
125 " (*) regex simplified -> double quotes changed into simple quotes.
126 " (*) strpart(str, idx, 1) -> str[idx]
128 " -> e.g. :Mark Mark.\{-}\ze(
130 " Avoid installing twice or when in unsupported Vim version.
131 if exists('g:loaded_mark') || (v:version == 701 && ! exists('*matchadd')) || (v:version < 702)
134 let g:loaded_mark = 1
136 "- default highlightings ------------------------------------------------------
137 " You may define your own colors in your vimrc file, in the form as below:
138 highlight def MarkWord1 ctermbg=Cyan ctermfg=Black guibg=#8CCBEA guifg=Black
139 highlight def MarkWord2 ctermbg=Green ctermfg=Black guibg=#A4E57E guifg=Black
140 highlight def MarkWord3 ctermbg=Yellow ctermfg=Black guibg=#FFDB72 guifg=Black
141 highlight def MarkWord4 ctermbg=Red ctermfg=Black guibg=#FF7272 guifg=Black
142 highlight def MarkWord5 ctermbg=Magenta ctermfg=Black guibg=#FFB3FF guifg=Black
143 highlight def MarkWord6 ctermbg=Blue ctermfg=Black guibg=#9999FF guifg=Black
145 " Default highlighting for the special search type.
146 " You can override this by defining / linking the 'SearchSpecialSearchType'
147 " highlight group before this script is sourced.
148 highlight def link SearchSpecialSearchType MoreMsg
151 "- mappings -------------------------------------------------------------------
152 nnoremap <silent> <Plug>MarkSet :<C-u>call mark#MarkCurrentWord()<CR>
153 vnoremap <silent> <Plug>MarkSet <C-\><C-n>:call mark#DoMark(mark#GetVisualSelectionAsLiteralPattern())<CR>
154 nnoremap <silent> <Plug>MarkRegex :<C-u>call mark#MarkRegex('')<CR>
155 vnoremap <silent> <Plug>MarkRegex <C-\><C-n>:call mark#MarkRegex(mark#GetVisualSelectionAsRegexp())<CR>
156 nnoremap <silent> <Plug>MarkClear :<C-u>call mark#DoMark(mark#CurrentMark()[0])<CR>
157 nnoremap <silent> <Plug>MarkAllClear :<C-u>call mark#DoMark()<CR>
159 nnoremap <silent> <Plug>MarkSearchCurrentNext :<C-u>call mark#SearchCurrentMark(0)<CR>
160 nnoremap <silent> <Plug>MarkSearchCurrentPrev :<C-u>call mark#SearchCurrentMark(1)<CR>
161 nnoremap <silent> <Plug>MarkSearchAnyNext :<C-u>call mark#SearchAnyMark(0)<CR>
162 nnoremap <silent> <Plug>MarkSearchAnyPrev :<C-u>call mark#SearchAnyMark(1)<CR>
163 nnoremap <silent> <Plug>MarkSearchNext :<C-u>if !mark#SearchNext(0)<Bar>execute 'normal! *zv'<Bar>endif<CR>
164 nnoremap <silent> <Plug>MarkSearchPrev :<C-u>if !mark#SearchNext(1)<Bar>execute 'normal! #zv'<Bar>endif<CR>
165 " When typed, [*#nN] open the fold at the search result, but inside a mapping or
166 " :normal this must be done explicitly via 'zv'.
169 if !hasmapto('<Plug>MarkSet', 'n')
170 nmap <unique> <silent> <Leader>m <Plug>MarkSet
172 if !hasmapto('<Plug>MarkSet', 'v')
173 vmap <unique> <silent> <Leader>m <Plug>MarkSet
175 if !hasmapto('<Plug>MarkRegex', 'n')
176 nmap <unique> <silent> <Leader>r <Plug>MarkRegex
178 if !hasmapto('<Plug>MarkRegex', 'v')
179 vmap <unique> <silent> <Leader>r <Plug>MarkRegex
181 if !hasmapto('<Plug>MarkClear', 'n')
182 nmap <unique> <silent> <Leader>n <Plug>MarkClear
184 " No default mapping for <Plug>MarkAllClear.
186 if !hasmapto('<Plug>MarkSearchCurrentNext', 'n')
187 nmap <unique> <silent> <Leader>* <Plug>MarkSearchCurrentNext
189 if !hasmapto('<Plug>MarkSearchCurrentPrev', 'n')
190 nmap <unique> <silent> <Leader># <Plug>MarkSearchCurrentPrev
192 if !hasmapto('<Plug>MarkSearchAnyNext', 'n')
193 nmap <unique> <silent> <Leader>/ <Plug>MarkSearchAnyNext
195 if !hasmapto('<Plug>MarkSearchAnyPrev', 'n')
196 nmap <unique> <silent> <Leader>? <Plug>MarkSearchAnyPrev
198 if !hasmapto('<Plug>MarkSearchNext', 'n')
199 nmap <unique> <silent> * <Plug>MarkSearchNext
201 if !hasmapto('<Plug>MarkSearchPrev', 'n')
202 nmap <unique> <silent> # <Plug>MarkSearchPrev
206 "- commands -------------------------------------------------------------------
207 command! -nargs=? Mark call mark#DoMark(<f-args>)