feat: more stuff
This commit is contained in:
parent
ab9a0f43b5
commit
5ca6b8b272
6 changed files with 67 additions and 52 deletions
48
doc/cp.txt
48
doc/cp.txt
|
|
@ -85,7 +85,7 @@ Optional configuration with lazy.nvim: >
|
|||
'g++', '-std=c++{version}', '-O2', '-Wall', '-Wextra',
|
||||
'-DLOCAL', '{source}', '-o', '{binary}',
|
||||
},
|
||||
run = { '{binary}' },
|
||||
test = { '{binary}' },
|
||||
debug = {
|
||||
'g++', '-std=c++{version}', '-g3',
|
||||
'-fsanitize=address,undefined', '-DLOCAL',
|
||||
|
|
@ -95,7 +95,7 @@ Optional configuration with lazy.nvim: >
|
|||
extension = "cc",
|
||||
},
|
||||
python = {
|
||||
run = { 'python3', '{source}' },
|
||||
test = { 'python3', '{source}' },
|
||||
debug = { 'python3', '{source}' },
|
||||
extension = "py",
|
||||
},
|
||||
|
|
@ -104,11 +104,8 @@ Optional configuration with lazy.nvim: >
|
|||
},
|
||||
},
|
||||
hooks = {
|
||||
before_run = function(ctx) vim.cmd.w() end,
|
||||
before_debug = function(ctx)
|
||||
-- ctx.problem_id, ctx.platform, ctx.source_file, etc.
|
||||
vim.cmd.w()
|
||||
end,
|
||||
before_test = function(ctx) vim.cmd.w() end,
|
||||
before_debug = function(ctx) ... end,
|
||||
setup_code = function(ctx)
|
||||
vim.wo.foldmethod = "marker"
|
||||
vim.wo.foldmarker = "{{{,}}}"
|
||||
|
|
@ -116,9 +113,10 @@ Optional configuration with lazy.nvim: >
|
|||
end,
|
||||
},
|
||||
test_panel = {
|
||||
diff_mode = "vim", -- "vim" or "git"
|
||||
toggle_key = "t", -- key to toggle test panel
|
||||
status_format = "compact", -- "compact" or "verbose"
|
||||
diff_mode = "vim", -- "vim" or "git"
|
||||
toggle_key = "t", -- toggle test panel
|
||||
next_test_key = "<c-n>", -- navigate to next test case
|
||||
prev_test_key = "<c-p>", -- navigate to previous test case
|
||||
},
|
||||
diff = {
|
||||
git = {
|
||||
|
|
@ -126,9 +124,6 @@ Optional configuration with lazy.nvim: >
|
|||
args = {"diff", "--no-index", "--word-diff=plain",
|
||||
"--word-diff-regex=.", "--no-prefix"},
|
||||
},
|
||||
vim = {
|
||||
enable_diffthis = true,
|
||||
},
|
||||
},
|
||||
snippets = { ... }, -- LuaSnip snippets
|
||||
filename = function(contest, contest_id, problem_id, config, language) ... end,
|
||||
|
|
@ -168,7 +163,7 @@ Optional configuration with lazy.nvim: >
|
|||
Fields: ~
|
||||
• {compile}? (`string[]`) Compile command template with
|
||||
`{version}`, `{source}`, `{binary}` placeholders.
|
||||
• {run} (`string[]`) Run command template.
|
||||
• {test} (`string[]`) Test execution command template.
|
||||
• {debug}? (`string[]`) Debug compile command template.
|
||||
• {version}? (`number`) Language version (e.g. 20, 23 for C++).
|
||||
• {extension} (`string`) File extension (e.g. "cc", "py").
|
||||
|
|
@ -180,23 +175,38 @@ Optional configuration with lazy.nvim: >
|
|||
• {diff_mode} (`string`, default: `"vim"`) Diff backend: "vim" or "git".
|
||||
Git provides character-level precision, vim uses built-in diff.
|
||||
• {toggle_key} (`string`, default: `"t"`) Key to toggle test panel.
|
||||
• {status_format} (`string`, default: `"compact"`) Status display format.
|
||||
• {next_test_key} (`string`, default: `"<c-n>"`) Key to navigate to next test case.
|
||||
• {prev_test_key} (`string`, default: `"<c-p>"`) Key to navigate to previous test case.
|
||||
|
||||
*cp.DiffConfig*
|
||||
|
||||
Fields: ~
|
||||
• {git} (`DiffGitConfig`) Git diff backend configuration.
|
||||
• {vim} (`DiffVimConfig`) Vim diff backend configuration.
|
||||
|
||||
*cp.Hooks*
|
||||
|
||||
Fields: ~
|
||||
• {before_test}? (`function`) Called before test panel opens.
|
||||
`function(ctx: ProblemContext)`
|
||||
• {before_debug}? (`function`) Called before debug compilation.
|
||||
`function(ctx: ProblemContext)`
|
||||
• {setup_code}? (`function`) Called after source file is opened.
|
||||
Used to configure buffer settings.
|
||||
Good for configuring buffer settings.
|
||||
`function(ctx: ProblemContext)`
|
||||
|
||||
*ProblemContext*
|
||||
|
||||
Fields: ~
|
||||
• {contest} (`string`) Platform name (e.g. "atcoder", "codeforces")
|
||||
• {contest_id} (`string`) Contest ID (e.g. "abc123", "1933")
|
||||
• {problem_id}? (`string`) Problem ID (e.g. "a", "b") - nil for CSES
|
||||
• {source_file} (`string`) Source filename (e.g. "abc123a.cpp")
|
||||
• {binary_file} (`string`) Binary output path (e.g. "build/abc123a.run")
|
||||
• {input_file} (`string`) Test input path (e.g. "io/abc123a.cpin")
|
||||
• {output_file} (`string`) Program output path (e.g. "io/abc123a.cpout")
|
||||
• {expected_file} (`string`) Expected output path (e.g. "io/abc123a.expected")
|
||||
• {problem_name} (`string`) Display name (e.g. "abc123a")
|
||||
|
||||
WORKFLOW *cp-workflow*
|
||||
|
||||
For the sake of consistency and simplicity, cp.nvim extracts contest/problem identifiers from
|
||||
|
|
@ -328,8 +338,8 @@ Test cases use competitive programming terminology:
|
|||
|
||||
Keymaps ~
|
||||
*cp-test-keys*
|
||||
<c-n> Navigate to next test case
|
||||
<c-p> Navigate to previous test case
|
||||
<c-n> Navigate to next test case (configurable via test_panel.next_test_key)
|
||||
<c-p> Navigate to previous test case (configurable via test_panel.prev_test_key)
|
||||
q Exit test panel (restore layout)
|
||||
t Toggle test panel (configurable via test_panel.toggle_key)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---@class LanguageConfig
|
||||
---@field compile? string[] Compile command template
|
||||
---@field run string[] Run command template
|
||||
---@field test string[] Test execution command template
|
||||
---@field debug? string[] Debug command template
|
||||
---@field executable? string Executable name
|
||||
---@field version? number Language version
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
---@class PartialLanguageConfig
|
||||
---@field compile? string[] Compile command template
|
||||
---@field run? string[] Run command template
|
||||
---@field test? string[] Test execution command template
|
||||
---@field debug? string[] Debug command template
|
||||
---@field executable? string Executable name
|
||||
---@field version? number Language version
|
||||
|
|
@ -27,25 +27,22 @@
|
|||
---@field timeout_ms? number
|
||||
|
||||
---@class Hooks
|
||||
---@field before_run? fun(ctx: ProblemContext)
|
||||
---@field before_test? fun(ctx: ProblemContext)
|
||||
---@field before_debug? fun(ctx: ProblemContext)
|
||||
---@field setup_code? fun(ctx: ProblemContext)
|
||||
|
||||
---@class TestPanelConfig
|
||||
---@field diff_mode "vim"|"git" Diff backend to use
|
||||
---@field toggle_key string Key to toggle test panel
|
||||
---@field status_format "compact"|"verbose" Status display format
|
||||
---@field next_test_key string Key to navigate to next test case
|
||||
---@field prev_test_key string Key to navigate to previous test case
|
||||
|
||||
---@class DiffGitConfig
|
||||
---@field command string Git executable name
|
||||
---@field args string[] Additional git diff arguments
|
||||
|
||||
---@class DiffVimConfig
|
||||
---@field enable_diffthis boolean Enable vim's diffthis
|
||||
|
||||
---@class DiffConfig
|
||||
---@field git DiffGitConfig
|
||||
---@field vim DiffVimConfig
|
||||
|
||||
---@class cp.Config
|
||||
---@field contests table<string, ContestConfig>
|
||||
|
|
@ -75,7 +72,7 @@ M.defaults = {
|
|||
contests = {},
|
||||
snippets = {},
|
||||
hooks = {
|
||||
before_run = nil,
|
||||
before_test = nil,
|
||||
before_debug = nil,
|
||||
setup_code = nil,
|
||||
},
|
||||
|
|
@ -85,16 +82,14 @@ M.defaults = {
|
|||
test_panel = {
|
||||
diff_mode = 'vim',
|
||||
toggle_key = 't',
|
||||
status_format = 'compact',
|
||||
next_test_key = '<c-n>',
|
||||
prev_test_key = '<c-p>',
|
||||
},
|
||||
diff = {
|
||||
git = {
|
||||
command = 'git',
|
||||
args = { 'diff', '--no-index', '--word-diff=plain', '--word-diff-regex=.', '--no-prefix' },
|
||||
},
|
||||
vim = {
|
||||
enable_diffthis = true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -119,8 +114,8 @@ function M.setup(user_config)
|
|||
|
||||
if user_config.hooks then
|
||||
vim.validate({
|
||||
before_run = {
|
||||
user_config.hooks.before_run,
|
||||
before_test = {
|
||||
user_config.hooks.before_test,
|
||||
{ 'function', 'nil' },
|
||||
true,
|
||||
},
|
||||
|
|
@ -146,13 +141,26 @@ function M.setup(user_config)
|
|||
end,
|
||||
"diff_mode must be 'vim' or 'git'",
|
||||
},
|
||||
toggle_key = { user_config.test_panel.toggle_key, 'string', true },
|
||||
status_format = {
|
||||
user_config.test_panel.status_format,
|
||||
toggle_key = {
|
||||
user_config.test_panel.toggle_key,
|
||||
function(value)
|
||||
return vim.tbl_contains({ 'compact', 'verbose' }, value)
|
||||
return type(value) == 'string' and value ~= ''
|
||||
end,
|
||||
"status_format must be 'compact' or 'verbose'",
|
||||
'toggle_key must be a non-empty string',
|
||||
},
|
||||
next_test_key = {
|
||||
user_config.test_panel.next_test_key,
|
||||
function(value)
|
||||
return type(value) == 'string' and value ~= ''
|
||||
end,
|
||||
'next_test_key must be a non-empty string',
|
||||
},
|
||||
prev_test_key = {
|
||||
user_config.test_panel.prev_test_key,
|
||||
function(value)
|
||||
return type(value) == 'string' and value ~= ''
|
||||
end,
|
||||
'prev_test_key must be a non-empty string',
|
||||
},
|
||||
})
|
||||
end
|
||||
|
|
@ -160,7 +168,6 @@ function M.setup(user_config)
|
|||
if user_config.diff then
|
||||
vim.validate({
|
||||
git = { user_config.diff.git, { 'table', 'nil' }, true },
|
||||
vim = { user_config.diff.vim, { 'table', 'nil' }, true },
|
||||
})
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -278,7 +278,7 @@ function M.run_problem(ctx, contest_config, is_debug)
|
|||
input_data = table.concat(vim.fn.readfile(ctx.input_file), '\n') .. '\n'
|
||||
end
|
||||
|
||||
local run_cmd = build_command(language_config.run, language_config.executable, substitutions)
|
||||
local run_cmd = build_command(language_config.test, language_config.executable, substitutions)
|
||||
local exec_result = execute_command(run_cmd, input_data, contest_config.timeout_ms)
|
||||
local formatted_output = format_output(exec_result, ctx.expected_file, is_debug)
|
||||
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ local function toggle_test_panel(is_debug)
|
|||
local test_render = require('cp.test_render')
|
||||
test_render.setup_highlights()
|
||||
local test_state = test_module.get_test_panel_state()
|
||||
return test_render.render_test_list(test_state, config.test_panel)
|
||||
return test_render.render_test_list(test_state)
|
||||
end
|
||||
|
||||
local function update_buffer_content(bufnr, lines)
|
||||
|
|
@ -305,7 +305,6 @@ local function toggle_test_panel(is_debug)
|
|||
end
|
||||
else
|
||||
update_buffer_content(test_buffers.actual_buf, actual_lines)
|
||||
vim.api.nvim_set_option_value('diff', true, { win = test_windows.expected_win })
|
||||
vim.api.nvim_set_option_value('diff', true, { win = test_windows.actual_win })
|
||||
vim.api.nvim_win_call(test_windows.expected_win, function()
|
||||
vim.cmd.diffthis()
|
||||
|
|
@ -349,10 +348,10 @@ local function toggle_test_panel(is_debug)
|
|||
refresh_test_panel()
|
||||
end
|
||||
|
||||
vim.keymap.set('n', '<c-n>', function()
|
||||
vim.keymap.set('n', config.test_panel.next_test_key, function()
|
||||
navigate_test_case(1)
|
||||
end, { buffer = test_buffers.tab_buf, silent = true })
|
||||
vim.keymap.set('n', '<c-p>', function()
|
||||
vim.keymap.set('n', config.test_panel.prev_test_key, function()
|
||||
navigate_test_case(-1)
|
||||
end, { buffer = test_buffers.tab_buf, silent = true })
|
||||
|
||||
|
|
@ -365,6 +364,10 @@ local function toggle_test_panel(is_debug)
|
|||
end, { buffer = buf, silent = true })
|
||||
end
|
||||
|
||||
if config.hooks and config.hooks.before_test then
|
||||
config.hooks.before_test(ctx)
|
||||
end
|
||||
|
||||
if is_debug and config.hooks and config.hooks.before_debug then
|
||||
config.hooks.before_debug(ctx)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ local function run_single_test_case(ctx, contest_config, test_case)
|
|||
end
|
||||
end
|
||||
|
||||
local run_cmd = build_command(language_config.run, language_config.executable, substitutions)
|
||||
local run_cmd = build_command(language_config.test, language_config.executable, substitutions)
|
||||
|
||||
local stdin_content = test_case.input .. '\n'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
---@class TestRenderConfig
|
||||
---@field status_format "compact"|"verbose"
|
||||
|
||||
---@class StatusInfo
|
||||
---@field text string
|
||||
---@field highlight_group string
|
||||
|
|
@ -32,10 +29,8 @@ end
|
|||
|
||||
---Render test cases list with improved layout
|
||||
---@param test_state TestPanelState
|
||||
---@param config? TestRenderConfig
|
||||
---@return string[]
|
||||
function M.render_test_list(test_state, config)
|
||||
config = config or { status_format = 'compact' }
|
||||
function M.render_test_list(test_state)
|
||||
local lines = {}
|
||||
|
||||
for i, test_case in ipairs(test_state.test_cases) do
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue