vim-debuglisted
Install: claude install-skill beixiyo/dotfiles
## 核心原则
1. **不要 `print` / `vim.print` / `:echom`,dump 到 `/tmp/xxx.log` + `pedit`**:cmdline 会被 noice / blink.cmp 浮窗遮挡,`:messages` 里 `\r` / BOM / 零宽字符肉眼透明
2. **`vim.inspect` 而不是 `tostring`**:会把 `"line\r"` / `"\xef\xbb\xbfbom"` / `"zero\u{200b}width"` 显式转义出来
3. **运行时 ≠ 磁盘**:`vim.api.nvim_buf_get_lines` 只是内存视图;`md5sum` / `wc -l` / `od -c` / `git show` 才是 ground truth。任何一项对不上,先怀疑「读入 / 转换」环节
4. **瞬态 bug 用 arm + defer**:bug 只在 `CmdlineEnter` / `WinNew` / `ModeChanged` 一瞬间可见,事件结束就恢复,手动触发抓不到。用 `once=true` autocmd + `vim.defer_fn(200)`(150~300ms 比较稳)等所有同步 + 异步 handler 跑完再 dump
5. **lazy 缓存**:改完 lua 文件不重启 nvim、不 `:Lazy reload`,`require` 不重读。dump 里加**哨兵常量**(每次改代码改字符串),版本号对不上就是缓存
---
## 诊断套件
### dump 命令(写文件 + pedit)
> dump 是快照不是 timeline。每次完整覆盖(`'w'`,不用 `'a'`);多份对比用 `tag` 分文件名
```lua
local LOG_BASE = '/tmp/myplug-debug'
local function dump(tag)
local log = (tag and tag ~= '')
and (LOG_BASE .. '.' .. tag .. '.log') or (LOG_BASE .. '.log')
local out = {}
local function add(s) out[#out + 1] = s end
add('SENTINEL: 2026-04-21-v1') -- 改代码就改这串,dump 出来对不上 = require 缓存
add('TS: ' .. os.date('%Y-%m-%d %H:%M:%S'))
add('TAG: ' .. (tag or '<none>'))
add(vim.inspect(require('myplug.state')._state))
-- 按需追加维度,见下表
-- 'w' 截断覆盖:dump 是快照不是 timeline,不要 'a' 把多次现场混在一起
local fh = io.open(log, 'w')
if fh then fh:write(table.concat(out, '\n')); fh:close() end
-- pedit 已开着旧 log 的预览窗时,写完会自动 :checktime 刷新,不用手动 reload
pcall(vim.cmd, 'silent botright pedit ' .. vim.fn.fnameesc