fix(runtime): let matchit and matchparen skips fallback on treesitter captures

When treesitter is enabled, by default syntax groups are not defined, but these
groups are used to identify where to skip matches in matchit and matchparen.

This patch does three things:
1. If syntax is enabled regardless of treesitter (`vim.bo.syntax='on'`):
   Use original implementation.
2. If treesitter is enabled and syntax is not:
   Match the syntax groups (i.e. `comment\|string`) against treesitter captures
   to check for skipped groups.
3. Add an explicit treesitter syntax for marking captures to skip:
   matchit uses `b:match_skip` to determine what counts as skippable
   Where 's:comment\|string' uses a match of the named syntax groups against
   a regex match of comment\|string, 't:comment\|string' now uses vim regex
   to match against the names of the treesitter capture groups.
This commit is contained in:
Emilia Simmons 2024-12-15 13:28:16 -05:00
parent 17383870dd
commit de68c14312
3 changed files with 15 additions and 1 deletions

View File

@ -222,6 +222,7 @@ function matchit#Match_wrapper(word, forward, mode) range
let view = winsaveview()
call cursor(0, curcol + 1)
if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
\ || skip =~ 'v:lua.vim.treesitter' && !exists('b:ts_highlight')
let skip = "0"
else
execute "if " .. skip .. "| let skip = '0' | endif"
@ -678,6 +679,7 @@ fun! matchit#MultiMatch(spflag, mode)
let middlepat = substitute(middlepat, ',', '\\|', 'g')
if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
\ || skip =~ 'v:lua.vim.treesitter' && !exists('b:ts_highlight')
let skip = '0'
else
try
@ -760,10 +762,16 @@ endfun
" S:foo becomes (current syntax item) !~ foo
" r:foo becomes (line before cursor) =~ foo
" R:foo becomes (line before cursor) !~ foo
" t:foo becomes (current treesitter captures) =~ foo
" T:foo becomes (current treesitter captures) !~ foo
fun! s:ParseSkip(str)
let skip = a:str
if skip[1] == ":"
if skip[0] ==# "s"
if skip[0] ==# "t" || skip[0] ==# "s" && &syntax != 'on' && exists("b:ts_highlight")
let skip = "match(v:lua.vim.treesitter.get_captures_at_cursor(), '" .. strpart(skip,2) .. "') != -1"
elseif skip[0] ==# "T" || skip[0] ==# "S" && &syntax != 'on' && exists("b:ts_highlight")
let skip = "match(v:lua.vim.treesitter.get_captures_at_cursor(), '" .. strpart(skip,2) .. "') == -1"
elseif skip[0] ==# "s"
let skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" ..
\ strpart(skip,2) .. "'"
elseif skip[0] ==# "S"

View File

@ -237,6 +237,8 @@ supported by matchit.vim:
S:foo becomes (current syntax item) !~ foo
r:foo becomes (line before cursor) =~ foo
R:foo becomes (line before cursor) !~ foo
t:foo becomes (current treesitter captures) =~ foo
T:foo becomes (current treesitter captures) !~ foo
(The "s" is meant to suggest "syntax", and the "r" is meant to suggest
"regular expression".)

View File

@ -109,6 +109,10 @@ func s:Highlight_Matching_Pair()
if !has("syntax") || !exists("g:syntax_on")
let s_skip = "0"
elseif exists("b:ts_highlight") && &syntax != 'on'
let s_skip = "match(v:lua.vim.treesitter.get_captures_at_cursor(), '"
\ .. 'string\|character\|singlequote\|escape\|symbol\|comment'
\ .. "') != -1"
else
" Build an expression that detects whether the current cursor position is
" in certain syntax types (string, comment, etc.), for use as