diff --git a/README.md b/README.md index 8ae673d9..3dddc2a2 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/doc/nvim-treesitter-context.txt b/doc/nvim-treesitter-context.txt index c9069005..ea5eb5a8 100644 --- a/doc/nvim-treesitter-context.txt +++ b/doc/nvim-treesitter-context.txt @@ -116,11 +116,14 @@ 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 }) < @@ -128,6 +131,23 @@ go_to_context({depth}) *nvim-treesitter-context-go_to_context()* 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()* diff --git a/lua/treesitter-context.lua b/lua/treesitter-context.lua index ba83b39b..0831e075 100644 --- a/lua/treesitter-context.lua +++ b/lua/treesitter-context.lua @@ -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 diff --git a/lua/treesitter-context/context.lua b/lua/treesitter-context/context.lua index 09c261f9..75fbd002 100644 --- a/lua/treesitter-context/context.lua +++ b/lua/treesitter-context/context.lua @@ -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 @@ -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 = {} @@ -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: @@ -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)