Skip to content

Commit b6f8757

Browse files
committed
Support for keyword based syntax highlighting (much faster)
See the following issues on GitHub: - #68 - #80 Please note that right now this 'feature' is not integrated with the "accelerated Python syntax highlighting" feature, because I'm considering ripping that out and replacing it with a *fast* Vim script implementation (if I can build one :-).
1 parent 5f17a01 commit b6f8757

File tree

3 files changed

+104
-31
lines changed

3 files changed

+104
-31
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,18 @@ By setting this option to true (1) you enable asynchronous tags file updates. Go
7272

7373
Note that asynchronous updates on Windows currently require the installation of my [vim-shell] [shell] plug-in (for obscure technical reasons that I want to fix but don't know how yet).
7474

75+
### The `g:easytags_syntax_keyword` option
76+
77+
When you look into how the dynamic syntax highlighting in the vim-easytags plug-in works you'll realize that vim-easytags is really abusing Vim's syntax highlighting engine. This can cause Vim to slow down to a crawl, depending on how big your tags files are. To make things worse in Vim 7.4 a new regex engine was introduced which exacerbates the problem (the patterns generated by vim-easytags bring out the worst of the new regex engine).
78+
79+
Since version 3.6 the vim-easytags plug-in tries to squeeze as much performance as possible out of Vim by using keyword highlighting where this is possible without sacrificing accuracy. If your Vim's syntax highlighting is still too slow you can add the following to your [vimrc script] [vimrc]:
80+
81+
let g:easytags_syntax_keyword = 'always'
82+
83+
The default value of this option is 'auto' which means to use keyword highlighting where this is possible without sacrificing accuracy. By changing it to 'always' you're telling vim-easytags to sacrifice accuracy in order to gain performance. Try it out and see what works best for you.
84+
85+
Please note that right now this 'feature' is not integrated with the "accelerated Python syntax highlighting" feature, because I'm considering ripping that out and replacing it with a *fast* Vim script implementation.
86+
7587
### The `g:easytags_languages` option
7688

7789
Exuberant Ctags supports many languages and can be extended via regular expression patterns, but for some languages separate tools with ctags-compatible output exist (e.g. [jsctags] [jsctags] for Javascript). To use these, the executable and its arguments must be configured:

autoload/xolox/easytags.vim

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
" Vim script
22
" Author: Peter Odding <[email protected]>
3-
" Last Change: July 8, 2014
3+
" Last Change: July 9, 2014
44
" URL: http://peterodding.com/code/vim/easytags/
55

6-
let g:xolox#easytags#version = '3.5'
6+
let g:xolox#easytags#version = '3.6'
77

88
" Plug-in initialization. {{{1
99

@@ -312,18 +312,45 @@ function! xolox#easytags#highlight() " {{{2
312312
endif
313313
let matches = filter(copy(taglist), filter)
314314
if matches != []
315-
" Convert matched tags to :syntax command and execute it.
316-
let matches = xolox#misc#list#unique(map(matches, 'xolox#misc#escape#pattern(get(v:val, "name"))'))
317-
let pattern = tagkind.pattern_prefix . '\%(' . join(matches, '\|') . '\)' . tagkind.pattern_suffix
318-
let template = 'syntax match %s /%s/ containedin=ALLBUT,%s'
319-
let command = printf(template, hlgroup_tagged, escape(pattern, '/'), xolox#easytags#syntax_groups_to_ignore())
320-
call xolox#misc#msg#debug("easytags.vim %s: Executing command '%s'.", g:xolox#easytags#version, command)
321-
try
322-
execute command
323-
catch /^Vim\%((\a\+)\)\=:E339/
324-
let msg = "easytags.vim %s: Failed to highlight %i %s tags because pattern is too big! (%i KB)"
325-
call xolox#misc#msg#warn(msg, g:xolox#easytags#version, len(matches), tagkind.hlgroup, len(pattern) / 1024)
326-
endtry
315+
" Convert matched tags to :syntax commands and execute them.
316+
let use_keywords_when = xolox#misc#option#get('easytags_syntax_keyword', 'auto')
317+
let tagkind_has_patterns = !(empty(tagkind.pattern_prefix) && empty(tagkind.pattern_suffix))
318+
if use_keywords_when == 'always' || (use_keywords_when == 'auto' && !tagkind_has_patterns)
319+
" Vim's ":syntax keyword" command doesn't use the regular
320+
" expression engine and the resulting syntax highlighting is
321+
" therefor much faster. Because of this we use the syntax
322+
" keyword command when 1) we can do so without sacrificing
323+
" accuracy or 2) the user explicitly chose to sacrifice
324+
" accuracy in order to make the highlighting faster.
325+
let keywords = []
326+
for tag in matches
327+
if s:is_keyword_compatible(tag)
328+
call add(keywords, tag.name)
329+
endif
330+
endfor
331+
if !empty(keywords)
332+
let template = 'syntax keyword %s %s containedin=ALLBUT,%s'
333+
let command = printf(template, hlgroup_tagged, join(keywords), xolox#easytags#syntax_groups_to_ignore())
334+
call xolox#misc#msg#debug("easytags.vim %s: Executing command '%s'.", g:xolox#easytags#version, command)
335+
execute command
336+
" Remove the tags that we just highlighted from the list of
337+
" tags that still need to be highlighted.
338+
call filter(matches, "!s:is_keyword_compatible(v:val)")
339+
endif
340+
endif
341+
if !empty(matches)
342+
let matches = xolox#misc#list#unique(map(matches, 'xolox#misc#escape#pattern(get(v:val, "name"))'))
343+
let pattern = tagkind.pattern_prefix . '\%(' . join(matches, '\|') . '\)' . tagkind.pattern_suffix
344+
let template = 'syntax match %s /%s/ containedin=ALLBUT,%s'
345+
let command = printf(template, hlgroup_tagged, escape(pattern, '/'), xolox#easytags#syntax_groups_to_ignore())
346+
call xolox#misc#msg#debug("easytags.vim %s: Executing command '%s'.", g:xolox#easytags#version, command)
347+
try
348+
execute command
349+
catch /^Vim\%((\a\+)\)\=:E339/
350+
let msg = "easytags.vim %s: Failed to highlight %i %s tags because pattern is too big! (%i KB)"
351+
call xolox#misc#msg#warn(msg, g:xolox#easytags#version, len(matches), tagkind.hlgroup, len(pattern) / 1024)
352+
endtry
353+
endif
327354
endif
328355
endif
329356
endfor
@@ -345,6 +372,13 @@ function! xolox#easytags#highlight() " {{{2
345372
endtry
346373
endfunction
347374

375+
function! s:is_keyword_compatible(tag)
376+
let name = get(a:tag, 'name', '')
377+
if !empty(name)
378+
return name =~ '^\k\+$' && len(name) <= 80
379+
endif
380+
endfunction
381+
348382
" Public supporting functions (might be useful to others). {{{1
349383

350384
function! xolox#easytags#get_tagsfile() " {{{2
@@ -391,7 +425,7 @@ function! xolox#easytags#syntax_groups_to_ignore() " {{{2
391425
" This happens when a group wildcard doesn't match *anything*. Why does Vim
392426
" always have to make everything so complicated? :-(
393427
let groups = ['.*String.*', '.*Comment.*']
394-
for group_name in ['cIncluded', 'cCppOut2', 'cCppInElse2', 'cCppOutIf2']
428+
for group_name in ['cIncluded', 'cCppOut2', 'cCppInElse2', 'cCppOutIf2', 'pythonDocTest', 'pythonDocTest2']
395429
if hlexists(group_name)
396430
call add(groups, group_name)
397431
endif
@@ -433,10 +467,10 @@ endfunction
433467

434468
function! xolox#easytags#define_tagkind(object) " {{{2
435469
if !has_key(a:object, 'pattern_prefix')
436-
let a:object.pattern_prefix = '\C\<'
470+
let a:object.pattern_prefix = ''
437471
endif
438472
if !has_key(a:object, 'pattern_suffix')
439-
let a:object.pattern_suffix = '\>'
473+
let a:object.pattern_suffix = ''
440474
endif
441475
if !has_key(s:tagkinds, a:object.filetype)
442476
let s:tagkinds[a:object.filetype] = []

doc/easytags.txt

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,21 @@ Contents ~
1212
4. Options |easytags-options|
1313
1. The |g:easytags_cmd| option
1414
2. The |g:easytags_async| option
15-
3. The |g:easytags_languages| option
16-
4. The |g:easytags_file| option
17-
5. The |g:easytags_dynamic_files| option
18-
6. The |g:easytags_by_filetype| option
19-
7. The |g:easytags_events| option
20-
8. The |g:easytags_always_enabled| option
21-
9. The |g:easytags_on_cursorhold| option
22-
10. The |g:easytags_updatetime_min| option
23-
11. The |g:easytags_auto_update| option
24-
12. The |g:easytags_auto_highlight| option
25-
13. The |g:easytags_autorecurse| option
26-
14. The |g:easytags_include_members| option
27-
15. The |g:easytags_resolve_links| option
28-
16. The |g:easytags_suppress_ctags_warning| option
15+
3. The |g:easytags_syntax_keyword| option
16+
4. The |g:easytags_languages| option
17+
5. The |g:easytags_file| option
18+
6. The |g:easytags_dynamic_files| option
19+
7. The |g:easytags_by_filetype| option
20+
8. The |g:easytags_events| option
21+
9. The |g:easytags_always_enabled| option
22+
10. The |g:easytags_on_cursorhold| option
23+
11. The |g:easytags_updatetime_min| option
24+
12. The |g:easytags_auto_update| option
25+
13. The |g:easytags_auto_highlight| option
26+
14. The |g:easytags_autorecurse| option
27+
15. The |g:easytags_include_members| option
28+
16. The |g:easytags_resolve_links| option
29+
17. The |g:easytags_suppress_ctags_warning| option
2930
5. Customizing the easytags plug-in |customizing-easytags-plug-in|
3031
1. Passing custom command line arguments to Exuberant Ctags |easytags-passing-custom-command-line-arguments-to-exuberant-ctags|
3132
2. Update & highlight tags immediately after save |easytags-update-highlight-tags-immediately-after-save|
@@ -203,6 +204,32 @@ Note that asynchronous updates on Windows currently require the installation of
203204
my vim-shell [12] plug-in (for obscure technical reasons that I want to fix but
204205
don't know how yet).
205206

207+
-------------------------------------------------------------------------------
208+
The *g:easytags_syntax_keyword* option
209+
210+
When you look into how the dynamic syntax highlighting in the vim-easytags
211+
plug-in works you'll realize that vim-easytags is really abusing Vim's syntax
212+
highlighting engine. This can cause Vim to slow down to a crawl, depending on
213+
how big your tags files are. To make things worse in Vim 7.4 a new regex engine
214+
was introduced which exacerbates the problem (the patterns generated by vim-
215+
easytags bring out the worst of the new regex engine).
216+
217+
Since version 3.6 the vim-easytags plug-in tries to squeeze as much performance
218+
as possible out of Vim by using keyword highlighting where this is possible
219+
without sacrificing accuracy. If your Vim's syntax highlighting is still too
220+
slow you can add the following to your |vimrc| script:
221+
>
222+
let g:easytags_syntax_keyword = 'always'
223+
<
224+
The default value of this option is 'auto' which means to use keyword
225+
highlighting where this is possible without sacrificing accuracy. By changing
226+
it to 'always' you're telling vim-easytags to sacrifice accuracy in order to
227+
gain performance. Try it out and see what works best for you.
228+
229+
Please note that right now this 'feature' is not integrated with the
230+
"accelerated Python syntax highlighting" feature, because I'm considering
231+
ripping that out and replacing it with a _fast_ Vim script implementation.
232+
206233
-------------------------------------------------------------------------------
207234
The *g:easytags_languages* option
208235

0 commit comments

Comments
 (0)