feat: add keymaps for visual mode text block movement

This commit is contained in:
2024-09-13 09:17:27 -04:00
parent 49f547aed2
commit 10802e429e
2 changed files with 144 additions and 24 deletions
+13
View File
@@ -14,6 +14,7 @@ local data = require("data")
-- Add keymapper function -- Add keymapper function
local add_keymap = data.func.add_keymap local add_keymap = data.func.add_keymap
-- local add_km = require("which-key").add
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━ General Keybinds ━━━━━━━━━━━━━━━━━━━━━━━ -- ━━━━━━━━━━━━━━━━━━━━━━━━━━ General Keybinds ━━━━━━━━━━━━━━━━━━━━━━━
-- Add keymaps for miscellaneous keybinds -- Add keymaps for miscellaneous keybinds
@@ -49,6 +50,18 @@ end
-- Add keymaps for overrides -- Add keymaps for overrides
add_keymap(data.keys.overrides) add_keymap(data.keys.overrides)
-- ━━━━━━━━━━━━━━━━━━━━━━━━━━━ Custom Mappings ━━━━━━━━━━━━━━━━━━━━━━━━━━━
-- Visual mode: Move selected block of text up
add_keymap("K", function()
data.func.move_visual(true)
end, "Move block of text up", "v")
-- Visual mode: Move selected block of text down
add_keymap("J", function()
data.func.move_visual(false)
end, "Move block of text down", "v")
-- Test Prompt: Enter your name
add_keymap("<leader>qP", function() add_keymap("<leader>qP", function()
data.func.InputPrompt("Enter your name: ", function(input) data.func.InputPrompt("Enter your name: ", function(input)
if input then if input then
+131 -24
View File
@@ -404,6 +404,57 @@ function M.InputPrompt(prompt, callback)
end end
end end
---@function Function to move blocks of text up and down
---@param up? boolean Whether to move the blocks up or down
--- Ex: Move selected block of text up: move_visual(true)
--- Move selected block of text down: move_visual(false)
---@param multiplier? integer The number of times to move the blocks
--- Ex: Move selected block of text up 3 times: move_visual(true, 3)
--- Move selected block of text down 2 times: move_visual(false, 2)
---@return nil
function M.move_visual(up, multiplier)
-- Handle parameter
local offset = 1
if up then
offset = -2
end
if multiplier then
offset = offset * multiplier
end
-- escape visual mode
vim.cmd("norm v")
-- GET REGION
-- eg region = { [103] = {0,-1}, [104] = {0,-1}, [105] = {0,-1}}
---@diagnostic disable-next-line: deprecated
local region = vim.region(0, "'<", "'>", vim.fn.visualmode(), true)
local function array_keys(array)
local keys = {}
for k in pairs(array) do
table.insert(keys, k)
end
return keys
end
-- GET LINES
-- eg lines = { 103, 104, 105 }
local lines = array_keys(region)
table.sort(lines)
-- GET TOP/BOTTOM LINE NUMBERS
local top = lines[1] + 1
local bottom = lines[#lines] + 1
-- EXECUTE
local new_pos = offset > 0 and bottom + offset or top + offset
vim.cmd(string.format("silent %d, %d move %d", top, bottom, new_pos))
-- eg :silent 104, 106 move 107
vim.cmd("norm gv")
end
---@function Function to reload the user's Neovim configuration ---@function Function to reload the user's Neovim configuration
---@return nil ---@return nil
function M.reload_config() function M.reload_config()
@@ -505,13 +556,14 @@ end
--- Options: --- Options:
--- - string: The name of the plugin module to check. --- - string: The name of the plugin module to check.
--- - table: A list of plugin modules to check. --- - table: A list of plugin modules to check.
---@param simple boolean|nil Whether to use a simple check (pcall(require, plugin)).
---@return boolean|table condition The installed state of the plugin(s). ---@return boolean|table condition The installed state of the plugin(s).
--- - boolean: The installed state of the plugin. --- - boolean: The installed state of the plugin.
--- - table: A list of installed states of the plugins. --- - table: A list of installed states of the plugins.
--- - boolean: The installed state of the plugin. --- - boolean: The installed state of the plugin.
--- The return type is determined based on the input type. --- The return type is determined based on the input type.
--- If the input is a table of plugin modules, the return type is a table. --- If the input is a table of plugin modules, the return type is a table.
function M.is_installed(plugins) function M.is_installed(plugins, simple)
local is_single = type(plugins) == "string" local is_single = type(plugins) == "string"
if type(plugins) == "string" then if type(plugins) == "string" then
plugins = { plugins } plugins = { plugins }
@@ -520,22 +572,26 @@ function M.is_installed(plugins)
local installed_plugins = {} local installed_plugins = {}
for _, plugin in ipairs(plugins) do for _, plugin in ipairs(plugins) do
local installed = false local installed = false
local lazy_installed = pcall(require, "lazy") if simple then
if lazy_installed then installed = pcall(require, plugin)
installed = require("lazy.core.config").plugins[plugin] ~= nil else
end local lazy_installed = pcall(require, "lazy")
local packer_installed = pcall(require, "packer_plugins") if lazy_installed then
if packer_installed then installed = require("lazy.core.config").plugins[plugin] ~= nil
---@diagnostic disable-next-line: undefined-field end
installed = _G.packer_plugins and _G.packer_plugins[plugin] ~= nil local packer_installed = pcall(require, "packer_plugins")
end if packer_installed then
if vim.fn.exists("g:plugs") == 1 then ---@diagnostic disable-next-line: undefined-field
installed = vim.g.plugs[plugin] ~= nil installed = _G.packer_plugins and _G.packer_plugins[plugin] ~= nil
end end
if not installed then if vim.fn.exists("g:plugs") == 1 then
local has_plug = pcall(require, plugin) installed = vim.g.plugs[plugin] ~= nil
if has_plug then end
installed = true if not installed then
local has_plug = pcall(require, plugin)
if has_plug then
installed = true
end
end end
end end
installed_plugins[plugin] = installed installed_plugins[plugin] = installed
@@ -548,14 +604,65 @@ function M.is_installed(plugins)
end end
end end
---@function Condition function to check filetype is not in list -- Function to create a floating terminal window
---@param disabled_filetypes string[] The list of filetypes to check function M.open_floating_terminal()
---@return boolean|function true if filetype is not in list, false otherwise -- Create a scratch buffer specifically for the terminal
function M.disable_on_filetypes(disabled_filetypes) local buf = vim.api.nvim_create_buf(false, true) -- Create an unnamed, non-file, scratch buffer
return function()
local filetype = vim.bo.filetype if not buf or buf == 0 then
return not vim.tbl_contains(disabled_filetypes, filetype) vim.notify("Failed to create buffer", vim.log.levels.ERROR)
return
end end
-- Get the dimensions of the current editor window
-- This helps us center the floating window
local ui = vim.api.nvim_list_uis()[1]
local width = ui.width
local height = ui.height
local win_width = math.floor(width * 0.8)
local win_height = math.floor(height * 0.8)
-- Define settings of the floating window, sizing it to 80% of the full editor size
local win_opts = {
style = "minimal", -- Minimal UI, no status line or tab line
relative = "editor", -- Float relative to the whole editor UI
width = win_width, -- Set width to 80% of editor width
height = win_height, -- Set height to 80% of editor height
row = math.floor((height - win_height) / 2), -- Centered vertically
col = math.floor((width - win_width) / 2), -- Centered horizontally
border = "rounded", -- Add a border for aesthetics (can be 'single', 'double', etc.)
}
-- Open the floating window with our newly created buffer
local win = vim.api.nvim_open_win(buf, true, win_opts)
-- Check if the window was created successfully
if not win or win == 0 then
vim.notify("Failed to create floating window", vim.log.levels.ERROR)
return
end
-- Set very specific buffer and window configurations
vim.api.nvim_set_option_value("bufhidden", "wipe", { buf = buf }) -- Auto-remove when the buffer is closed
vim.api.nvim_set_option_value("winblend", 10, { win = win }) -- Add slight transparency to the floating window
-- Now that the floating window is ready, we run the terminal shell in the created buffer
-- Open the terminal in the buffer when we're sure the buffer is set up in the float
vim.fn.termopen(vim.o.shell, {
on_exit = function()
-- Safety measure: Ensure the window still exists before trying to close it
if vim.api.nvim_win_is_valid(win) then
-- Notify the user that the terminal has closed
vim.notify("Terminal closed", vim.log.levels.INFO)
-- Close and wipe the associated floating window and its buffer
vim.api.nvim_win_close(win, true) -- Force close the terminal window
end
end,
})
-- Switch focus to the terminal window in the floating buffer and enter insert mode
vim.api.nvim_set_current_win(win)
vim.cmd("startinsert!") -- Automatically enter insert mode within the terminal
end end
---@function Helper function to add keymaps with common properties ---@function Helper function to add keymaps with common properties