Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(*): overhaul, new select_* functions #6

Closed
wants to merge 1 commit into from
Closed
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
41 changes: 35 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,54 @@ Plug 'theHamsta/crazy-node-movement'
Plug 'nvim-treesitter/nvim-treesitter', {'do': ':TSUpdate'}
Plug 'nvim-treesitter/nvim-treesitter-textobjects'
```
### crazy.nvim

```lua
{
"theHamsta/crazy-node-movement",
-- rename to requires for Packer.nvim
dependenices = {
"nvim-treesitter/nvim-treesitter",
"nvim-treesitter/nvim-treesitter-textobjects"
},
config = function()
-- ... see nvim-treesitter.configssetup below
end
}
```

## Configuration
The configuration is like any other nvim-treesitter module.

```lua
require "nvim-treesitter.configs".setup {
node_movement = {
enable = true,
-- NOTE: NO mappings are attached by default
keymaps = {
move_up = "<a-k>",
move_down = "<a-j>",
move_left = "<a-h>",
move_right = "<a-l>",
swap_left = "<s-a-h>", -- will only swap when one of "swappable_textobjects" is selected
swap_right = "<s-a-l>",
-- These are going to higlight node in normal mode
move_up = "<a-k>",
move_down = "<a-j>",
move_left = "<a-h>",
move_right = "<a-l>",
swap_left = "<s-a-h>", -- will only swap when one of "swappable_textobjects" is selected
swap_right = "<s-a-l>",
select_current_node = "<leader><Cr>",

-- These mappings directly select node in visual mode
-- select_up = "<a-k>",
-- select_down = "<a-j>",
-- select_left = "<a-h>",
-- select_right = "<a-l>",
},
swappable_textobjects = {'@function.outer', '@parameter.inner', '@statement.outer'},
allow_switch_parents = true, -- more craziness by switching parents while staying on the same level, false prevents you from accidentally jumping out of a function
allow_next_parent = true, -- more craziness by going up one level if next node does not have children
-- Specify color fog the higlighting group
highlight = {
group = "Search", -- A highlight-group to link to (copy colors)
fg = "#EEEEEE" -- Static colors; set group to nil to use
}
}
}
```
Expand Down
19 changes: 12 additions & 7 deletions lua/crazy-node-movement.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,23 @@ function M.init()
is_supported = function(lang)
return parsers.has_parser(lang)
end,
-- No mappings are attached by default
keymaps = {
move_up = "<a-k>",
move_down = "<a-j>",
move_left = "<a-h>",
move_right = "<a-l>",
swap_left = "<s-a-h>",
swap_right = "<s-a-l>",
select_current_node = "<leader><cr>",
-- move_up = "<a-k>",
-- move_down = "<a-j>",
-- move_left = "<a-h>",
-- move_right = "<a-l>",
-- swap_left = "<s-a-h>",
-- swap_right = "<s-a-l>",
-- select_current_node = "<leader><cr>",
},
swappable_textobjects = { "@function.outer", "@parameter.inner", "@statement.outer" },
allow_switch_parents = true,
allow_next_parent = true,
highlight = {
group = "Search",
fg = "#EEEEEE"
}
},
}
end
Expand Down
158 changes: 112 additions & 46 deletions lua/crazy-node-movement/node_movement.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,22 @@ local ts_utils = require "nvim-treesitter.ts_utils"
local caching = require "nvim-treesitter.caching"
local shared = require "nvim-treesitter.textobjects.shared"
local textobject_swap = require "nvim-treesitter.textobjects.swap"
local cmd = api.nvim_command
local augroup = vim.api.nvim_create_augroup
local autocmd = vim.api.nvim_create_autocmd

local M = {}
M.current_node = {}

-- stylua: ignore start
local hl_namespace = api.nvim_create_namespace "crazy-node-movement"
local hl_group = "CrazyNodeMovementCurrent"

local au_group_name= "CrazyNodeMovement"

local keyseq_MLA = vim.api.nvim_replace_termcodes("m<", true, false, true) -- Set left '< mark
local keyseq_MRA = vim.api.nvim_replace_termcodes("m>", true, false, true) -- Set right '> mark
-- stylua: ignore start

M.current_node = {}
local swappable_textobjects = {}
local tick = {}
local favorite_child = caching.create_buffer_cache()
Expand All @@ -20,6 +30,19 @@ function M.clear_highlights(buf)
api.nvim_buf_clear_namespace(buf, hl_namespace, 0, -1)
end

function M.highlight_current_node(tsNode, buf, config)
M.clear_highlights(buf)
api.nvim_set_hl_ns(hl_namespace)
if config.highlight.group then
-- NOTE: This call misbehaves when :tabnew is called from vim.cmd...
-- api.nvim_set_hl(hl_namespace, hl_group, { link = config.highlight.group })
vim.cmd("highlight link " .. hl_group .. " " .. config.highlight.group)
else
api.nvim_set_hl(hl_namespace, hl_group, { fg = config.highlight.fg })
end
ts_utils.highlight_node(tsNode, buf, hl_namespace, hl_group)
end

local function current_node_ok(buf)
local new_tick = api.nvim_buf_get_changedtick(buf)
if not tick[buf] or new_tick > tick[buf] then
Expand All @@ -37,9 +60,9 @@ function M.maybe_clear_highlights(buf)
end
end

function M.do_node_movement(kind, swap)
function M.do_node_movement(kind, swap, selectNode)
local buf = vim.api.nvim_get_current_buf()

local config = require("nvim-treesitter.configs").get_module "node_movement"
local current_node = M.current_node[buf]

if not current_node_ok(buf) then
Expand Down Expand Up @@ -135,8 +158,14 @@ function M.do_node_movement(kind, swap)
else
ts_utils.goto_node(destination_node)
end
M.clear_highlights(buf)
ts_utils.highlight_node(destination_node, buf, hl_namespace, "CrazyNodeMovementCurrent")

print(("debug: %s: buf entering"):format(debug.getinfo(1).source))
print(vim.inspect(buf))
if selectNode then
M.select_current_node(destination_node, buf)
else
M.highlight_current_node(destination_node, buf, config)
end
end
end

Expand All @@ -163,65 +192,102 @@ M.swap_right = function()
M.do_node_movement("right", true)
end

M.select_current_node = function()
local buf = vim.api.nvim_get_current_buf()
local current_node = M.current_node[buf]
if not current_node_ok(buf) then
-- stylua: ignore start
-- Export select_up, select_down, select_left, select_right
local select_to_move_map = {
select_up = "up",
select_down = "down",
select_left = "left",
select_right = "right"
}
for select_action, move_action in pairs(select_to_move_map) do
M[select_action] = function()
M.do_node_movement(move_action, false, true)
end
end
-- stylua: ignore end

M.select_current_node = function(destination_node, buf)
buf = buf or vim.api.nvim_get_current_buf()
local current_node = destination_node or M.current_node[buf]
if not (destination_node or current_node_ok(buf)) then
current_node = ts_utils.get_node_at_cursor()
M.current_node[buf] = current_node
end
if current_node then
ts_utils.update_selection(buf, current_node)
local start_row, start_col, end_row, end_col = ts_utils.get_vim_range({
vim.treesitter.get_node_range(current_node),
}, buf)

M.clear_highlights(buf)
-- NOTE: Ordering is important: ALWAYS put the cursor at leftmost col!
vim.api.nvim_win_set_cursor(0, { end_row, end_col - 1 })
vim.api.nvim_feedkeys(keyseq_MLA, "x", false)
vim.api.nvim_win_set_cursor(0, { start_row, start_col - 1 })
vim.api.nvim_feedkeys(keyseq_MRA, "x", false)
vim.cmd [[noautocmd normal! gv]]
end
end

-- TODO: Move to plugin/crazy-node-movement.lua
function M.attach(bufnr)
local buf = bufnr or api.nvim_get_current_buf()

local config = require("nvim-treesitter.configs").get_module "node_movement"
config._attachedMappings = {}
swappable_textobjects = config.swappable_textobjects
allow_switch_parents = config.allow_switch_parents
allow_next_parent = config.allow_next_parent
for funcname, mapping in pairs(config.keymaps) do
api.nvim_buf_set_keymap(
buf,
"n",
mapping,
string.format(":lua require'crazy-node-movement.node_movement'.%s()<CR>", funcname),
{ silent = true }
)
if funcname == "select_current_node" then
api.nvim_buf_set_keymap(
buf,
"o",
mapping,
string.format(":lua require'crazy-node-movement.node_movement'.%s()<CR>", funcname),
{ silent = true }
)
if string.match(funcname, "move") and mapping ~= "" then
table.insert(config._attachedMappings, mapping)
api.nvim_buf_set_keymap(buf, "n", mapping, "", {
silent = true,
callback = M[funcname],
})
end
if string.match(funcname, "select") and mapping ~= "" then
table.insert(config._attachedMappings, mapping)
api.nvim_buf_set_keymap(buf, "v", mapping, "", {
silent = true,
callback = M[funcname],
})
end
end
cmd(string.format("augroup CrazyNodeMovementCurrent_%d", bufnr))
cmd "au!"
-- luacheck: push ignore 631
cmd(
string.format(
[[autocmd CursorMoved <buffer=%d> lua require'crazy-node-movement.node_movement'.maybe_clear_highlights(%d)]],
bufnr,
bufnr
)
)
-- luacheck: pop
cmd "augroup END"
end

function M.detach(bufnr)
local buf = bufnr or api.nvim_get_current_buf()
if config.keymaps.select_current_node and mapping ~= "" then
api.nvim_buf_set_keymap(buf, "o", config.keymaps.select_current_node, "", {
silent = true,
callback = M.select_current_node,
})
end

local au_group_id = augroup(au_group_name, { clear = false })

M.clear_highlights(bufnr)
vim.cmd(string.format("autocmd! CrazyNodeMovementCurrent_%d CursorMoved", bufnr))
autocmd({
"CursorMoved",
}, {
group = au_group_id,
buffer = buf,
callback = function(opts)
M.maybe_clear_highlights(opts.buf)
end,
})

end

function M.detach(buf)
local buf = buf or api.nvim_get_current_buf()

M.clear_highlights(buf)
vim.api.nvim_del_augroup_by_name(au_group_name)
local config = require("nvim-treesitter.configs").get_module "node_movement"
for _, mapping in pairs(config.keymaps) do
api.nvim_buf_del_keymap(buf, "n", mapping)
for _, mapping in ipairs(config._attachedMappings) do
local bufferHasMapping = vim.fn.mapcheck(mapping, "n") ~= ""
if bufferHasMapping then
api.nvim_buf_del_keymap(buf, "n", mapping)
end
end
config._attachedMappings = nil
end

return M
1 change: 1 addition & 0 deletions plugin/crazy-node-movement.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require("crazy-node-movement").init()
3 changes: 0 additions & 3 deletions plugin/crazy-node-movement.vim

This file was deleted.