feat: enhance editor with treesitter, autotag, search/replace, folds, git, and UI plugins

This commit is contained in:
sankalp committed 2025-10-14 22:20:57 +05:45
1 parent 07e3442b1e
commit 06e05e042d
12 files changed
+476 -483

No files matched your search

+29
View File
@@ -109,3 +109,32 @@ map({ 'n', 'v' }, 'L', '$', { desc = 'Move to the end of the line' })
-- Search inside visually highlighted text.
map('x', 'g/', '<esc>/\\%V', { silent = false, desc = 'Search inside visual selection' })
-- Search & replace in current file/line
map('v', '<leader>rw', '"9y:%s@<c-r>9@<c-r>9@g<left><left>', { desc = 'Search & replace selection', silent = false })
map('n', '<leader>rw', 'viw"9y:%s@<c-r>9@<c-r>9@g<left><left>', { desc = 'Search & replace word', silent = false })
map(
'v',
'<leader>rl',
'"9y:s@<c-r>9@<c-r>9@g<left><left>',
{ desc = 'Search & replace in current line', silent = false }
)
map(
'n',
'<leader>rl',
'viw"9y:s@<c-r>9@<c-r>9@g<left><left>',
{ desc = 'Search & replace word in current line', silent = false }
)
-- Folds
map('n', '<leader><', function()
if not vim.opt.foldmethod then
vim.opt.foldmethod = 'indent'
end
vim.cmd('normal! zM')
end, { desc = 'Fold all' })
map('n', '<leader>>', function()
vim.opt.foldenable = false
vim.cmd('normal! zR')
end, { desc = 'Open all folds' })
+57
View File
@@ -0,0 +1,57 @@
return {
-- auto pairs
{
'windwp/nvim-autopairs',
enabled = false,
event = 'InsertEnter',
config = function()
local npairs = require('nvim-autopairs')
npairs.setup({
check_ts = true,
enable_check_bracket_line = true,
fast_wrap = {},
map_cr = true,
map_bs = true,
})
end,
},
-- auto tag
{
'windwp/nvim-ts-autotag',
ft = {
'html',
'xml',
'javascript',
'typescript',
'javascriptreact',
'typescriptreact',
'jsx',
'tsx',
'vue',
'svelte',
'markdown',
'htmldjango',
},
event = 'InsertEnter',
lazy = true,
config = function()
require('nvim-ts-autotag').setup({
enable_close = true,
enable_rename = true,
enable_close_on_slash = true,
})
end,
},
-- split join code
{
'Wansmer/treesj',
keys = { '<space>m', '<space>j', '<space>s' },
dependencies = { 'nvim-treesitter/nvim-treesitter' }, -- if you install parsers with `nvim-treesitter`
config = function()
require('treesj').setup()
end,
},
}
+1 -41
View File
@@ -24,6 +24,7 @@ return {
end,
},
-- comment
{
'numToStr/Comment.nvim',
version = false,
@@ -88,47 +89,6 @@ return {
opts = {},
},
-- inline diagnostic
{
'rachartier/tiny-inline-diagnostic.nvim',
event = 'VeryLazy',
priority = 1000,
config = function()
require('tiny-inline-diagnostic').setup()
vim.diagnostic.config({ virtual_text = false }) -- Disable default virtual text
end,
},
-- code action
{
'rachartier/tiny-code-action.nvim',
dependencies = {
{
'folke/snacks.nvim',
opts = {
terminal = {},
},
},
},
event = 'LspAttach',
config = function()
local codeaction = require('tiny-code-action')
codeaction.setup({
picker = {
'buffer',
opts = {
auto_preview = true,
hotkeys = true,
hotkeys_mode = 'sequential',
},
},
})
vim.keymap.set('n', '<leader>.', codeaction.code_action)
end,
},
-- visual multi
{
'mg979/vim-visual-multi',
+3 -3
View File
@@ -23,8 +23,8 @@ return {
},
signs_staged_enable = true,
signcolumn = true, -- Toggle with `:Gitsigns toggle_signs`
numhl = false, -- Toggle with `:Gitsigns toggle_numhl`
linehl = false, -- Toggle with `:Gitsigns toggle_linehl`
numhl = false, -- Toggle with `:Gitsigns toggle_numhl`
linehl = false, -- Toggle with `:Gitsigns toggle_linehl`
word_diff = false, -- Toggle with `:Gitsigns toggle_word_diff`
watch_gitdir = {
follow_files = true,
@@ -43,7 +43,7 @@ return {
current_line_blame_formatter = '<author>, <author_time:%R> - <summary>',
sign_priority = 6,
update_debounce = 100,
status_formatter = nil, -- Use default
status_formatter = nil, -- Use default
max_file_length = 40000, -- Disable if file is longer than this (in lines)
preview_config = {
-- Options passed to nvim_open_win
-145
View File
@@ -1,145 +0,0 @@
return {
-- treesitter
{
'nvim-treesitter/nvim-treesitter',
build = ':TSUpdate',
event = { 'BufReadPost', 'BufNewFile' },
config = function()
require('nvim-treesitter').setup({
ensure_installed = {
'c',
'markdown',
'python',
'java',
'cpp',
'bash',
'lua',
'make',
'latex',
'json',
'jsonc',
'sql',
'yaml',
'toml',
'javascript',
'typescript',
'gitignore',
'go',
'rust',
'html',
'css',
'scss',
'markdown_inline',
},
auto_install = true,
highlight = {
enable = true,
additional_vim_regex_highlighting = true,
},
indent = {
enable = true,
},
})
end,
},
-- rendering for html, latex, md
{
'OXY2DEV/markview.nvim',
lazy = false,
-- to load before treesitter
priority = 45,
config = function()
require('markview').setup({
markdown = {
code_blocks = { sign = false },
},
})
end,
},
-- markdown preview
{
'iamcco/markdown-preview.nvim',
build = 'cd app && yarn install',
init = function()
vim.g.mkdp_filetypes = { 'markdown' }
end,
ft = 'markdown',
cmd = { 'MarkdownPreviewToggle', 'MarkdownPreview' },
},
{
'danymat/neogen',
dependencies = { 'nvim-treesitter/nvim-treesitter' },
opts = {
snippet_engine = 'luasnip',
languages = {
python = {
template = {
annotation_convention = 'google_docstrings',
},
},
},
},
},
-- auto pairs
{
'windwp/nvim-autopairs',
enabled = false,
event = 'InsertEnter',
config = function()
local npairs = require('nvim-autopairs')
npairs.setup({
check_ts = true,
enable_check_bracket_line = true,
fast_wrap = {},
map_cr = true,
map_bs = true,
})
end,
},
{
'windwp/nvim-ts-autotag',
ft = {
'html',
'xml',
'javascript',
'typescript',
'javascriptreact',
'typescriptreact',
'jsx',
'tsx',
'vue',
'svelte',
'markdown',
},
event = 'InsertEnter',
lazy = true,
config = function()
require('nvim-ts-autotag').setup({
enable_close = true,
enable_rename = true,
enable_close_on_slash = true,
})
end,
},
{
'Wansmer/treesj',
keys = { '<space>m', '<space>j', '<space>s' },
dependencies = { 'nvim-treesitter/nvim-treesitter' }, -- if you install parsers with `nvim-treesitter`
config = function()
require('treesj').setup()
end,
},
{
'davidmh/mdx.nvim',
config = true,
dependencies = { 'nvim-treesitter/nvim-treesitter' },
},
}
+41
View File
@@ -66,4 +66,45 @@ return {
})
end,
},
-- inline diagnostic
{
'rachartier/tiny-inline-diagnostic.nvim',
event = 'VeryLazy',
priority = 1000,
config = function()
require('tiny-inline-diagnostic').setup()
vim.diagnostic.config({ virtual_text = false }) -- Disable default virtual text
end,
},
-- code action
{
'rachartier/tiny-code-action.nvim',
dependencies = {
{
'folke/snacks.nvim',
opts = {
terminal = {},
},
},
},
event = 'LspAttach',
config = function()
local codeaction = require('tiny-code-action')
codeaction.setup({
picker = {
'buffer',
opts = {
auto_preview = true,
hotkeys = true,
hotkeys_mode = 'sequential',
},
},
})
vim.keymap.set('n', '<leader>.', codeaction.code_action)
end,
},
}
+45
View File
@@ -0,0 +1,45 @@
return {
-- treesitter
{
'nvim-treesitter/nvim-treesitter',
build = ':TSUpdate',
event = { 'BufReadPost', 'BufNewFile' },
config = function()
require('nvim-treesitter').setup({
ensure_installed = {
'c',
'markdown',
'python',
'java',
'cpp',
'bash',
'lua',
'make',
'latex',
'json',
'jsonc',
'sql',
'yaml',
'toml',
'javascript',
'typescript',
'gitignore',
'go',
'rust',
'html',
'css',
'scss',
'markdown_inline',
},
auto_install = true,
highlight = {
enable = true,
additional_vim_regex_highlighting = true,
},
indent = {
enable = true,
},
})
end,
},
}
+116
View File
@@ -0,0 +1,116 @@
return {
-- rendering for html, latex, md
{
'OXY2DEV/markview.nvim',
lazy = false,
-- to load before treesitter
priority = 45,
config = function()
require('markview').setup({
markdown = {
code_blocks = { sign = false },
},
})
end,
},
-- markdown preview
{
'iamcco/markdown-preview.nvim',
build = 'cd app && yarn install',
init = function()
vim.g.mkdp_filetypes = { 'markdown' }
end,
ft = 'markdown',
cmd = { 'MarkdownPreviewToggle', 'MarkdownPreview' },
},
-- fold
{
'kevinhwang91/nvim-ufo',
event = { 'BufReadPost', 'BufNewFile' },
dependencies = { 'kevinhwang91/promise-async', event = 'BufReadPost' },
opts = {
provider_selector = function()
return { 'lsp', 'indent' }
end,
fold_virt_text_handler = function(virtText, lnum, endLnum, width, truncate)
local newVirtText = {}
local suffix = (' … %d '):format(endLnum - lnum)
local sufWidth = vim.fn.strdisplaywidth(suffix)
local targetWidth = width - sufWidth
local curWidth = 0
for _, chunk in ipairs(virtText) do
local chunkText = chunk[1]
local chunkWidth = vim.fn.strdisplaywidth(chunkText)
if targetWidth > curWidth + chunkWidth then
table.insert(newVirtText, chunk)
else
chunkText = truncate(chunkText, targetWidth - curWidth)
local hlGroup = chunk[2]
table.insert(newVirtText, { chunkText, hlGroup })
chunkWidth = vim.fn.strdisplaywidth(chunkText)
-- str width returned from truncate() may less than 2nd argument, need padding
if curWidth + chunkWidth < targetWidth then
suffix = suffix .. (' '):rep(targetWidth - curWidth - chunkWidth)
end
break
end
curWidth = curWidth + chunkWidth
end
table.insert(newVirtText, { suffix, 'MoreMsg' })
return newVirtText
end,
open_fold_hl_timeout = 0,
},
keys = {
{ 'fd', 'zd', desc = 'Delete fold under cursor' },
{ 'fo', 'zo', desc = 'Open fold under cursor' },
{ 'fO', 'zO', desc = 'Open all folds under cursor' },
{ 'fc', 'zC', desc = 'Close all folds under cursor' },
{ 'fa', 'za', desc = 'Toggle fold under cursor' },
{ 'fA', 'zA', desc = 'Toggle all folds under cursor' },
{ 'fv', 'zv', desc = 'Show cursor line' },
{
'fM',
function()
require('ufo').closeAllFolds()
end,
desc = 'Close all folds',
},
{
'fR',
function()
require('ufo').openAllFolds()
end,
desc = 'Open all folds',
},
{
'fm',
function()
require('ufo').closeFoldsWith()
end,
desc = 'Fold more',
},
{
'fr',
function()
require('ufo').openFoldsExceptKinds()
end,
desc = 'Fold less',
},
{ 'fx', 'zx', desc = 'Update folds' },
{ 'fz', 'zz', desc = 'Center this line' },
{ 'ft', 'zt', desc = 'Top this line' },
{ 'fb', 'zb', desc = 'Bottom this line' },
{ 'fg', 'zg', desc = 'Add word to spell list' },
{ 'fw', 'zw', desc = 'Mark word as bad/misspelling' },
{ 'fe', 'ze', desc = 'Right this line' },
{ 'fE', 'zE', desc = 'Delete all folds in current buffer' },
{ 'fs', 'zs', desc = 'Left this line' },
{ 'fH', 'zH', desc = 'Half screen to the left' },
{ 'fL', 'zL', desc = 'Half screen to the right' },
},
},
}
+181
View File
@@ -0,0 +1,181 @@
return {
{
'danymat/neogen',
dependencies = { 'nvim-treesitter/nvim-treesitter' },
opts = {
snippet_engine = 'luasnip',
languages = {
python = {
template = {
annotation_convention = 'google_docstrings',
},
},
},
},
},
{
'davidmh/mdx.nvim',
config = true,
dependencies = { 'nvim-treesitter/nvim-treesitter' },
},
-- better escape
{
'max397574/better-escape.nvim',
config = function()
require('better_escape').setup({
mappings = {
-- i for insert, other modes are the first letter too
i = {
-- map kj to exit insert mode
k = {
j = '<Esc>',
},
-- map jk and jj to exit insert mode
j = {
k = '<Esc>',
j = '<Esc>',
},
-- disable jj
j = {
j = false,
},
},
},
})
end,
},
-- Navigator
{
'numToStr/Navigator.nvim',
event = 'VeryLazy',
config = function()
require('Navigator').setup({
auto_save = 'current',
disable_on_zoom = false,
mux = 'auto',
})
end,
},
-- float terminal
{
'akinsho/toggleterm.nvim',
cmd = { 'ToggleTerm' },
version = '*',
config = function()
require('toggleterm').setup({
size = 10,
open_mapping = [[<c-\>]],
hide_numbers = true,
shade_filetypes = {},
shade_terminals = true,
shading_factor = '2',
start_in_insert = true,
insert_mappings = true,
terminal_mappings = true,
persist_size = true,
direction = 'float', -- 'vertical' | 'horizontal' | 'tab' | 'float'
close_on_exit = true,
shell = vim.o.shell,
float_opts = {
border = 'curved', -- 'single', 'double', 'shadow', etc.
winblend = 0, -- Set to 0 for full transparency
highlights = {
border = 'Normal',
background = 'Normal',
},
},
})
end,
},
-- smooth scrolling
{
'karb94/neoscroll.nvim',
opts = {},
},
-- discord presence
-- {
-- "vyfor/cord.nvim",
-- event = "VeryLazy",
-- },
-- uv
{
'benomahony/uv.nvim',
ft = 'python',
event = 'BufReadPre',
opts = {
picker_integration = true,
keymaps = {
prefix = '<leader>u', -- Main prefix for uv commands
commands = true, -- Show uv commands menu (<leader>x)
run_file = true, -- Run current file (<leader>xr)
run_selection = true, -- Run selected code (<leader>xs)
run_function = true, -- Run function (<leader>xf)
venv = true, -- Environment management (<leader>xe)
init = true, -- Initialize uv project (<leader>xi)
add = true, -- Add a package (<leader>xa)
remove = true, -- Remove a package (<leader>xd)
sync = true, -- Sync packages (<leader>xc)
sync_all = true, -- Sync all packages, extras and groups (<leader>xC)
},
},
},
-- wakatime
{ 'wakatime/vim-wakatime', event = 'VimEnter', lazy = false },
-- workflow
{
'm4xshen/hardtime.nvim',
lazy = false,
opts = {},
},
-- file operations
{
'chrisgrieser/nvim-genghis',
keys = {
{
'<leader>fn',
function()
require('genghis').createNewFile()
end,
desc = 'New File',
},
{
'<leader>fd',
function()
require('genghis').duplicateFile()
end,
desc = 'Duplicate File',
},
{
'<leader>fr',
function()
require('genghis').renameFile()
end,
desc = 'Rename File',
},
{
'<leader>fx',
function()
require('genghis').chmodx()
end,
desc = 'Make Executable',
},
},
},
-- Working with file permissions
{
'lambdalisue/vim-suda',
cmd = { 'SudaRead', 'SudaWrite' },
},
}
-288
View File
@@ -1,288 +0,0 @@
return {
--harpoon
{
'ThePrimeagen/harpoon',
branch = 'harpoon2',
dependencies = { 'nvim-lua/plenary.nvim' },
config = function()
local harpoon = require('harpoon')
harpoon:setup()
vim.keymap.set('n', '<leader>ha', function()
harpoon:list():add()
end, { desc = 'Harpoon add file' })
vim.keymap.set('n', '<leader>hl', function()
harpoon.ui:toggle_quick_menu(harpoon:list())
end, { desc = 'Harpoon quick menu' })
for i = 1, 9 do
vim.keymap.set('n', '<A-' .. i .. '>', function()
harpoon:list():select(i)
end, { desc = 'Harpoon to file ' .. i })
end
end,
},
-- better escape
{
'max397574/better-escape.nvim',
config = function()
require('better_escape').setup({
mappings = {
-- i for insert, other modes are the first letter too
i = {
-- map kj to exit insert mode
k = {
j = '<Esc>',
},
-- map jk and jj to exit insert mode
j = {
k = '<Esc>',
j = '<Esc>',
},
-- disable jj
j = {
j = false,
},
},
},
})
end,
},
-- Navigator
{
'numToStr/Navigator.nvim',
event = 'VeryLazy',
config = function()
require('Navigator').setup({
auto_save = 'current',
disable_on_zoom = false,
mux = 'auto',
})
end,
},
-- float terminal
{
'akinsho/toggleterm.nvim',
cmd = { 'ToggleTerm' },
version = '*',
config = function()
require('toggleterm').setup({
size = 10,
open_mapping = [[<c-\>]],
hide_numbers = true,
shade_filetypes = {},
shade_terminals = true,
shading_factor = '2',
start_in_insert = true,
insert_mappings = true,
terminal_mappings = true,
persist_size = true,
direction = 'float', -- 'vertical' | 'horizontal' | 'tab' | 'float'
close_on_exit = true,
shell = vim.o.shell,
float_opts = {
border = 'curved', -- 'single', 'double', 'shadow', etc.
winblend = 0, -- Set to 0 for full transparency
highlights = {
border = 'Normal',
background = 'Normal',
},
},
})
end,
},
-- smooth scrolling
{
'karb94/neoscroll.nvim',
opts = {},
},
-- discord presence
-- {
-- "vyfor/cord.nvim",
-- event = "VeryLazy",
-- },
-- uv
{
'benomahony/uv.nvim',
ft = 'python',
event = 'BufReadPre',
opts = {
picker_integration = true,
keymaps = {
prefix = '<leader>u', -- Main prefix for uv commands
commands = true, -- Show uv commands menu (<leader>x)
run_file = true, -- Run current file (<leader>xr)
run_selection = true, -- Run selected code (<leader>xs)
run_function = true, -- Run function (<leader>xf)
venv = true, -- Environment management (<leader>xe)
init = true, -- Initialize uv project (<leader>xi)
add = true, -- Add a package (<leader>xa)
remove = true, -- Remove a package (<leader>xd)
sync = true, -- Sync packages (<leader>xc)
sync_all = true, -- Sync all packages, extras and groups (<leader>xC)
},
},
},
{ 'wakatime/vim-wakatime', event = 'VimEnter', lazy = false },
{
'm4xshen/hardtime.nvim',
lazy = false,
opts = {},
},
-- file operations
{
'chrisgrieser/nvim-genghis',
keys = {
{
'<leader>fn',
function()
require('genghis').createNewFile()
end,
desc = 'New File',
},
{
'<leader>fd',
function()
require('genghis').duplicateFile()
end,
desc = 'Duplicate File',
},
{
'<leader>fr',
function()
require('genghis').renameFile()
end,
desc = 'Rename File',
},
{
'<leader>fx',
function()
require('genghis').chmodx()
end,
desc = 'Make Executable',
},
},
},
-- fold
{
'kevinhwang91/nvim-ufo',
event = { 'BufReadPost', 'BufNewFile' },
dependencies = { 'kevinhwang91/promise-async', event = 'BufReadPost' },
opts = {
provider_selector = function()
return { 'lsp', 'indent' }
end,
fold_virt_text_handler = function(virtText, lnum, endLnum, width, truncate)
local newVirtText = {}
local suffix = (' … %d '):format(endLnum - lnum)
local sufWidth = vim.fn.strdisplaywidth(suffix)
local targetWidth = width - sufWidth
local curWidth = 0
for _, chunk in ipairs(virtText) do
local chunkText = chunk[1]
local chunkWidth = vim.fn.strdisplaywidth(chunkText)
if targetWidth > curWidth + chunkWidth then
table.insert(newVirtText, chunk)
else
chunkText = truncate(chunkText, targetWidth - curWidth)
local hlGroup = chunk[2]
table.insert(newVirtText, { chunkText, hlGroup })
chunkWidth = vim.fn.strdisplaywidth(chunkText)
-- str width returned from truncate() may less than 2nd argument, need padding
if curWidth + chunkWidth < targetWidth then
suffix = suffix .. (' '):rep(targetWidth - curWidth - chunkWidth)
end
break
end
curWidth = curWidth + chunkWidth
end
table.insert(newVirtText, { suffix, 'MoreMsg' })
return newVirtText
end,
open_fold_hl_timeout = 0,
},
keys = {
{ 'fd', 'zd', desc = 'Delete fold under cursor' },
{ 'fo', 'zo', desc = 'Open fold under cursor' },
{ 'fO', 'zO', desc = 'Open all folds under cursor' },
{ 'fc', 'zC', desc = 'Close all folds under cursor' },
{ 'fa', 'za', desc = 'Toggle fold under cursor' },
{ 'fA', 'zA', desc = 'Toggle all folds under cursor' },
{ 'fv', 'zv', desc = 'Show cursor line' },
{
'fM',
function()
require('ufo').closeAllFolds()
end,
desc = 'Close all folds',
},
{
'fR',
function()
require('ufo').openAllFolds()
end,
desc = 'Open all folds',
},
{
'fm',
function()
require('ufo').closeFoldsWith()
end,
desc = 'Fold more',
},
{
'fr',
function()
require('ufo').openFoldsExceptKinds()
end,
desc = 'Fold less',
},
{ 'fx', 'zx', desc = 'Update folds' },
{ 'fz', 'zz', desc = 'Center this line' },
{ 'ft', 'zt', desc = 'Top this line' },
{ 'fb', 'zb', desc = 'Bottom this line' },
{ 'fg', 'zg', desc = 'Add word to spell list' },
{ 'fw', 'zw', desc = 'Mark word as bad/misspelling' },
{ 'fe', 'ze', desc = 'Right this line' },
{ 'fE', 'zE', desc = 'Delete all folds in current buffer' },
{ 'fs', 'zs', desc = 'Left this line' },
{ 'fH', 'zH', desc = 'Half screen to the left' },
{ 'fL', 'zL', desc = 'Half screen to the right' },
},
},
-- Dimming the highlights of unused functions, variables, parameters, and more.
{
'zbirenbaum/neodim',
enabled = false,
event = 'LspAttach',
config = function()
require('neodim').setup({
alpha = 0.5,
blend_color = nil,
hide = {
underline = true,
virtual_text = true,
signs = true,
},
regex = {
'[uU]nused',
'[nN]ever [rR]ead',
'[nN]ot [rR]ead',
},
priority = 128,
disable = {},
})
end,
},
}
+2 -4
View File
@@ -34,7 +34,7 @@ return {
show_help = false,
show_keys = true,
triggers = {
{ '<auto>', mode = 'nvisoct' },
{ '<auto>', mode = 'nvisoct' },
{ '<leader>', mode = { 'n', 'v' } },
},
})
@@ -114,8 +114,6 @@ return {
{ '<leader>gw', ':lua require("snacks").gitbrowse()<cr>', desc = 'Git Browse' },
{ '<leader>gp', ':lua Snacks.picker.git_branches()<cr>', desc = 'Pick and Switch Git Branches' },
{ '<leader>h', group = 'Harpoon' },
{ '<leader>gt', group = 'Toggle' },
{ '<leader>gtb', ':Gitsigns toggle_current_line_blame<cr>', desc = 'Blame' },
{ '<leader>gtd', ':Gitsigns toggle_deleted<cr>', desc = 'Deleted' },
@@ -181,10 +179,10 @@ return {
{ '<leader>r', group = ' Refactor' },
{ '<leader>rd', '', desc = 'Go To Definition' }, -- treesitter navigation
{ '<leader>rD', '', desc = 'List Definition' },
{ '<leader>rh', '', desc = 'List Definition Head' },
{ '<leader>rj', '', desc = 'Next Usage' },
{ '<leader>rk', '', desc = 'Previous Usage' },
{ '<leader>rl', '', desc = 'List Definition' },
{ '<leader>rn', '', desc = 'Swap Next' },
{ '<leader>rp', '', desc = 'Swap Previous' },
{ '<leader>rr', '', desc = 'Smart Rename' },