diff --git a/lua/pending/init.lua b/lua/pending/init.lua index 0fd3a98..4e093bf 100644 --- a/lua/pending/init.lua +++ b/lua/pending/init.lua @@ -918,22 +918,33 @@ function M.edit(id_str, rest) log.info('Task #' .. id .. ' updated: ' .. table.concat(feedback, ', ')) end +---@param args? string ---@return nil -function M.auth() +function M.auth(args) local oauth = require('pending.sync.oauth') - vim.ui.select({ 'Google Tasks', 'Google Calendar', 'Google Tasks and Google Calendar' }, { - prompt = 'Authenticate with:', - }, function(choice) - if not choice then - return - end + local parts = {} + for w in (args or ''):gmatch('%S+') do + table.insert(parts, w) + end + local action = parts[#parts] + if action == parts[1] and (action == 'gtasks' or action == 'gcal') then + action = nil + end + + if action == 'clear' then + oauth.google_client:clear_tokens() + log.info('OAuth tokens cleared — run :Pending auth to re-authenticate.') + elseif action == 'reset' then + oauth.google_client:_wipe() + log.info('OAuth tokens and credentials cleared — run :Pending auth to set up from scratch.') + else local creds = oauth.google_client:resolve_credentials() if creds.client_id == oauth.BUNDLED_CLIENT_ID then oauth.google_client:setup() else oauth.google_client:auth() end - end) + end end ---@param args string @@ -952,7 +963,7 @@ function M.command(args) local id_str, edit_rest = rest:match('^(%S+)%s*(.*)') M.edit(id_str, edit_rest) elseif cmd == 'auth' then - M.auth() + M.auth(rest) elseif SYNC_BACKEND_SET[cmd] then local action = rest:match('^(%S+)') run_sync(cmd, action) diff --git a/lua/pending/sync/gcal.lua b/lua/pending/sync/gcal.lua index 942fbec..1fe8557 100644 --- a/lua/pending/sync/gcal.lua +++ b/lua/pending/sync/gcal.lua @@ -134,16 +134,7 @@ local function with_token(callback) oauth.async(function() local token = oauth.google_client:get_access_token() if not token then - oauth.google_client:auth(function() - oauth.async(function() - local fresh = oauth.google_client:get_access_token() - if fresh then - callback(fresh) - else - log.error(oauth.google_client.name .. ': authorization failed or was cancelled') - end - end) - end) + log.warn('not authenticated — run :Pending auth') return end callback(token) diff --git a/lua/pending/sync/gtasks.lua b/lua/pending/sync/gtasks.lua index 9fc7459..6c8bef3 100644 --- a/lua/pending/sync/gtasks.lua +++ b/lua/pending/sync/gtasks.lua @@ -404,16 +404,7 @@ local function with_token(callback) oauth.async(function() local token = oauth.google_client:get_access_token() if not token then - oauth.google_client:auth(function() - oauth.async(function() - local fresh = oauth.google_client:get_access_token() - if fresh then - callback(fresh) - else - log.error(oauth.google_client.name .. ': authorization failed or was cancelled') - end - end) - end) + log.warn('not authenticated — run :Pending auth') return end callback(token) diff --git a/lua/pending/sync/oauth.lua b/lua/pending/sync/oauth.lua index 224476b..8539ea6 100644 --- a/lua/pending/sync/oauth.lua +++ b/lua/pending/sync/oauth.lua @@ -496,6 +496,11 @@ function OAuthClient:_wipe() os.remove(vim.fn.stdpath('data') .. '/pending/google_credentials.json') end +---@return nil +function OAuthClient:clear_tokens() + os.remove(self:token_path()) +end + ---@param opts { name: string, scope: string, port: integer, config_key: string } ---@return pending.OAuthClient function M.new(opts) diff --git a/plugin/pending.lua b/plugin/pending.lua index d246fba..e456f09 100644 --- a/plugin/pending.lua +++ b/plugin/pending.lua @@ -213,6 +213,21 @@ end, { if cmd_line:match('^Pending%s+edit') then return complete_edit(arg_lead, cmd_line) end + if cmd_line:match('^Pending%s+auth') then + local after_auth = cmd_line:match('^Pending%s+auth%s+(.*)') or '' + local parts = {} + for w in after_auth:gmatch('%S+') do + table.insert(parts, w) + end + local trailing = after_auth:match('%s$') + if #parts == 0 or (#parts == 1 and not trailing) then + return filter_candidates(arg_lead, { 'gcal', 'gtasks', 'clear', 'reset' }) + end + if #parts == 1 or (#parts == 2 and not trailing) then + return filter_candidates(arg_lead, { 'clear', 'reset' }) + end + return {} + end local backend_set = pending.sync_backend_set() local matched_backend = cmd_line:match('^Pending%s+(%S+)') if matched_backend and backend_set[matched_backend] then