pi-super-vim0.1.0
Write pi prompts in a real vim: one gvim tab per session, :Pi sends it back to pi
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi-super-vim
用 vim 的 tab 来写 pi 的 prompt。pi 还在原来的终端里跑,输出也在原来的地方;pi 答完一轮之后,
它会在一个常驻的 gvim 里把「当前 session 的输入 tab」准备好,你在 vim 里写完 :Pi,这段文字就被
当成你刚刚在 pi 里敲下的输入。
┌───────────────┐ ① 一轮结束(agent_settled) ┌──────────────────────────┐
│ pi (终端) │ ──── gvim --remote-expr ───────► │ gvim (常驻, 一个 server)│
│ │ session id 找到/新建 tab │ tab: pi:01a19799 │
│ │ tab 内容清空 │ (buffer: <sid>.md) │
│ │ │ │
│ │ ② 你在 vim 里写 prompt, │ :Pi :PiSteer :PiQueue│
│ │ :Pi / :w ────────────► │ :w 也等于发送 │
│ │ (写请求文件) └──────────────────────────┘
│ pi 把文字当作 │ ◄── ③ 扩展监听请求文件, pi.sendUserMessage()
└───────────────┘
为什么不真的往终端里「敲键」:那需要 Windows 的 SendKeys / 剪贴板注入,焦点、编码、粘贴模式、
长文本都会出问题。这里扩展直接调用 pi 自己的 pi.sendUserMessage(),效果和你在 pi 里输入回车
完全一样(TUI 里会出现一条 user 消息,然后正常开始下一轮),但可靠得多。
组成
| 文件 | 作用 |
|---|---|
pi-super-vim.ts |
pi 扩展:管理 gvim server、按 session 开关 tab、监听请求文件、投递给 pi |
vim/pi-super-vim.vim |
vim 这一半:维护 prompt buffer、:Pi 等命令、tab 标题、草稿保护 |
.pi/extensions/pi-super-vim.ts |
让 pi 在本项目里自动加载上面的扩展(转发一行) |
test/harness.mjs |
不需要模型的自测脚本(假的 pi API + 真 gvim 往返) |
环境要求
- 仅 Windows + gvim。这个扩展是给「Windows 终端里打中文/长 prompt 难受」写的,Linux/macOS 没实测,也不打算支持。 非 Windows 上请在 gvim 里自己写,别提 issue。
- 官方 Vim for Windows(
C:\Program Files\Vim\vim92\里面同时有gvim.exe和vim.exe)。gvim.exe当 server,vim.exe当无窗口的 client(能拿到--remote-expr的输出和退出码)。 - Vim 8.1 以上(用到
bufadd()/win_findbuf()/tabpagebuflist())——9.x 实测没问题 - pi 1.4+
安装
本项目里已经放好了 .pi/extensions/pi-super-vim.ts,在这个目录下启动 pi 就会加载(项目本地
扩展需要信任该项目)。或者显式加载:
pi --extension D:\new-start\pi-super-vim\pi-super-vim.ts
想全局使用,装成一个 pi package(仓库根目录的 package.json 已经按 pi 的 package 规范写好:
pi.extensions 指向 ./pi-super-vim.ts,files 带上 vim/):
pi install npm:pi-super-vim # 推荐
pi install git:github.com/LittleGuo/pi-super-vim@v0.1.0 # 从 GitHub 装(锁版本,不经过 npm)
vim/pi-super-vim.vim 由扩展从包所在目录直接读,不用手动复制。
不想走 package 也可以手工丢文件(pi 会加载带 index.ts 的子目录):
%USERPROFILE%\.pi\agent\extensions\pi-super-vim\index.ts <- 由 pi-super-vim.ts 改名/复制
%USERPROFILE%\.pi\agent\extensions\pi-super-vim\vim\pi-super-vim.vim
如果你还想在自己手动启动的 vim 里也能用 :Pi(而不是只在 pi 打开的 tab 里):
/pivim install # 复制 vim/pi-super-vim.vim 到 ~/.vim/plugin/
使用
- 正常跟 pi 说话。
- pi 答完,gvim 自动启动(第一次会慢一点)或切到当前 session 的 tab,标题是
pi:<session id 前 8 位>, 光标已经在插入模式,tab 内容已清空。 - 写你的下一段 prompt。
Esc然后:
| vim 命令 | 作用 |
|---|---|
:Pi |
发送(pi 空闲就立刻开始;pi 正忙就排队,等同 followUp) |
:PiQueue |
显式排队,等当前这一轮结束后再处理 |
:PiSteer |
插话 / 打断当前这一轮(steer) |
:w |
和 :Pi 一样,等于「提交」(不会写磁盘) |
:PiClear |
清空 buffer(u 可以撤销回来) |
:PiClose |
关掉这个 tab(里面有没发的字时会保留) |
清空规则(按你的要求,但不会吃掉你的草稿):
- 这一轮结束后打开 tab 时,如果里面是上次已经发出去的内容,或者你根本没动过 -> 清空;
- 如果你在 pi 回答期间已经写了下一条、还没发 -> 保留,绝不覆盖。
pi 里的命令:
| 命令 | 作用 |
|---|---|
/pivim |
现在就把 vim tab 打开/切过来(不等一轮结束) |
/pivim status |
打印 gvim / client / 插件 / 控制目录 / session 状态,排查用 |
/pivim close |
关闭当前 session 的 tab |
/pivim install |
把 vim 插件复制到 ~/.vim/plugin/ |
细节
- 一个 gvim,多个 tab:gvim 用固定的 server 名(默认
PI_SUPER_VIM)常驻;每个 pi session 一个 tab(tab 变量t:pi_tablabel、buffer 变量b:pi_session),所以同时开几个 pi 也不会串。 - buffer 是 scratch buffer:
buftype=acwrite、无 swap、无 undofile、markdown 语法/折行, 名字是<控制目录>/<session id>.md,但不会真的写这个文件。 - 通信目录:默认
%TEMP%\pi-super-vim\(os.tmpdir()),里面有<sid>.req/.req.tmp:vim 写给 pi 的请求(JSON:text / mode / sid / ts),扩展监听目录 + 1s 轮询兜底, 谁先看到谁处理,文件先删再投递,避免重复发送;<sid>.cmd.vim:扩展写给 vim 执行的小脚本;<sid>.draft:你还没发出去、又关掉 vim 的草稿,下次打开自动恢复;debug.log:只有PI_SUPER_VIM_DEBUG=1时才写。
- tab 标题:插件默认会把
tabline换成自己的实现(显示pi:<id>,有没发出去的字时带+;普通 tab 显示文件名), 但仅在你的tabline本来就是空的时才接管,不会覆盖你已有的配置;想彻底关掉设let g:pi_super_vim_tabline = 0。 - 退出:pi 退出(或
/new、/resume换 session)时会关掉对应 tab;最后一个 tab 关掉时 gvim 顺势退出。 有未发送文字时保留 tab 并写草稿。/pivim close同理。
配置(环境变量)
| 变量 | 默认 | 说明 |
|---|---|---|
PI_SUPER_VIM_SERVER |
PI_SUPER_VIM |
gvim server 名 |
PI_SUPER_VIM_DIR |
%TEMP%\pi-super-vim |
请求/草稿/命令文件目录 |
PI_SUPER_VIM_GVIM |
自动查找 | gvim.exe 路径 |
PI_SUPER_VIM_CLIENT |
自动查找 | console vim.exe 路径(拿输出用) |
PI_SUPER_VIM_PLUGIN |
本目录 vim/pi-super-vim.vim |
vim 插件路径 |
PI_SUPER_VIM_AUTO |
1 |
0 = 一轮结束后不自动弹 vim,只用 /pivim |
PI_SUPER_VIM_STARTINSERT |
1 |
打开 tab 时是否直接进插入模式 |
PI_SUPER_VIM_CLOSE |
1 |
pi 退出时是否关闭 tab |
PI_SUPER_VIM_DEBUG |
0 |
1 = 往 <控制目录>/debug.log 写日志 |
vim 侧变量(可放 vimrc,或者等 pi 打开 tab 后 :let,只影响这个 server):
| 变量 | 默认 | 说明 |
|---|---|---|
g:pi_super_vim_startinsert |
1 |
同 PI_SUPER_VIM_STARTINSERT |
g:pi_super_vim_draft |
1 |
关掉 vim 时是否保存未发送草稿 |
g:pi_super_vim_tabline |
1 |
是否接管(空的)tabline 显示 tab 名 |
排查
/pivim status:先看 gvim / client / 插件路径是否都找到了。PI_SUPER_VIM_DEBUG=1后看%TEMP%\pi-super-vim\debug.log:每次--serverlist、--remote-expr的内容和结果都在里面。- 报
E449 收到无效的表达式一般是--remote-expr的表达式里混进了|之类的东西。 本扩展不自己拼长表达式,而是把整段 vim 脚本写到<sid>.cmd.vim再execute(readfile(...)),所以不会踩这个坑。 - 报
gvim not found:装官方 Vim for Windows,或者设PI_SUPER_VIM_GVIM。 - 第一次打开要 0.2~1s(启动 gvim + 等 server 注册),之后每次切 tab 大约 2 次 vim client 调用(~0.15s), 对交互没有影响。
自测
不需要模型、不需要 pi:
node test/harness.mjs
它会:加载扩展 -> 造假 pi API / 假 ctx -> 开 tab -> 用真的 vim 插件写内容并 :Pi / :w ->
检查 pi 收到的文本、清空规则、草稿保护、第二个 session 的 tab、忙时排队、退出时关 tab。
跑完自己 qa! 关掉测试用的 gvim。