Skip to content
This repository was archived by the owner on Nov 13, 2024. It is now read-only.

Commit 98a6d56

Browse files
committed
added simple implementation of visual mode holdswapping
1 parent a411025 commit 98a6d56

File tree

2 files changed

+79
-45
lines changed

2 files changed

+79
-45
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ The .go_to_top_node_and_execute_commands() method takes 2 arguments:
110110

111111
1. boolean: if false then it will jump to the beginning of the node, if true it jumps to the end.
112112

113-
1. lua table: a table that contains strings, each tring is a vim command example: { "normal! O", "normal! O", "startinsert" }
113+
1. lua table: a table that contains strings, each string is a vim command example: { "normal! O", "normal! O", "startinsert" }
114114

115115
---
116116

@@ -267,4 +267,6 @@ Example mapping:
267267
```lua
268268
-- Holds a node, or swaps the held node
269269
vim.keymap.set("n", "gnh", "<cmd>STSSwapOrHold<cr>", opts)
270+
-- Same for visual
271+
vim.keymap.set("x", "gnh", "<cmd>STSSwapOrHoldVisual<cr>", opts)
270272
```

lua/syntax-tree-surfer/init.lua

Lines changed: 76 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -63,53 +63,73 @@ function M.update_selection(buf, node, selection_mode) -- rip from the old ts_ut
6363
vim.fn.setpos(".", { buf, end_row, end_col, 0 })
6464
end --}}}
6565

66-
M.surf = function(direction, mode, move) --{{{
66+
local get_visual_node = function() --{{{
6767
local node = ts_utils.get_node_at_cursor() -- declare node and bufnr
68-
local bufnr = vim.api.nvim_get_current_buf()
6968

7069
if node == nil then -- prevent errors
7170
return
7271
end
7372

74-
if mode == "visual" then
75-
local nodeA = node
76-
vim.cmd("normal! o")
77-
local nodeB = ts_utils.get_node_at_cursor()
78-
vim.cmd("normal! o")
79-
local root = ts_utils.get_root_for_node(node)
80-
81-
if nodeA:id() ~= nodeB:id() then --> get the true node
82-
local true_range = find_range_from_2nodes(nodeA, nodeB)
83-
local parent = nodeA:parent()
84-
local start_row_P, start_col_P, end_row_P, end_col_P = parent:range()
85-
86-
while
87-
start_row_P ~= true_range[1]
88-
or start_col_P ~= true_range[2]
89-
or end_row_P ~= true_range[3]
90-
or end_col_P ~= true_range[4]
91-
do
92-
if parent:parent() == nil then
93-
break
94-
end
95-
parent = parent:parent()
96-
start_row_P, start_col_P, end_row_P, end_col_P = parent:range()
97-
end
73+
local nodeA = node
74+
vim.cmd("normal! o")
75+
local nodeB = ts_utils.get_node_at_cursor()
76+
vim.cmd("normal! o")
77+
local root = ts_utils.get_root_for_node(node)
78+
79+
if nodeA:id() ~= nodeB:id() then --> get the true node
80+
local true_range = find_range_from_2nodes(nodeA, nodeB)
81+
local parent = nodeA:parent()
82+
local start_row_P, start_col_P, end_row_P, end_col_P = parent:range()
83+
84+
while
85+
start_row_P ~= true_range[1]
86+
or start_col_P ~= true_range[2]
87+
or end_row_P ~= true_range[3]
88+
or end_col_P ~= true_range[4]
89+
do
90+
if parent:parent() == nil then
91+
break
92+
end
93+
parent = parent:parent()
94+
start_row_P, start_col_P, end_row_P, end_col_P = parent:range()
95+
end
9896

99-
node = parent
100-
end
97+
node = parent
98+
end
10199

102-
if node == root then -- catch some edge cases
103-
node = nodeA
104-
end
105-
end
100+
if node == root then -- catch some edge cases
101+
node = nodeA
102+
end
106103

107104
local parent = node:parent() --> if parent only has 1 child, move up the tree
108105
while parent ~= nil and parent:named_child_count() == 1 do
109106
node = parent
110107
parent = node:parent()
111108
end
112109

110+
return node
111+
112+
end --}}}
113+
114+
M.surf = function(direction, mode, move) --{{{
115+
local node = ts_utils.get_node_at_cursor() -- declare node and bufnr
116+
local bufnr = vim.api.nvim_get_current_buf()
117+
118+
if node == nil then -- prevent errors
119+
return
120+
end
121+
122+
if mode == "visual" then-- {{{
123+
node = get_visual_node()
124+
else
125+
local parent = node:parent()
126+
while parent ~= nil and parent:named_child_count() == 1 do
127+
node = parent
128+
parent = node:parent()
129+
end
130+
end --}}}
131+
132+
113133
local target --> setting the target, depending on the direction
114134
if direction == "parent" then
115135
target = node:parent()
@@ -866,22 +886,22 @@ end, {})
866886

867887
-- version 2.2
868888

889+
869890
local held_node = nil --store the held node internally
870-
local function hold_focused_node() --{{{
871-
local new_node = ts_utils.get_node_at_cursor()
891+
local function hold_node(node) --{{{
872892
local bufnr = vim.api.nvim_get_current_buf()
873893

874-
if new_node ~= nil then
875-
local end_row, end_col = new_node:end_()
894+
if node ~= nil then
895+
local end_row, end_col = node:end_()
876896

877897
--clear old extmark
878898
if held_node and held_node.extmark_id then
879-
api.nvim_buf_del_extmark(0, ns, held_node.extmark_id)
899+
-- api.nvim_buf_del_extmark(0, ns, held_node.extmark_id)
880900
end
881901

882902
-- store the held node with extra data for checks/extmark deletion
883903
held_node = {
884-
node = new_node,
904+
node = node,
885905
bufnr = bufnr,
886906
extmark_id = set_extmark_then_delete_it( -- set the extmark and save it for deletion
887907
end_row,
@@ -894,11 +914,11 @@ local function hold_focused_node() --{{{
894914
end
895915
end --}}}
896916

897-
local function swap_held_and_focused_node() --{{{
917+
local function swap_held_node(node) --{{{
898918
local bufnr = vim.api.nvim_get_current_buf()
899919

900920
if held_node ~= nil and held_node.bufnr == bufnr then -- make sure we're swapping nodes in the same buffer
901-
ts_utils.swap_nodes(held_node.node, ts_utils.get_node_at_cursor(), bufnr, true)
921+
ts_utils.swap_nodes(held_node.node, node, bufnr, true)
902922
api.nvim_buf_del_extmark(0, ns, held_node.extmark_id) --clear the extmark, probably don't need it after this
903923
held_node = nil
904924
else
@@ -910,16 +930,28 @@ local function swap_held_and_focused_node() --{{{
910930
end
911931
end --}}}
912932

913-
local function hold_or_swap() --{{{
933+
local function hold_or_swap(visual_mode) --{{{
914934
if held_node == nil then
915-
hold_focused_node()
935+
if visual_mode then
936+
hold_node(get_visual_node())
937+
else
938+
hold_node(ts_utils.get_node_at_cursor())
939+
end
916940
else
917-
swap_held_and_focused_node()
941+
if visual_mode then
942+
swap_held_node(get_visual_node())
943+
else
944+
swap_held_node(ts_utils.get_node_at_cursor())
945+
end
918946
end
919947
end --}}}
920948

921949
vim.api.nvim_create_user_command("STSSwapOrHold", function()
922-
hold_or_swap()
950+
hold_or_swap(false)
951+
end, {})
952+
953+
vim.api.nvim_create_user_command("STSSwapOrHoldVisual", function()
954+
hold_or_swap(true)
923955
end, {})
924956

925957
return M

0 commit comments

Comments
 (0)