Initial commit
This commit is contained in:
236
lua/cave/python/interpreter.lua
Normal file
236
lua/cave/python/interpreter.lua
Normal file
@@ -0,0 +1,236 @@
|
||||
local Context = require "cave.context"
|
||||
local Meta = require "cave.meta"
|
||||
local Module = require "cave.python.module"
|
||||
local Path = require "cave.path"
|
||||
local Runnable = require "cave.python.runnable"
|
||||
local Script = require "cave.python.script"
|
||||
local Task = require "cave.task"
|
||||
|
||||
local List = Meta.List
|
||||
local Map = Meta.Map
|
||||
local Str = Meta.String
|
||||
local validate = Meta.validate
|
||||
|
||||
---@class cave.Python.Interpreter
|
||||
---@field id string
|
||||
---@field path cave.Path
|
||||
---@field args string[]
|
||||
---@field env table<string, string>
|
||||
---@field runnables table<string, cave.Python.Runnable>
|
||||
---@field context cave.Context
|
||||
local Interpreter = Meta.derive "Python.Interpreter"
|
||||
|
||||
---@return string
|
||||
function Interpreter:valid_path() return self.path:executable():tostring() end
|
||||
|
||||
---@return overseer.TemplateDefinition[]
|
||||
function Interpreter:templates()
|
||||
local templates = {}
|
||||
for _, runnable in pairs(self.runnables) do
|
||||
vim.list_extend(templates, { self:run_template(runnable), self:debug_template(runnable) })
|
||||
end
|
||||
return templates
|
||||
end
|
||||
|
||||
---@param runnable cave.Python.Runnable
|
||||
---@return overseer.TemplateDefinition
|
||||
function Interpreter:run_template(runnable)
|
||||
local name = ("python.%s.run.%s"):format(self.id, runnable.id)
|
||||
local script, module = runnable:concrete()
|
||||
local args = vim.list_extend({}, self.args)
|
||||
vim.list_extend(
|
||||
args,
|
||||
(script and { script:valid_file() }) or (module and { "-m", module.name }) or error "Unsupported runnable"
|
||||
)
|
||||
vim.list_extend(args, runnable.args)
|
||||
local template_definition = {
|
||||
name = name,
|
||||
builder = function()
|
||||
---@type overseer.TaskDefinition
|
||||
local task_definition = {
|
||||
name = name,
|
||||
cmd = { self:valid_path() },
|
||||
args = args,
|
||||
env = vim.tbl_extend("keep", runnable.env, self.env),
|
||||
cwd = runnable:valid_cwd(),
|
||||
components = { { "defaults" } },
|
||||
}
|
||||
return task_definition
|
||||
end,
|
||||
params = {},
|
||||
tags = { Task.Tag.Run },
|
||||
}
|
||||
return template_definition
|
||||
end
|
||||
|
||||
---@param runnable cave.Python.Runnable
|
||||
---@return overseer.TemplateDefinition
|
||||
function Interpreter:debug_template(runnable)
|
||||
local name = ("python.%s.debug.%s"):format(self.id, runnable.id)
|
||||
local template_definition = {}
|
||||
template_definition.builder = function()
|
||||
local script, module = runnable:concrete()
|
||||
|
||||
---@type DebugpyLaunchConfig
|
||||
local dap_config = {
|
||||
name = name,
|
||||
type = "python",
|
||||
request = "launch",
|
||||
module = module and module.name,
|
||||
program = script and script:valid_file(),
|
||||
cwd = runnable:valid_cwd(),
|
||||
args = runnable.args,
|
||||
env = vim.tbl_extend("keep", runnable.env, self.env),
|
||||
python = vim.list_extend({ self:valid_path() }, self.args),
|
||||
}
|
||||
|
||||
if vim.tbl_isempty(dap_config.env) then dap_config.env = nil end
|
||||
|
||||
---@type overseer.TaskDefinition
|
||||
local task_definition = {
|
||||
name = name,
|
||||
cmd = {},
|
||||
components = { { "defaults" }, { "dap", config = dap_config } },
|
||||
}
|
||||
return task_definition
|
||||
end
|
||||
template_definition.params = {}
|
||||
template_definition.tags = { Task.Tag.Debug }
|
||||
template_definition.name = name
|
||||
return template_definition
|
||||
end
|
||||
|
||||
---@class cave.Python.Interpreter.Factory
|
||||
---@field id_ string?
|
||||
---@field path_ cave.Path?
|
||||
---@field args_ string[]
|
||||
---@field env_ table<string, string>
|
||||
---@field runnables_ cave.Python.Runnable.Factory[]
|
||||
---@field context_ cave.Context
|
||||
local Factory = Meta.derive "Python.Interpreter.Factory"
|
||||
|
||||
---@param context cave.Context
|
||||
function Factory:init(context)
|
||||
self.args_ = {}
|
||||
self.env_ = {}
|
||||
self.runnables_ = {}
|
||||
self.context_ = context
|
||||
end
|
||||
|
||||
---@param context cave.Context
|
||||
---@return cave.Python.Interpreter.Factory
|
||||
function Factory.new(context)
|
||||
validate { context = { context, Context } }
|
||||
local factory = setmetatable({}, Factory)
|
||||
factory:init(context)
|
||||
return factory
|
||||
end
|
||||
|
||||
---@return string
|
||||
function Factory:get_id() return self.id_ or "python" end
|
||||
|
||||
---@return cave.Path
|
||||
function Factory:get_path() return self.path_ or Path.new "python" end
|
||||
|
||||
---@return string[]
|
||||
function Factory:get_args() return self.args_ end
|
||||
|
||||
---@return table<string, string>
|
||||
function Factory:get_env() return self.env_ end
|
||||
|
||||
---@return cave.Python.Runnable.Factory[]
|
||||
function Factory:get_runnables() return self.runnables_ end
|
||||
|
||||
---@param id string
|
||||
---@return cave.Python.Interpreter.Factory
|
||||
function Factory:id(id)
|
||||
validate { id = { id, Str } }
|
||||
self.id_ = id
|
||||
return self
|
||||
end
|
||||
|
||||
---@param path_like cave.PathLike
|
||||
---@return cave.Python.Interpreter.Factory
|
||||
function Factory:path(path_like)
|
||||
validate { path_like = { path_like, Path.Like } }
|
||||
self.path_ = Path.like(path_like)
|
||||
return self
|
||||
end
|
||||
|
||||
---@param args string[]
|
||||
---@return cave.Python.Interpreter.Factory
|
||||
function Factory:args(args)
|
||||
validate { args = { args, List(Str) } }
|
||||
vim.list_extend(self.args_, args)
|
||||
return self
|
||||
end
|
||||
|
||||
---@param arg string
|
||||
---@return cave.Python.Interpreter.Factory
|
||||
function Factory:arg(arg) return self:args { arg } end
|
||||
|
||||
---@param env table<string, string>
|
||||
---@return cave.Python.Interpreter.Factory
|
||||
function Factory:env(env)
|
||||
validate { env = { env, Map(Str, Str) } }
|
||||
vim.tbl_extend("error", self.env_, env)
|
||||
return self
|
||||
end
|
||||
|
||||
---@param name string
|
||||
---@return cave.Python.Module.Factory
|
||||
function Factory:module(name)
|
||||
validate { name = { name, Str } }
|
||||
local module_factory = Module.Factory.new(name, self.context_)
|
||||
table.insert(self.runnables_, module_factory)
|
||||
return module_factory
|
||||
end
|
||||
|
||||
---@param file_path_like cave.PathLike
|
||||
---@return cave.Python.Script.Factory
|
||||
function Factory:script(file_path_like)
|
||||
validate { file = { file_path_like, Path.Like } }
|
||||
local file = Path.like(file_path_like)
|
||||
local script_factory = Script.Factory.new(file, self.context_)
|
||||
table.insert(self.runnables_, script_factory)
|
||||
return script_factory
|
||||
end
|
||||
|
||||
---@param runnables cave.Python.Runnable.Factory[]
|
||||
---@return cave.Python.Interpreter.Factory
|
||||
function Factory:runnables(runnables)
|
||||
validate { runnables = { runnables, List(Runnable.Factory) } }
|
||||
for _, runnable in ipairs(runnables) do
|
||||
table.insert(self.runnables_, runnable:copy())
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---@param runnable cave.Python.Runnable.Factory
|
||||
---@return cave.Python.Interpreter.Factory
|
||||
function Factory:runnable(runnable) return self:runnables { runnable } end
|
||||
|
||||
---@param interpreter cave.Python.Interpreter
|
||||
function Factory:init_interpreter(interpreter)
|
||||
interpreter.id = self:get_id()
|
||||
interpreter.path = self:get_path()
|
||||
interpreter.args = self:get_args()
|
||||
interpreter.env = self:get_env()
|
||||
interpreter.runnables = {}
|
||||
for _, runnable_factory in pairs(self:get_runnables()) do
|
||||
local runnable = runnable_factory:build()
|
||||
assert(interpreter.runnables[runnable.id] == nil)
|
||||
interpreter.runnables[runnable.id] = runnable
|
||||
end
|
||||
end
|
||||
|
||||
---@return cave.Python.Interpreter
|
||||
function Factory:build()
|
||||
local interpreter = setmetatable({}, Interpreter)
|
||||
self:init_interpreter(interpreter)
|
||||
return interpreter
|
||||
end
|
||||
|
||||
Interpreter.Factory = Factory
|
||||
|
||||
return Interpreter
|
||||
Reference in New Issue
Block a user