cp.nvim/CLAUDE.md
2025-09-12 09:21:49 -05:00

11 KiB

CP.nvim Analysis & Modernization Plan

Current Architecture Overview

Plugin Structure

  • Main Logic: lua/cp/init.lua (297 lines) - Core plugin functionality
  • Configuration: lua/cp/config.lua (16 lines) - Contest settings and defaults
  • Snippets: lua/cp/snippets.lua (21 lines) - LuaSnip integration
  • Entry Point: plugin/cp.lua (7 lines) - Plugin initialization
  • Vim Integration: after/ directory with filetype detection, syntax highlighting, and buffer settings

Current Build System (Make/Shell-Based)

Templates Structure

templates/
├── makefile                    # Build orchestration
├── compile_flags.txt          # Release flags: -O2, -DLOCAL
├── debug_flags.txt           # Debug flags: -g3, -fsanitize=address,undefined, -DLOCAL
├── .clang-format             # Code formatting rules (Google style)
├── scripts/
│   ├── run.sh               # Compilation + execution workflow
│   ├── debug.sh            # Debug compilation + execution
│   ├── scrape.sh           # Problem scraping orchestration
│   └── utils.sh            # Core build/execution utilities
├── scrapers/               # Python scrapers for each judge
│   ├── atcoder.py         # AtCoder problem scraping
│   ├── codeforces.py      # Codeforces problem scraping (with cloudscraper)
│   └── cses.py            # CSES problem scraping
└── io/                    # Input/output files directory

Build Workflow Analysis

Compilation Process (utils.sh:compile_source):

g++ @compile_flags.txt $flags "$src" -o "$bin" 2>"$output"

Execution Process (utils.sh:execute_binary):

  • Timeout: 2-second hardcoded timeout using timeout 2s
  • Debug Mode: LD_PRELOAD with AddressSanitizer when debugging
  • Output Processing:
    • Truncates to first 1000 lines
    • Appends metadata: [code], [time], [debug], [matches]
    • Compares with .expected file if available
  • Signal Handling: Maps exit codes to signal names (SIGSEGV, SIGFPE, etc.)

Current Neovim Integration

Command System

  • :CP <contest> - Setup contest environment
  • :CP <contest> <problem_id> [letter] - Setup problem + scrape
  • :CP run - Compile and execute current problem
  • :CP debug - Compile with debug flags and execute
  • :CP diff - Toggle diff mode between output and expected

Current vim.system Usage

-- Only used for async compilation in init.lua:148, 166
vim.system({ "make", "run", vim.fn.expand("%:t") }, {}, callback)
vim.system({ "make", "debug", vim.fn.expand("%:t") }, {}, callback)

Window Management

  • Current Layout: Code editor | Output window + Input window (vsplit + split)
  • Diff Mode:
    • Uses vim.cmd.diffthis() and vim.cmd.diffoff()
    • Session saving with mksession! and restoration
    • Manual window arrangement with vim.cmd.only(), splits, and wincmd
    • vim-zoom dependency: Listed as optional for "better diff view" but not used in code

File Type Integration

  • Auto-detection: */io/*.incpinput, */io/*.outcpoutput
  • Buffer Settings: Disables line numbers, signs, status column for I/O files
  • Syntax Highlighting: Custom syntax for output metadata ([code], [time], etc.)

Current Configuration System

Contest-Specific Settings

defaults = {
  contests = {
    atcoder = { cpp_version = 23 },
    codeforces = { cpp_version = 23 },
    cses = { cpp_version = 20 },
  },
  snippets = {},
}

File-Based Configuration Dependencies

  • compile_flags.txt - Compiler flags for release builds
  • debug_flags.txt - Debug-specific compiler flags
  • .clang-format - Code formatting configuration
  • Missing: .clangd file (referenced in makefile but doesn't exist)

Proposed Modernization: Full Lua Migration

1. Replace Make/Shell System with vim.system

Benefits of Native Lua Implementation

  • Better Error Handling: Lua error handling vs shell exit codes
  • Timeout Control: vim.system supports timeout parameter directly
  • Streaming I/O: Native stdin/stdout handling without temp files
  • Progress Reporting: Real-time compilation/execution feedback
  • Cross-Platform: Remove shell script dependencies

Proposed Build System

local function compile_cpp(src_path, output_path, flags, timeout_ms)
  local compile_cmd = { "g++", unpack(flags), src_path, "-o", output_path }
  return vim.system(compile_cmd, { timeout = timeout_ms or 10000 })
end

local function execute_with_timeout(binary_path, input_data, timeout_ms)
  return vim.system(
    { binary_path },
    {
      stdin = input_data,
      timeout = timeout_ms or 2000,
      stdout = true,
      stderr = true,
    }
  )
end

2. Configuration Migration to Pure Lua

Replace File-Based Config with Lua Tables

config = {
  contests = {
    atcoder = { 
      cpp_version = 23,
      compile_flags = { "-std=c++23", "-O2", "-DLOCAL", "-Wall", "-Wextra" },
      debug_flags = { "-std=c++23", "-g3", "-fsanitize=address,undefined", "-DLOCAL" },
      timeout_ms = 2000,
    },
    -- ... other contests
  },
  clangd_config = {
    CompileFlags = { Add = { "-std=c++23", "-DLOCAL" } },
    Diagnostics = { ClangTidy = { Add = { "readability-*" } } },
  },
  clang_format = {
    BasedOnStyle = "Google",
    AllowShortFunctionsOnASingleLine = false,
    -- ... other formatting options
  }
}

Dynamic File Generation

  • Generate .clangd YAML from Lua config
  • Generate .clang-format from Lua config
  • Eliminate static template files

3. Enhanced Window Management (Remove vim-zoom Dependency)

Current Diff Implementation Issues

  • Manual session management with temp files
  • No proper view state restoration
  • Hardcoded window arrangements

Proposed Native Window Management

local function save_window_state()
  return {
    layout = vim.fn.winrestcmd(),
    views = vim.tbl_map(function(win)
      return {
        winid = win,
        view = vim.fn.winsaveview(),
        bufnr = vim.api.nvim_win_get_buf(win)
      }
    end, vim.api.nvim_list_wins())
  }
end

local function restore_window_state(state)
  vim.cmd(state.layout)
  for _, view_state in ipairs(state.views) do
    if vim.api.nvim_win_is_valid(view_state.winid) then
      vim.api.nvim_win_call(view_state.winid, function()
        vim.fn.winrestview(view_state.view)
      end)
    end
  end
end

Improved Diff Mode

  • Use vim.diff() API for programmatic diff generation
  • Better window state management with winsaveview/winrestview
  • Native zoom functionality without external dependency

4. Enhanced I/O and Timeout Management

Current Limitations

  • Hardcoded 2-second timeout
  • Shell-based timeout implementation
  • Limited output processing

Proposed Improvements

local function execute_solution(config)
  local start_time = vim.loop.hrtime()
  
  local result = vim.system(
    { config.binary_path },
    {
      stdin = config.input_data,
      timeout = config.timeout_ms,
      stdout = true,
      stderr = true,
    }
  )
  
  local end_time = vim.loop.hrtime()
  local execution_time = (end_time - start_time) / 1000000 -- Convert to ms
  
  return {
    stdout = result.stdout,
    stderr = result.stderr,
    code = result.code,
    time_ms = execution_time,
    timed_out = result.code == 124,
  }
end

5. Integrated Problem Scraping

Current Python Integration

  • Separate uv environment management
  • Shell script orchestration for scraping
  • External Python dependencies (requests, beautifulsoup4, cloudscraper)

Proposed Native Integration Options

Option A: Keep Python, Improve Integration

local function scrape_problem(contest, problem_id, problem_letter)
  local scraper_path = get_scraper_path(contest)
  local args = contest == "cses" and { problem_id } or { problem_id, problem_letter }
  
  return vim.system(
    { "uv", "run", scraper_path, unpack(args) },
    { cwd = plugin_path, timeout = 30000 }
  )
end

Option B: Native Lua HTTP (Future)

  • Wait for Neovim native HTTP client
  • Eliminate Python dependency entirely
  • Pure Lua HTML parsing (challenging)

Implementation Challenges & Considerations

Technical Feasibility

Definitely Possible

  • Replace makefile with vim.system calls
  • Migrate configuration to pure Lua tables
  • Implement native window state management
  • Add configurable timeouts
  • Remove vim-zoom dependency

⚠️ Requires Careful Implementation

  • Signal Handling: Shell scripts handle SIGSEGV, SIGFPE mapping - need Lua equivalent
  • AddressSanitizer Integration: LD_PRELOAD handling in debug mode
  • Cross-Platform: Shell scripts provide some cross-platform abstraction

🤔 Complex/Questionable

  • Complete Python Elimination: Would require native HTTP client + HTML parsing
  • Output Truncation Logic: Currently truncates to 1000 lines efficiently in shell

Migration Strategy

Phase 1: Core Build System

  1. Replace vim.system({ "make", ... }) with direct vim.system({ "g++", ... })
  2. Migrate compile/debug flags from txt files to Lua config
  3. Implement native timeout and execution management

Phase 2: Window Management

  1. Implement native window state saving/restoration
  2. Remove vim-zoom dependency mention
  3. Enhance diff mode with better view management

Phase 3: Configuration Integration

  1. Generate .clangd/.clang-format from Lua config
  2. Consolidate all configuration in single config table
  3. Add runtime configuration validation

Phase 4: Enhanced Features

  1. Configurable timeouts per contest
  2. Better error reporting and progress feedback
  3. Enhanced output processing and metadata

User Experience Impact

Advantages

  • Simpler Dependencies: No external shell scripts or makefile
  • Better Error Messages: Native Lua error handling
  • Configurable Timeouts: Per-contest timeout settings
  • Improved Performance: Direct system calls vs shell interpretation
  • Better Integration: Native Neovim APIs throughout

Potential Concerns

  • Compatibility: Users relying on current makefile system
  • Feature Parity: Ensuring all current functionality is preserved
  • Debugging: Shell scripts are easier to debug independently

Recommendation

Proceed with modernization - The proposed changes align well with Neovim 0.9+ capabilities and would significantly improve the plugin's maintainability and user experience. The migration is technically feasible with the main complexity being in preserving exact feature parity during the transition.

Priority Order:

  1. Build system migration (highest impact, lowest risk)
  2. Window management improvements (removes external dependency)
  3. Configuration consolidation (improves user experience)
  4. Enhanced I/O and timeout management (adds new capabilities)

The plugin's current architecture is well-designed, making this modernization an enhancement rather than a rewrite.