diff --git a/doc/cp.nvim.txt b/doc/cp.nvim.txt index 4a66764..ef4135e 100644 --- a/doc/cp.nvim.txt +++ b/doc/cp.nvim.txt @@ -432,21 +432,29 @@ COMMANDS *cp-commands* :CP race stop Cancel an active race countdown. - Submit Commands ~ - :CP login [platform] + Credential Commands ~ + :CP credentials set [platform] Set or update stored credentials for a platform. Always prompts for username and password, overwriting any previously saved credentials. If [platform] is omitted, uses the active platform. Examples: > - :CP login atcoder - :CP login codeforces + :CP credentials set atcoder + :CP credentials set codeforces < + :CP credentials clear [platform] + Remove stored credentials. Without [platform], + clears credentials for all platforms. + Examples: > + :CP credentials clear atcoder + :CP credentials clear +< + Submit Commands ~ :CP submit [--lang {language}] Submit the current solution to the online judge. Uses stored credentials (set via - :CP login). Prompts on first use if no - credentials are saved. + :CP credentials set). Prompts on first use + if no credentials are saved. --lang: Submit solution for a specific language. State Restoration ~ @@ -952,23 +960,31 @@ Count down to a contest's start time and automatically run setup at T=0. Statusline integration: see |cp-race-status|. +============================================================================== +CREDENTIALS *cp-credentials* + +Manage stored login credentials for platform submission. + +Credentials are stored under _credentials in the main cache file +(stdpath('data')/cp-nvim.json). Use :CP cache read to inspect them. + +:CP credentials set [platform] + Set or update credentials for a platform. Always prompts for + username and password, overwriting any previously saved values. + Omit [platform] to use the currently active platform. + +:CP credentials clear [platform] + Remove stored credentials. Without [platform], clears all platforms. + ============================================================================== SUBMIT *cp-submit* Submit the current solution to the online judge. -:CP login [platform] *cp-login* - Set or update stored credentials for a platform. Always prompts for - username and password, overwriting any previously saved credentials. - Omit [platform] to use the currently active platform. - - Credentials are stored in the main cache file under _credentials. - Use this command before submitting for the first time, or any time - you need to update stored credentials. - :CP submit [--lang {language}] Submit the current solution. Uses stored credentials (set via - :CP login). Prompts on first use if no credentials are saved. + :CP credentials set). Prompts on first use if no credentials + are saved. --lang: Override the language to submit. Platform support: diff --git a/lua/cp/cache.lua b/lua/cp/cache.lua index 60c91de..baea9b9 100644 --- a/lua/cp/cache.lua +++ b/lua/cp/cache.lua @@ -388,6 +388,18 @@ function M.set_credentials(platform, creds) M.save() end +---@param platform string? +function M.clear_credentials(platform) + if platform then + if cache_data._credentials then + cache_data._credentials[platform] = nil + end + else + cache_data._credentials = nil + end + M.save() +end + function M.clear_all() local creds = cache_data._credentials cache_data = {} diff --git a/lua/cp/commands/init.lua b/lua/cp/commands/init.lua index 3eca340..2a6be0a 100644 --- a/lua/cp/commands/init.lua +++ b/lua/cp/commands/init.lua @@ -83,12 +83,20 @@ local function parse_command(args) else return { type = 'action', action = 'interact' } end - elseif first == 'login' then - return { - type = 'action', - action = 'login', - platform = args[2], - } + elseif first == 'credentials' then + local subcommand = args[2] + if not subcommand then + return { type = 'error', message = 'credentials command requires subcommand (set, clear)' } + end + if vim.tbl_contains({ 'set', 'clear' }, subcommand) then + return { + type = 'credentials', + subcommand = subcommand, + platform = args[3], + } + else + return { type = 'error', message = 'unknown credentials subcommand: ' .. subcommand } + end elseif first == 'stress' then return { type = 'action', @@ -323,8 +331,6 @@ function M.handle_command(opts) edit.toggle_edit(cmd.test_index) elseif cmd.action == 'stress' then require('cp.stress').toggle(cmd.generator_cmd, cmd.brute_cmd) - elseif cmd.action == 'login' then - require('cp.login').login(cmd.platform) elseif cmd.action == 'submit' then require('cp.submit').submit({ language = cmd.language }) elseif cmd.action == 'race' then @@ -360,6 +366,13 @@ function M.handle_command(opts) local setup = require('cp.setup') setup.setup_contest(platform, contest_id, problem_id, cmd.language) + elseif cmd.type == 'credentials' then + local creds = require('cp.credentials') + if cmd.subcommand == 'set' then + creds.set(cmd.platform) + elseif cmd.subcommand == 'clear' then + creds.clear(cmd.platform) + end elseif cmd.type == 'cache' then local cache_commands = require('cp.commands.cache') cache_commands.handle_cache_command(cmd) diff --git a/lua/cp/constants.lua b/lua/cp/constants.lua index 02b7089..c1add6a 100644 --- a/lua/cp/constants.lua +++ b/lua/cp/constants.lua @@ -13,7 +13,7 @@ M.ACTIONS = { 'race', 'stress', 'submit', - 'login', + 'credentials', } M.PLATFORM_DISPLAY_NAMES = { diff --git a/lua/cp/login.lua b/lua/cp/credentials.lua similarity index 57% rename from lua/cp/login.lua rename to lua/cp/credentials.lua index e1e8f25..f9b18b9 100644 --- a/lua/cp/login.lua +++ b/lua/cp/credentials.lua @@ -4,29 +4,42 @@ local cache = require('cp.cache') local logger = require('cp.log') local state = require('cp.state') -function M.login(platform) +function M.set(platform) platform = platform or state.get_platform() if not platform then - logger.log('No platform specified. Usage: :CP login ', vim.log.levels.ERROR) + logger.log( + 'No platform specified. Usage: :CP credentials set ', + vim.log.levels.ERROR + ) return end vim.ui.input({ prompt = platform .. ' username: ' }, function(username) if not username or username == '' then - logger.log('Login cancelled', vim.log.levels.WARN) + logger.log('Cancelled', vim.log.levels.WARN) return end vim.fn.inputsave() local password = vim.fn.inputsecret(platform .. ' password: ') vim.fn.inputrestore() if not password or password == '' then - logger.log('Login cancelled', vim.log.levels.WARN) + logger.log('Cancelled', vim.log.levels.WARN) return end cache.load() cache.set_credentials(platform, { username = username, password = password }) - logger.log(platform .. ' credentials saved', vim.log.levels.INFO) + logger.log(platform .. ' credentials saved', vim.log.levels.INFO, true) end) end +function M.clear(platform) + cache.load() + cache.clear_credentials(platform) + if platform then + logger.log(platform .. ' credentials cleared', vim.log.levels.INFO, true) + else + logger.log('all credentials cleared', vim.log.levels.INFO, true) + end +end + return M diff --git a/plugin/cp.lua b/plugin/cp.lua index 51bb858..41e474f 100644 --- a/plugin/cp.lua +++ b/plugin/cp.lua @@ -103,8 +103,8 @@ end, { end end return filter_candidates(candidates) - elseif args[2] == 'login' then - return filter_candidates(platforms) + elseif args[2] == 'credentials' then + return filter_candidates({ 'set', 'clear' }) elseif args[2] == 'race' then local candidates = { 'stop' } vim.list_extend(candidates, platforms) @@ -126,6 +126,8 @@ end, { cache.load() local contests = cache.get_cached_contest_ids(args[3]) return filter_candidates(contests) + elseif args[2] == 'credentials' and vim.tbl_contains({ 'set', 'clear' }, args[3]) then + return filter_candidates(platforms) elseif args[2] == 'cache' and args[3] == 'clear' then local candidates = vim.list_extend({}, platforms) table.insert(candidates, '')