Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -404,9 +404,13 @@ hi TreesitterContextLineNumberBottom gui=underline guisp=Grey
## Jumping to context (upwards)

```lua
vim.keymap.set("n", "[c", function()
vim.keymap.set("n", "[C", function()
require("treesitter-context").go_to_context(vim.v.count1)
end, { silent = true })

vim.keymap.set("n", "[c", function()
require("treesitter-context").go_to_parent(vim.v.count1)
end, { silent = true })
```

## Adding support for other languages
Expand Down
24 changes: 22 additions & 2 deletions doc/nvim-treesitter-context.txt
Original file line number Diff line number Diff line change
Expand Up @@ -116,18 +116,38 @@ enable() *nvim-treesitter-context-enable()*

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

Jump to the context at {depth}.
Jump to parent scope within the context window at {depth}.

A depth of 1 implies nearest, 2 second nearest and so on. Set to
`vim.v.count1` to support motions with counts as depth.

Example use in a keymap:
>lua
vim.keymap.set("n", "[c", function()
vim.keymap.set("n", "[C", function()
require("treesitter-context").go_to_context(vim.v.count1)
end, { silent = true })
<

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

go_to_parent({depth}) *nvim-treesitter-context-go_to_parent()*

Jump to parent scope at {depth}.

A depth of 1 implies nearest, 2 second nearest and so on. Set to
`vim.v.count1` to support motions with counts as depth.

Example use in a keymap:
>lua
vim.keymap.set("n", "[c", function()
require("treesitter-context").go_to_parent(vim.v.count1)
end, { silent = true })
<

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


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

Expand Down
45 changes: 34 additions & 11 deletions lua/treesitter-context.lua
Original file line number Diff line number Diff line change
Expand Up @@ -301,30 +301,53 @@ function M.setup(options)
end
end

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

for idx = #contexts, 1, -1 do
local c = contexts[idx]
for idx = #ranges, 1, -1 do
local c = ranges[idx]
if depth == 0 then
break
end
if c[1] + 1 < line then
context = c
range = c
depth = depth - 1
end
end

if not context then
if not range then
return
end

vim.cmd([[ normal! m' ]]) -- add current cursor position to the jump list
api.nvim_win_set_cursor(0, { context[1] + 1, context[2] })
vim.cmd([[normal! m']]) -- add current cursor position to the jump list
api.nvim_win_set_cursor(0, { range[1] + 1, range[2] })
end

--- Jump to parent scope at depth.
---
--- A depth of 1 implies nearest, 2 second nearest and so on. Set to
--- `vim.v.count1` to support motions with counts as depth.
---
--- @param depth integer? default 1
function M.go_to_parent(depth)
depth = depth or 1
local ranges = require('treesitter-context.context').get(nil, true) or {}
go_to(depth, ranges)
end

--- Jump to parent scope within the context window at depth.
---
--- A depth of 1 implies nearest, 2 second nearest and so on. Set to
--- `vim.v.count1` to support motions with counts as depth.
---
--- @param depth integer? default 1
function M.go_to_context(depth)
depth = depth or 1
local ranges = require('treesitter-context.context').get() or {}
go_to(depth, ranges)
end

return M
13 changes: 8 additions & 5 deletions lua/treesitter-context/context.lua
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ end
--- @param bufnr integer
--- @return Range4, string[]
local function get_text_for_range(range, bufnr)
local start_row, end_row, end_col = range[1], range[3], range[4]
local start_row, start_col, end_row, end_col = range[1], range[2], range[3], range[4]

if end_col == 0 then
end_row = end_row - 1
Expand Down Expand Up @@ -218,7 +218,7 @@ local function get_text_for_range(range, bufnr)
end_row = end_row + 1
end

return { start_row, 0, end_row, end_col }, lines
return { start_row, start_col, end_row, end_col }, lines
end

local M = {}
Expand Down Expand Up @@ -313,9 +313,11 @@ local function range_is_valid(range)
end

--- @param winid? integer
--- @param full_context? boolean default false
--- @return Range4[]?, string[]?
function M.get(winid)
function M.get(winid, full_context)
winid = winid or api.nvim_get_current_win()
full_context = full_context or false
local bufnr = api.nvim_win_get_buf(winid)

-- vim.treesitter.get_parser() calls bufload(), but we don't actually want to load the buffer:
Expand Down Expand Up @@ -369,8 +371,9 @@ function M.get(winid)

local contexts_end_row = top_row + separator_offset + num_context_lines

-- Only process the parent if it is not in view.
if parent_start_row < contexts_end_row then
-- Only process the parent if it is not in view
-- noteable exception when full_context is true
if parent_start_row < contexts_end_row or full_context then
local range0 = context_range(parent, bufnr, query)
if range0 and range_is_valid(range0) then
local range, lines = get_text_for_range(range0, bufnr)
Expand Down
Loading