Skip to content

Commit

Permalink
Refactor managed command (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
andre-kotake authored Nov 15, 2024
2 parents cb2e322 + 6f692af commit 0d30547
Show file tree
Hide file tree
Showing 19 changed files with 535 additions and 417 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true

[*.lua]
insert_final_newline = true
max_line_length = 80
quote_type = double
47 changes: 0 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,53 +89,6 @@ Encrypted files have partial supported. Tested and working fine for gpg encrypti
- `:Telescope nvim-chezmoi managed`: Lists managed files. Same as `:ChezmoiManaged`.
- `:Telescope nvim-chezmoi special_files`: Lists all chezmoi special files under source directory. Same as `ChezmoiFiles`.

## API

### nvim-chezmoi.chezmoi

#### run

You may use `nvim-chezmoi.chezmoi.run` function in order to execute commands and provide custom functionality.

```lua
local chezmoi = require("nvim-chezmoi.chezmoi")
local result = chezmoi.run("managed", {
args = {
"--path-style",
"relative"
},
})
vim.print(vim.inspect(result))
```

Only commands that return `stdout` or `stderr` are fully supported.

The parameters for `exec` are:

- `cmd (string)`: Command to execute, e.g. "source-path"
- `opts (ChezmoiCmdOpts)`: Additional opts for command execution.

Returns a `ChezmoiCommandResult`.

##### ChezmoiCmdOpts

```lua
---@class ChezmoiCmdOpts
---@field args? string[] Additional args to append to `cmd`, e.g. ".bashrc"
---@field callback? fun(result: ChezmoiCommandResult): any Callback to execute on success
---@field force? boolean Force execution ignoring cache always. Default `false`.
---@field stdin? string[] `stdin` if needed for command.
```

##### ChezmoiCommandResult

```lua
---Result of an executed command
---@class ChezmoiCommandResult
---@field success boolean `true` if command returned status code 0.
---@field data table The result data from command execution or error messages if `success` is `false`.
```

## To do

- Auto apply on save/quit.
Expand Down
123 changes: 123 additions & 0 deletions lua/nvim-chezmoi/chezmoi/command.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
local log = require("nvim-chezmoi.core.log")
local utils = require("nvim-chezmoi.core.utils")
local Job = require("plenary.job")

---@class ChezmoiCommand
---@field cmd string
---@field args? string[] Default args for command.
local M = {
args = {},
}
M.__index = M

---@param args? string|table
---@return ChezmoiAutoCommand[]
function M:autoCommands(args)
error(debug.traceback("autoCommands not implemented."))
end

function M:create_autocmds(args)
local commands = self:autoCommands(args)
for _, cmd in ipairs(commands) do
vim.api.nvim_create_autocmd(
cmd.event,
vim.tbl_deep_extend("force", cmd.opts or {}, {
group = utils.augroup(cmd.opts.group),
})
)
end
end

---@return ChezmoiUserCommand[]
function M:userCommands()
error(debug.traceback("bufUserCommands not implemented."))
end

function M:create_user_commands()
local commands = self:userCommands()
for _, cmd in pairs(commands) do
vim.api.nvim_create_user_command(
cmd.name,
cmd.callback,
vim.tbl_deep_extend("force", cmd.opts or {}, {
desc = cmd.desc,
})
)
end
end

---@param bufnr integer
---@return ChezmoiUserCommand[]
function M:bufUserCommands(bufnr)
error(debug.traceback(bufnr .. ": bufUserCommands not implemented."))
end

---@param bufnr integer
function M:create_buf_user_commands(bufnr)
local commands = self:bufUserCommands(bufnr)
local existing_cmds = vim.api.nvim_buf_get_commands(bufnr, {})

for _, cmd in ipairs(commands) do
if not existing_cmds[cmd.name] then
-- Create the user command if it doesn't exist
vim.api.nvim_buf_create_user_command(
bufnr,
cmd.name,
cmd.callback,
vim.tbl_deep_extend("force", cmd.opts or {}, {
desc = cmd.desc,
})
)
end
end
end

---@param job Job
---@return ChezmoiCommandResult
local function getJobResult(job)
local result = job:result()
local success = job.code == 0

if not success then
-- Error, trim each and join with newline
local stderr = {}
for _, v in ipairs(job:stderr_result()) do
stderr[#stderr + 1] = v:gsub("^%s*(.-)%s*$", "%1")
end
result = { table.concat(stderr, "\n") }
success = false
end

return {
args = job.args,
success = success,
data = result,
}
end

---@param self ChezmoiCommand
---@param args string[]
local function newJob(self, args)
vim.list_extend(args, self.args)
args = vim.list_extend({ self.cmd }, args)
return Job:new({
command = "chezmoi",
args = args,
})
end

---@param args? string[]
---@return ChezmoiCommandResult
function M:exec(args)
local job = newJob(self, args or {})
job:sync()
local result = getJobResult(job)

if not result.success then
log.error(result.data)
end

return result
end

return M
33 changes: 33 additions & 0 deletions lua/nvim-chezmoi/chezmoi/commands/apply.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
local command = require("nvim-chezmoi.chezmoi.command")

---@class ChezmoiApply:ChezmoiCommand
local M = setmetatable({
cmd = "apply",
args = { "--force" },
}, {
__index = command,
})

---@return ChezmoiUserCommand[]
function M:userCommands()
return {
{
name = "ChezmoiApply",
desc = "Applies current chezmoi file. Accepts optional files arguments.",
callback = function(cmd)
local args = cmd.fargs
if #args > 0 then
for i, value in ipairs(args) do
args[i] = vim.fn.fnamemodify(vim.fn.expand(value), ":p")
end
end
self:exec(args)
end,
opts = {
nargs = "*",
},
},
}
end

return M
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
local base = require("nvim-chezmoi.chezmoi.wrapper._base")
local chezmoi = require("nvim-chezmoi.chezmoi")
local command = require("nvim-chezmoi.chezmoi.command")
local chezmoi_helper = require("nvim-chezmoi.chezmoi.helper")
local log = require("nvim-chezmoi.core.log")

---@class ChezmoiDecrypt: ChezmoiCommandWrapper
local M = setmetatable({}, {
__index = base,

---@return ChezmoiCommandResult
__call = function(self, file)
return self:exec(file)
end,
---@class ChezmoiDecrypt: ChezmoiCommand
local M = setmetatable({
cmd = "decrypt",
}, {
__index = command,
})

function M:create_autocmds(bufnr)
base.create_autocmds({
function M:autoCommands(bufnr)
return {
{
event = "BufWritePre",
opts = {
Expand All @@ -27,7 +23,6 @@ function M:create_autocmds(bufnr)
local encrypted_lines =
vim.fn.systemlist("chezmoi encrypt", decrypted_lines)
local code = vim.v.shell_error

if code == 0 then
local source_path = chezmoi_helper.get_encrypted_path(ev.file)
vim.fn.writefile(encrypted_lines, source_path)
Expand All @@ -46,32 +41,30 @@ function M:create_autocmds(bufnr)
end,
},
},
})
}
end

---@param file string
---@return ChezmoiCommandResult
function M:exec(file)
local decrypted_result = vim.fn.systemlist("chezmoi decrypt " .. file)
local code = vim.v.shell_error
local bufnr = -1
if code ~= 0 then
log.error(decrypted_result)
else
bufnr = chezmoi_helper.create_buf(
chezmoi_helper.get_decrypted_path(file),
decrypted_result,
true,
false,
true
)
vim.bo[bufnr].modified = false
self:create_autocmds(bufnr)
local result = command.exec(self, { file })
if not result.success then
return result
end

local bufnr = chezmoi_helper.create_buf(
chezmoi_helper.get_decrypted_path(file),
result.data,
true,
false,
true
)
vim.bo[bufnr].modified = false
self:create_autocmds(bufnr)

return {
success = bufnr ~= -1,
data = bufnr,
data = { bufnr },
}
end

Expand Down
Loading

0 comments on commit 0d30547

Please sign in to comment.