Syntax: Fasten highlighting, from 200ms to 20ms for first screen update

Problem:

The loading of a .md file was slow due to multiple nested lookback.
It is advised in vim help to prefer \zs, see :h /\@<
Anyway, it is useless to nest them.

089.080  000.085  000.085: sourcing /home/mtourneb/.vim/after/syntax/vimwiki.vim
089.264  005.184: opening buffers
089.322  000.058: BufEnter autocommands
089.323  000.001: editing files in windows
089.414  000.091: VimEnter autocommands
089.415  000.001: before starting main loop
303.698  214.283: first screen update
303.700  000.002: --- VIM STARTED ---

Solution:

Remove the function s:expand_delimiter in vars.vim.
It was doing a duplicate job with vimwiki#u#hi_expand_regex
And ... well avoid lookback as much as possible

091.784  000.087  000.087: sourcing /home/mtourneb/.vim/after/syntax/vimwiki.vim
091.991  006.034: opening buffers
092.050  000.059: BufEnter autocommands
092.052  000.002: editing files in windows
092.172  000.120: VimEnter autocommands
092.173  000.001: before starting main loop
112.574  020.401: first screen update
112.578  000.004: --- VIM STARTED ---
This commit is contained in:
Tinmarino
2023-03-18 01:45:02 -03:00
parent f4bd841a4c
commit 72d02207b0
5 changed files with 46 additions and 56 deletions
+27 -17
View File
@@ -295,13 +295,19 @@ endfunction
function! vimwiki#u#get_punctuation_string() abort function! vimwiki#u#get_punctuation_string() abort
" Faster " Faster
" See: https://github.github.com/gfm/#ascii-punctuation-character " See: https://github.github.com/gfm/#ascii-punctuation-character
return '!"#$%&''()*+,-./:;<=>?@\[\\\]^`{}|~' " res = '!"#$%&''()*+,-./:;<=>?@\[\\\]^`{}|~'
" But I removed the * as it is treated as a special case
return '!"#$%&''()+,-./:;<=>?@\[\\\]^`{}|~'
endfunction endfunction
function! vimwiki#u#hi_expand_regex(lst) abort function! vimwiki#u#hi_expand_regex(lst) abort
" Helper: Expand regex from reduced typeface delimiters " Helper: Expand regex from reduced typeface delimiters
" :param: list<list,delimiters>> with reduced regex " :param: list<list,delimiters>> with reduced regex
" 1: Left delimiter
" 2: right delimiter
" 3: possible characters to ignore (default '$^' => never match)
" 4: can multiply delimiter (boolean) (default 0 => do not repeat)
" Return: list with extended regex delimiters (not inside a word) " Return: list with extended regex delimiters (not inside a word)
" -- [['\*_', '_\*']] -> [['\*_\S\@=', '\S\@<=_\*\%(\s\|$\)\@=']] " -- [['\*_', '_\*']] -> [['\*_\S\@=', '\S\@<=_\*\%(\s\|$\)\@=']]
" Note: For purposes of this definition, the beginning and the end of the line count as Unicode whitespace. " Note: For purposes of this definition, the beginning and the end of the line count as Unicode whitespace.
@@ -313,42 +319,46 @@ function! vimwiki#u#hi_expand_regex(lst) abort
for a_delimiter in a:lst for a_delimiter in a:lst
let r_left_del = a_delimiter[0] let r_left_del = a_delimiter[0]
let r_right_del = a_delimiter[1] let r_right_del = a_delimiter[1]
let r_repeat_del = len(a_delimiter) >= 3 ? a_delimiter[2] : '$^'
let b_can_mult = len(a_delimiter) >= 4 ? a_delimiter[3] : 0
" Craft the repeatable middle
let r_mult = b_can_mult ? '\+' : ''
let r_left_repeat = '\%(\%(' . r_left_del . '\)' . r_mult . '\)'
let r_right_repeat = '\%(\%(' . r_right_del . '\)' . r_mult . '\)'
let r_unescaped_repeat = '\%(\\\|\\\@<!' . r_repeat_del . '\)'
" Regex Start: " Regex Start:
" Left-Flanking is not followed by space (or need of line) " Left-Flanking is not followed by space (or need of line)
let r_left_prefix = '\%(^\|[[:space:]]\@<=\)'
let r_left_prefix = '\\\@<!'
" -- not followed by Unicode whitespace,
let r_left_suffix = '\%([[:space:]\n]\@!\)'
" Left Case1: not followed by punctuation " Left Case1: not followed by punctuation, start with blacklist
let r_left_suffix1 = '\%(\%([[:space:]\n' . punctuation . ']\)\@!\)'
" -- Can escape the leftflank " -- Can escape the leftflank
let r_left_prefix1 = '\%(^\|\\\@<!\)' let r_left_prefix1 = '\%(^\|' . r_unescaped_repeat . '\@<!\)'
let r_left_suffix1 = '\%(\%([[:space:]\n' . punctuation . ']\|' . r_unescaped_repeat . '\)\@!\)'
" Left Case2: followed by punctuation so must be preceded by Unicode whitespace or start of line or a punctuation character. " Left Case2: followed by punctuation so must be preceded by whitelisted Unicode whitespace or start of line or a punctuation character.
let r_left_suffix2 = '\%([' . punctuation . ']\@=\)'
let r_left_prefix2 = '\%(\%(^\|[[:space:]\n' . punctuation . ']\)\@<=\)' let r_left_prefix2 = '\%(\%(^\|[[:space:]\n' . punctuation . ']\)\@<=\)'
let r_left_suffix2 = '\%([' . punctuation . ']\@=\)'
" Left Concatenate " Left Concatenate
let r_start = '\%(' . r_left_prefix1 . r_left_del . r_left_suffix1 let r_start = '\%(' . r_left_prefix1 . '\zs' . r_left_repeat . '\ze' . r_left_suffix1
let r_start .= '\|' . r_left_prefix2 . r_left_del . r_left_suffix2 . '\)' let r_start .= '\|' . r_left_prefix2 . '\zs' . r_left_repeat . '\ze' . r_left_suffix2 . '\)'
" Regex End: " Regex End:
" not preceded by Unicode whitespace " not preceded by Unicode whitespace
let r_right_prefix = '\(^\|[^[:space:]]\@<=\)' let r_right_prefix = '\(^\|[^[:space:]]\@<=\)'
" Right Case1: not preceded by a punctuation character (or start of line) " Right Case1: not preceded by a punctuation character (or start of line)
let r_right_prefix1 = '\%(\%(^\|[^[:space:]' . punctuation . ']\)\@<=\)' let r_right_prefix1 = '\%(^\|\%([[:space:]\n' . punctuation . ']\|' . r_unescaped_repeat . '\)\@<!\)'
let r_right_suffix1 = '' let r_right_suffix1 = '\%($\|' . r_unescaped_repeat . '\@!\)'
" Right Case2: preceded by a punctuation character and followed by Unicode whitespace or end of line or a punctuation character " Right Case2: preceded by a punctuation character and followed by Unicode whitespace or end of line or a punctuation character
let r_right_prefix2 = '\%([' . punctuation . ']\@<=\)' let r_right_prefix2 = '\%([' . punctuation . ']\@<=\)'
let r_right_suffix2 = '\%(\%($\|[[:space:]' . punctuation . ']\)\@<=\)' let r_right_suffix2 = '\%(\%($\|[[:space:]' . punctuation . ']\)\@<=\)'
" Right Concatenate " Right Concatenate
let r_end = '\%(' . r_right_prefix1 . r_right_del . r_right_suffix1 let r_end = '\%(' . r_right_prefix1 . r_right_repeat . r_right_suffix1
let r_end .= '\|' . r_right_prefix2 . r_right_del . r_right_suffix2 . '\)' let r_end .= '\|' . r_right_prefix2 . r_right_repeat . r_right_suffix2 . '\)'
call add(res, [r_start, r_end]) call add(res, [r_start, r_end])
endfor endfor
+8 -35
View File
@@ -753,19 +753,19 @@ function! s:get_markdown_syntaxlocal() abort
\ 'symH': {'type': type(0), 'default': 0}, \ 'symH': {'type': type(0), 'default': 0},
\ 'typeface': {'type': type({}), 'default': { \ 'typeface': {'type': type({}), 'default': {
\ 'bold': vimwiki#u#hi_expand_regex([ \ 'bold': vimwiki#u#hi_expand_regex([
\ [s:expand_delimiter('__', 1), s:expand_delimiter('__', 1)], \ ['__', '__', '[_*]', 1],
\ [s:expand_delimiter('\*\*', 1), s:expand_delimiter('\*\*', 1)], \ ['\*\*', '\*\*', '[_*]', 1],
\ ]), \ ]),
\ 'italic': vimwiki#u#hi_expand_regex([ \ 'italic': vimwiki#u#hi_expand_regex([
\ [s:expand_delimiter('_', 0), s:expand_delimiter('_', 0)], \ ['_', '_', '[_*]', 0],
\ [s:expand_delimiter('\*', 0), s:expand_delimiter('\*', 0)], \ ['\*', '\*', '[_*]', 0],
\ [s:expand_delimiter('\*_', 1), s:expand_delimiter('_\*', 1)], \ ['\*_', '_\*', '[_*]', 1],
\ [s:expand_delimiter('_\*', 1), s:expand_delimiter('\*_', 1)], \ ['_\*', '\*_', '[_*]', 1],
\ ]), \ ]),
\ 'underline': vimwiki#u#hi_expand_regex([]), \ 'underline': vimwiki#u#hi_expand_regex([]),
\ 'bold_italic': vimwiki#u#hi_expand_regex([ \ 'bold_italic': vimwiki#u#hi_expand_regex([
\ [s:expand_delimiter('\*\*\*', 1), s:expand_delimiter('\*\*\*', 1)], \ ['___', '___', '[_*]', 1],
\ [s:expand_delimiter('___', 1), s:expand_delimiter('___', 1)], \ ['\*\*\*', '\*\*\*', '[_*]', 1],
\ ]), \ ]),
\ 'code': [ \ 'code': [
\ ['\%(^\|[^`\\]\)\@<=`\%($\|[^`]\)\@=', \ ['\%(^\|[^`\\]\)\@<=`\%($\|[^`]\)\@=',
@@ -1344,33 +1344,6 @@ function! s:normalize_syntax_settings(syntax) abort
endfunction endfunction
function! s:expand_delimiter(delim, b_can_mult) abort
" Helper: From a delimiter to the lookhead defensive version
" See: also vimwiki#u#hi_expand_regex
" TODO: get some cache to avoid recrafting the same prefix always
" Clause: if nothing, return nothing
if len(a:delim) == 0
return '\%(\)'
endif
" let c_start = a:delim[0] ==# '\' ? a:delim[0:1] : a:delim[0]
" let c_end = (len(a:delim) > 1 && a:delim[-2:-2] ==# '\') ? a:delim[-2:-1] : a:delim[-1:]
" Hardcode for markdown
let c_start = '[_*]'
let c_end = '[_*]'
let rx_mult = a:b_can_mult ? '\+' : ''
let rx_start = '\%(^\|\%(\\\@<!' . c_start . '\)\@<!\)'
let rx_middle = '\%(\%(' . a:delim . '\)' . rx_mult . '\)'
let rx_end = '\%($\|\%(\\\@<!' . c_end . '\)\@!\)'
let res = '\%(' . rx_start . rx_middle . rx_end . '\)'
return res
endfunction
" ---------------------------------------------------------- " ----------------------------------------------------------
" 4. Command (exported) {{{1 " 4. Command (exported) {{{1
" ---------------------------------------------------------- " ----------------------------------------------------------
+6 -1
View File
@@ -7,10 +7,16 @@ Execute (Setup search testing wrapper):
Log 'Cheating for old vim version, do not want to reverse bug' Log 'Cheating for old vim version, do not want to reverse bug'
return return
endif endif
" Execute command and grab output
redir => output redir => output
silent execute a:search_command silent execute a:search_command
redir END redir END
" The location list should not be empty
Assert !empty(getloclist(0)), a:test_name.": no location list result" Assert !empty(getloclist(0)), a:test_name.": no location list result"
" The location list should contains entries
Assert match(output, '\d of \d') > -1, a:test_name.": no result message" Assert match(output, '\d of \d') > -1, a:test_name.": no result message"
" Tests that VimwikiSearch is quoting the pattern correctly. " Tests that VimwikiSearch is quoting the pattern correctly.
@@ -30,7 +36,6 @@ Execute (Search test wiki):
AssertEqual "= Test Wiki =", getline(1) AssertEqual "= Test Wiki =", getline(1)
AssertEqual "vimwiki", &filetype AssertEqual "vimwiki", &filetype
call TestSearch('VimwikiSearch foo', 'pattern with no spaces') call TestSearch('VimwikiSearch foo', 'pattern with no spaces')
call TestSearch('VimwikiSearch foo bar', 'pattern with spaces') call TestSearch('VimwikiSearch foo bar', 'pattern with spaces')
call TestSearch('VimwikiSearch foo\bar', 'pattern with ''\''') call TestSearch('VimwikiSearch foo\bar', 'pattern with ''\''')
+3 -1
View File
@@ -37,6 +37,7 @@ Given vimwiki (Markdown typeface with escape sequence #1044: _ __ * ** {{{2):
a ~~staaill deleted~~ Del 9 a ~~staaill deleted~~ Del 9
$$Eq\$$ uation follows$ Math 10 $$Eq\$$ uation follows$ Math 10
`code \` not finished inline` Code 11 `code \` not finished inline` Code 11
012345678901234567890
Execute (Set syntax markdown): Execute (Set syntax markdown):
call SetSyntax('markdown') call SetSyntax('markdown')
@@ -48,7 +49,8 @@ Execute (Assert Syntax of escape typeface):
AssertEqual 'VimwikiBold4' , SyntaxAt(4, 14) . 4 AssertEqual 'VimwikiBold4' , SyntaxAt(4, 14) . 4
AssertEqual 'VimwikiItalic5' , SyntaxAt(5, 14) . 5 AssertEqual 'VimwikiItalic5' , SyntaxAt(5, 14) . 5
" See: #1303 where an escape start can close the region " See: #1303 where an escape start can close the region
AssertEqual '6' , SyntaxAt(6, 14) . 6 " Fixed removing vars.vim::expand_delimiter
AssertEqual 'VimwikiItalic6' , SyntaxAt(6, 14) . 6
AssertEqual 'VimwikiSuperScript7', SyntaxAt(7, 14) . 7 AssertEqual 'VimwikiSuperScript7', SyntaxAt(7, 14) . 7
AssertEqual 'VimwikiSubScript8' , SyntaxAt(8, 14) . 8 AssertEqual 'VimwikiSubScript8' , SyntaxAt(8, 14) . 8
AssertEqual 'VimwikiDelText9' , SyntaxAt(9, 14) . 9 AssertEqual 'VimwikiDelText9' , SyntaxAt(9, 14) . 9
+2 -2
View File
@@ -623,8 +623,8 @@ Execute (Set Markdown):
Execute (Assert Syntax): Execute (Assert Syntax):
CommentLine 'Empty emphasis' CommentLine 'Empty emphasis'
AssertEqual '', SyntaxAt(1, 1) AssertEqual '1', SyntaxAt(1, 1) . 1
AssertEqual '', SyntaxAt(2, 1) AssertEqual '2', SyntaxAt(2, 1) . 2
Given vimwiki (Typeface: https://github.github.com/gfm/#example-446): Given vimwiki (Typeface: https://github.github.com/gfm/#example-446):