Problem: when a user runs `:Pending s3 auth` with no bucket configured, auth succeeds but offers no way to create the bucket. The user must manually run `aws s3api create-bucket` and update their config. Solution: add `util.input()` coroutine-aware prompt wrapper and a `create_bucket()` flow in `s3.lua` that prompts for bucket name and region, handles the `us-east-1` LocationConstraint quirk, and logs a config snippet on success. Called automatically from `auth()` when `sync.s3.bucket` is absent.
98 lines
2.2 KiB
Lua
98 lines
2.2 KiB
Lua
local log = require('pending.log')
|
|
|
|
---@class pending.SystemResult
|
|
---@field code integer
|
|
---@field stdout string
|
|
---@field stderr string
|
|
|
|
---@class pending.CountPart
|
|
---@field [1] integer
|
|
---@field [2] string
|
|
|
|
---@class pending.sync.util
|
|
local M = {}
|
|
|
|
local _sync_in_flight = false
|
|
|
|
---@param fn fun(): nil
|
|
function M.async(fn)
|
|
coroutine.resume(coroutine.create(fn))
|
|
end
|
|
|
|
---@param args string[]
|
|
---@param opts? table
|
|
---@return pending.SystemResult
|
|
function M.system(args, opts)
|
|
local co = coroutine.running()
|
|
if not co then
|
|
return vim.system(args, opts or {}):wait() --[[@as pending.SystemResult]]
|
|
end
|
|
vim.system(args, opts or {}, function(result)
|
|
vim.schedule(function()
|
|
coroutine.resume(co, result)
|
|
end)
|
|
end)
|
|
return coroutine.yield() --[[@as { code: integer, stdout: string, stderr: string }]]
|
|
end
|
|
|
|
---@param opts? {prompt?: string, default?: string}
|
|
---@return string?
|
|
function M.input(opts)
|
|
local co = coroutine.running()
|
|
if not co then
|
|
error('util.input() must be called inside a coroutine')
|
|
end
|
|
vim.ui.input(opts or {}, function(result)
|
|
vim.schedule(function()
|
|
coroutine.resume(co, result)
|
|
end)
|
|
end)
|
|
return coroutine.yield() --[[@as string?]]
|
|
end
|
|
|
|
---@param name string
|
|
---@param fn fun(): nil
|
|
function M.with_guard(name, fn)
|
|
if _sync_in_flight then
|
|
log.warn(name .. ': Sync already in progress — please wait.')
|
|
return
|
|
end
|
|
_sync_in_flight = true
|
|
local ok, err = pcall(fn)
|
|
_sync_in_flight = false
|
|
if not ok then
|
|
log.error(name .. ': ' .. tostring(err))
|
|
end
|
|
end
|
|
|
|
---@return boolean
|
|
function M.sync_in_flight()
|
|
return _sync_in_flight
|
|
end
|
|
|
|
---@param s pending.Store
|
|
function M.finish(s)
|
|
s:save()
|
|
require('pending')._recompute_counts()
|
|
local buffer = require('pending.buffer')
|
|
if buffer.bufnr() and vim.api.nvim_buf_is_valid(buffer.bufnr()) then
|
|
buffer.render(buffer.bufnr())
|
|
end
|
|
end
|
|
|
|
---@param parts pending.CountPart[]
|
|
---@return string
|
|
function M.fmt_counts(parts)
|
|
local items = {}
|
|
for _, p in ipairs(parts) do
|
|
if p[1] > 0 then
|
|
table.insert(items, p[1] .. ' ' .. p[2])
|
|
end
|
|
end
|
|
if #items == 0 then
|
|
return 'nothing to do'
|
|
end
|
|
return table.concat(items, ' | ')
|
|
end
|
|
|
|
return M
|