Skip to content

Commit 7102a3a

Browse files
committed
feat(enhancement): support nearest parent
Fixes #453
1 parent 153a076 commit 7102a3a

File tree

4 files changed

+90
-19
lines changed

4 files changed

+90
-19
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,9 +404,13 @@ hi TreesitterContextLineNumberBottom gui=underline guisp=Grey
404404
## Jumping to context (upwards)
405405

406406
```lua
407-
vim.keymap.set("n", "[c", function()
407+
vim.keymap.set("n", "[C", function()
408408
require("treesitter-context").go_to_context(vim.v.count1)
409409
end, { silent = true })
410+
411+
vim.keymap.set("n", "[c", function()
412+
require("treesitter-context").go_to_parent(vim.v.count1)
413+
end, { silent = true })
410414
```
411415

412416
## Adding support for other languages

doc/nvim-treesitter-context.txt

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,18 +116,41 @@ enable() *nvim-treesitter-context-enable()*
116116

117117
go_to_context({depth}) *nvim-treesitter-context-go_to_context()*
118118

119-
Jump to the context at {depth}.
119+
Jump to parent scope within the context
120+
window at {depth}.
121+
122+
A depth of 1 implies nearest, 2 second
123+
nearest and so on. Set to `vim.v.count1`
124+
to support motions with counts as depth.
120125

121126
Example use in a keymap:
122127
>lua
123-
vim.keymap.set("n", "[c", function()
128+
vim.keymap.set("n", "[C", function()
124129
require("treesitter-context").go_to_context(vim.v.count1)
125130
end, { silent = true })
126131
<
127132

128133
Parameters: ~
129134
{depth} (`integer`, default: `1`) Depth to jump to.
130135

136+
go_to_parent({depth}) *nvim-treesitter-context-go_to_parent()*
137+
138+
Jump to parent scope at {depth}.
139+
140+
A depth of 1 implies nearest, 2 second
141+
nearest and so on. Set to `vim.v.count1`
142+
to support motions with counts as depth.
143+
144+
Example use in a keymap:
145+
>lua
146+
vim.keymap.set("n", "[c", function()
147+
require("treesitter-context").go_to_parent(vim.v.count1)
148+
end, { silent = true })
149+
<
150+
151+
Parameters: ~
152+
{depth} (`integer`, default: `1`) Depth to jump to.
153+
131154

132155
setup({config}) *nvim-treesitter-context-setup()*
133156

lua/treesitter-context.lua

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ local Render = defer_require('treesitter-context.render')
2626
--- @type table<integer, Range4[]>
2727
local all_contexts = {}
2828

29+
--- @type table<integer, Range4[]>
30+
local all_parent_ranges = {}
31+
2932
--- Schedule a function to run on the next event loop iteration.
3033
--- If the function is called again within 150ms, it will be scheduled
3134
--- again to run on the next event loop iteration. This means that
@@ -115,8 +118,10 @@ local update_single_context = throttle_by_id(function(winid)
115118
return
116119
end
117120

118-
local context_ranges, context_lines = require('treesitter-context.context').get(bufnr, winid)
121+
local context_ranges, context_lines, parent_ranges =
122+
require('treesitter-context.context').get(bufnr, winid)
119123
all_contexts[bufnr] = context_ranges
124+
all_parent_ranges[bufnr] = parent_ranges
120125

121126
if not context_ranges or #context_ranges == 0 then
122127
Render.close(winid)
@@ -310,31 +315,59 @@ function M.setup(options)
310315
end
311316
end
312317

313-
--- @param depth integer? default 1
314-
function M.go_to_context(depth)
315-
depth = depth or 1
318+
--- @param depth integer
319+
--- @param ranges Range4[]
320+
local function go_to(depth, ranges)
316321
local line = api.nvim_win_get_cursor(0)[1]
317-
local context = nil
318-
local bufnr = api.nvim_get_current_buf()
319-
local contexts = all_contexts[bufnr] or {}
322+
local range = nil
320323

321-
for idx = #contexts, 1, -1 do
322-
local c = contexts[idx]
324+
for idx = #ranges, 1, -1 do
325+
local c = ranges[idx]
323326
if depth == 0 then
324327
break
325328
end
326329
if c[1] + 1 < line then
327-
context = c
330+
range = c
328331
depth = depth - 1
329332
end
330333
end
331334

332-
if context == nil then
335+
if range == nil then
333336
return
334337
end
335338

336-
vim.cmd([[ normal! m' ]]) -- add current cursor position to the jump list
337-
api.nvim_win_set_cursor(0, { context[1] + 1, context[2] })
339+
vim.cmd([[normal! m']]) -- add current cursor position to the jump list
340+
api.nvim_win_set_cursor(0, { range[1] + 1, range[2] })
341+
vim.cmd([[normal! ^]]) -- place cursor at start of text
342+
end
343+
344+
--- Jump to parent scope at depth.
345+
---
346+
--- A depth of 1 implies nearest, 2 second
347+
--- nearest and so on. Set to `vim.v.count1`
348+
--- to support motions with counts as depth.
349+
---
350+
--- @param depth integer? default 1
351+
function M.go_to_parent(depth)
352+
depth = depth or 1
353+
local bufnr = api.nvim_get_current_buf()
354+
local ranges = all_parent_ranges[bufnr] or {}
355+
go_to(depth, ranges)
356+
end
357+
358+
--- Jump to parent scope within the context
359+
--- window at depth.
360+
---
361+
--- A depth of 1 implies nearest, 2 second
362+
--- nearest and so on. Set to `vim.v.count1`
363+
--- to support motions with counts as depth.
364+
---
365+
--- @param depth integer? default 1
366+
function M.go_to_context(depth)
367+
depth = depth or 1
368+
local bufnr = api.nvim_get_current_buf()
369+
local ranges = all_contexts[bufnr] or {}
370+
go_to(depth, ranges)
338371
end
339372

340373
return M

lua/treesitter-context/context.lua

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ end
316316

317317
--- @param bufnr integer
318318
--- @param winid integer
319-
--- @return Range4[]?, string[]?
319+
--- @return Range4[]?, string[]?, Range4[]?
320320
function M.get(bufnr, winid)
321321
-- vim.treesitter.get_parser() calls bufload(), but we don't actually want to load the buffer:
322322
-- this method is called during plugin init, before other plugins or the user's config
@@ -345,6 +345,7 @@ function M.get(bufnr, winid)
345345
end
346346

347347
local context_ranges = {} --- @type Range4[]
348+
local parent_ranges = {} --- @type Range4[]
348349
local context_lines = {} --- @type string[][]
349350
local contexts_height = 0
350351

@@ -354,6 +355,7 @@ function M.get(bufnr, winid)
354355
local line_range = { node_row, col0, node_row, col0 + 1 }
355356

356357
context_ranges = {}
358+
parent_ranges = {}
357359
context_lines = {}
358360
contexts_height = 0
359361

@@ -366,7 +368,7 @@ function M.get(bufnr, winid)
366368

367369
local contexts_end_row = top_row + separator_offset + math.min(max_lines, contexts_height)
368370

369-
-- Only process the parent if it is not in view.
371+
-- context_ranges: Only process the parent if it is not in view.
370372
if parent_start_row < contexts_end_row then
371373
local range0 = context_range(parent, bufnr, query)
372374
if range0 and range_is_valid(range0) then
@@ -386,6 +388,15 @@ function M.get(bufnr, winid)
386388
end
387389
end
388390
end
391+
392+
-- parent_ranges: Process all
393+
local range0 = context_range(parent, bufnr, query)
394+
if range0 and range_is_valid(range0) then
395+
local range, _lines = get_text_for_range(range0, bufnr)
396+
if range_is_valid(range) then
397+
parent_ranges[#parent_ranges + 1] = range
398+
end
399+
end
389400
end
390401
end
391402

@@ -401,7 +412,7 @@ function M.get(bufnr, winid)
401412
trim_contexts(context_ranges, context_lines, trim, config.trim_scope == 'outer')
402413
end
403414

404-
return context_ranges, tbl_flatten(context_lines)
415+
return context_ranges, tbl_flatten(context_lines), parent_ranges
405416
end
406417

407418
return M

0 commit comments

Comments
 (0)