Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add restore-file implementation, rename commands #1

Merged
merged 1 commit into from
Feb 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,8 @@ require("neorg").setup({

The archive module adds the following commands:

### `:Neorg archive current-file`
### `:Neorg archive archive-file`
Moves the currently opened file to the archive: `archive-workspace/workspace-name/path-to-file`

### TODO `:Neorg archive current-directory`
Moves the current file's directory to the archive: `archive-workspace/workspace-name/path-to-directory`
### TODO `:Neorg archive restore`
### TODO `:Neorg archive restore-file`
Moves an archived file back to it's workspace from `archive-workspace/workspace/file,norg` to `workspace/file.norg`
239 changes: 126 additions & 113 deletions lua/neorg/modules/external/archive/module.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,141 +8,154 @@ local refactor ---@type external.refactor
local module = modules.create("external.archive")

module.config.public = {
-- (Optional) Archive workspace name, defaults to "archive"
workspace = "archive",
-- (Optional) Enable/disable confirming archive operations
confirm = true
-- (Optional) Archive workspace name, defaults to "archive"
workspace = "archive",
-- (Optional) Enable/disable confirming archive operations
confirm = true,
}

module.events.subscribed = {
["core.neorgcmd"] = {
["archive.current-file"] = true,
["archive.current-directory"] = true,
["archive.restore"] = true,
},
["core.neorgcmd"] = {
["archive.archive-file"] = true,
["archive.restore-file"] = true,
},
}


module.setup = function()
return {
success = true,
requires = {
"core.dirman",
"core.neorgcmd",
"external.refactor"
},
}
return {
success = true,
requires = {
"core.dirman",
"core.neorgcmd",
"external.refactor",
},
}
end

module.load = function()
dirman = module.required["core.dirman"]
refactor = module.required["external.refactor"]
neorgcmd = module.required["core.neorgcmd"]

local archive_workspace = dirman.get_workspace(module.config.public.workspace)
if (not archive_workspace) then
log.fatal("[neorg-archive] Archive workspace not found! Please add one to your Neorg config")
return
end

neorgcmd.add_commands_from_table({
archive = {
min_args = 1,
max_args = 1,
args = 1,
condition = "norg",
subcommands = {
["current-file"] = {
args = 0,
name = "archive.current-file",
},
["current-directory"] = {
args = 0,
name = "archive.current-directory",
},
["restore"] = {
args = 0,
name = "archive.restore",
},


},
},
})
dirman = module.required["core.dirman"]
refactor = module.required["external.refactor"]
neorgcmd = module.required["core.neorgcmd"]

local archive_workspace = dirman.get_workspace(module.config.public.workspace)
if not archive_workspace then
log.fatal("Archive workspace not found! Add " .. module.config.public.workspace .. " to your dirman workspaces")
return
end

neorgcmd.add_commands_from_table({
archive = {
min_args = 1,
max_args = 1,
args = 1,
condition = "norg",
subcommands = {
["archive-file"] = {
args = 0,
name = "archive.archive-file",
},
["restore-file"] = {
args = 0,
name = "archive.restore-file",
},
},
},
})
end

module.on_event = function(event)
if event.split_type[1] == "core.neorgcmd" then
if event.split_type[2] == "archive.current-file" then
module.public.archive_current_file()
elseif event.split_type[2] == "archive.current-directory" then
module.public.archive_current_directory()
elseif event.split_type[2] == "archive.restore" then
module.public.restore()
end
end
end

module.public.archive_current_file = function()
if (not module.private.confirm_archive_operation("archive current file")) then
return
end

local workspace = dirman.get_workspace_match()
if (workspace == module.config.public.workspace) then
log.error("Cannot archive files within the archive workspace!")
return
end

local archive_path = tostring(dirman.get_workspace(module.config.public.workspace))
local current_path = vim.api.nvim_buf_get_name(0)
local current_workspace_path = tostring(dirman.get_workspace(workspace))

local new_path = current_path:gsub("^" .. current_workspace_path, archive_path .. "/" .. workspace)

local success = refactor.rename_file(current_path, new_path)
if (not success) then
log.error("Failed to archive " .. current_path)
end

if (vim.fn.filereadable(current_path)) then
log.info("[neorg-archive] File not moved to archive, moving to" .. new_path)
os.rename(current_path, new_path)
end

vim.api.nvim_command('edit ' .. new_path)
log.info("Archived file under " .. new_path)
if event.split_type[1] == "core.neorgcmd" then
if event.split_type[2] == "archive.archive-file" then
module.public.archive_file()
elseif event.split_type[2] == "archive.restore-file" then
module.public.restore_file()
end
end
end

module.public.archive_current_directory = function()
if (not module.private.confirm_archive_operation("archive current directory")) then
return
end

local workspace = dirman.get_current_workspace()
if (workspace == module.config.public.workspace) then
log.error("Cannot archive files within the archive workspace!")
return
end
-- TODO
module.public.archive_file = function()
if not module.private.confirm_archive_operation("archive file") then
return
end

local workspace = dirman.get_workspace_match()
if workspace == module.config.public.workspace then
log.error("Cannot archive files within the archive workspace!")
return
end

local archive_path = tostring(dirman.get_workspace(module.config.public.workspace))
local current_path = vim.api.nvim_buf_get_name(0)
local current_workspace_path = tostring(dirman.get_workspace(workspace))

local new_path = current_path:gsub("^" .. current_workspace_path, archive_path .. "/" .. workspace)

local success = refactor.rename_file(current_path, new_path)
if not success then
log.error("Failed to refactor " .. current_path)
if module.config.public.refactor_fail then
return
end
end

if vim.fn.filereadable(current_path) then
log.info("File not moved to archive, moving to" .. new_path)
os.rename(current_path, new_path)
end

vim.api.nvim_command("edit " .. new_path)
log.info("Archived file under " .. new_path)
end

module.public.archive_restore = function()
if (not module.private.confirm_archive_operation("restore current file")) then
return
end
-- TODO
module.public.restore_file = function()
if not module.private.confirm_archive_operation("restore file") then
return
end

local archive_path = tostring(dirman.get_workspace(module.config.public.workspace))
local current_path = vim.api.nvim_buf_get_name(0)
if not current_path:match("^" .. archive_path) then
log.error("Cannot restore files outside of the archive workspace")
return
end

local workspace_name = current_path:match(archive_path .. "/([^/]+)/")
if not workspace_name then
log.error("Could not determine original workspace from path")
return
end

local workspace_path = tostring(dirman.get_workspace(workspace_name))
if not workspace_path then
log.error("Workspace '" .. workspace_name .. "' not found!")
return
end

local restore_path = current_path:gsub("^" .. archive_path .. "/" .. workspace_name, workspace_path)

local success = refactor.rename_file(current_path, restore_path)
if not success then
log.error("Failed to restore " .. current_path)
return
end

if vim.fn.filereadable(current_path) then
log.info("File not moved to original location, moving to " .. restore_path)
os.rename(current_path, restore_path)
end

vim.api.nvim_command("edit " .. restore_path)
log.info("Restored file to " .. restore_path)
end


--- Confirm archive operations based on module configuration
---@param operation string #The name of the operation to confirm, used in user prompt
---@return boolean #Confirmation status, if false abort operation
module.private.confirm_archive_operation = function(operation)
if (module.config.public.confirm) then
return vim.fn.confirm("Are you sure you want to " .. operation .. "? y/n", "&Yes\n&No", 2) == 1
end
return true
if module.config.public.confirm then
return vim.fn.confirm("Are you sure you want to " .. operation .. "? y/n", "&Yes\n&No", 2) == 1
end
return true
end

return module