refactor: module structure
parent
6077a6376f
commit
ad0830b013
|
|
@ -3,251 +3,19 @@ if version.major == 0 and version.minor < 10 then
|
||||||
vim.notify("nvim-genghis requires at least nvim 0.10.", vim.log.levels.WARN)
|
vim.notify("nvim-genghis requires at least nvim 0.10.", vim.log.levels.WARN)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
local mv = require("genghis.file-movement")
|
-- redirect to `operations.copy` or `operations.file`
|
||||||
local u = require("genghis.utils")
|
setmetatable(M, {
|
||||||
|
__index = function(_, key)
|
||||||
local fn = vim.fn
|
return function(...)
|
||||||
local cmd = vim.cmd
|
local module = vim.startswith(key, "copy") and "copy" or "file"
|
||||||
local osPathSep = package.config:sub(1, 1)
|
require("genghis.operations." .. module)[key](...)
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
---Performing common file operation tasks
|
|
||||||
---@param op "rename"|"duplicate"|"new"|"newFromSel"|"move-rename"
|
|
||||||
local function fileOp(op)
|
|
||||||
local oldFilePath = vim.api.nvim_buf_get_name(0)
|
|
||||||
local oldName = vim.fs.basename(oldFilePath)
|
|
||||||
local dir = vim.fs.dirname(oldFilePath) -- same directory, *not* pwd
|
|
||||||
local oldNameNoExt = oldName:gsub("%.%w+$", "")
|
|
||||||
local oldExt = fn.expand("%:e")
|
|
||||||
if oldExt ~= "" then oldExt = "." .. oldExt end
|
|
||||||
local lspSupportsRenaming = mv.lspSupportsRenaming()
|
|
||||||
|
|
||||||
local prevReg
|
|
||||||
if op == "newFromSel" then
|
|
||||||
prevReg = fn.getreg("z")
|
|
||||||
u.leaveVisualMode()
|
|
||||||
cmd([['<,'>delete z]])
|
|
||||||
end
|
|
||||||
|
|
||||||
local promptStr, prefill
|
|
||||||
if op == "duplicate" then
|
|
||||||
promptStr = "Duplicate File as: "
|
|
||||||
prefill = oldNameNoExt .. "-1"
|
|
||||||
elseif op == "rename" then
|
|
||||||
promptStr = lspSupportsRenaming and "Rename File & Update Imports:" or "Rename File to:"
|
|
||||||
prefill = oldNameNoExt
|
|
||||||
elseif op == "move-rename" then
|
|
||||||
promptStr = lspSupportsRenaming and "Move-Rename File & Update Imports:"
|
|
||||||
or "Move & Rename File to:"
|
|
||||||
prefill = dir .. osPathSep
|
|
||||||
elseif op == "new" or op == "newFromSel" then
|
|
||||||
promptStr = "Name for New File: "
|
|
||||||
prefill = ""
|
|
||||||
end
|
|
||||||
|
|
||||||
vim.ui.input({
|
|
||||||
prompt = promptStr,
|
|
||||||
default = prefill,
|
|
||||||
completion = "dir", -- allows for completion via cmp-omni
|
|
||||||
}, function(newName)
|
|
||||||
cmd.redraw() -- Clear message area from ui.input prompt
|
|
||||||
if not newName then return end -- input has been canceled
|
|
||||||
|
|
||||||
if op == "move-rename" and newName:find("/$") then newName = newName .. oldName end
|
|
||||||
if op == "new" and newName == "" then newName = "Untitled" end
|
|
||||||
|
|
||||||
-- GUARD Validate filename
|
|
||||||
local invalidName = newName:find("^%s+$")
|
|
||||||
or newName:find("[\\:]")
|
|
||||||
or (newName:find("^/") and not op == "move-rename")
|
|
||||||
local sameName = newName == oldName
|
|
||||||
local emptyInput = newName == ""
|
|
||||||
|
|
||||||
if invalidName or sameName or emptyInput then
|
|
||||||
if op == "newFromSel" then
|
|
||||||
cmd.undo() -- undo deletion
|
|
||||||
fn.setreg("z", prevReg) -- restore register content
|
|
||||||
end
|
|
||||||
if invalidName or emptyInput then
|
|
||||||
u.notify("Invalid filename.", "error")
|
|
||||||
elseif sameName then
|
|
||||||
u.notify("Cannot use the same filename.", "warn")
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
end,
|
||||||
-- DETERMINE PATH AND EXTENSION
|
})
|
||||||
local hasPath = newName:find(osPathSep)
|
|
||||||
if hasPath then
|
|
||||||
local newFolder = vim.fs.dirname(newName)
|
|
||||||
fn.mkdir(newFolder, "p") -- create folders if necessary
|
|
||||||
end
|
|
||||||
|
|
||||||
local extProvided = newName:find(".%.[^/]*$") -- non-leading dot to not include dotfiles without extension
|
|
||||||
if not extProvided then newName = newName .. oldExt end
|
|
||||||
local newFilePath = (op == "move-rename") and newName or dir .. osPathSep .. newName
|
|
||||||
|
|
||||||
if u.fileExists(newFilePath) then
|
|
||||||
u.notify(("File with name %q already exists."):format(newFilePath), "error")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- EXECUTE FILE OPERATION
|
|
||||||
cmd.update()
|
|
||||||
if op == "duplicate" then
|
|
||||||
local success = vim.uv.fs_copyfile(oldFilePath, newFilePath)
|
|
||||||
if success then
|
|
||||||
cmd.edit(newFilePath)
|
|
||||||
u.notify(("Duplicated %q as %q."):format(oldName, newName))
|
|
||||||
end
|
|
||||||
elseif op == "rename" or op == "move-rename" then
|
|
||||||
mv.sendWillRenameToLsp(oldFilePath, newFilePath)
|
|
||||||
local success = mv.moveFile(oldFilePath, newFilePath)
|
|
||||||
if success then
|
|
||||||
cmd.edit(newFilePath)
|
|
||||||
u.bwipeout("#")
|
|
||||||
u.notify(("Renamed %q to %q."):format(oldName, newName))
|
|
||||||
if lspSupportsRenaming then vim.cmd.wall() end
|
|
||||||
end
|
|
||||||
elseif op == "new" or op == "newFromSel" then
|
|
||||||
cmd.edit(newFilePath)
|
|
||||||
if op == "newFromSel" then
|
|
||||||
cmd("put z") -- cmd.put("z") does not work
|
|
||||||
fn.setreg("z", prevReg) -- restore register content
|
|
||||||
end
|
|
||||||
cmd.write(newFilePath)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.renameFile() fileOp("rename") end
|
|
||||||
function M.moveAndRenameFile() fileOp("move-rename") end
|
|
||||||
function M.duplicateFile() fileOp("duplicate") end
|
|
||||||
function M.createNewFile() fileOp("new") end
|
|
||||||
function M.moveSelectionToNewFile() fileOp("newFromSel") end
|
|
||||||
|
|
||||||
function M.moveToFolderInCwd()
|
|
||||||
local curFilePath = vim.api.nvim_buf_get_name(0)
|
|
||||||
local parentOfCurFile = vim.fs.dirname(curFilePath) .. osPathSep
|
|
||||||
local filename = vim.fs.basename(curFilePath)
|
|
||||||
local lspSupportsRenaming = mv.lspSupportsRenaming()
|
|
||||||
local cwd = vim.uv.cwd() .. osPathSep
|
|
||||||
|
|
||||||
-- determine destinations in cwd
|
|
||||||
local foldersInCwd = vim.fs.find(function(name, path)
|
|
||||||
local fullPath = path .. osPathSep .. name .. osPathSep
|
|
||||||
local relative_path = osPathSep .. vim.fn.fnamemodify(fullPath, ":~:.")
|
|
||||||
local ignoreDirs = relative_path:find("/%.git/")
|
|
||||||
or relative_path:find("%.app/") -- macos pseudo-folders
|
|
||||||
or relative_path:find("/node_modules/")
|
|
||||||
or relative_path:find("/%.venv/")
|
|
||||||
or relative_path:find("/%.") -- hidden folders
|
|
||||||
or fullPath == parentOfCurFile
|
|
||||||
return not ignoreDirs
|
|
||||||
end, { type = "directory", limit = math.huge })
|
|
||||||
|
|
||||||
-- sort by modification time
|
|
||||||
table.sort(foldersInCwd, function(a, b)
|
|
||||||
local aMtime = vim.uv.fs_stat(a).mtime.sec
|
|
||||||
local bMtime = vim.uv.fs_stat(b).mtime.sec
|
|
||||||
return aMtime > bMtime
|
|
||||||
end)
|
|
||||||
-- insert cwd at bottom, since modification of is likely due to subfolders
|
|
||||||
if cwd ~= parentOfCurFile then table.insert(foldersInCwd, cwd) end
|
|
||||||
|
|
||||||
-- prompt user and move
|
|
||||||
local promptStr = "Choose Destination Folder"
|
|
||||||
if lspSupportsRenaming then promptStr = promptStr .. " (with updated imports)" end
|
|
||||||
vim.ui.select(foldersInCwd, {
|
|
||||||
prompt = promptStr,
|
|
||||||
kind = "genghis.moveToFolderInCwd",
|
|
||||||
format_item = function(path) return path:sub(#cwd) end, -- only relative path
|
|
||||||
}, function(destination)
|
|
||||||
if not destination then return end
|
|
||||||
local newFilePath = destination .. osPathSep .. filename
|
|
||||||
|
|
||||||
-- GUARD
|
|
||||||
if u.fileExists(newFilePath) then
|
|
||||||
u.notify(("File %q already exists at %q."):format(filename, destination), "error")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
mv.sendWillRenameToLsp(curFilePath, newFilePath)
|
|
||||||
local success = mv.moveFile(curFilePath, newFilePath)
|
|
||||||
if success then
|
|
||||||
cmd.edit(newFilePath)
|
|
||||||
u.bwipeout("#")
|
|
||||||
local msg = ("Moved %q to %q"):format(filename, destination)
|
|
||||||
local append = lspSupportsRenaming and " and updated imports." or "."
|
|
||||||
u.notify(msg .. append)
|
|
||||||
if lspSupportsRenaming then vim.cmd.wall() end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
---copying file information
|
|
||||||
---@param expandOperation string
|
|
||||||
local function copyOp(expandOperation)
|
|
||||||
local register = "+"
|
|
||||||
local toCopy = fn.expand(expandOperation)
|
|
||||||
fn.setreg(register, toCopy)
|
|
||||||
vim.notify(toCopy, vim.log.levels.INFO, { title = "Copied" })
|
|
||||||
end
|
|
||||||
|
|
||||||
-- DOCS for the modifiers
|
|
||||||
-- https://neovim.io/doc/user/builtin.html#expand()
|
|
||||||
-- https://neovim.io/doc/user/cmdline.html#filename-modifiers
|
|
||||||
function M.copyFilepath() copyOp("%:p") end
|
|
||||||
function M.copyFilepathWithTilde() copyOp("%:~") end
|
|
||||||
function M.copyFilename() copyOp("%:t") end
|
|
||||||
function M.copyRelativePath() copyOp("%:.") end
|
|
||||||
function M.copyDirectoryPath() copyOp("%:p:h") end
|
|
||||||
function M.copyRelativeDirectoryPath() copyOp("%:.:h") end
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
---Makes current file executable
|
|
||||||
function M.chmodx()
|
|
||||||
local filename = vim.api.nvim_buf_get_name(0)
|
|
||||||
local perm = fn.getfperm(filename)
|
|
||||||
perm = perm:gsub("r(.)%-", "r%1x") -- add x to every group that has r
|
|
||||||
fn.setfperm(filename, perm)
|
|
||||||
u.notify("Execution Permission granted.")
|
|
||||||
cmd.edit()
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param opts? { trashCmd: string }
|
|
||||||
function M.trashFile(opts)
|
|
||||||
local userCmd = opts and opts.trashCmd
|
|
||||||
local system = vim.uv.os_uname().sysname:lower()
|
|
||||||
local defaultCmd
|
|
||||||
if system == "darwin" then defaultCmd = "trash" end
|
|
||||||
if system:find("windows") then defaultCmd = "trash" end
|
|
||||||
if system:find("linux") then defaultCmd = "gio trash" end
|
|
||||||
local trashCmd = userCmd or defaultCmd
|
|
||||||
assert(defaultCmd, "Unknown operating system. Please provide a custom trashCmd.")
|
|
||||||
|
|
||||||
local trashArgs = vim.split(trashCmd, " ")
|
|
||||||
local oldFilePath = vim.api.nvim_buf_get_name(0)
|
|
||||||
table.insert(trashArgs, oldFilePath)
|
|
||||||
|
|
||||||
cmd("silent! update")
|
|
||||||
local oldName = vim.fs.basename(oldFilePath)
|
|
||||||
local result = vim.system(trashArgs):wait()
|
|
||||||
if result.code == 0 then
|
|
||||||
u.bwipeout()
|
|
||||||
u.notify(("%q deleted"):format(oldName))
|
|
||||||
else
|
|
||||||
local outmsg = (result.stdout or "") .. (result.stderr or "")
|
|
||||||
u.notify(("Trashing %q failed: " .. outmsg):format(oldName), "error")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
return M
|
return M
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
local M = {}
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@param expandOperation string
|
||||||
|
local function copyOp(expandOperation)
|
||||||
|
local register = "+"
|
||||||
|
local toCopy = vim.fn.expand(expandOperation)
|
||||||
|
vim.fn.setreg(register, toCopy)
|
||||||
|
vim.notify(toCopy, vim.log.levels.INFO, { title = "Copied" })
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DOCS for the modifiers
|
||||||
|
-- https://neovim.io/doc/user/builtin.html#expand()
|
||||||
|
-- https://neovim.io/doc/user/cmdline.html#filename-modifiers
|
||||||
|
function M.copyFilepath() copyOp("%:p") end
|
||||||
|
function M.copyFilepathWithTilde() copyOp("%:~") end
|
||||||
|
function M.copyFilename() copyOp("%:t") end
|
||||||
|
function M.copyRelativePath() copyOp("%:.") end
|
||||||
|
function M.copyDirectoryPath() copyOp("%:p:h") end
|
||||||
|
function M.copyRelativeDirectoryPath() copyOp("%:.:h") end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
return M
|
||||||
|
|
@ -0,0 +1,221 @@
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
local rename = require("genghis.support.lsp-rename")
|
||||||
|
local u = require("genghis.support.utils")
|
||||||
|
local osPathSep = package.config:sub(1, 1)
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---@param op "rename"|"duplicate"|"new"|"new-from-selection"|"move-rename"
|
||||||
|
local function fileOp(op)
|
||||||
|
local oldFilePath = vim.api.nvim_buf_get_name(0)
|
||||||
|
local oldName = vim.fs.basename(oldFilePath)
|
||||||
|
local dir = vim.fs.dirname(oldFilePath) -- same directory, *not* pwd
|
||||||
|
local oldNameNoExt = oldName:gsub("%.%w+$", "")
|
||||||
|
local oldExt = vim.fn.expand("%:e")
|
||||||
|
if oldExt ~= "" then oldExt = "." .. oldExt end
|
||||||
|
local lspSupportsRenaming = rename.lspSupportsRenaming()
|
||||||
|
|
||||||
|
local prevReg
|
||||||
|
if op == "new-from-selection" then
|
||||||
|
prevReg = vim.fn.getreg("z")
|
||||||
|
u.leaveVisualMode()
|
||||||
|
vim.cmd([['<,'>delete z]])
|
||||||
|
end
|
||||||
|
|
||||||
|
local promptStr, prefill
|
||||||
|
if op == "duplicate" then
|
||||||
|
promptStr = "Duplicate File as: "
|
||||||
|
prefill = oldNameNoExt .. "-1"
|
||||||
|
elseif op == "rename" then
|
||||||
|
promptStr = lspSupportsRenaming and "Rename File & Update Imports:" or "Rename File to:"
|
||||||
|
prefill = oldNameNoExt
|
||||||
|
elseif op == "move-rename" then
|
||||||
|
promptStr = lspSupportsRenaming and "Move-Rename File & Update Imports:"
|
||||||
|
or "Move & Rename File to:"
|
||||||
|
prefill = dir .. osPathSep
|
||||||
|
elseif op == "new" or op == "new-from-selection" then
|
||||||
|
promptStr = "Name for New File: "
|
||||||
|
prefill = ""
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.ui.input({
|
||||||
|
prompt = promptStr,
|
||||||
|
default = prefill,
|
||||||
|
completion = "dir", -- allows for completion via cmp-omni
|
||||||
|
}, function(newName)
|
||||||
|
vim.cmd.redraw() -- Clear message area from ui.input prompt
|
||||||
|
if not newName then return end -- input has been canceled
|
||||||
|
|
||||||
|
if op == "move-rename" and newName:find("/$") then newName = newName .. oldName end
|
||||||
|
if op == "new" and newName == "" then newName = "Untitled" end
|
||||||
|
|
||||||
|
-- GUARD Validate filename
|
||||||
|
local invalidName = newName:find("^%s+$")
|
||||||
|
or newName:find("[\\:]")
|
||||||
|
or (newName:find("^/") and not op == "move-rename")
|
||||||
|
local sameName = newName == oldName
|
||||||
|
local emptyInput = newName == ""
|
||||||
|
|
||||||
|
if invalidName or sameName or emptyInput then
|
||||||
|
if op == "new-from-selection" then
|
||||||
|
vim.cmd.undo() -- undo deletion
|
||||||
|
vim.fn.setreg("z", prevReg) -- restore register content
|
||||||
|
end
|
||||||
|
if invalidName or emptyInput then
|
||||||
|
u.notify("Invalid filename.", "error")
|
||||||
|
elseif sameName then
|
||||||
|
u.notify("Cannot use the same filename.", "warn")
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- DETERMINE PATH AND EXTENSION
|
||||||
|
local hasPath = newName:find(osPathSep)
|
||||||
|
if hasPath then
|
||||||
|
local newFolder = vim.fs.dirname(newName)
|
||||||
|
vim.fn.mkdir(newFolder, "p") -- create folders if necessary
|
||||||
|
end
|
||||||
|
|
||||||
|
local extProvided = newName:find(".%.[^/]*$") -- non-leading dot to not include dotfiles without extension
|
||||||
|
if not extProvided then newName = newName .. oldExt end
|
||||||
|
local newFilePath = (op == "move-rename") and newName or dir .. osPathSep .. newName
|
||||||
|
|
||||||
|
if u.fileExists(newFilePath) then
|
||||||
|
u.notify(("File with name %q already exists."):format(newFilePath), "error")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- EXECUTE FILE OPERATION
|
||||||
|
vim.cmd.update()
|
||||||
|
if op == "duplicate" then
|
||||||
|
local success = vim.uv.fs_copyfile(oldFilePath, newFilePath)
|
||||||
|
if success then
|
||||||
|
vim.cmd.edit(newFilePath)
|
||||||
|
u.notify(("Duplicated %q as %q."):format(oldName, newName))
|
||||||
|
end
|
||||||
|
elseif op == "rename" or op == "move-rename" then
|
||||||
|
rename.sendWillRenameToLsp(oldFilePath, newFilePath)
|
||||||
|
local success = rename.moveFile(oldFilePath, newFilePath)
|
||||||
|
if success then
|
||||||
|
vim.cmd.edit(newFilePath)
|
||||||
|
u.bwipeout("#")
|
||||||
|
u.notify(("Renamed %q to %q."):format(oldName, newName))
|
||||||
|
if lspSupportsRenaming then vim.cmd.wall() end
|
||||||
|
end
|
||||||
|
elseif op == "new" or op == "new-from-selection" then
|
||||||
|
vim.cmd.edit(newFilePath)
|
||||||
|
if op == "new-from-selection" then
|
||||||
|
vim.cmd("put z") -- cmd.put("z") does not work
|
||||||
|
vim.fn.setreg("z", prevReg) -- restore register content
|
||||||
|
end
|
||||||
|
vim.cmd.write(newFilePath)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.renameFile() fileOp("rename") end
|
||||||
|
function M.moveAndRenameFile() fileOp("move-rename") end
|
||||||
|
function M.duplicateFile() fileOp("duplicate") end
|
||||||
|
function M.createNewFile() fileOp("new") end
|
||||||
|
function M.moveSelectionToNewFile() fileOp("new-from-selection") end
|
||||||
|
|
||||||
|
function M.moveToFolderInCwd()
|
||||||
|
local curFilePath = vim.api.nvim_buf_get_name(0)
|
||||||
|
local parentOfCurFile = vim.fs.dirname(curFilePath) .. osPathSep
|
||||||
|
local filename = vim.fs.basename(curFilePath)
|
||||||
|
local lspSupportsRenaming = rename.lspSupportsRenaming()
|
||||||
|
local cwd = vim.uv.cwd() .. osPathSep
|
||||||
|
|
||||||
|
-- determine destinations in cwd
|
||||||
|
local foldersInCwd = vim.fs.find(function(name, path)
|
||||||
|
local fullPath = path .. osPathSep .. name .. osPathSep
|
||||||
|
local relative_path = osPathSep .. vim.fn.fnamemodify(fullPath, ":~:.")
|
||||||
|
local ignoreDirs = relative_path:find("/%.git/")
|
||||||
|
or relative_path:find("%.app/") -- macos pseudo-folders
|
||||||
|
or relative_path:find("/node_modules/")
|
||||||
|
or relative_path:find("/%.venv/")
|
||||||
|
or relative_path:find("/%.") -- hidden folders
|
||||||
|
or fullPath == parentOfCurFile
|
||||||
|
return not ignoreDirs
|
||||||
|
end, { type = "directory", limit = math.huge })
|
||||||
|
|
||||||
|
-- sort by modification time
|
||||||
|
table.sort(foldersInCwd, function(a, b)
|
||||||
|
local aMtime = vim.uv.fs_stat(a).mtime.sec
|
||||||
|
local bMtime = vim.uv.fs_stat(b).mtime.sec
|
||||||
|
return aMtime > bMtime
|
||||||
|
end)
|
||||||
|
-- insert cwd at bottom, since modification of is likely due to subfolders
|
||||||
|
if cwd ~= parentOfCurFile then table.insert(foldersInCwd, cwd) end
|
||||||
|
|
||||||
|
-- prompt user and move
|
||||||
|
local promptStr = "Choose Destination Folder"
|
||||||
|
if lspSupportsRenaming then promptStr = promptStr .. " (with updated imports)" end
|
||||||
|
vim.ui.select(foldersInCwd, {
|
||||||
|
prompt = promptStr,
|
||||||
|
kind = "genghis.moveToFolderInCwd",
|
||||||
|
format_item = function(path) return path:sub(#cwd) end, -- only relative path
|
||||||
|
}, function(destination)
|
||||||
|
if not destination then return end
|
||||||
|
local newFilePath = destination .. osPathSep .. filename
|
||||||
|
|
||||||
|
-- GUARD
|
||||||
|
if u.fileExists(newFilePath) then
|
||||||
|
u.notify(("File %q already exists at %q."):format(filename, destination), "error")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
rename.sendWillRenameToLsp(curFilePath, newFilePath)
|
||||||
|
local success = rename.moveFile(curFilePath, newFilePath)
|
||||||
|
if success then
|
||||||
|
vim.cmd.edit(newFilePath)
|
||||||
|
u.bwipeout("#")
|
||||||
|
local msg = ("Moved %q to %q"):format(filename, destination)
|
||||||
|
local append = lspSupportsRenaming and " and updated imports." or "."
|
||||||
|
u.notify(msg .. append)
|
||||||
|
if lspSupportsRenaming then vim.cmd.wall() end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---Makes current file executable
|
||||||
|
function M.chmodx()
|
||||||
|
local filename = vim.api.nvim_buf_get_name(0)
|
||||||
|
local perm = vim.fn.getfperm(filename)
|
||||||
|
perm = perm:gsub("r(.)%-", "r%1x") -- add x to every group that has r
|
||||||
|
vim.fn.setfperm(filename, perm)
|
||||||
|
u.notify("Execution Permission granted.")
|
||||||
|
vim.cmd.edit()
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param opts? { trashCmd: string }
|
||||||
|
function M.trashFile(opts)
|
||||||
|
local userCmd = opts and opts.trashCmd
|
||||||
|
local system = vim.uv.os_uname().sysname:lower()
|
||||||
|
local defaultCmd
|
||||||
|
if system == "darwin" then defaultCmd = "trash" end
|
||||||
|
if system:find("windows") then defaultCmd = "trash" end
|
||||||
|
if system:find("linux") then defaultCmd = "gio trash" end
|
||||||
|
local trashCmd = userCmd or defaultCmd
|
||||||
|
assert(defaultCmd, "Unknown operating system. Please provide a custom trashCmd.")
|
||||||
|
|
||||||
|
local trashArgs = vim.split(trashCmd, " ")
|
||||||
|
local oldFilePath = vim.api.nvim_buf_get_name(0)
|
||||||
|
table.insert(trashArgs, oldFilePath)
|
||||||
|
|
||||||
|
vim.cmd("silent! update")
|
||||||
|
local oldName = vim.fs.basename(oldFilePath)
|
||||||
|
local result = vim.system(trashArgs):wait()
|
||||||
|
if result.code == 0 then
|
||||||
|
u.bwipeout()
|
||||||
|
u.notify(("%q deleted"):format(oldName))
|
||||||
|
else
|
||||||
|
local outmsg = (result.stdout or "") .. (result.stderr or "")
|
||||||
|
u.notify(("Trashing %q failed: " .. outmsg):format(oldName), "error")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
return M
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
local u = require("genghis.utils")
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
---Requests a 'workspace/willRenameFiles' on any running LSP client, that supports it
|
---Requests a 'workspace/willRenameFiles' on any running LSP client, that supports it
|
||||||
|
|
@ -43,8 +42,11 @@ end
|
||||||
---@param oldFilePath string
|
---@param oldFilePath string
|
||||||
---@param newFilePath string
|
---@param newFilePath string
|
||||||
function M.moveFile(oldFilePath, newFilePath)
|
function M.moveFile(oldFilePath, newFilePath)
|
||||||
|
local u = require("genghis.support.utils")
|
||||||
|
|
||||||
local renamed, _ = vim.uv.fs_rename(oldFilePath, newFilePath)
|
local renamed, _ = vim.uv.fs_rename(oldFilePath, newFilePath)
|
||||||
if renamed then return true end
|
if renamed then return true end
|
||||||
|
|
||||||
---try `fs_copyfile` to support moving across partitions
|
---try `fs_copyfile` to support moving across partitions
|
||||||
local copied, copiedError = vim.uv.fs_copyfile(oldFilePath, newFilePath)
|
local copied, copiedError = vim.uv.fs_copyfile(oldFilePath, newFilePath)
|
||||||
if copied then
|
if copied then
|
||||||
|
|
@ -56,10 +58,8 @@ function M.moveFile(oldFilePath, newFilePath)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
u.notify(
|
local msg = ("Failed to copy %q to %q: %q"):format(oldFilePath, newFilePath, copiedError)
|
||||||
("Failed to move %q to %q: %q"):format(oldFilePath, newFilePath, copiedError),
|
u.notify(msg, "error")
|
||||||
"error"
|
|
||||||
)
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Loading…
Reference in New Issue