repositories / dotfiles
dotfiles
bugabingas dorkfiles
owned by admin
neovim/lua/bugabinga/pivi/runtime.lua
Raw--- Locates the assets pivi ships and the address a child needs to reach back.
--- Everything here is additive: pivi adds its companion extension and its skill
--- to the user's own Pi, and never removes what the user configured.
local runtime_file = function( relative )
local found = vim.api.nvim_get_runtime_file( relative, false )[1]
if found then return vim.fs.normalize( found ) end
return nil
end
local extension_path = function()
return runtime_file 'lua/bugabinga/pivi/extension/index.ts'
end
local client_path = function()
return runtime_file 'lua/bugabinga/pivi/extension/client.lua'
end
local skill_path = function()
return runtime_file 'lua/bugabinga/pivi/skills/pivi/SKILL.md'
end
--- Directories a global npm install commonly uses.
--- A Neovim started from a desktop launcher inherits a smaller PATH than a
--- shell does, so PATH alone is not a reliable way to find Pi.
local install_directories = function()
local home = vim.fs.normalize( vim.uv.os_homedir() or '' )
local directories = {}
-- Built without holes: a nil entry would end iteration early.
local add = function( directory )
if directory and directory ~= '' then
table.insert( directories, vim.fs.normalize( directory ) )
end
end
add( vim.env.PIVI_PI_DIR )
add( vim.env.NPM_CONFIG_PREFIX )
if vim.env.NPM_CONFIG_PREFIX then add( vim.env.NPM_CONFIG_PREFIX .. '/bin' ) end
add( home .. '/.local/share/npm' )
add( home .. '/.local/bin' )
add( home .. '/AppData/Roaming/npm' )
add( home .. '/.npm-global/bin' )
add( home .. '/.bun/bin' )
add '/usr/local/bin'
add '/opt/homebrew/bin'
return directories
end
local names = function()
if vim.fn.has 'win32' == 1 then return { 'pi.cmd', 'pi.exe', 'pi.bat', 'pi', } end
return { 'pi', }
end
local probe = function( candidate )
if candidate == nil or candidate == '' then return nil end
if vim.fn.executable( candidate ) == 1 then
local resolved = vim.fn.exepath( candidate )
return vim.fs.normalize( resolved ~= '' and resolved or candidate )
end
local stat = vim.uv.fs_stat( candidate )
if stat and stat.type == 'file' then return vim.fs.normalize( candidate ) end
return nil
end
--- Resolves the Pi executable to a real path.
--- A bare name is not enough: on Windows the launcher is a `.CMD` shim, and an
--- unresolved name reaches the process spawner as a missing file.
--- @return string? path
--- @return string? failure
local executable = function()
local configured = vim.g.pivi_executable
if configured then
local found = probe( configured )
if found then return found end
return nil, 'pi executable not found: ' .. tostring( configured )
end
for _, name in ipairs( names() ) do
local found = probe( name )
if found then return found end
end
for _, directory in ipairs( install_directories() ) do
if directory and directory ~= '' then
for _, name in ipairs( names() ) do
local found = probe( vim.fs.normalize( directory .. '/' .. name ) )
if found then return found end
end
end
end
return nil, 'pi not found on PATH or in the usual install directories; set vim.g.pivi_executable'
end
--- Environment the companion extension needs to reach this Neovim instance.
local bridge_environment = function()
local address = vim.v.servername
if address == nil or address == '' then return nil end
return {
PIVI_NVIM_ADDRESS = address,
PIVI_NVIM_EXE = vim.v.progpath,
PIVI_NVIM_CLIENT = client_path(),
}
end
return {
file = runtime_file,
install_directories = install_directories,
executable = executable,
extension_path = extension_path,
client_path = client_path,
skill_path = skill_path,
bridge_environment = bridge_environment,
}