Skip to content

Commit 452d8ac

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

File tree

4 files changed

+92
-19
lines changed

4 files changed

+92
-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+
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: 21 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 = {}
@@ -272,6 +272,11 @@ local function iter_context_parents(bufnr, line_range)
272272
return
273273
end
274274
parents = get_parent_nodes(tree, line_range)
275+
276+
--- NOTE: because for some reason the get_parent_nodes returns a
277+
--- repeated node at the very end
278+
table.remove(parents)
279+
275280
query = get_context_query(tree:lang())
276281
until parents and query
277282
return parents, query
@@ -313,7 +318,7 @@ local function range_is_valid(range)
313318
end
314319

315320
--- @param winid? integer
316-
--- @return Range4[]?, string[]?
321+
--- @return Range4[]?, string[]?, Range4[]?
317322
function M.get(winid)
318323
winid = winid or api.nvim_get_current_win()
319324
local bufnr = api.nvim_win_get_buf(winid)
@@ -345,6 +350,7 @@ function M.get(winid)
345350
end
346351

347352
local context_ranges = {} --- @type Range4[]
353+
local parent_ranges = {} --- @type Range4[]
348354
local context_lines = {} --- @type string[][]
349355
local contexts_height = 0
350356

@@ -354,6 +360,7 @@ function M.get(winid)
354360
local line_range = { node_row, col0, node_row, col0 + 1 }
355361

356362
context_ranges = {}
363+
parent_ranges = {}
357364
context_lines = {}
358365
contexts_height = 0
359366

@@ -369,7 +376,7 @@ function M.get(winid)
369376

370377
local contexts_end_row = top_row + separator_offset + num_context_lines
371378

372-
-- Only process the parent if it is not in view.
379+
-- context_ranges: Only process the parent if it is not in view.
373380
if parent_start_row < contexts_end_row then
374381
local range0 = context_range(parent, bufnr, query)
375382
if range0 and range_is_valid(range0) then
@@ -389,6 +396,15 @@ function M.get(winid)
389396
end
390397
end
391398
end
399+
400+
-- parent_ranges: Process all
401+
local range0 = context_range(parent, bufnr, query)
402+
if range0 and range_is_valid(range0) then
403+
local range, _lines = get_text_for_range(range0, bufnr)
404+
if range_is_valid(range) then
405+
parent_ranges[#parent_ranges + 1] = range
406+
end
407+
end
392408
end
393409
end
394410

@@ -404,7 +420,7 @@ function M.get(winid)
404420
trim_contexts(context_ranges, context_lines, trim, config.trim_scope == 'outer')
405421
end
406422

407-
return context_ranges, tbl_flatten(context_lines)
423+
return context_ranges, tbl_flatten(context_lines), parent_ranges
408424
end
409425

410426
return M

0 commit comments

Comments
 (0)