├── README.md
├── _config.yml
├── autoload
└── matchtag.vim
└── plugin
└── matchtag.vim
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # vim-matchtag
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Highlight matching tags in any files such as html, xml, js, jsx, vue, svelte.
12 |
13 | ## Installation
14 |
15 |
16 | How to install
17 |
18 | - [VundleVim][1]
19 |
20 | Plugin 'leafOfTree/vim-matchtag'
21 |
22 | - [vim-pathogen][2]
23 |
24 | cd ~/.vim/bundle && \
25 | git clone https://github.com/leafOfTree/vim-matchtag --depth 1
26 |
27 | - [vim-plug][3]
28 |
29 | Plug 'leafOfTree/vim-matchtag'
30 |
31 | - Or manually, clone this plugin to `path/to/this_plugin`, and add it to `rtp` in vimrc
32 |
33 | set rtp+=path/to/this_plugin
34 |
35 |
36 |
37 |
38 | ## How it works
39 |
40 | This plugin finds the matching tag and highlight it. Mainly inspired by vim builtin `matchparen` using `searchpairpos` and `matchaddpos`. Feel free to open an issue or a pull request.
41 |
42 | ## Configuration
43 |
44 | Set global variable to `1` to enable or `0` to disalbe. Or a proper value to make it effective. Ex:
45 |
46 | ```vim
47 | let g:vim_matchtag_enable_by_default = 1
48 | let g:vim_matchtag_files = '*.html,*.xml,*.js,*.jsx,*.ts,*.tsx,*.vue,*.svelte,*.jsp,*.php,*.erb,*.astro'
49 | ```
50 |
51 | | variable | description | default |
52 | |--------------------------------------|-----------------------------------------------------|---------|
53 | | g:vim_matchtag_files | Enable on these files. | *See ^* |
54 | | g:vim_matchtag_enable_by_default | Enable by default. | 1 |
55 | | g:vim_matchtag_highlight_cursor_on | Highlight the tag when the cursor is on it. | 0 |
56 | | **Mappings / Performance / debug related** |||
57 | | g:vim_matchtag_mapping_toggle | Key mapping to toggle highlighting. | `''` |
58 | | g:vim_matchtag_mapping_toggle_highlight_cursor_on | Key mapping to toggle `highlight_cursor_on`. | `''` |
59 | | g:vim_matchtag_skip | Syntax to skip. | *See +* |
60 | | g:vim_matchtag_skip_except | Syntax not to skip. | *See +* |
61 | | g:vim_matchtag_timeout | The search stops after timeout milliseconds. | 50 |
62 | | g:vim_matchtag_disable_cache | Disable the cache for lines.
(By default the lines are cached until text changed) | 0 |
63 | | g:vim_matchtag_debug | Echo debug messages. | 0 |
64 |
65 | **Note**
66 |
67 | - If you prefer to enable it on demand, you can set `g:vim_matchtag_enable_by_default` to `0` then toggle it by `:MatchTagToggle`.
68 |
69 | - ^: It is a comma separated file pattern (`:h autocmd-patterns`). It defaults to
70 |
71 | ```vim
72 | let g:vim_matchtag_files = '*.html,*.xml,*.js,*.jsx,*.ts,*.tsx,*.vue,*.svelte,*.jsp,*.php,*.erb,*.astro'
73 | ```
74 | - +: Both are patterns (`:h pattern`). The default values are
75 |
76 | ```vim
77 | let g:vim_matchtag_skip = 'javascript\|css\|script\|style'
78 | let g:vim_matchtag_skip_except = 'html\|template'
79 | ```
80 | - See [performance](#performance) if there are lags.
81 |
82 | ### Highlighting
83 |
84 | When the matching tag is found, the highlight group is `matchTag` (by default `Visual`). Otherwise, it's `matchTagError` (by default `Error`).
85 |
86 | You could change them as follows.
87 |
88 | ```vim
89 | highlight link matchTag Search
90 | highlight link matchTag MatchParen
91 | highlight matchTag gui=reverse
92 |
93 | highlight link matchTagError Todo
94 | ```
95 |
96 | If these don't take effect, try putting them at the end of your vimrc.
97 |
98 | ### Commands
99 |
100 | There are commands you can call directly or add key mapping to.
101 |
102 | - `:MatchTagToggle` Toggle highlighting.
103 |
104 | - `:MatchTagToggleHighlightCursorOn` Toggle highlighting of the tag when the cursor is on it.
105 |
106 | ## Performance
107 |
108 | The highlighting should take about `0.001`~`0.01` depending on the file content. If there is a freeze, you can try
109 |
110 | ```vim
111 | let g:vim_matchtag_skip = '' " Syntax to skip
112 | let g:vim_matchtag_skip_except = '' " Syntax not to skip
113 |
114 | call matchtag#ReportTime()
115 | ```
116 | and feel free to open an issue.
117 |
118 | You can show the syntax stack under the cursor by running
119 | ```vim
120 | echo map(synstack(line('.'), col('.')), { _, id -> synIDattr(id, 'name') })
121 | ```
122 |
123 | ## Others
124 |
125 | - Jump between matching tags? See `:h matchit`.
126 |
127 | ## Credits
128 |
129 | - matchparen.vim
130 |
131 | [1]: https://github.com/VundleVim/Vundle.vim
132 | [2]: https://github.com/tpope/vim-pathogen
133 | [3]: https://github.com/junegunn/vim-plug
134 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/autoload/matchtag.vim:
--------------------------------------------------------------------------------
1 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
2 | "
3 | " Settings {{{
4 | "
5 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
6 | let s:name = 'vim-matchtag'
7 | let s:match_id = 999
8 | let s:tagname_regexp = '[0-9A-Za-z_.-]'
9 | let s:empty_tagname = '\v<(area|base|br|col|embed|hr|input|img|keygen|link|meta|param|source|track|wbr)>'
10 | let s:component_name = '\v\C^[A-Z]\w+'
11 | let s:exists_text_changed = exists('##TextChanged')
12 |
13 | "}}}
14 |
15 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
16 | "
17 | " Configs {{{
18 | "
19 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
20 | function! s:GetConfig(name, default)
21 | let name = 'g:vim_matchtag_'.a:name
22 | return exists(name) ? eval(name) : a:default
23 | endfunction
24 |
25 | let s:highlight_cursor_on = s:GetConfig('highlight_cursor_on', s:GetConfig('both', 0))
26 | let s:debug = s:GetConfig('debug', 0)
27 | let s:timeout = s:GetConfig('timeout', 50)
28 | let s:disable_cache = s:GetConfig('disable_cache',
29 | \ !s:exists_text_changed)
30 | let s:skip = s:GetConfig('skip',
31 | \ 'javascript\|css\|script\|style')
32 | let s:skip_except = s:GetConfig('skip_except',
33 | \ 'html\|template')
34 | "}}}
35 |
36 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
37 | "
38 | " Functions {{{
39 | "
40 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
41 | " The function that is invoked (very often) to definie a ":match"
42 | " highlighting for any matching tag.
43 | function! matchtag#HighlightMatchingTag()
44 | " Remove any previous match.
45 | if exists('w:matchtag_hl_on') && w:matchtag_hl_on
46 | call s:DeleteMatch()
47 | let w:matchtag_hl_on = 0
48 | endif
49 |
50 | " Avoid removing the popup menu.
51 | " Or return when there are no colors
52 | if pumvisible() || (&t_Co < 8 && !has('gui_running'))
53 | return
54 | endif
55 |
56 | " Skip if current position contains specific syntax
57 | if s:IsInSkipSyntax()
58 | call s:Log('Skip syntax')
59 | return
60 | endif
61 |
62 | call s:HighlightTag()
63 | endfunction
64 |
65 | let s:cached_lines = {}
66 | function! s:ResetLineCache()
67 | let s:cached_lines = {}
68 | endfunction
69 |
70 | if !s:disable_cache
71 | " Cache lines
72 | function! s:GetLine(number)
73 | let number = a:number
74 | if has_key(s:cached_lines, number)
75 | return s:cached_lines[number]
76 | else
77 | let line = getline(number)
78 | let s:cached_lines[number] = line
79 | return line
80 | endif
81 | endfunction
82 | else
83 | function! s:GetLine(number)
84 | return getline(a:number)
85 | endfunction
86 | endif
87 |
88 | function! s:HighlightTag()
89 | let save_cursor = getcurpos()
90 |
91 | let [cursor_row, cursor_col] = save_cursor[1:2]
92 | if cursor_col < min([cursor_row * &shiftwidth, 20])
93 | let bracket_col = searchpos('^\s\+\zs<', 'n', cursor_row, s:timeout)[1]
94 | if cursor_col < bracket_col
95 | call cursor(0, bracket_col)
96 | endif
97 | endif
98 |
99 | let [row, col] = s:GetTagPos()
100 | if row
101 | " Find current tag
102 | let line = s:GetLine(row)
103 | let tagname = s:GetTagName(line, col)
104 | let pos = [[row, col+1, len(tagname)]]
105 | call s:Log('On tag '.tagname)
106 |
107 | " Set cursor to tag start to search backward correctly
108 | call cursor(row, col)
109 |
110 | let [match_row, match_col, offset] = s:SearchMatchTag(tagname)
111 | if match_row " Find matching tag
112 | let match_line = match_row == row
113 | \ ? line
114 | \ : s:GetLine(match_row)
115 | let match_tagname = s:GetTagName(match_line, match_col)
116 |
117 | " Highlight tags
118 | " Current tag
119 | let cursor_on_tag = cursor_row == row
120 | \ && cursor_col >= col
121 | \ && cursor_col <= (col+len(tagname)+1)
122 | if !cursor_on_tag || s:highlight_cursor_on
123 | call matchaddpos('MatchTag', pos, 10, s:match_id)
124 | endif
125 | " Matching tag
126 | let match_pos = [[
127 | \match_row,
128 | \match_col+offset,
129 | \len(match_tagname)+1-offset
130 | \]]
131 | call matchaddpos('MatchTag', match_pos, 10, s:match_id+1)
132 | call s:Log('Matching tag '.match_tagname)
133 | else " No matching tag found
134 | if s:IsEmptyTag(tagname)
135 | " Current tag is emtpy
136 | call matchaddpos('MatchTag', pos, 10, s:match_id)
137 | call s:Log('Current tag is empty: '.tagname)
138 | else
139 | " Matching tag not found
140 | call matchaddpos('MatchTagError', pos, 10, s:match_id)
141 | call s:Log('Matching tag Not found')
142 | endif
143 | endif
144 | let w:matchtag_hl_on = 1
145 | endif
146 |
147 | call setpos('.', save_cursor)
148 | endfunction
149 |
150 | function! s:IsEmptyTag(tagname)
151 | return match(a:tagname, s:empty_tagname) != -1
152 | \|| match(a:tagname, s:component_name) != -1
153 | endfunction
154 |
155 | " Compare two positions
156 | " 0: pos1 is after pos2
157 | " 1: pos1 is ahead of pos2
158 | function! s:IsAheadOf(pos1, pos2)
159 | let [row1, col1] = a:pos1
160 | let [row2, col2] = a:pos2
161 | if row2 > row1 || (row2 == row1 && col2 > col1)
162 | return 1
163 | else
164 | return 0
165 | endif
166 | endfunction
167 |
168 | function! s:IsEmptyPos(pos)
169 | let [row, col] = a:pos
170 | return row == 0 && col == 0
171 | endfunction
172 |
173 | function! s:IsSamePos(pos1, pos2)
174 | let [row1, col1] = a:pos1
175 | let [row2, col2] = a:pos2
176 | return row1 == row2 && col1 == col2
177 | endfunction
178 |
179 | function! s:NotAfter(main, excludes)
180 | let regexp = '\('.join(split(a:excludes, ','), '\|').'\)'
181 | return a:main.regexp.'\@!'
182 | endfunction
183 |
184 | function! s:NotBefore(main, excludes)
185 | let regexp = '\('.join(split(a:excludes, ','), '\|').'\)'
186 | return regexp.'\@' in empty tag
192 | " - '', '?>' in php tags
193 | " - '' in html comments
194 | " - '=>' in JavaScript
195 | let s:open_bracket_regexp = s:NotAfter('<', '?,!')
196 | let s:close_bracket_regexp = s:NotBefore('>', '?,=')
197 | let s:open_bracket_forward_regexp = s:NotAfter('', '?')
198 | let s:close_bracket_forward_regexp = s:NotBefore('>', '?,-,=')
199 |
200 | function! s:GetTagPos()
201 | call s:Log('GetTagPos')
202 |
203 | if s:IsInComment()
204 | call s:Log('In coment, skip')
205 | return [0, 0]
206 | endif
207 |
208 | let timeout = s:timeout
209 | let firstline = line('w0')
210 | let lastline = line('w$')
211 |
212 | " Search for '<' backward
213 | let open_bracket = searchpos(s:open_bracket_regexp, 'cbnW', firstline, timeout)
214 | " Search for '>' backward
215 | let close_bracket = searchpos(s:close_bracket_regexp, 'bnW', firstline, timeout)
216 |
217 | let near_open = s:IsAheadOf(close_bracket, open_bracket)
218 | let near_close = !near_open
219 |
220 | " Search for '<' forward
221 | let open_bracket_forward = searchpos(s:open_bracket_forward_regexp, 'nW', lastline, timeout)
222 | " Search for '>' forward
223 | let close_bracket_forward = searchpos(s:close_bracket_forward_regexp, 'cnW', lastline, timeout)
224 |
225 | let near_close_forward = s:IsAheadOf(close_bracket_forward, open_bracket_forward)
226 | \ || s:IsEmptyPos(open_bracket_forward)
227 | let near_open_forward = !near_close_forward
228 |
229 | " On tag
230 | if near_open && near_close_forward
231 | call s:Log('On tag')
232 | return open_bracket
233 | endif
234 |
235 | " Check if in tag
236 | " Check forward
237 | if near_open_forward
238 | call s:Log('Find close tag forward ')
239 | return open_bracket_forward
240 | endif
241 | " Check backward
242 | if near_close
243 | let open_of_closetag
244 | \ = searchpos('', 'bcnW', firstline, timeout)
245 | let close_of_closetag
246 | \ = searchpos('/\zs>', 'bcnW', firstline, timeout)
247 |
248 | if !s:IsSamePos(open_bracket, open_of_closetag)
249 | \ && !s:IsSamePos(close_bracket, close_of_closetag)
250 |
251 | let line = s:GetLine(open_bracket[0])
252 | let tagname = s:GetTagName(line, open_bracket[1])
253 | if s:IsEmptyTag(tagname)
254 | call s:Log('After an empty tag')
255 | return [0, 0]
256 | endif
257 |
258 | call s:Log('Find open tag backward')
259 | return open_bracket
260 | endif
261 | endif
262 |
263 | " Not on/in tag
264 | if s:IsEmptyPos(open_bracket)
265 | call s:Log('Not on/in tag, no open bracket')
266 | return [0, 0]
267 | endif
268 | if s:IsEmptyPos(close_bracket_forward)
269 | call s:Log('Not on/in tag, no close bracket')
270 | return [0, 0]
271 | endif
272 |
273 | call s:Log('Not on/in tag, <: '.near_open.', >: '.near_close_forward)
274 | return [0, 0]
275 | endfunction
276 |
277 | function! s:GetTagName(line, col)
278 | let line = a:line
279 | let col = a:col
280 |
281 | let end = col + 1
282 | while line[end] =~ s:tagname_regexp
283 | let end += 1
284 | endwhile
285 | let tagname = line[col: end-1]
286 | return tagname
287 | endfunction
288 |
289 | function! s:SearchMatchTag(tagname)
290 | let tagname = a:tagname
291 | let flags = 'nW'
292 | if tagname[0] == '/'
293 | let start = '<'.tagname[1:]
294 | let end = tagname
295 | let flags = flags.'b'
296 |
297 | " Don't include '<' if search backward
298 | let offset = 1
299 | else
300 | let start = '<'.tagname
301 | let end = '/'.tagname
302 | let offset = 0
303 | endif
304 | let [row, col] = searchpairpos(start, '', end, flags, function('s:IsInCommentOrString'), 0, s:timeout)
305 |
306 | return [row, col, offset]
307 | endfunction
308 |
309 | function! s:IsInCommentOrString()
310 | let names = s:SynNames()
311 | return s:containSyntax(names, '\ccomment\|string$')
312 | endfunction
313 |
314 | function! s:IsInComment()
315 | let names = s:SynNames()
316 | return s:containSyntax(names, '\ccomment$')
317 | endfunction
318 |
319 | function! s:IsInSkipSyntax()
320 | let names = s:SynNames()
321 | if empty(names)
322 | " Don't skip empty syntax to support treesitter
323 | return 0
324 | else
325 | return s:containSyntax(names, s:skip)
326 | \&& !s:containSyntax(names, s:skip_except)
327 | endif
328 | endfunction
329 |
330 | function! s:SynNames()
331 | let lnum = line('.')
332 | let cnum = col('.')
333 | let ids = synstack(lnum, cnum)
334 | let names = map(ids, { _, id -> synIDattr(id, 'name') })
335 |
336 | if empty(names)
337 | let names = s:NearSynNames(lnum)
338 | endif
339 | return names
340 | endfunction
341 |
342 | function! s:NearSynNames(lnum)
343 | let lnum = a:lnum
344 | let cnum = col('$')
345 | let names = []
346 | if empty(names)
347 | " Try next line if empty
348 | let nextlnum = nextnonblank(lnum)
349 | let nextcnum = cnum
350 | let ids = synstack(nextlnum, nextcnum)
351 | let names = map(ids, { _, id -> synIDattr(id, 'name') })
352 | endif
353 | if empty(names)
354 | " Try prev line if empty
355 | let prevlnum = prevnonblank(lnum)
356 | let prevcnum = cnum
357 | let ids = synstack(prevlnum, prevcnum)
358 | let names = map(ids, { _, id -> synIDattr(id, 'name') })
359 | endif
360 |
361 | " Not sure why names become 0 when opening empty file
362 | if empty(names)
363 | return []
364 | else
365 | return names
366 | endif
367 | endfunction
368 |
369 | function! s:containSyntax(names, pat)
370 | if empty(a:pat)
371 | return 0
372 | endif
373 |
374 | for syn in a:names
375 | if syn =~ a:pat
376 | return 1
377 | endif
378 | endfor
379 | endfunction
380 |
381 | function! s:DeleteMatch()
382 | silent! call matchdelete(s:match_id)
383 | silent! call matchdelete(s:match_id+1)
384 | endfunction
385 |
386 | function! matchtag#DisableMatchTag()
387 | let g:loaded_matchtag = 0
388 | autocmd! matchtag
389 | call s:DeleteMatch()
390 | endfunction
391 |
392 | function! matchtag#EnableMatchTag()
393 | let g:loaded_matchtag = 1
394 |
395 | let files = s:GetConfig('files', g:vim_matchtag_files_default)
396 | augroup matchtag
397 | autocmd! matchtag
398 | execute 'autocmd! CursorMoved,CursorMovedI,WinEnter '.files
399 | \.' call matchtag#HighlightMatchingTag()'
400 |
401 | " Clear match for all buffers
402 | autocmd BufWinEnter * call s:DeleteMatch()
403 |
404 | if s:exists_text_changed
405 | execute 'autocmd! TextChanged,TextChangedI '.files
406 | \.' call s:ResetLineCache()'
407 | \.'|call matchtag#HighlightMatchingTag()'
408 |
409 | execute 'autocmd! BufLeave '.files
410 | \.' call s:ResetLineCache()'
411 | endif
412 | augroup END
413 |
414 | silent! doautocmd CursorMoved
415 | endfunction
416 |
417 | function! matchtag#Toggle()
418 | if exists('g:loaded_matchtag') && g:loaded_matchtag
419 | call s:Log('Disable')
420 | call matchtag#DisableMatchTag()
421 | else
422 | call s:Log('Enable')
423 | call matchtag#EnableMatchTag()
424 | endif
425 | endfunction
426 |
427 | function! matchtag#ToggleHighlightCursorOn()
428 | let s:highlight_cursor_on = 1 - s:highlight_cursor_on
429 | silent! doautocmd CursorMoved
430 | endfunction
431 |
432 | function! s:Log(msg)
433 | if s:debug
434 | echom '['.s:name.'] '.a:msg
435 | endif
436 | endfunction
437 |
438 | function! matchtag#Log(msg)
439 | call s:Log(msg)
440 | endfunction
441 |
442 | function! matchtag#ReportTime()
443 | let save_cursor = getcurpos()
444 | call s:ResetLineCache()
445 |
446 | let total = 0
447 | let max = 0
448 | let max_line = 0
449 | for i in range(1, line('$'))
450 | call cursor(i, 1)
451 | let start = reltime()
452 | call matchtag#HighlightMatchingTag()
453 | let end = reltime()
454 | let duration = reltime(start, end)
455 | echom 'line '.i.', time: '.reltimestr(duration)
456 | let value = reltimefloat(duration)
457 | let total += value
458 | if max < value
459 | let max = value
460 | let max_line = i
461 | endif
462 | endfor
463 | let ave = total / line('$')
464 |
465 | call setpos('.', save_cursor)
466 | echom 'report Ave: '.string(ave)
467 | \.' Max: '.string(max).' on line '.max_line
468 | endfunction
469 |
470 |
471 | "}}}
472 | " vim: fdm=marker
473 |
--------------------------------------------------------------------------------
/plugin/matchtag.vim:
--------------------------------------------------------------------------------
1 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
2 | " Vim plugin for highlighting matching tags
3 | " Maintainer: leafOfTree
4 | " CREDITS: Inspired by matchParen.
5 | "
6 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
7 |
8 | " Exit quickly when:
9 | " - this plugin was already loaded (or disabled)
10 | " - when "compatiable" is set
11 | " - the "CursorMoved" autocmd event is not available.
12 | if exists('g:loaded_matchtag')
13 | \ || exists('*s:HighlightMatchingTag')
14 | \ || !exists('##CursorMoved')
15 | \ || &cp
16 | finish
17 | endif
18 |
19 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
20 | "
21 | " Config {{{
22 | "
23 | """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
24 | function! s:GetConfig(name, default)
25 | let name = 'g:vim_matchtag_'.a:name
26 | return exists(name) ? eval(name) : a:default
27 | endfunction
28 |
29 | let s:mapping_toggle = s:GetConfig('mapping_toggle', '')
30 | let s:mapping_toggle_highlight_cursor_on = s:GetConfig('mapping_toggle_highlight_cursor_on',
31 | \s:GetConfig('mapping_both', ''))
32 | let s:enable_by_default = s:GetConfig('enable_by_default', 1)
33 |
34 | " Use global variable so it can also be used by scripts in autoload
35 | let g:vim_matchtag_files_default = '*.html,*.xml,*.js,*.jsx,*.ts,*.tsx,*.vue,*.svelte,*.jsp,*.php,*.erb,*.astro'
36 | let s:files = s:GetConfig('files', g:vim_matchtag_files_default)
37 | "}}}
38 |
39 | " Highlight
40 | highlight default link matchTag Visual
41 | highlight default link matchTagError Error
42 |
43 | " Command
44 | command! MatchTagToggle call matchtag#Toggle()
45 | command! MatchTagToggleHighlightCursorOn call matchtag#ToggleHighlightCursorOn()
46 | command! MatchTagToggleBoth call matchtag#ToggleHighlightCursorOn()
47 |
48 | " Mapping
49 | augroup matchtag-maping
50 | autocmd! matchtag-maping
51 | if !empty(s:mapping_toggle)
52 | execute 'autocmd BufNewFile,BufRead '.s:files
53 | \.' nnoremap '
54 | \.s:mapping_toggle.' :MatchTagToggle'
55 | endif
56 | if !empty(s:mapping_toggle_highlight_cursor_on)
57 | execute 'autocmd BufNewFile,BufRead '.s:files
58 | \.' nnoremap '
59 | \.s:mapping_toggle_highlight_cursor_on.' :MatchTagToggleHighlightCursorOn'
60 | endif
61 | augroup END
62 |
63 | function! s:ShouldEnableFile()
64 | return stridx(s:files, '*.'.&filetype) != -1 || stridx(s:files, expand('%:t')) != -1
65 | endfunction
66 |
67 | " Enable by default for specific files
68 | if s:enable_by_default
69 | if s:ShouldEnableFile()
70 | call matchtag#EnableMatchTag()
71 | else
72 | execute 'autocmd BufNewFile,BufRead '.s:files
73 | \.' ++once call matchtag#EnableMatchTag()'
74 | endif
75 | endif
76 | " vim: fdm=marker
77 |
--------------------------------------------------------------------------------