From 3e0b7beabf4c7f1a4db0fcce9112c4dd44e5ec0d Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Tue, 3 Mar 2026 16:26:48 -0500 Subject: [PATCH] feat: add :CP login command for explicit credential management Problem: credentials were only set implicitly on first :CP submit. There was no way to update wrong credentials, log out, or set credentials ahead of time without editing the cache JSON manually. Solution: add :CP login [platform] which always prompts for username and password and overwrites any saved credentials for that platform. Omitting the platform falls back to the active platform. Wire the command through constants, parse_command, handle_command, and add tab-completion (suggests platform names). Document in vimdoc under the SUBMIT section and in the commands reference. --- doc/cp.nvim.txt | 27 +++++++++++++++++++++++---- lua/cp/commands/init.lua | 8 ++++++++ lua/cp/constants.lua | 1 + lua/cp/login.lua | 32 ++++++++++++++++++++++++++++++++ plugin/cp.lua | 2 ++ 5 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 lua/cp/login.lua diff --git a/doc/cp.nvim.txt b/doc/cp.nvim.txt index 4a10227..4a66764 100644 --- a/doc/cp.nvim.txt +++ b/doc/cp.nvim.txt @@ -433,10 +433,20 @@ COMMANDS *cp-commands* Cancel an active race countdown. Submit Commands ~ + :CP login [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 submit [--lang {language}] Submit the current solution to the online - judge. Prompts for credentials on first use - and stores them for subsequent submissions. + judge. Uses stored credentials (set via + :CP login). Prompts on first use if no + credentials are saved. --lang: Submit solution for a specific language. State Restoration ~ @@ -947,9 +957,18 @@ 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. Prompts for credentials on first use - and stores them for subsequent submissions. + Submit the current solution. Uses stored credentials (set via + :CP login). Prompts on first use if no credentials are saved. --lang: Override the language to submit. Platform support: diff --git a/lua/cp/commands/init.lua b/lua/cp/commands/init.lua index 1e158c7..3eca340 100644 --- a/lua/cp/commands/init.lua +++ b/lua/cp/commands/init.lua @@ -83,6 +83,12 @@ 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 == 'stress' then return { type = 'action', @@ -317,6 +323,8 @@ 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 diff --git a/lua/cp/constants.lua b/lua/cp/constants.lua index 21e8f62..02b7089 100644 --- a/lua/cp/constants.lua +++ b/lua/cp/constants.lua @@ -13,6 +13,7 @@ M.ACTIONS = { 'race', 'stress', 'submit', + 'login', } M.PLATFORM_DISPLAY_NAMES = { diff --git a/lua/cp/login.lua b/lua/cp/login.lua new file mode 100644 index 0000000..e1e8f25 --- /dev/null +++ b/lua/cp/login.lua @@ -0,0 +1,32 @@ +local M = {} + +local cache = require('cp.cache') +local logger = require('cp.log') +local state = require('cp.state') + +function M.login(platform) + platform = platform or state.get_platform() + if not platform then + logger.log('No platform specified. Usage: :CP login ', 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) + 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) + return + end + cache.load() + cache.set_credentials(platform, { username = username, password = password }) + logger.log(platform .. ' credentials saved', vim.log.levels.INFO) + end) +end + +return M diff --git a/plugin/cp.lua b/plugin/cp.lua index e9b159b..51bb858 100644 --- a/plugin/cp.lua +++ b/plugin/cp.lua @@ -103,6 +103,8 @@ end, { end end return filter_candidates(candidates) + elseif args[2] == 'login' then + return filter_candidates(platforms) elseif args[2] == 'race' then local candidates = { 'stop' } vim.list_extend(candidates, platforms)