Files
dotfiles/nvim/.config/nvim/lua/plugins/nvim-surround.lua
T

228 lines
6.9 KiB
Lua

-- nvim-surround configuration with autopairs, treesitter, and comment integration
-- Place this in ~/.config/nvim/lua/plugins/nvim-surround.lua (for lazy.nvim)
return {
-- nvim-surround: manipulate surroundings
{
"kylechui/nvim-surround",
version = "*",
event = "VeryLazy",
dependencies = {
"nvim-treesitter/nvim-treesitter",
"nvim-treesitter/nvim-treesitter-textobjects",
},
config = function()
require("nvim-surround").setup({
keymaps = {
insert = "<C-g>s",
insert_line = "<C-g>S",
normal = "ys",
normal_cur = "yss",
normal_line = "yS",
normal_cur_line = "ySS",
visual = "S",
visual_line = "gS",
delete = "ds",
change = "cs",
change_line = "cS",
},
-- Custom surrounds
surrounds = {
-- Function call surround
["f"] = {
add = function()
local result = require("nvim-surround.config").get_input("Enter function name: ")
if result then
return { { result .. "(" }, { ")" } }
end
end,
find = function()
return require("nvim-surround.config").get_selection({ motion = "a(" })
end,
delete = "^([^(]+%()().-(%))()$",
change = {
target = "^([^(]+%()().-(%))()$",
replacement = function()
local result = require("nvim-surround.config").get_input("Enter function name: ")
if result then
return { { result .. "(" }, { ")" } }
end
end,
},
},
-- Markdown code block
["c"] = {
add = function()
local lang = require("nvim-surround.config").get_input("Enter language: ")
return { { "```" .. (lang or "") }, { "```" } }
end,
},
-- HTML/JSX tag with class
["C"] = {
add = function()
local class = require("nvim-surround.config").get_input("Enter class name: ")
if class then
return { { '<div class="' .. class .. '">' }, { "</div>" } }
end
end,
},
-- Template literal (JavaScript/TypeScript)
["`"] = {
add = { "`", "`" },
find = "`.-`",
delete = "^(`)().-(`)()$",
},
},
-- Use treesitter for better text object detection
move_cursor = "begin",
indent_lines = function(start, stop)
local b = vim.bo
-- Only indent if the buffer is not a special filetype
if b.ft ~= "help" and b.ft ~= "man" and b.ft ~= "qf" then
vim.cmd(string.format("silent normal! %dG=%dG", start, stop))
end
end,
})
end,
},
-- nvim-autopairs: auto-close brackets with integration
{
"windwp/nvim-autopairs",
event = "InsertEnter",
dependencies = { "hrsh7th/nvim-cmp" },
config = function()
local npairs = require("nvim-autopairs")
local Rule = require("nvim-autopairs.rule")
local cond = require("nvim-autopairs.conds")
npairs.setup({
check_ts = true, -- Use treesitter
ts_config = {
lua = { "string", "source" },
javascript = { "string", "template_string" },
java = false,
},
disable_filetype = { "TelescopePrompt", "spectre_panel" },
fast_wrap = {
map = "<M-e>",
chars = { "{", "[", "(", '"', "'" },
pattern = string.gsub([[ [%'%"%)%>%]%)%}%,] ]], "%s+", ""),
offset = 0,
end_key = "$",
keys = "qwertyuiopzxcvbnmasdfghjkl",
check_comma = true,
highlight = "PmenuSel",
highlight_grey = "LineNr",
},
enable_moveright = true,
enable_afterquote = true,
enable_check_bracket_line = true,
enable_bracket_in_quote = true,
enable_abbr = false,
break_undo = true,
map_cr = true,
map_bs = true,
map_c_h = false,
map_c_w = false,
})
-- Add spacing inside pairs
local brackets = { { "(", ")" }, { "[", "]" }, { "{", "}" } }
npairs.add_rules({
Rule(" ", " "):with_pair(function(opts)
local pair = opts.line:sub(opts.col - 1, opts.col)
return vim.tbl_contains({
brackets[1][1] .. brackets[1][2],
brackets[2][1] .. brackets[2][2],
brackets[3][1] .. brackets[3][2],
}, pair)
end),
})
for _, bracket in pairs(brackets) do
npairs.add_rules({
Rule(bracket[1] .. " ", " " .. bracket[2])
:with_pair(function()
return false
end)
:with_move(function(opts)
return opts.prev_char:match(".%" .. bracket[2]) ~= nil
end)
:use_key(bracket[2]),
})
end
-- Add arrow function for JavaScript/TypeScript
npairs.add_rules({
Rule("%(.*%)%s*=>$", " { }", { "typescript", "typescriptreact", "javascript", "javascriptreact" })
:use_regex(true)
:set_end_pair_length(2),
})
-- Integration with nvim-cmp
local cmp_autopairs = require("nvim-autopairs.completion.cmp")
local cmp = require("cmp")
cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done())
end,
},
-- Comment.nvim: smart commenting with treesitter
{
"numToStr/Comment.nvim",
event = { "BufReadPre", "BufNewFile" },
dependencies = {
"nvim-treesitter/nvim-treesitter",
"JoosepAlviste/nvim-ts-context-commentstring", -- For better JSX/TSX comments
},
config = function()
require("Comment").setup({
-- Use treesitter for comment detection
pre_hook = require("ts_context_commentstring.integrations.comment_nvim").create_pre_hook(),
padding = true,
sticky = true,
ignore = "^$", -- Ignore empty lines
-- LHS of toggle mappings in NORMAL mode
toggler = {
line = "gcc", -- Line-comment toggle
block = "gbc", -- Block-comment toggle
},
-- LHS of operator-pending mappings in NORMAL and VISUAL mode
opleader = {
line = "gc", -- Line-comment keymap
block = "gb", -- Block-comment keymap
},
-- LHS of extra mappings
extra = {
above = "gcO", -- Add comment on the line above
below = "gco", -- Add comment on the line below
eol = "gcA", -- Add comment at the end of line
},
mappings = {
basic = true,
extra = true,
},
})
end,
},
-- nvim-ts-context-commentstring: JSX/TSX comment support
{
"JoosepAlviste/nvim-ts-context-commentstring",
lazy = true,
opts = {
enable_autocmd = false, -- Disable auto commands, Comment.nvim handles it
},
},
}