Merge pull request #34 from barrett-ruth/fix/move-to-defaults
Fix Default Configs
This commit is contained in:
commit
a825df595e
11 changed files with 126 additions and 223 deletions
123
doc/cp.txt
123
doc/cp.txt
|
|
@ -77,7 +77,7 @@ Optional configuration with lazy.nvim: >
|
|||
opts = {
|
||||
debug = false,
|
||||
contests = {
|
||||
default = {
|
||||
codeforces = {
|
||||
cpp = {
|
||||
compile = {
|
||||
'g++', '-std=c++{version}', '-O2', '-Wall', '-Wextra',
|
||||
|
|
@ -89,7 +89,7 @@ Optional configuration with lazy.nvim: >
|
|||
'-fsanitize=address,undefined', '-DLOCAL',
|
||||
'{source}', '-o', '{binary}',
|
||||
},
|
||||
version = 20,
|
||||
version = 23,
|
||||
extension = "cc",
|
||||
},
|
||||
python = {
|
||||
|
|
@ -97,9 +97,9 @@ Optional configuration with lazy.nvim: >
|
|||
debug = { 'python3', '{source}' },
|
||||
extension = "py",
|
||||
},
|
||||
default_language = "cpp",
|
||||
timeout_ms = 2000,
|
||||
},
|
||||
codeforces = { cpp = { version = 23 } },
|
||||
},
|
||||
hooks = {
|
||||
before_run = function(ctx) vim.cmd.w() end,
|
||||
|
|
@ -107,64 +107,65 @@ Optional configuration with lazy.nvim: >
|
|||
-- ctx.problem_id, ctx.platform, ctx.source_file, etc.
|
||||
vim.cmd.w()
|
||||
end,
|
||||
setup_code = function(ctx)
|
||||
vim.wo.foldmethod = "marker"
|
||||
vim.wo.foldmarker = "{{{,}}}"
|
||||
vim.diagnostic.enable(false)
|
||||
end,
|
||||
},
|
||||
snippets = { ... }, -- LuaSnip snippets
|
||||
tile = function(source_buf, input_buf, output_buf) ... end,
|
||||
filename = function(contest, problem_id, problem_letter) ... end,
|
||||
filename = function(contest, contest_id, problem_id, config, language) ... end,
|
||||
}
|
||||
}
|
||||
<
|
||||
|
||||
Configuration options:
|
||||
*cp.Config*
|
||||
|
||||
contests Dictionary of contest configurations - each contest inherits from 'default'.
|
||||
Fields: ~
|
||||
• {contests} (`table<string,ContestConfig>`) Contest configurations.
|
||||
• {hooks} (`cp.Hooks`) Hook functions called at various stages.
|
||||
• {snippets} (`table[]`) LuaSnip snippet definitions.
|
||||
• {debug} (`boolean`, default: `false`) Show info messages
|
||||
during operation.
|
||||
• {tile}? (`function`) Custom window arrangement function.
|
||||
`function(source_buf, input_buf, output_buf)`
|
||||
• {filename}? (`function`) Custom filename generation function.
|
||||
`function(contest, contest_id, problem_id, config, language)`
|
||||
Should return full filename with extension.
|
||||
(default: uses problem_id or contest_id)
|
||||
|
||||
cpp C++ language configuration
|
||||
compile Compile command template with {version}, {source}, {binary} placeholders
|
||||
run Run command template with {binary} placeholder
|
||||
debug Debug compile command template
|
||||
version C++ standard version (e.g. 20, 23)
|
||||
extension File extension for C++ files (default: "cc")
|
||||
*cp.ContestConfig*
|
||||
|
||||
python Python language configuration
|
||||
run Run command template with {source} placeholder
|
||||
debug Debug run command template
|
||||
extension File extension for Python files (default: "py")
|
||||
Fields: ~
|
||||
• {cpp} (`LanguageConfig`) C++ language configuration.
|
||||
• {python} (`LanguageConfig`) Python language configuration.
|
||||
• {default_language} (`string`, default: `"cpp"`) Default language when
|
||||
`--lang` not specified.
|
||||
• {timeout_ms} (`number`, default: `2000`) Execution timeout in
|
||||
milliseconds.
|
||||
|
||||
default_language Default language when --lang not specified (default: "cpp")
|
||||
*cp.LanguageConfig*
|
||||
|
||||
timeout_ms Duration (ms) to run/debug before timeout
|
||||
Fields: ~
|
||||
• {compile}? (`string[]`) Compile command template with
|
||||
`{version}`, `{source}`, `{binary}` placeholders.
|
||||
• {run} (`string[]`) Run 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").
|
||||
• {executable}? (`string`) Executable name for interpreted languages.
|
||||
|
||||
snippets LuaSnip snippets by contest type
|
||||
*cp.Hooks*
|
||||
|
||||
hooks Functions called at specific events
|
||||
before_run Called before :CP run
|
||||
function(ctx)
|
||||
ctx contains:
|
||||
- problem_id: string
|
||||
- platform: string (atcoder/codeforces/cses)
|
||||
- contest_id: string
|
||||
- source_file: string (path to source)
|
||||
- input_file: string (path to .cpin)
|
||||
- output_file: string (path to .cpout)
|
||||
- expected_file: string (path to .expected)
|
||||
- contest_config: table (language configs)
|
||||
(default: nil, do nothing)
|
||||
before_debug Called before :CP debug
|
||||
function(ctx)
|
||||
Same ctx as before_run
|
||||
(default: nil, do nothing)
|
||||
|
||||
debug Show info messages during operation
|
||||
(default: false, silent operation)
|
||||
|
||||
tile Custom function to arrange windows
|
||||
function(source_buf, input_buf, output_buf)
|
||||
(default: nil, uses built-in layout)
|
||||
|
||||
filename Custom function to generate filenames
|
||||
function(contest, problem_id, problem_letter)
|
||||
(default: nil, uses problem_id + letter + ".cc")
|
||||
Fields: ~
|
||||
• {before_run}? (`function`) Called before `:CP run`.
|
||||
`function(ctx: ProblemContext)`
|
||||
• {before_debug}? (`function`) Called before `:CP debug`.
|
||||
`function(ctx: ProblemContext)`
|
||||
• {setup_code}? (`function`) Called after source file is opened.
|
||||
Used to configure buffer settings.
|
||||
`function(ctx: ProblemContext)`
|
||||
|
||||
WORKFLOW *cp-workflow*
|
||||
|
||||
|
|
@ -232,7 +233,7 @@ Example: Setting up and solving AtCoder contest ABC324
|
|||
|
||||
3. Start with problem A: >
|
||||
:CP a
|
||||
< This creates abc324a.cc and scrapes test cases
|
||||
< This creates a.cc and scrapes test cases
|
||||
|
||||
4. Code your solution, then test: >
|
||||
:CP run
|
||||
|
|
@ -259,32 +260,26 @@ FILE STRUCTURE *cp-files*
|
|||
|
||||
cp.nvim creates the following file structure upon problem setup:
|
||||
|
||||
{contest_id}{problem_id}.cc " Source file (e.g. abc324a.cc)
|
||||
{problem_id}.{ext} " Source file (e.g. a.cc, b.py)
|
||||
build/
|
||||
{contest_id}{problem_id}.run " Compiled binary
|
||||
{problem_id}.run " Compiled binary
|
||||
io/
|
||||
{contest_id}{problem_id}.cpin " Test input
|
||||
{contest_id}{problem_id}.cpout " Program output
|
||||
{contest_id}{problem_id}.expected " Expected output
|
||||
{problem_id}.cpin " Test input
|
||||
{problem_id}.cpout " Program output
|
||||
{problem_id}.expected " Expected output
|
||||
|
||||
The plugin automatically manages this structure and navigation between problems
|
||||
maintains proper file associations.
|
||||
|
||||
SNIPPETS *cp-snippets*
|
||||
|
||||
cp.nvim integrates with LuaSnip for automatic template expansion. When you
|
||||
open a new problem file, type the contest name and press <Tab> to expand.
|
||||
cp.nvim integrates with LuaSnip for automatic template expansion. Built-in
|
||||
snippets include basic C++ and Python templates for each contest type.
|
||||
|
||||
Built-in snippets include basic C++ and Python templates for each contest type.
|
||||
Custom snippets can be added via configuration.
|
||||
Snippet trigger names must EXACTLY match platform names ("codeforces" for
|
||||
CodeForces, "cses" for CSES, etc.).
|
||||
|
||||
IMPORTANT: Snippet trigger names must exactly match the contest/platform names:
|
||||
- "codeforces" for Codeforces problems
|
||||
- "atcoder" for AtCoder problems
|
||||
- "cses" for CSES problems
|
||||
|
||||
The plugin automatically selects the appropriate template based on the file
|
||||
extension (e.g., .cc files get C++ templates, .py files get Python templates).
|
||||
Custom snippets can be added via the `snippets` configuration field.
|
||||
|
||||
HEALTH CHECK *cp-health*
|
||||
|
||||
|
|
|
|||
|
|
@ -26,19 +26,10 @@
|
|||
---@field default_language? string
|
||||
---@field timeout_ms? number
|
||||
|
||||
---@class HookContext
|
||||
---@field problem_id string
|
||||
---@field platform string
|
||||
---@field contest_id string
|
||||
---@field source_file string
|
||||
---@field input_file string
|
||||
---@field output_file string
|
||||
---@field expected_file string
|
||||
---@field contest_config table
|
||||
|
||||
---@class Hooks
|
||||
---@field before_run? fun(ctx: HookContext)
|
||||
---@field before_debug? fun(ctx: HookContext)
|
||||
---@field before_run? fun(ctx: ProblemContext)
|
||||
---@field before_debug? fun(ctx: ProblemContext)
|
||||
---@field setup_code? fun(ctx: ProblemContext)
|
||||
|
||||
---@class cp.Config
|
||||
---@field contests table<string, ContestConfig>
|
||||
|
|
@ -57,89 +48,22 @@
|
|||
---@field filename? fun(contest: string, contest_id: string, problem_id?: string, config: cp.Config, language?: string): string
|
||||
|
||||
local M = {}
|
||||
|
||||
local filetype_to_language = {
|
||||
cc = "cpp",
|
||||
c = "cpp",
|
||||
py = "python",
|
||||
py3 = "python",
|
||||
}
|
||||
local languages = require("cp.languages")
|
||||
|
||||
---@type cp.Config
|
||||
M.defaults = {
|
||||
contests = {
|
||||
default = {
|
||||
cpp = {
|
||||
compile = {
|
||||
"g++",
|
||||
"-std=c++{version}",
|
||||
"-O2",
|
||||
"-DLOCAL",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"{source}",
|
||||
"-o",
|
||||
"{binary}",
|
||||
},
|
||||
run = { "{binary}" },
|
||||
debug = {
|
||||
"g++",
|
||||
"-std=c++{version}",
|
||||
"-g3",
|
||||
"-fsanitize=address,undefined",
|
||||
"-DLOCAL",
|
||||
"{source}",
|
||||
"-o",
|
||||
"{binary}",
|
||||
},
|
||||
executable = nil,
|
||||
version = 20,
|
||||
extension = "cc",
|
||||
},
|
||||
python = {
|
||||
compile = nil,
|
||||
run = { "{source}" },
|
||||
debug = { "{source}" },
|
||||
executable = "python3",
|
||||
extension = "py",
|
||||
},
|
||||
default_language = "cpp",
|
||||
timeout_ms = 2000,
|
||||
},
|
||||
---@type PartialContestConfig
|
||||
atcoder = {
|
||||
---@type PartialLanguageConfig
|
||||
cpp = { version = 23 },
|
||||
},
|
||||
---@type PartialContestConfig
|
||||
codeforces = {
|
||||
---@type PartialLanguageConfig
|
||||
cpp = { version = 23 },
|
||||
},
|
||||
---@type PartialContestConfig
|
||||
cses = {
|
||||
---@type PartialLanguageConfig
|
||||
cpp = { version = 20 },
|
||||
},
|
||||
},
|
||||
contests = {},
|
||||
snippets = {},
|
||||
hooks = {
|
||||
before_run = nil,
|
||||
before_debug = nil,
|
||||
setup_code = nil,
|
||||
},
|
||||
debug = false,
|
||||
tile = nil,
|
||||
filename = nil,
|
||||
}
|
||||
|
||||
---@param base_config table
|
||||
---@param contest_config table
|
||||
---@return table
|
||||
local function extend_contest_config(base_config, contest_config)
|
||||
local result = vim.tbl_deep_extend("force", base_config, contest_config)
|
||||
return result
|
||||
end
|
||||
|
||||
---@param user_config cp.UserConfig|nil
|
||||
---@return cp.Config
|
||||
function M.setup(user_config)
|
||||
|
|
@ -161,6 +85,7 @@ function M.setup(user_config)
|
|||
vim.validate({
|
||||
before_run = { user_config.hooks.before_run, { "function", "nil" }, true },
|
||||
before_debug = { user_config.hooks.before_debug, { "function", "nil" }, true },
|
||||
setup_code = { user_config.hooks.setup_code, { "function", "nil" }, true },
|
||||
})
|
||||
end
|
||||
|
||||
|
|
@ -168,13 +93,15 @@ function M.setup(user_config)
|
|||
for contest_name, contest_config in pairs(user_config.contests) do
|
||||
for lang_name, lang_config in pairs(contest_config) do
|
||||
if type(lang_config) == "table" and lang_config.extension then
|
||||
if not vim.tbl_contains(vim.tbl_keys(filetype_to_language), lang_config.extension) then
|
||||
if
|
||||
not vim.tbl_contains(vim.tbl_keys(languages.filetype_to_language), lang_config.extension)
|
||||
then
|
||||
error(
|
||||
("Invalid extension '%s' for language '%s' in contest '%s'. Valid extensions: %s"):format(
|
||||
lang_config.extension,
|
||||
lang_name,
|
||||
contest_name,
|
||||
table.concat(vim.tbl_keys(filetype_to_language), ", ")
|
||||
table.concat(vim.tbl_keys(languages.filetype_to_language), ", ")
|
||||
)
|
||||
)
|
||||
end
|
||||
|
|
@ -185,43 +112,23 @@ function M.setup(user_config)
|
|||
end
|
||||
|
||||
local config = vim.tbl_deep_extend("force", M.defaults, user_config or {})
|
||||
|
||||
local default_contest = config.contests.default
|
||||
for contest_name, contest_config in pairs(config.contests) do
|
||||
if contest_name ~= "default" then
|
||||
config.contests[contest_name] = extend_contest_config(default_contest, contest_config)
|
||||
end
|
||||
end
|
||||
|
||||
return config
|
||||
end
|
||||
|
||||
---@param contest string
|
||||
---@param contest_id string
|
||||
---@param problem_id? string
|
||||
---@param config cp.Config
|
||||
---@param language? string
|
||||
---@return string
|
||||
local function default_filename(contest, contest_id, problem_id, config, language)
|
||||
local function default_filename(contest_id, problem_id)
|
||||
vim.validate({
|
||||
contest = { contest, "string" },
|
||||
contest_id = { contest_id, "string" },
|
||||
problem_id = { problem_id, { "string", "nil" }, true },
|
||||
config = { config, "table" },
|
||||
language = { language, { "string", "nil" }, true },
|
||||
})
|
||||
|
||||
local full_problem_id = contest_id:lower()
|
||||
if contest == "atcoder" or contest == "codeforces" then
|
||||
if problem_id then
|
||||
full_problem_id = full_problem_id .. problem_id:lower()
|
||||
end
|
||||
if problem_id then
|
||||
return problem_id:lower()
|
||||
else
|
||||
return contest_id:lower()
|
||||
end
|
||||
|
||||
local contest_config = config.contests[contest] or config.contests.default
|
||||
local target_language = language or contest_config.default_language
|
||||
local language_config = contest_config[target_language]
|
||||
return full_problem_id .. "." .. language_config.extension
|
||||
end
|
||||
|
||||
M.default_filename = default_filename
|
||||
|
|
|
|||
|
|
@ -103,9 +103,9 @@ local function compile_generic(language_config, substitutions)
|
|||
local compile_cmd = substitute_template(language_config.compile, substitutions)
|
||||
logger.log(("compiling: %s"):format(table.concat(compile_cmd, " ")))
|
||||
|
||||
local start_time = vim.loop.hrtime()
|
||||
local start_time = vim.uv.hrtime()
|
||||
local result = vim.system(compile_cmd, { text = true }):wait()
|
||||
local compile_time = (vim.loop.hrtime() - start_time) / 1000000
|
||||
local compile_time = (vim.uv.hrtime() - start_time) / 1000000
|
||||
|
||||
if result.code == 0 then
|
||||
logger.log(("compilation successful (%.1fms)"):format(compile_time))
|
||||
|
|
@ -129,7 +129,7 @@ local function execute_command(cmd, input_data, timeout_ms)
|
|||
|
||||
logger.log(("executing: %s"):format(table.concat(cmd, " ")))
|
||||
|
||||
local start_time = vim.loop.hrtime()
|
||||
local start_time = vim.uv.hrtime()
|
||||
|
||||
local result = vim.system(cmd, {
|
||||
stdin = input_data,
|
||||
|
|
@ -137,7 +137,7 @@ local function execute_command(cmd, input_data, timeout_ms)
|
|||
text = true,
|
||||
}):wait()
|
||||
|
||||
local end_time = vim.loop.hrtime()
|
||||
local end_time = vim.uv.hrtime()
|
||||
local execution_time = (end_time - start_time) / 1000000
|
||||
|
||||
local actual_code = result.code or 0
|
||||
|
|
|
|||
|
|
@ -89,9 +89,9 @@ local function setup_problem(contest_id, problem_id, language)
|
|||
state.test_cases = cached_test_cases
|
||||
end
|
||||
|
||||
local ctx = problem.create_context(state.platform, contest_id, problem_id, config, language)
|
||||
local scrape_ctx = problem.create_context(state.platform, contest_id, problem_id, config, language)
|
||||
|
||||
local scrape_result = scrape.scrape_problem(ctx)
|
||||
local scrape_result = scrape.scrape_problem(scrape_ctx)
|
||||
|
||||
if not scrape_result.success then
|
||||
logger.log("scraping failed: " .. (scrape_result.error or "unknown error"), vim.log.levels.WARN)
|
||||
|
|
@ -107,7 +107,7 @@ local function setup_problem(contest_id, problem_id, language)
|
|||
end
|
||||
end
|
||||
|
||||
vim.cmd.e(ctx.source_file)
|
||||
vim.cmd.e(scrape_ctx.source_file)
|
||||
|
||||
if vim.api.nvim_buf_get_lines(0, 0, -1, true)[1] == "" then
|
||||
local has_luasnip, luasnip = pcall(require, "luasnip")
|
||||
|
|
@ -135,13 +135,11 @@ local function setup_problem(contest_id, problem_id, language)
|
|||
end
|
||||
end
|
||||
|
||||
vim.api.nvim_set_option_value("winbar", "", { scope = "local" })
|
||||
vim.api.nvim_set_option_value("foldlevel", 0, { scope = "local" })
|
||||
vim.api.nvim_set_option_value("foldmethod", "marker", { scope = "local" })
|
||||
vim.api.nvim_set_option_value("foldmarker", "{{{,}}}", { scope = "local" })
|
||||
vim.api.nvim_set_option_value("foldtext", "", { scope = "local" })
|
||||
local ctx = problem.create_context(state.platform, state.contest_id, state.problem_id, config, language)
|
||||
|
||||
vim.diagnostic.enable(false)
|
||||
if config.hooks and config.hooks.setup_code then
|
||||
config.hooks.setup_code(ctx)
|
||||
end
|
||||
|
||||
local source_buf = vim.api.nvim_get_current_buf()
|
||||
local input_buf = vim.fn.bufnr(ctx.input_file, true)
|
||||
|
|
@ -179,16 +177,7 @@ local function run_problem()
|
|||
local ctx = problem.create_context(state.platform, state.contest_id, state.problem_id, config)
|
||||
|
||||
if config.hooks and config.hooks.before_run then
|
||||
config.hooks.before_run({
|
||||
problem_id = problem_id,
|
||||
platform = state.platform,
|
||||
contest_id = state.contest_id,
|
||||
source_file = ctx.source_file,
|
||||
input_file = ctx.input_file,
|
||||
output_file = ctx.output_file,
|
||||
expected_file = ctx.expected_file,
|
||||
contest_config = contest_config,
|
||||
})
|
||||
config.hooks.before_run(ctx)
|
||||
end
|
||||
|
||||
vim.schedule(function()
|
||||
|
|
@ -212,16 +201,7 @@ local function debug_problem()
|
|||
local ctx = problem.create_context(state.platform, state.contest_id, state.problem_id, config)
|
||||
|
||||
if config.hooks and config.hooks.before_debug then
|
||||
config.hooks.before_debug({
|
||||
problem_id = problem_id,
|
||||
platform = state.platform,
|
||||
contest_id = state.contest_id,
|
||||
source_file = ctx.source_file,
|
||||
input_file = ctx.input_file,
|
||||
output_file = ctx.output_file,
|
||||
expected_file = ctx.expected_file,
|
||||
contest_config = contest_config,
|
||||
})
|
||||
config.hooks.before_debug(ctx)
|
||||
end
|
||||
|
||||
vim.schedule(function()
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ M.filetype_to_language = {
|
|||
cc = M.CPP,
|
||||
cxx = M.CPP,
|
||||
cpp = M.CPP,
|
||||
c = M.CPP,
|
||||
py = M.PYTHON,
|
||||
py3 = M.PYTHON,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,9 +26,30 @@ function M.create_context(contest, contest_id, problem_id, config, language)
|
|||
language = { language, { "string", "nil" }, true },
|
||||
})
|
||||
|
||||
local filename_fn = config.filename or require("cp.config").default_filename
|
||||
local source_file = filename_fn(contest, contest_id, problem_id, config, language)
|
||||
local base_name = vim.fn.fnamemodify(source_file, ":t:r")
|
||||
local contest_config = config.contests[contest]
|
||||
if not contest_config then
|
||||
error(("No contest config found for '%s'"):format(contest))
|
||||
end
|
||||
|
||||
local target_language = language or contest_config.default_language
|
||||
local language_config = contest_config[target_language]
|
||||
if not language_config then
|
||||
error(("No language config found for '%s' in contest '%s'"):format(target_language, contest))
|
||||
end
|
||||
if not language_config.extension then
|
||||
error(("No extension configured for language '%s' in contest '%s'"):format(target_language, contest))
|
||||
end
|
||||
|
||||
local base_name
|
||||
if config.filename then
|
||||
local source_file = config.filename(contest, contest_id, problem_id, config, language)
|
||||
base_name = vim.fn.fnamemodify(source_file, ":t:r")
|
||||
else
|
||||
local default_filename = require("cp.config").default_filename
|
||||
base_name = default_filename(contest_id, problem_id)
|
||||
end
|
||||
|
||||
local source_file = base_name .. "." .. language_config.extension
|
||||
|
||||
return {
|
||||
contest = contest,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
---@field height integer
|
||||
|
||||
local M = {}
|
||||
local languages = require("cp.languages")
|
||||
|
||||
function M.clearcol()
|
||||
vim.api.nvim_set_option_value("number", false, { scope = "local" })
|
||||
|
|
@ -78,7 +79,7 @@ function M.restore_layout(state, tile_fn)
|
|||
local source_file
|
||||
if source_files ~= "" then
|
||||
local files = vim.split(source_files, "\n")
|
||||
local valid_extensions = { "cc", "cpp", "cxx", "c", "py", "py3" }
|
||||
local valid_extensions = vim.tbl_keys(languages.filetype_to_language)
|
||||
for _, file in ipairs(files) do
|
||||
local ext = vim.fn.fnamemodify(file, ":e")
|
||||
if vim.tbl_contains(valid_extensions, ext) then
|
||||
|
|
@ -87,11 +88,9 @@ function M.restore_layout(state, tile_fn)
|
|||
end
|
||||
end
|
||||
source_file = source_file or files[1]
|
||||
else
|
||||
source_file = problem_id .. ".cc"
|
||||
end
|
||||
|
||||
if vim.fn.filereadable(source_file) == 0 then
|
||||
if not source_file or vim.fn.filereadable(source_file) == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -26,8 +26,10 @@ end, {
|
|||
end, lang_completions)
|
||||
end
|
||||
|
||||
if ArgLead == "--lang" then
|
||||
return { "--lang" }
|
||||
if ArgLead:match("^%-") and not ArgLead:match("^--lang") then
|
||||
return vim.tbl_filter(function(completion)
|
||||
return completion:find(ArgLead, 1, true) == 1
|
||||
end, { "--lang" })
|
||||
end
|
||||
|
||||
local args = vim.split(vim.trim(CmdLine), "%s+")
|
||||
|
|
@ -43,7 +45,6 @@ end, {
|
|||
|
||||
if num_args == 2 then
|
||||
local candidates = { "--lang" }
|
||||
vim.list_extend(candidates, platforms)
|
||||
vim.list_extend(candidates, actions)
|
||||
local cp = require("cp")
|
||||
local context = cp.get_current_context()
|
||||
|
|
@ -56,6 +57,8 @@ end, {
|
|||
table.insert(candidates, problem.id)
|
||||
end
|
||||
end
|
||||
else
|
||||
vim.list_extend(candidates, platforms)
|
||||
end
|
||||
return vim.tbl_filter(function(cmd)
|
||||
return cmd:find(ArgLead, 1, true) == 1
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ neovim plugin for competitive programming.
|
|||
|
||||
https://private-user-images.githubusercontent.com/62671086/489116291-391976d1-c2f4-49e6-a79d-13ff05e9be86.mp4?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NTc3NDQ1ODEsIm5iZiI6MTc1Nzc0NDI4MSwicGF0aCI6Ii82MjY3MTA4Ni80ODkxMTYyOTEtMzkxOTc2ZDEtYzJmNC00OWU2LWE3OWQtMTNmZjA1ZTliZTg2Lm1wND9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTA5MTMlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwOTEzVDA2MTgwMVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWI0Zjc0YmQzNWIzNGZkM2VjZjM3NGM0YmZmM2I3MmJkZGQ0YTczYjIxMTFiODc3MjQyMzY3ODc2ZTUxZDRkMzkmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.MBK5q_Zxr0gWuzfjwmSbB7P7dtWrATrT5cDOosdPRuQ
|
||||
|
||||
[video config](https://github.com/barrett-ruth/dots/blob/main/nvim/lua/plugins/cp.lua)
|
||||
|
||||
> Sample test data from [codeforces](https://codeforces.com) is scraped via [cloudscraper](https://github.com/VeNoMouS/cloudscraper). Use at your own risk.
|
||||
|
||||
## Features
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ def scrape(url: str) -> list[tuple[str, str]]:
|
|||
lines = [div.get_text().strip() for div in divs]
|
||||
text = "\n".join(lines)
|
||||
else:
|
||||
text = inp_pre.get_text().replace("\r", "")
|
||||
text = inp_pre.get_text().replace("\r", "").strip()
|
||||
all_inputs.append(text)
|
||||
|
||||
for out_section in output_sections:
|
||||
|
|
@ -41,7 +41,7 @@ def scrape(url: str) -> list[tuple[str, str]]:
|
|||
lines = [div.get_text().strip() for div in divs]
|
||||
text = "\n".join(lines)
|
||||
else:
|
||||
text = out_pre.get_text().replace("\r", "")
|
||||
text = out_pre.get_text().replace("\r", "").strip()
|
||||
all_outputs.append(text)
|
||||
|
||||
if all_inputs and all_outputs:
|
||||
|
|
|
|||
|
|
@ -1,4 +1 @@
|
|||
std = "vim"
|
||||
|
||||
[config]
|
||||
lua52 = true
|
||||
std = "lua51+vim"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue