feat(commands): implement :CP open [problem|contest|standings] (#319)

## Problem

There was no way to open a problem, contest, or standings page in the
browser from within the plugin.

## Solution

Add `contest_url` and `standings_url` to `MetadataResult` and persist
them in the cache. Add `cache.get_open_urls` to resolve all three URLs.
Wire up `:CP open [problem|contest|standings]` in `commands/init.lua`
to call `vim.ui.open`, warning when a URL is unavailable (e.g. CSES
has no standings). Closes #315.
This commit is contained in:
Barrett Ruth 2026-03-05 19:16:05 -05:00 committed by GitHub
parent b959f29bd4
commit 7bf4cf2538
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 65 additions and 2 deletions

View file

@ -245,6 +245,12 @@ local function parse_command(args)
debug = debug,
mode = mode,
}
elseif first == 'open' then
local target = args[2] or 'problem'
if not vim.tbl_contains({ 'problem', 'contest', 'standings' }, target) then
return { type = 'error', message = 'Usage: :CP open [problem|contest|standings]' }
end
return { type = 'action', action = 'open', requires_context = true, subcommand = target }
elseif first == 'pick' then
local language = nil
if #args >= 3 and args[2] == '--lang' then
@ -375,6 +381,20 @@ function M.handle_command(opts)
require('cp.race').start(cmd.platform, cmd.contest, cmd.language)
elseif cmd.action == 'race_stop' then
require('cp.race').stop()
elseif cmd.action == 'open' then
local cache = require('cp.cache')
cache.load()
local urls =
cache.get_open_urls(state.get_platform(), state.get_contest_id(), state.get_problem_id())
local url = urls and urls[cmd.subcommand]
if not url or url == '' then
logger.log(
("No URL available for '%s'"):format(cmd.subcommand),
{ level = vim.log.levels.WARN }
)
return
end
vim.ui.open(url)
elseif cmd.action == 'login' then
require('cp.credentials').login(cmd.platform)
elseif cmd.action == 'logout' then