@@ -1536,18 +1536,28 @@ H.get_matched_range_pairs_builtin = function(captures)
15361536 -- Get parser (LanguageTree) at cursor (important for injected languages)
15371537 local pos = vim .api .nvim_win_get_cursor (0 )
15381538 local lang_tree = parser :language_for_range ({ pos [1 ] - 1 , pos [2 ], pos [1 ] - 1 , pos [2 ] })
1539- local lang = lang_tree :lang ()
1540-
1541- -- Get query file depending on the local language
1542- local query = vim .treesitter .query .get (lang , ' textobjects' )
1543- if query == nil then H .error_treesitter (' query' ) end
15441539
1540+ local missing_query_langs = {}
15451541 -- Compute matched ranges for both outer and inner captures
1542+ -- Maybe go up parent trees to work with injected languages
15461543 local outer_ranges , inner_ranges = {}, {}
1547- for _ , tree in ipairs (lang_tree :trees ()) do
1548- local root = tree :root ()
1549- vim .list_extend (outer_ranges , H .get_match_ranges_builtin (root , buf_id , query , captures .outer :sub (2 )))
1550- vim .list_extend (inner_ranges , H .get_match_ranges_builtin (root , buf_id , query , captures .inner :sub (2 )))
1544+ while (vim .tbl_isempty (inner_ranges ) or vim .tbl_isempty (outer_ranges )) and lang_tree ~= nil do
1545+ local lang = lang_tree :lang ()
1546+ -- Get query file depending on the local language
1547+ local query = vim .treesitter .query .get (lang , ' textobjects' )
1548+
1549+ if query ~= nil then
1550+ for _ , tree in ipairs (lang_tree :trees ()) do
1551+ local root = tree :root ()
1552+ vim .list_extend (outer_ranges , H .get_match_ranges_builtin (root , buf_id , query , captures .outer :sub (2 )))
1553+ vim .list_extend (inner_ranges , H .get_match_ranges_builtin (root , buf_id , query , captures .inner :sub (2 )))
1554+ end
1555+ end
1556+ if query == nil then missing_query_langs [lang ] = true end
1557+
1558+ -- `LanguageTree:parent()` was added in Neovim<0.10
1559+ -- TODO: Drop extra check after compatibility with Neovim=0.9 is dropped
1560+ lang_tree = lang_tree .parent and lang_tree :parent () or nil
15511561 end
15521562
15531563 -- Match outer and inner ranges: for each outer range pick the biggest inner
@@ -1556,6 +1566,11 @@ H.get_matched_range_pairs_builtin = function(captures)
15561566 for i , outer in ipairs (outer_ranges ) do
15571567 res [i ] = { outer = outer , inner = H .get_biggest_nested_range (inner_ranges , outer ) }
15581568 end
1569+
1570+ if vim .tbl_isempty (res ) and not vim .tbl_isempty (missing_query_langs ) then
1571+ H .error_treesitter (' query' , vim .tbl_keys (missing_query_langs ))
1572+ end
1573+
15591574 return res
15601575end
15611576
@@ -1601,11 +1616,18 @@ H.get_biggest_nested_range = function(ranges, parent)
16011616 return best_range
16021617end
16031618
1604- H .error_treesitter = function (failed_get )
1619+ H .error_treesitter = function (failed_get , langs )
16051620 local buf_id , ft = vim .api .nvim_get_current_buf (), vim .bo .filetype
1606- local has_lang , lang = pcall (vim .treesitter .language .get_lang , ft )
1607- lang = has_lang and lang or ft
1608- local msg = string.format (' Can not get %s for buffer %d and language "%s".' , failed_get , buf_id , lang )
1621+ if langs == nil then
1622+ local has_lang , ft_lang = pcall (vim .treesitter .language .get_lang , ft )
1623+ -- `vim.treesitter.language.get_lang()` defaults to `ft` on Neovim>0.11
1624+ -- TODO: Drop check after compatibility with Neovim=0.10 is dropped
1625+ langs = (has_lang and ft_lang ~= nil ) and { ft_lang } or { ft }
1626+ end
1627+ table.sort (langs )
1628+ local langs_str = table.concat (vim .tbl_map (vim .inspect , langs ), ' , ' )
1629+ local langs_noun = # langs == 1 and ' language' or ' languages'
1630+ local msg = string.format (' Can not get %s for buffer %d and %s %s.' , failed_get , buf_id , langs_noun , langs_str )
16091631 H .error (msg )
16101632end
16111633
0 commit comments