Skip to content

Commit

Permalink
Merge pull request #87 from brenton-leighton/feat_visual_mode_put
Browse files Browse the repository at this point in the history
Feature: visual mode put commands
  • Loading branch information
brenton-leighton authored Feb 19, 2025
2 parents 3915468 + f6a04fe commit 1ac15d0
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 20 deletions.
10 changes: 6 additions & 4 deletions lua/multiple-cursors/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ local insert_mode_completion = require("multiple-cursors.insert_mode.completion"
local insert_mode_escape = require("multiple-cursors.insert_mode.escape")

local visual_mode_modify_area = require("multiple-cursors.visual_mode.modify_area")
local visual_mode_delete_yank_change = require("multiple-cursors.visual_mode.delete_yank_change")
local visual_mode_delete_yank_change_put = require("multiple-cursors.visual_mode.delete_yank_change_put")
local visual_mode_edit = require("multiple-cursors.visual_mode.edit")
local visual_mode_escape = require("multiple-cursors.visual_mode.escape")

Expand Down Expand Up @@ -171,9 +171,11 @@ default_key_maps = {
{"x", "i", visual_mode_modify_area.i},

-- Delete, yank, change
{"x", {"d", "<Del>"}, visual_mode_delete_yank_change.d},
{"x", "y", visual_mode_delete_yank_change.y},
{"x", "c", visual_mode_delete_yank_change.c},
{"x", {"d", "<Del>"}, visual_mode_delete_yank_change_put.d},
{"x", "y", visual_mode_delete_yank_change_put.y},
{"x", "c", visual_mode_delete_yank_change_put.c},
{"x", "p", visual_mode_delete_yank_change_put.p},
{"x", "P", visual_mode_delete_yank_change_put.P},

-- Indentation
{"x", ">", visual_mode_edit.indent},
Expand Down
105 changes: 89 additions & 16 deletions lua/multiple-cursors/virtual_cursors.lua
Original file line number Diff line number Diff line change
Expand Up @@ -430,35 +430,63 @@ function M.normal_mode_delete_yank(register, count, cmd, motion_cmd)

end

-- Determine which register(s) to use for the put command
-- If every virtual cursor has a register, use them
-- Otherwise use the real register
-- If the real register isn't occupied, then fail
--
-- Returns:
-- 2 for virtual cursor registers
-- 1 for real register
-- 0 for failure
local function which_registers(register)

local use_vc_registers = true

-- Check that every virtual cursor has a register
for _, vc in ipairs(virtual_cursors) do
if vc.editable and not vc:has_register(register) then
use_vc_registers = false
break
end
end

-- Use virtual cursor registers
if use_vc_registers then
return 2
end

-- Return 0 if the real register doesn't have data
local register_info = vim.fn.getreginfo(register)
if next(register_info) == nil then
return 0
end

-- Use the real register
return 1

end

-- Execute a normal command to perform a put at each virtual cursor
-- The register is first saved, the replaced by the virtual cursor register
-- After executing the command the unnamed register is restored
function M.normal_mode_put(register, count, cmd)

local use_own_register = true
-- Determine which registers to use
local tmp = which_registers(register)

for _, vc in ipairs(virtual_cursors) do
if vc.editable and not vc:has_register(register) then
use_own_register = false
break
end
if tmp == 0 then
return
end

-- If not using each virtual cursor's register
if not use_own_register then
-- Return if the main register doesn't have data
local register_info = vim.fn.getreginfo(register)
if next(register_info) == nil then
return
end
end
local use_vc_registers = tmp == 2

M.edit_with_cursor(function(vc, idx)

local register_info = nil

-- If the virtual cursor has data for the register
if use_own_register then
if use_vc_registers then
-- Save the register
register_info = vim.fn.getreginfo(register)
-- Set the register from the virtual cursor
Expand All @@ -468,7 +496,7 @@ function M.normal_mode_put(register, count, cmd)
-- Put the register
common.normal_bang(register, count, cmd, nil)

-- Restore the register
-- Restore the real register
if register_info then
vim.fn.setreg(register, register_info)
end
Expand Down Expand Up @@ -525,6 +553,47 @@ function M.visual_mode_delete_yank(register, cmd)

end

-- Visual mode p and P commands
function M.visual_mode_put(register, count, cmd)

-- Determine which registers to use
local tmp = which_registers(register)

if tmp == 0 then
return
end

local use_vc_registers = tmp == 2

M.visual_mode(function(vc, idx)

local register_info = nil

-- If the virtual cursor has data for the register
if use_vc_registers then
-- Save the register
register_info = vim.fn.getreginfo(register)
-- Set the register from the virtual cursor
vc:set_register(register)
end

-- Put the register
common.normal_bang(register, count, cmd, nil)

-- Save the register for "p"
if cmd == "p" then
vc:save_register(register)
end

-- Restore the real register
if register_info then
vim.fn.setreg(register, register_info)
end

end)

end


-- Go to commands ("G" and "gg") -----------------------------------------------

Expand Down Expand Up @@ -645,6 +714,10 @@ end

-- Insert each line of from into to
local function concatenate_regcontents(from, to)
if not from then
return
end

for _, line in ipairs(from) do
table.insert(to, line)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,15 @@ function M.c()
common.feedkeys(nil, 0, "i", nil)
end

-- Put
local function visual_mode_put_and_feedkeys(cmd)
local register = vim.v.register
local count = vim.v.count
virtual_cursors.visual_mode_put(register, count, cmd)
common.feedkeys(register, count, cmd, nil)
end

function M.p() visual_mode_put_and_feedkeys("p") end
function M.P() visual_mode_put_and_feedkeys("P") end

return M

0 comments on commit 1ac15d0

Please sign in to comment.