Skip to content

Commit 80ab4ce

Browse files
committed
feat(enhancement): support nearest parent
Fixes #453
1 parent 33b3f5a commit 80ab4ce

File tree

4 files changed

+87
-19
lines changed

4 files changed

+87
-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: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -301,30 +301,60 @@ function M.setup(options)
301301
end
302302
end
303303

304-
--- @param depth integer? default 1
305-
function M.go_to_context(depth)
306-
depth = depth or 1
304+
--- @param depth integer
305+
--- @param ranges Range4[]
306+
local function go_to(depth, ranges)
307307
local line = api.nvim_win_get_cursor(0)[1]
308-
local context = nil
309-
local contexts = require('treesitter-context.context').get() or {}
308+
local range = nil
310309

311-
for idx = #contexts, 1, -1 do
312-
local c = contexts[idx]
310+
for idx = #ranges, 1, -1 do
311+
local c = ranges[idx]
313312
if depth == 0 then
314313
break
315314
end
316315
if c[1] + 1 < line then
317-
context = c
316+
range = c
318317
depth = depth - 1
319318
end
320319
end
321320

322-
if not context then
321+
if not range then
323322
return
324323
end
325324

326-
vim.cmd([[ normal! m' ]]) -- add current cursor position to the jump list
327-
api.nvim_win_set_cursor(0, { context[1] + 1, context[2] })
325+
vim.cmd([[normal! m']]) -- add current cursor position to the jump list
326+
api.nvim_win_set_cursor(0, { range[1] + 1, range[2] })
327+
end
328+
329+
--- Jump to parent scope at depth.
330+
---
331+
--- A depth of 1 implies nearest, 2 second
332+
--- nearest and so on. Set to `vim.v.count1`
333+
--- to support motions with counts as depth.
334+
---
335+
--- @param depth integer? default 1
336+
function M.go_to_parent(depth)
337+
depth = depth or 1
338+
339+
--- @type table?, table?, table?
340+
local _, _, ranges = require('treesitter-context.context').get()
341+
ranges = ranges or {}
342+
table.remove(ranges) --- NOTE: there's repetition for unknown reasons
343+
go_to(depth, ranges)
344+
end
345+
346+
--- Jump to parent scope within the context
347+
--- window at depth.
348+
---
349+
--- A depth of 1 implies nearest, 2 second
350+
--- nearest and so on. Set to `vim.v.count1`
351+
--- to support motions with counts as depth.
352+
---
353+
--- @param depth integer? default 1
354+
function M.go_to_context(depth)
355+
depth = depth or 1
356+
local ranges = require('treesitter-context.context').get() or {}
357+
go_to(depth, ranges)
328358
end
329359

330360
return M

lua/treesitter-context/context.lua

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ end
190190
--- @param bufnr integer
191191
--- @return Range4, string[]
192192
local function get_text_for_range(range, bufnr)
193-
local start_row, end_row, end_col = range[1], range[3], range[4]
193+
local start_row, start_col, end_row, end_col = range[1], range[2], range[3], range[4]
194194

195195
if end_col == 0 then
196196
end_row = end_row - 1
@@ -218,7 +218,7 @@ local function get_text_for_range(range, bufnr)
218218
end_row = end_row + 1
219219
end
220220

221-
return { start_row, 0, end_row, end_col }, lines
221+
return { start_row, start_col, end_row, end_col }, lines
222222
end
223223

224224
local M = {}
@@ -313,7 +313,7 @@ local function range_is_valid(range)
313313
end
314314

315315
--- @param winid? integer
316-
--- @return Range4[]?, string[]?
316+
--- @return Range4[]?, string[]?, Range4[]?
317317
function M.get(winid)
318318
winid = winid or api.nvim_get_current_win()
319319
local bufnr = api.nvim_win_get_buf(winid)
@@ -345,6 +345,7 @@ function M.get(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(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

@@ -369,7 +371,7 @@ function M.get(winid)
369371

370372
local contexts_end_row = top_row + separator_offset + num_context_lines
371373

372-
-- Only process the parent if it is not in view.
374+
-- context_ranges: Only process the parent if it is not in view.
373375
if parent_start_row < contexts_end_row then
374376
local range0 = context_range(parent, bufnr, query)
375377
if range0 and range_is_valid(range0) then
@@ -389,6 +391,15 @@ function M.get(winid)
389391
end
390392
end
391393
end
394+
395+
-- parent_ranges: Process all
396+
local range0 = context_range(parent, bufnr, query)
397+
if range0 and range_is_valid(range0) then
398+
local range, _lines = get_text_for_range(range0, bufnr)
399+
if range_is_valid(range) then
400+
parent_ranges[#parent_ranges + 1] = range
401+
end
402+
end
392403
end
393404
end
394405

@@ -404,7 +415,7 @@ function M.get(winid)
404415
trim_contexts(context_ranges, context_lines, trim, config.trim_scope == 'outer')
405416
end
406417

407-
return context_ranges, tbl_flatten(context_lines)
418+
return context_ranges, tbl_flatten(context_lines), parent_ranges
408419
end
409420

410421
return M

0 commit comments

Comments
 (0)