Skip to content

Commit

Permalink
feat(maps): added visual support + unittests
Browse files Browse the repository at this point in the history
  • Loading branch information
ColinKennedy committed Nov 22, 2024
1 parent 7a1d6a9 commit c78aed9
Show file tree
Hide file tree
Showing 2 changed files with 196 additions and 16 deletions.
43 changes: 37 additions & 6 deletions lua/cursor_text_objects.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@
local M = {}

local _Direction = { down = "down", up = "up" }

local unpack = unpack or table.unpack -- Future Lua versions use table.unpack
local _DirectionMark = { down = "]", up = "[" }
local _PositionType = { character_wise = "`", line_wise = "'" }

local _CURSOR
local _DIRECTION
local _OPERATOR
local _OPERATOR_FUNCTION

local unpack = unpack or table.unpack -- Future Lua versions use table.unpack

--- Check if the operatorfunc that is running will run on a whole-line.
---
--- See Also:
Expand Down Expand Up @@ -62,7 +64,7 @@ local function _adjust_marks(mode)
local inclusive_toggle = ""

if _DIRECTION == _Direction.up then
direction = "["
direction = _DirectionMark.up

if not is_line then
local buffer, row, column, offset = unpack(vim.fn.getpos("'" .. direction))
Expand All @@ -75,7 +77,7 @@ local function _adjust_marks(mode)
vim.fn.setpos("'" .. direction, { buffer, row, column, offset })
end
else
direction = "]"
direction = _DirectionMark.down

local buffer, row, column, offset = unpack(vim.fn.getpos("'" .. direction))

Expand Down Expand Up @@ -115,9 +117,38 @@ end
--- The caller context. See `:help :map-operator` for details.
---
function M.visual(mode)
local _, mark, direction = _adjust_marks(mode)
vim.fn.setpos(".", _CURSOR)

local mark

if _is_line_mode(mode) then
mark = "'" -- Includes only line information
else
mark = "`" -- Includes column information
end

local direction

if _DIRECTION == _Direction.up then
direction = _DirectionMark.up
else
direction = _DirectionMark.down
end

local _, row, column, _ = unpack(vim.fn.getpos("'" .. direction))

if mark == _PositionType.line_wise then
if direction == _DirectionMark.down then
column = #vim.fn.getline(row)
else
column = 0
end
else
column = column - 1
end

vim.cmd(string.format("normal v%s%s", mark, direction))
vim.cmd("normal v")
vim.api.nvim_win_set_cursor(0, { row, column })
end

--- Remember anything that we will need to recall once we execute `operatorfunc`.
Expand Down
169 changes: 159 additions & 10 deletions spec/cursor_text_objects_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,17 @@ local function _call_command(keys)
end

--- Add mappings for unittests.
local function _initialize_mappings()
vim.keymap.set("o", "[", "<Plug>(cursor-text-objects-up)")
vim.keymap.set("o", "]", "<Plug>(cursor-text-objects-down)")
vim.keymap.set("x", "[", "<Plug>(cursor-text-objects-up)")
vim.keymap.set("x", "]", "<Plug>(cursor-text-objects-down)")
---
---@param up string? The key(s) to set as the "go the top to the cursor".
---@param down string? The key(s) to set as the "go from the cursor down".
---
local function _initialize_mappings(up, down)
up = up or "["
down = down or "]"
vim.keymap.set("o", up, "<Plug>(cursor-text-objects-up)")
vim.keymap.set("o", down, "<Plug>(cursor-text-objects-down)")
vim.keymap.set("x", up, "<Plug>(cursor-text-objects-up)")
vim.keymap.set("x", down, "<Plug>(cursor-text-objects-down)")
end

--- Create a new Vim buffer with `text` contents.
Expand All @@ -49,11 +55,18 @@ local function _make_buffer(text, file_type)
end

--- Remove any the default mappings that were added from `_initialize_mappings`.
local function _revert_mappings()
vim.keymap.del("o", "[")
vim.keymap.del("o", "]")
vim.keymap.del("x", "[")
vim.keymap.del("x", "]")
---
---@param up string? The key(s) to set as the "go the top to the cursor".
---@param down string? The key(s) to set as the "go from the cursor down".
---
local function _revert_mappings(up, down)
up = up or "["
down = down or "]"

vim.keymap.del("o", up)
vim.keymap.del("o", down)
vim.keymap.del("x", up)
vim.keymap.del("x", down)
end

--- Make sure `input` becomes `expected` when `keys` are called.
Expand Down Expand Up @@ -130,6 +143,37 @@ describe("basic", function()
end)
end)

describe("custom mappings", function()
before_each(function()
_initialize_mappings("{", "}")
end)
after_each(function()
_revert_mappings("{", "}")
end)

it("works with keys, not just [ / ]", function()
_run_simple_test(
{ 2, 0 },
"c}ap",
[[
some text
more text <-- NOTE: The cursor will be set here
even more lines!
still part of the paragraph
another paragraph
with text in it
]],
[[
some text
another paragraph
with text in it
]]
)
end)
end)

describe(":help c", function()
before_each(_initialize_mappings)
after_each(_revert_mappings)
Expand Down Expand Up @@ -1235,6 +1279,111 @@ describe(":help g~", function()
end)
end)

describe(":help v", function()
before_each(_initialize_mappings)
after_each(_revert_mappings)

describe("character-wise", function()
describe("down", function()
it("works with visual selection", function()
local _, window = _make_buffer([[
A paragraph of text and sentences. Here's another sentence
that spans multiple lines <-- NOTE: The cursor will be set here
but our code should handle it. And lastly.
A sentence that starts on its own line.
]])
vim.api.nvim_win_set_cursor(window, { 2, 23 })

-- NOTE: We yank the visual selection so we can assert it later
_call_command("v]asy")

assert.same(
[[t spans multiple lines <-- NOTE: The cursor will be set here
but our code should handle it. ]],
vim.fn.getreg("")
)
end)
end)

describe("up", function()
it("works with visual selection", function()
local _, window = _make_buffer([[
A paragraph of text and sentences. Here's another sentence
that spans multiple lines <-- NOTE: The cursor will be set here
but our code should handle it. And lastly.
A sentence that starts on its own line.
]])
vim.api.nvim_win_set_cursor(window, { 2, 23 })

-- NOTE: We yank the visual selection so we can assert it later
_call_command("v[asy")

assert.same(
[[Here's another sentence
that]],
vim.fn.getreg("")
)
end)
end)
end)

describe("line-wise", function()
describe("down", function()
it("works with visual selection", function()
local _, window = _make_buffer([[
aaaa
bbbb <-- NOTE: The cursor will be set here
cccc
next
lines
blah
]])
vim.api.nvim_win_set_cursor(window, { 2, 0 })

-- NOTE: We yank the visual selection so we can assert it later
_call_command("v]apy")

assert.same(
[[
bbbb <-- NOTE: The cursor will be set here
cccc
]],
vim.fn.getreg("")
)
end)
end)

describe("up", function()
it("works with visual selection", function()
local _, window = _make_buffer([[
aaaa
bbbb
cccc
next
lines <-- NOTE: The cursor will be set here
blah
]])
vim.api.nvim_win_set_cursor(window, { 6, 4 })

-- NOTE: We yank the visual selection so we can assert it later
_call_command("v[apy")

assert.same(
[[
next
]],
vim.fn.getreg("")
)
end)
end)
end)
end)

describe(":help y", function()
before_each(_initialize_mappings)
after_each(_revert_mappings)
Expand Down

0 comments on commit c78aed9

Please sign in to comment.