163 lines
4.4 KiB
Lua
163 lines
4.4 KiB
Lua
local M = {}
|
|
|
|
local constants = require('cp.constants')
|
|
local logger = require('cp.log')
|
|
local state = require('cp.state')
|
|
|
|
local platforms = constants.PLATFORMS
|
|
local actions = constants.ACTIONS
|
|
|
|
---@class ParsedCommand
|
|
---@field type string
|
|
---@field error string?
|
|
---@field action? string
|
|
---@field message? string
|
|
---@field contest? string
|
|
---@field platform? string
|
|
---@field problem_id? string
|
|
---@field interactor_cmd? string
|
|
|
|
--- Turn raw args into normalized structure to later dispatch
|
|
---@param args string[] The raw command-line mode args
|
|
---@return ParsedCommand
|
|
local function parse_command(args)
|
|
if vim.tbl_isempty(args) then
|
|
return {
|
|
type = 'restore_from_file',
|
|
}
|
|
end
|
|
|
|
local first = args[1]
|
|
|
|
if vim.tbl_contains(actions, first) then
|
|
if first == 'cache' then
|
|
local subcommand = args[2]
|
|
if not subcommand then
|
|
return { type = 'error', message = 'cache command requires subcommand' }
|
|
end
|
|
if vim.tbl_contains({ 'clear', 'read' }, subcommand) then
|
|
local platform = args[3]
|
|
return {
|
|
type = 'cache',
|
|
subcommand = subcommand,
|
|
platform = platform,
|
|
}
|
|
else
|
|
return { type = 'error', message = 'unknown cache subcommand: ' .. subcommand }
|
|
end
|
|
elseif first == 'interact' then
|
|
local inter = args[2]
|
|
if inter and inter ~= '' then
|
|
return { type = 'action', action = 'interact', interactor_cmd = inter }
|
|
else
|
|
return { type = 'action', action = 'interact' }
|
|
end
|
|
else
|
|
return { type = 'action', action = first }
|
|
end
|
|
end
|
|
|
|
if vim.tbl_contains(platforms, first) then
|
|
if #args == 1 then
|
|
return {
|
|
type = 'error',
|
|
message = 'Too few arguments - specify a contest.',
|
|
}
|
|
elseif #args == 2 then
|
|
return {
|
|
type = 'contest_setup',
|
|
platform = first,
|
|
contest = args[2],
|
|
}
|
|
elseif #args == 3 then
|
|
return {
|
|
type = 'error',
|
|
message = 'Setup contests with :CP <platform> <contest_id>.',
|
|
}
|
|
else
|
|
return { type = 'error', message = 'Too many arguments' }
|
|
end
|
|
end
|
|
|
|
if #args == 1 then
|
|
return {
|
|
type = 'problem_jump',
|
|
problem_id = first,
|
|
}
|
|
end
|
|
|
|
return { type = 'error', message = 'Unknown command or no contest context.' }
|
|
end
|
|
|
|
--- Core logic for handling `:CP ...` commands
|
|
---@return nil
|
|
function M.handle_command(opts)
|
|
local cmd = parse_command(opts.fargs)
|
|
|
|
if cmd.type == 'error' then
|
|
logger.log(cmd.message, vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
if cmd.type == 'restore_from_file' then
|
|
local restore = require('cp.restore')
|
|
restore.restore_from_current_file()
|
|
elseif cmd.type == 'action' then
|
|
local setup = require('cp.setup')
|
|
local ui = require('cp.ui.panel')
|
|
|
|
if cmd.action == 'interact' then
|
|
ui.toggle_interactive(cmd.interactor_cmd)
|
|
elseif cmd.action == 'run' then
|
|
ui.run_io_view()
|
|
elseif cmd.action == 'panel' then
|
|
ui.toggle_panel()
|
|
elseif cmd.action == 'debug' then
|
|
ui.toggle_panel({ debug = true })
|
|
elseif cmd.action == 'next' then
|
|
setup.navigate_problem(1)
|
|
elseif cmd.action == 'prev' then
|
|
setup.navigate_problem(-1)
|
|
elseif cmd.action == 'pick' then
|
|
local picker = require('cp.commands.picker')
|
|
picker.handle_pick_action()
|
|
end
|
|
elseif cmd.type == 'problem_jump' then
|
|
local platform = state.get_platform()
|
|
local contest_id = state.get_contest_id()
|
|
local problem_id = cmd.problem_id
|
|
|
|
if not (platform and contest_id) then
|
|
logger.log('No contest is currently active.', vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
local cache = require('cp.cache')
|
|
cache.load()
|
|
local contest_data = cache.get_contest_data(platform, contest_id)
|
|
|
|
if not (contest_data and contest_data.index_map and contest_data.index_map[problem_id]) then
|
|
logger.log(
|
|
("%s contest '%s' has no problem '%s'."):format(
|
|
constants.PLATFORM_DISPLAY_NAMES[platform],
|
|
contest_id,
|
|
problem_id
|
|
),
|
|
vim.log.levels.ERROR
|
|
)
|
|
return
|
|
end
|
|
|
|
local setup = require('cp.setup')
|
|
setup.setup_contest(platform, contest_id, problem_id)
|
|
elseif cmd.type == 'cache' then
|
|
local cache_commands = require('cp.commands.cache')
|
|
cache_commands.handle_cache_command(cmd)
|
|
elseif cmd.type == 'contest_setup' then
|
|
local setup = require('cp.setup')
|
|
setup.setup_contest(cmd.platform, cmd.contest, nil)
|
|
return
|
|
end
|
|
end
|
|
|
|
return M
|