对于一名追求效率的开发者来说,网页版的 LeetCode 编辑器往往难以满足我们的“手感”。通过将 LeetCode 集成到本地 VIM 环境,我们可以利用强大的插件生态、自动化的测试脚本以及断点调试工具,打造一个极简且高效的刷题工作流。

以下是我基于 Go 语言构建的本地化刷题环境总结。

1. 核心工具链

要实现“优雅”,离不开以下几个核心组件:

VIM插件与配置

Plug 'fatih/vim-go', { 'do': ':GoUpdateBinaries' }
Plug 'puremourning/vimspector'


" go
let g:UltiSnipsExpandTrigger="<tab>"
let g:UltiSnipsJumpForwardTrigger="<c-b>"
let g:UltiSnipsJumpBackwardTrigger="<c-z>"
" If you want :UltiSnipsEdit to split your window.
let g:UltiSnipsEditSplit="vertical"
let g:go_debug_mappings_enabled = 0
let g:vimspector_enable_mappings = 'HUMAN'

" 调试常用组合
" 先取消空格键原有的映射(保持纯净)
augroup BgHighlight
  autocmd!
  " 进入窗口时开启高亮
  autocmd WinEnter * set cursorline
  " 离开窗口时关闭高亮
  autocmd WinLeave * set nocursorline
augroup END
".vim/after/ftplugin/go.vim

" shortcut like vscode
nnoremap <buffer> <silent> <F2> :hide GoRename<CR>
nnoremap <buffer> <silent> <F4> :hide GoBuild<CR>
nnoremap <buffer> <silent> <C-F5> :hide GoRun<CR>
nnoremap <buffer> <silent> <S-F5> :hide VimspectorReset<CR>

2. 自动化工作流:从题目 ID 到代码模板

脚本参考 https://github.com/qtopie/leetcode/tree/main/scripts

我编写了一个 leetcode-edit 脚本,只需要输入题目编号(如 bash scripts/leetcode-edit 384),系统会自动完成以下操作:

  1. 目录标准化: 根据题目编号和缩写自动创建目录,例如 384.shuffle-an-array/
  2. 代码拉取: 调用 leetcode-cli 下载题目描述和代码模板。
  3. 格式修正: 自动为下载的代码添加 package main 声明,确保本地编译器不报错。
  4. 配置文件注入: 为该题目生成专用的 .vimspector.json,配置好调试参数。

脚本内容:scripts/leetcode-edit

#!/bin/bash
set -euo pipefail

# ... (省略部分路径处理逻辑)

# 核心步骤:
# 1. 下载/编辑题目
# 2. 标准化 Go 文件 (添加 package main)
# 3. 确保 vimspector 配置存在
# 4. 自动生成测试用例
# 5. 执行 leetcode edit 打开编辑器

normalize_go_file "${target_code}"
ensure_vimspector_config "${dir}" "${dlv_bin}"
generate_go_tests "${dir}"

exec leetcode edit "${id}" "$@"

3. 测试驱动:自动生成测试用例

我开发了一个 generate-go-tests.py 脚本,它能解析 main.go 中的函数签名,并结合 LeetCode 的样例数据自动生成可运行的 Go 测试文件。

脚本内容:scripts/generate-go-tests.py

#!/usr/bin/env python3
import json
import re
import subprocess
import sys
from pathlib import Path

# 该脚本会自动解析题目函数签名:
# - 支持 int, string, slice 等基础类型
# - 支持 *ListNode, *TreeNode 等 LeetCode 专用数据结构
# - 支持“设计类”题目 (Constructor) 的自动跳过与模板生成

def render_tests(main_go: Path, test_data: Path, target: Path):
    func_name, params, return_type = parse_signature(main_go)

    # 针对 Constructor 类型的特殊处理
    if func_name == "Constructor":
        target.write_text(f"// ... (跳过直接生成,提供 Skip 模板)")
        return

    # 解析样例数据并生成测试代码
    # ...

4. 调试神器:Vimspector 断点调试

通过 leetcode-edit 自动生成的 .vimspector.json,可以实现一键 F5 进入调试状态。

配置示例:.vimspector.json

{
  "configurations": {
    "Debug TestDebug": {
      "adapter": "delve-local",
      "filetypes": [ "go" ],
      "configuration": {
        "request": "launch",
        "mode": "test",
        "program": "${workspaceRoot}",
        "args": [ "-test.run", "TestDebug" ]
      }
    }
  }
}

目标像VSCode那样快速Debug代码 alt text

效果图 alt text

快捷键:

5. 配置文件:leetcode.toml

这是 leetcode-cli 的核心配置,注意在 Linux 环境下修正 editor 路径。

[code]
editor = "vim" # 确保 Linux 下路径正确
test = true
lang = "golang"
pick = "${fid}.${slug}/main"
inject_before = ["package main"]
comment_problem_desc = true
comment_leading = "//"

[cookies]
csrf = "********" # 已加密/隐藏
session = "********" # 已加密/隐藏
site = "leetcode.com"

[storage]
cache = ".leetcode-problems"
code = "leetcode"
root = "~/workspace/codejam"

6. 总结

这套方案的核心在于自动化。通过脚本化重复性工作,你可以把 100% 的精力集中在算法逻辑本身。

当你按下 bash scripts/leetcode-edit <id>,VIM 带着题目和测试用例准时出现在你面前时,那种掌控感就是所谓的“优雅”。