Skip to content

Swaparound Feature #38

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

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
16 changes: 16 additions & 0 deletions lua/treewalker/nodes.lua
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,22 @@ function M.next_sib(node)
return node:next_named_sibling()
end

---@param node TSNode
---@param fn function
---@return TSNode | nil
function M.farthest_sibling(node, fn)
if not node then return nil end

---@type TSNode | nil
local iter = fn(node)

while iter do
node = iter
iter = fn(iter)
end
return node
end

-- Convenience for give me back prev sibling of a potentially nil node
---@param node TSNode | nil
function M.prev_sib(node)
Expand Down
4 changes: 2 additions & 2 deletions lua/treewalker/swap.lua
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ function M.swap_right()
current = strategies.get_highest_string_node(current) or current
current = nodes.get_highest_coincident(current)

local target = nodes.next_sib(current)
local target = nodes.next_sib(current) or nodes.farthest_sibling(current, nodes.prev_sib)

if not current or not target then return end

Expand Down Expand Up @@ -158,7 +158,7 @@ function M.swap_left()
current = strategies.get_highest_string_node(current) or current
current = nodes.get_highest_coincident(current)

local target = nodes.prev_sib(current)
local target = nodes.prev_sib(current) or nodes.farthest_sibling(current, nodes.next_sib)

if not current or not target then return end

Expand Down
8 changes: 8 additions & 0 deletions tests/treewalker/c_sharp_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,12 @@ describe("In a C Sharp file", function()
assert.same(first_block, lines.get_lines(30, 48))
h.assert_cursor_at(7, 5)
end)

it("swaparound behavior works", function()
vim.fn.cursor(52, 31)
tw.swap_left()
assert.same(" public static int Add(int b, int a) => a + b;", lines.get_line(52))
tw.swap_right()
assert.same(" public static int Add(int a, int b) => a + b;", lines.get_line(52))
end)
end)
8 changes: 8 additions & 0 deletions tests/treewalker/c_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,12 @@ describe("In a c file:", function()
assert.same(first_block, lines.get_lines(68, 72))
assert.same(second_block, lines.get_lines(63, 66))
end)

it("swaparound behavior works", function()
vim.fn.cursor(11, 24)
tw.swap_left()
assert.same("Account* createAccount(float initialBalance, int accountNumber) {", lines.get_line(11))
tw.swap_right()
assert.same("Account* createAccount(int accountNumber, float initialBalance) {", lines.get_line(11))
end)
end)
11 changes: 9 additions & 2 deletions tests/treewalker/haskell_spec.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local load_fixture = require "tests.load_fixture"
local tw = require 'treewalker'
local h = require 'tests.treewalker.helpers'
local lines = require 'treewalker.lines'

describe("In a haskell file: ", function()
before_each(function()
Expand All @@ -27,6 +28,12 @@ describe("In a haskell file: ", function()
tw.move_out()
h.assert_cursor_at(19, 1)
end)
end)


it("swaparound behavior works", function()
vim.fn.cursor(40, 15)
tw.swap_left()
assert.same(" printEvens [9, 3, 5, 7, 1]", lines.get_line(40))
tw.swap_right()
assert.same(" printEvens [1, 3, 5, 7, 9]", lines.get_line(40))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey so I pulled down your branch and tested out the functionality, and saw this test in particular. This is the only one with more than 2 parameters. At first I thought it was perfect but when I played with it, the swapping behavior isn't quite how I expect it to be. The way it is now the first and last items swap. This leads to these really interesting reorderings if you cycle through - a fascinating mathematical phenomenon, but not the desired behavior. What should happen is, if the node is at the end, it should just move itself to the other end.

Here, use these for the haskell tests:

  it("swaparound behavior works", function()
    vim.fn.cursor(40, 15) -- [|1, 3, 5, 7, 9]
    assert.same("  printEvens [1, 3, 5, 7, 9]", lines.get_line(40))
    tw.swap_left()
    assert.same("  printEvens [3, 5, 7, 9, 1]", lines.get_line(40))
    tw.swap_left()
    assert.same("  printEvens [5, 7, 9, 1, 3]", lines.get_line(40))
    tw.swap_left()
    assert.same("  printEvens [7, 9, 1, 3, 5]", lines.get_line(40))
    tw.swap_left()
    assert.same("  printEvens [9, 1, 3, 5, 7]", lines.get_line(40))
    tw.swap_left() -- back to original order
    assert.same("  printEvens [1, 3, 5, 7, 9]", lines.get_line(40))

    vim.fn.cursor(40, 27) -- [|1, 3, 5, 7, |9]
    assert.same("  printEvens [1, 3, 5, 7, 9]", lines.get_line(40))
    tw.swap_right()
    assert.same("  printEvens [9, 1, 3, 5, 7]", lines.get_line(40))
    tw.swap_right()
    assert.same("  printEvens [7, 9, 1, 3, 5]", lines.get_line(40))
  end)

end)
end)
9 changes: 8 additions & 1 deletion tests/treewalker/lua_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,14 @@ describe("Swapping in a regular lua file:", function()
apply_text_edits_stub:revert()
end)

it("swaparound behavior works", function()
vim.fn.cursor(38, 32)
tw.swap_left()
assert.same("local function have_same_range(node2, node1)", lines.get_line(38))
tw.swap_right()
assert.same("local function have_same_range(node1, node2)", lines.get_line(38))
end)

-- Actually I don't think this is supposed to work. It's ambiguous what
-- node we're on. We'd need to do the lowest coincident that is the highest string
-- or something.
Expand All @@ -341,4 +349,3 @@ describe("Swapping in a regular lua file:", function()
assert.same(" print('one' .. 'two' .. 'three')", lines.get_line(188))
end)
end)

9 changes: 8 additions & 1 deletion tests/treewalker/python_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,12 @@ describe("In a python file: ", function()
assert.same(bottom_before, lines.get_lines(118, 131))
assert.same(top_before, lines.get_lines(135, 136))
end)
end)

it("swaparound feature works", function()
vim.fn.cursor(14, 18)
tw.swap_left()
assert.same(" def __init__(name, self):", lines.get_line(14))
tw.swap_right()
assert.same(" def __init__(self, name):", lines.get_line(14))
end)
end)
8 changes: 8 additions & 0 deletions tests/treewalker/ruby_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,13 @@ describe("In a ruby file: ", function()
assert.same(first_block, lines.get_lines(15, 19))
h.assert_cursor_at(16, 3)
end)

it("swaparound feature works", function()
vim.fn.cursor(40, 27)
tw.swap_left()
assert.same(" def process_transaction(callback = nil, amount)", lines.get_line(40))
tw.swap_right()
assert.same(" def process_transaction(amount, callback = nil)", lines.get_line(40))
end)
end)