Skip to content

Commit

Permalink
feat(plugins): support including yazi flavors with .build_flavor
Browse files Browse the repository at this point in the history
  • Loading branch information
mikavilpas committed Jun 3, 2024
1 parent aed05d5 commit 54b6389
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 49 deletions.
2 changes: 2 additions & 0 deletions documentation/plugin-manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,5 @@ For further reading, please refer to the following resources:

- Yazi plugin documentation <https://yazi-rs.github.io/docs/plugins/overview>
- lazy.nvim documentation <https://github.com/folke/lazy.nvim>
- General discussion on the idea
<https://github.com/folke/lazy.nvim/discussions/1488>
68 changes: 46 additions & 22 deletions lua/yazi/plugin.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
local M = {}

--- A specification that represents information about the plugin or flavor to
--- install. Note that this is compatible with LazyPlugin, the lazy.nvim plugin
--- specification table, so you can just pass that.
---@alias YaziLazyNvimSpec { name: string, dir: string }

---@alias YaziSpecInstallationResultSuccess { message: string, from: string, to: string }
---@alias YaziSpecInstallationResultFailure { message: string, from: string, to?: string, error: string }

--- Helper utility for compatibility with
--- [lazy.nvim](https://github.com/folke/lazy.nvim).
---
Expand All @@ -19,33 +27,57 @@ local M = {}
---
--- For more information, see the yazi.nvim documentation.
---
---@param plugin YaziLazyNvimPlugin
---@param plugin YaziLazyNvimSpec
---@param options? { yazi_dir: string }
---@return YaziPluginInstallationResultSuccess | YaziPluginInstallationResultFailure
function M.build_plugin(plugin, options)
local yazi_dir = options and options.yazi_dir
or vim.fn.expand('~/.config/yazi')
local to = vim.fs.normalize(vim.fs.joinpath(yazi_dir, 'plugins', plugin.name))

local dir = vim.loop.fs_stat(plugin.dir)
return M.symlink(plugin, to)
end

---@param flavor YaziLazyNvimSpec
---@param options? { yazi_dir: string }
function M.build_flavor(flavor, options)
local yazi_dir = options and options.yazi_dir
or vim.fn.expand('~/.config/yazi')

local flavor_dir = vim.fn.expand(vim.fs.joinpath(yazi_dir, 'flavors'))
if vim.uv.fs_stat(flavor_dir) == nil then
vim.uv.fs_mkdir(flavor_dir, 493) -- 0755 in octal
end

local to = vim.fs.normalize(vim.fs.joinpath(flavor_dir, flavor.name))

return M.symlink(flavor, to)
end

--- A general implementation of a symlink operation. For yazi plugins and
--- flavors, prefer using `build_plugin` and `build_flavor` instead.
---@param spec YaziLazyNvimSpec
---@param to string
---@return YaziSpecInstallationResultSuccess | YaziSpecInstallationResultFailure
function M.symlink(spec, to)
local dir = vim.uv.fs_stat(spec.dir)
if dir == nil or dir.type ~= 'directory' then
---@type YaziPluginInstallationResultFailure
---@type YaziSpecInstallationResultFailure
local result = {
error = 'plugin directory does not exist',
from = plugin.dir,
message = 'yazi.nvim: failed to install plugin',
error = 'yazi plugin/flavor directory does not exist',
from = spec.dir,
message = 'yazi.nvim: failed to install',
}
vim.notify(vim.inspect(result))
return result
end

local success, error = vim.uv.fs_symlink(plugin.dir, to)
local success, error = vim.uv.fs_symlink(spec.dir, to)

if not success then
---@type YaziPluginInstallationResultFailure
---@type YaziSpecInstallationResultFailure
local result = {
message = 'yazi.nvim: failed to install plugin',
from = plugin.dir,
message = 'yazi.nvim: failed to install',
from = spec.dir,
to = to,
error = error or 'unknown error',
}
Expand All @@ -54,23 +86,15 @@ function M.build_plugin(plugin, options)
return result
end

---@type YaziPluginInstallationResultSuccess
---@type YaziSpecInstallationResultSuccess
local result = {
message = 'yazi.nvim: successfully installed plugin ' .. plugin.name,
from = plugin.dir,
message = 'yazi.nvim: successfully installed ' .. spec.name,
from = spec.dir,
to = to,
}

vim.notify(vim.inspect(result))
return result
end

--- Represents information about the plugin to install. Note that this is
--- compatible with LazyPlugin, the lazy.nvim plugin specification table, so
--- you can just pass that.
---@alias YaziLazyNvimPlugin { name: string, dir: string }

---@alias YaziPluginInstallationResultSuccess { message: string, from: string, to: string }
---@alias YaziPluginInstallationResultFailure { message: string, from: string, to?: string, error: string }

return M
83 changes: 56 additions & 27 deletions tests/yazi/plugin_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,41 +15,70 @@ describe('installing a plugin', function()
vim.fn.delete(base_dir, 'rf')
end)

it('can install if everything goes well', function()
local plugin_dir = vim.fs.joinpath(base_dir, 'test-plugin')
local yazi_dir = vim.fs.joinpath(base_dir, 'fake-yazi-dir')
describe('installing a plugin', function()
it('can install if everything goes well', function()
local plugin_dir = vim.fs.joinpath(base_dir, 'test-plugin')
local yazi_dir = vim.fs.joinpath(base_dir, 'fake-yazi-dir')

vim.fn.mkdir(plugin_dir)
vim.fn.mkdir(yazi_dir)
vim.fn.mkdir(vim.fs.joinpath(yazi_dir, 'plugins'))
vim.fn.mkdir(plugin_dir)
vim.fn.mkdir(yazi_dir)
vim.fn.mkdir(vim.fs.joinpath(yazi_dir, 'plugins'))

plugin.build_plugin({
dir = plugin_dir,
name = 'test-plugin',
}, { yazi_dir = yazi_dir })
plugin.build_plugin({
dir = plugin_dir,
name = 'test-plugin',
}, { yazi_dir = yazi_dir })

-- verify that the plugin was symlinked
-- yazi_dir/plugins/test-plugin -> plugin_dir
local symlink =
vim.loop.fs_readlink(vim.fs.joinpath(yazi_dir, 'plugins', 'test-plugin'))
-- verify that the plugin was symlinked
-- yazi_dir/plugins/test-plugin -> plugin_dir
local symlink =
vim.uv.fs_readlink(vim.fs.joinpath(yazi_dir, 'plugins', 'test-plugin'))

assert.are.same(plugin_dir, symlink)
assert.are.same(plugin_dir, symlink)
end)

it('warns the user if the plugin directory does not exist', function()
local plugin_dir = vim.fs.joinpath(base_dir, 'test-plugin')
local yazi_dir = vim.fs.joinpath(base_dir, 'fake-yazi-dir')

-- NOTE: we are not creating the plugin directory
-- vim.fn.mkdir(plugin_dir)
vim.fn.mkdir(yazi_dir)
vim.fn.mkdir(vim.fs.joinpath(yazi_dir, 'plugins'))

local result = plugin.build_plugin({
dir = plugin_dir,
name = 'test-plugin-2',
}, { yazi_dir = yazi_dir })

assert.is_equal(
result.error,
'yazi plugin/flavor directory does not exist'
)
assert.is_equal(result.from, plugin_dir)
end)
end)

it('warns the user if the plugin directory does not exist', function()
local plugin_dir = vim.fs.joinpath(base_dir, 'test-plugin')
local yazi_dir = vim.fs.joinpath(base_dir, 'fake-yazi-dir')
describe('installing a flavor', function()
it('can install if everything goes well', function()
local flavor_dir = vim.fs.joinpath(base_dir, 'test-flavor')
local yazi_dir = vim.fs.joinpath(base_dir, 'fake-yazi-dir')

vim.fn.mkdir(flavor_dir)
vim.fn.mkdir(yazi_dir)
vim.fn.mkdir(vim.fs.joinpath(yazi_dir, 'flavors'))

-- NOTE: we are not creating the plugin directory
-- vim.fn.mkdir(plugin_dir)
vim.fn.mkdir(yazi_dir)
vim.fn.mkdir(vim.fs.joinpath(yazi_dir, 'plugins'))
plugin.build_flavor({
dir = flavor_dir,
name = 'test-flavor',
}, { yazi_dir = yazi_dir })

local result = plugin.build_plugin({
dir = plugin_dir,
name = 'test-plugin-2',
}, { yazi_dir = yazi_dir })
-- verify that the flavor was symlinked
-- yazi_dir/flavors/test-flavor -> flavor_dir
local symlink =
vim.uv.fs_readlink(vim.fs.joinpath(yazi_dir, 'flavors', 'test-flavor'))

assert.is_equal(result.error, 'plugin directory does not exist')
assert.are.same(flavor_dir, symlink)
end)
end)
end)

0 comments on commit 54b6389

Please sign in to comment.