|
| 1 | +" Script Name: mark.vim |
| 2 | +" Version: 1.1.2 |
| 3 | +" Last Change: March 23, 2005 |
| 4 | +" Author: Yuheng Xie <[email protected]> |
| 5 | +" |
| 6 | +" Description: a little script to highlight several words in different colors |
| 7 | +" simultaneously |
| 8 | +" |
| 9 | +" Usage: call Mark(regexp) to mark a regular expression. |
| 10 | +" call Mark(regexp) with exactly the same regexp to unmark it. |
| 11 | +" call Mark() to clear all marks. |
| 12 | +" |
| 13 | +" You may map keys for the call in your vimrc file for |
| 14 | +" convenience. The default keys is: |
| 15 | +" Highlighting: |
| 16 | +" Normal \m mark or unmark the word under or before the cursor |
| 17 | +" \r manually input a regular expression |
| 18 | +" \n clear this mark (i.e. the mark under the cursor), |
| 19 | +" or clear all marks |
| 20 | +" Visual \m mark or unmark a visual selection |
| 21 | +" Searching: |
| 22 | +" Normal * jump to the next occurrence of this mark |
| 23 | +" # jump to the previous occurrence of this mark |
| 24 | +" combined with VIM's / and ? etc. |
| 25 | +" |
| 26 | +" The default colors/groups setting is for marking six |
| 27 | +" different words in different colors. You may define your own |
| 28 | +" colors in your vimrc file. That is to define highlight group |
| 29 | +" names as "MarkWordN", where N is a number. An example could be |
| 30 | +" found below. |
| 31 | +" |
| 32 | +" Bugs: some colored words could not be highlighted |
| 33 | + |
| 34 | +" default colors/groups |
| 35 | +" you may define your own colors in you vimrc file, in the form as below: |
| 36 | +hi MarkWord1 ctermbg=Cyan ctermfg=Black guibg=#8CCBEA guifg=Black |
| 37 | +hi MarkWord2 ctermbg=Green ctermfg=Black guibg=#A4E57E guifg=Black |
| 38 | +hi MarkWord3 ctermbg=Yellow ctermfg=Black guibg=#FFDB72 guifg=Black |
| 39 | +hi MarkWord4 ctermbg=Red ctermfg=Black guibg=#FF7272 guifg=Black |
| 40 | +hi MarkWord5 ctermbg=Magenta ctermfg=Black guibg=#FFB3FF guifg=Black |
| 41 | +hi MarkWord6 ctermbg=Blue ctermfg=Black guibg=#9999FF guifg=Black |
| 42 | + |
| 43 | +" you may map keys to call Mark() in your vimrc file to trigger the functions. |
| 44 | +" examples: |
| 45 | +" mark or unmark the word under or before the cursor |
| 46 | +nmap \m :let w=PrevWord()<bar>if w!=""<bar>cal Mark("\\<".w."\\>")<bar>en<cr> |
| 47 | +" manually input a regular expression |
| 48 | +nmap \r :cal inputsave()<bar>let r=input("@")<bar>cal inputrestore()<bar>if r!=""<bar>cal Mark(r)<bar>en<cr> |
| 49 | +" clear the mark under the cursor, or clear all marks |
| 50 | +nmap \n :cal Mark(ThisMark())<cr> |
| 51 | +" jump to the next occurrence of this mark |
| 52 | +nnoremap * :let w=ThisMark()<bar>if w!=""<bar>cal search(w)<bar>el<bar>exe "norm! *"<bar>en<cr> |
| 53 | +" jump to the previous occurrence of this mark |
| 54 | +nnoremap # :let w=ThisMark()<bar>if w!=""<bar>cal search(w,"b")<bar>el<bar>exe "norm! #"<bar>en<cr> |
| 55 | +" mark or unmark a visual selection |
| 56 | +vnoremap \m "my:cal Mark("\\V".substitute(@m,"\\n","\\\\n","g"))<cr> |
| 57 | +
|
| 58 | +" define variables if they don't exist |
| 59 | +function! InitMarkVaribles() |
| 60 | + if !exists("g:mwCycleMax") |
| 61 | + let i = 1 |
| 62 | + while hlexists("MarkWord" . i) |
| 63 | + let i = i + 1 |
| 64 | + endwhile |
| 65 | + let g:mwCycleMax = i - 1 |
| 66 | + endif |
| 67 | + if !exists("b:mwCycle") |
| 68 | + let b:mwCycle = 1 |
| 69 | + endif |
| 70 | + let i = 1 |
| 71 | + while i <= g:mwCycleMax |
| 72 | + if !exists("b:mwWord" . i) |
| 73 | + let b:mwWord{i} = "" |
| 74 | + endif |
| 75 | + let i = i + 1 |
| 76 | + endwhile |
| 77 | +endfunction |
| 78 | + |
| 79 | +" return the word under or before the cursor |
| 80 | +function! PrevWord() |
| 81 | + let line = getline(".") |
| 82 | + if line[col(".") - 1] =~ "\\w" |
| 83 | + return expand("<cword>") |
| 84 | + else |
| 85 | + return substitute(strpart(line, 0, col(".") - 1), "^.\\{-}\\(\\w\\+\\)\\W*$", "\\1", "") |
| 86 | + endif |
| 87 | +endfunction |
| 88 | + |
| 89 | +" mark or unmark a regular expression |
| 90 | +function! Mark(...) " Mark(regexp) |
| 91 | + " define variables if they don't exist |
| 92 | + call InitMarkVaribles() |
| 93 | + |
| 94 | + " clear all marks if regexp is null |
| 95 | + let regexp = "" |
| 96 | + if a:0 > 0 |
| 97 | + let regexp = a:1 |
| 98 | + endif |
| 99 | + if regexp == "" |
| 100 | + let i = 1 |
| 101 | + while i <= g:mwCycleMax |
| 102 | + if b:mwWord{i} != "" |
| 103 | + let b:mwWord{i} = "" |
| 104 | + exe "syntax clear MarkWord" . i |
| 105 | + endif |
| 106 | + let i = i + 1 |
| 107 | + endwhile |
| 108 | + return |
| 109 | + endif |
| 110 | + |
| 111 | + " clear the mark if it has been marked |
| 112 | + let i = 1 |
| 113 | + while i <= g:mwCycleMax |
| 114 | + if regexp == b:mwWord{i} |
| 115 | + let b:mwWord{i} = "" |
| 116 | + exe "syntax clear MarkWord" . i |
| 117 | + return |
| 118 | + endif |
| 119 | + let i = i + 1 |
| 120 | + endwhile |
| 121 | + |
| 122 | + " add to history |
| 123 | + call histadd("/", regexp) |
| 124 | + call histadd("@", regexp) |
| 125 | + |
| 126 | + " quote regexp with / etc. e.g. pattern => /pattern/ |
| 127 | + let quote = "/?~!@#$%^&*+-=,.:" |
| 128 | + let i = 0 |
| 129 | + while i < strlen(quote) |
| 130 | + if stridx(regexp, strpart(quote, i, 1)) < 0 |
| 131 | + let quoted_regexp = strpart(quote, i, 1) . regexp . strpart(quote, i, 1) |
| 132 | + break |
| 133 | + endif |
| 134 | + let i = i + 1 |
| 135 | + endwhile |
| 136 | + if i >= strlen(quote) |
| 137 | + return |
| 138 | + endif |
| 139 | + |
| 140 | + " choose an unused mark group |
| 141 | + let i = 1 |
| 142 | + while i <= g:mwCycleMax |
| 143 | + if b:mwWord{i} == "" |
| 144 | + let b:mwWord{i} = regexp |
| 145 | + if i < g:mwCycleMax |
| 146 | + let b:mwCycle = i + 1 |
| 147 | + else |
| 148 | + let b:mwCycle = 1 |
| 149 | + endif |
| 150 | + exe "syntax clear MarkWord" . i |
| 151 | + exe "syntax match MarkWord" . i . " " . quoted_regexp . " containedin=ALL" |
| 152 | + return |
| 153 | + endif |
| 154 | + let i = i + 1 |
| 155 | + endwhile |
| 156 | + |
| 157 | + " choose a mark group by cycle |
| 158 | + let i = 1 |
| 159 | + while i <= g:mwCycleMax |
| 160 | + if b:mwCycle == i |
| 161 | + let b:mwWord{i} = regexp |
| 162 | + if i < g:mwCycleMax |
| 163 | + let b:mwCycle = i + 1 |
| 164 | + else |
| 165 | + let b:mwCycle = 1 |
| 166 | + endif |
| 167 | + exe "syntax clear MarkWord" . i |
| 168 | + exe "syntax match MarkWord" . i . " " . quoted_regexp . " containedin=ALL" |
| 169 | + return |
| 170 | + endif |
| 171 | + let i = i + 1 |
| 172 | + endwhile |
| 173 | +endfunction |
| 174 | + |
| 175 | +" return the mark string under the cursor. multi-lines marks not supported |
| 176 | +function! ThisMark() |
| 177 | + " define variables if they don't exist |
| 178 | + call InitMarkVaribles() |
| 179 | + |
| 180 | + let line = getline(".") |
| 181 | + let i = 1 |
| 182 | + while i <= g:mwCycleMax |
| 183 | + if b:mwWord{i} != "" |
| 184 | + let start = 0 |
| 185 | + while start >= 0 && start < strlen(line) && start < col(".") |
| 186 | + let b = match(line, b:mwWord{i}, start) |
| 187 | + let e = matchend(line, b:mwWord{i}, start) |
| 188 | + if b < col(".") && col(".") <= e |
| 189 | + return b:mwWord{i} |
| 190 | + endif |
| 191 | + let start = e |
| 192 | + endwhile |
| 193 | + endif |
| 194 | + let i = i + 1 |
| 195 | + endwhile |
| 196 | + return "" |
| 197 | +endfunction |
| 198 | + |
| 199 | +" vim: ts=2 sw=2 |
0 commit comments