189 lines
5.3 KiB
Lua
189 lines
5.3 KiB
Lua
local Env = require "cave.env"
|
|
local Meta = require "cave.meta"
|
|
local Path = require "cave.path"
|
|
local Project = require "cave.project"
|
|
local Util = require "cave.util"
|
|
local ClassLogger = require "cave.log.class_logger"
|
|
local TemplateProvider = require "cave.template_provider"
|
|
|
|
local workspaces = require "workspaces"
|
|
local overseer = require "overseer"
|
|
|
|
local Str = Meta.String
|
|
local validate = Meta.validate
|
|
local Optional = Meta.Optional
|
|
|
|
---@class cave.Manager
|
|
---@field project? cave.Project
|
|
---@field env cave.Env
|
|
---@field template_provider cave.TemplateProvider
|
|
local Manager = Meta.derive "Manager"
|
|
Manager.log = ClassLogger.new(Manager)
|
|
|
|
function Manager:init()
|
|
self.env = Env:new()
|
|
---@return overseer.TemplateDefinition[]
|
|
local function project_templates() return self.project and self.project.templates or {} end
|
|
self.template_provider = TemplateProvider.new("cave.nvim", project_templates)
|
|
overseer.register_template(self.template_provider)
|
|
---@param task_defn overseer.TaskDefinition
|
|
---@param _ overseer.TaskUtil
|
|
local function on_template_run(task_defn, _)
|
|
local name = task_defn.name
|
|
if name == nil or self.project == nil then return end
|
|
self.project:on_template_run(name)
|
|
end
|
|
|
|
overseer.add_template_hook(nil, on_template_run)
|
|
end
|
|
|
|
---@return cave.Manager
|
|
function Manager.new()
|
|
local manager = setmetatable({}, Manager)
|
|
manager:init()
|
|
return manager
|
|
end
|
|
|
|
---@return table<string, cave.Project>
|
|
function Manager:get_projects()
|
|
local projects = {}
|
|
if self.project ~= nil then projects[self.project.name] = self.project end
|
|
for _, ws in pairs(workspaces.get()) do
|
|
local project = Project.new(Path.new(ws.path), ws.name, ws.custom)
|
|
if projects[project.name] == nil then projects[project.name] = project end
|
|
end
|
|
return projects
|
|
end
|
|
|
|
---@param lead string
|
|
---@return string[]
|
|
function Manager:project_name_complete(lead)
|
|
validate { lead = { lead, Str } }
|
|
local projects = self:get_projects()
|
|
local project_names = {}
|
|
for project_name, _ in pairs(projects) do
|
|
if vim.startswith(project_name, lead) then table.insert(project_names, project_name) end
|
|
end
|
|
return project_names
|
|
end
|
|
|
|
---@param lead string
|
|
---@return string[]
|
|
function Manager:project_dir_complete(lead)
|
|
validate { lead = { lead, Str } }
|
|
local projects = self:get_projects()
|
|
local project_dirs = {}
|
|
for _, project in pairs(projects) do
|
|
local project_dir = tostring(project.dir)
|
|
if vim.startswith(project_dir, lead) then table.insert(project_dirs, project_dir) end
|
|
end
|
|
return project_dirs
|
|
end
|
|
|
|
---@param dir string?
|
|
---@param name string?
|
|
function Manager:add_project(dir, name)
|
|
validate { dir = { dir, Optional(Str) }, name = { name, Optional(Str) } }
|
|
local log = Manager.log:call("dir=%q, name=%s", dir, name and ("%q"):format(name) or "nil")
|
|
|
|
local project_dir = Path.new(dir or Path.cwd())
|
|
assert(project_dir:is_absolute())
|
|
local project_name = name or project_dir:basename()
|
|
local project_uuid = Util.generate_uuid()
|
|
if not project_dir:is_dir() then return log:err("%q is not a directory", project_dir) end
|
|
|
|
local projects = self:get_projects()
|
|
local project_exists = projects[project_name] ~= nil
|
|
if project_exists then return log:err("project with name %q already exists", project_name) end
|
|
|
|
local project = Project.new(project_dir, project_name, project_uuid)
|
|
|
|
workspaces.add(tostring(project.dir), project.name)
|
|
workspaces.set_custom(project.name, project.uuid)
|
|
|
|
log:ok()
|
|
end
|
|
|
|
---@param name string
|
|
function Manager:remove_project(name)
|
|
validate { name = { name, Str } }
|
|
local log = Manager.log:call("name=%q", name)
|
|
|
|
local projects = self:get_projects()
|
|
local project = projects[name]
|
|
if project == nil then return log:err "projectdoesn't exist" end
|
|
|
|
if project == self.project then self:close_project() end
|
|
|
|
workspaces.remove(name)
|
|
|
|
log:ok()
|
|
end
|
|
|
|
---@param old_name string
|
|
---@param new_name string
|
|
function Manager:rename_project(old_name, new_name)
|
|
validate { new_name = { new_name, Str }, old_name = { old_name, Str } }
|
|
local log = Manager.log:call("old_name=%q, new_name=%q", old_name, new_name)
|
|
|
|
if new_name == old_name then return log:ok() end
|
|
|
|
local projects = self:get_projects()
|
|
local project = projects[old_name]
|
|
if project == nil then return log:err "project with old name doesn't exist" end
|
|
if projects[new_name] ~= nil then return log:err "project with new name already exists" end
|
|
|
|
project:rename(new_name)
|
|
|
|
if project == self.project then self.env:update() end
|
|
|
|
workspaces.rename(old_name, new_name)
|
|
|
|
log:ok()
|
|
end
|
|
|
|
---@param name string
|
|
function Manager:open_project(name)
|
|
validate { name = { name, Str } }
|
|
local log = Manager.log:call("name=%q", name)
|
|
|
|
if self.project ~= nil and self.project.name == name then return log:ok() end
|
|
|
|
local projects = self:get_projects()
|
|
local project = projects[name]
|
|
if project == nil then return log:err "project doesn't exist" end
|
|
|
|
self:close_project()
|
|
self.project = project
|
|
|
|
self.env:update(self.project)
|
|
|
|
project:open()
|
|
|
|
log:ok()
|
|
end
|
|
|
|
function Manager:open_project_config()
|
|
local log = Manager.log:call()
|
|
|
|
if self.project == nil then return log:ok() end
|
|
|
|
vim.cmd.edit(tostring(self.project.config_script))
|
|
|
|
log:ok()
|
|
end
|
|
|
|
function Manager:close_project()
|
|
local log = Manager.log:call()
|
|
if self.project == nil then return log:ok() end
|
|
|
|
self.project:close()
|
|
self.project = nil
|
|
|
|
self.env:update()
|
|
|
|
log:ok()
|
|
end
|
|
|
|
return Manager
|