优先读 visual 环境变量,再 fallback 到 editor;windows 同样优先检查 editor;启动时须分离路径与参数,避免 shell 注入,并验证可执行性及编码支持。

linux/macos 下优先读 EDITOR 环境变量,但别忽略 VISUAL
大多数 unix-like 系统把默认编辑器存在 EDITOR 里,但实际终端环境下,VISUAL 的优先级更高——尤其当程序运行在图形会话中(比如 VS Code 终端、GNOME Terminal)。如果只查 EDITOR,可能拿到 vi 而不是用户真正想用的 code --wait。
- 先调用
getenv("VISUAL"),非空且可执行就直接用 - 再 fallback 到
getenv("EDITOR"),常见值如vim、nano、code --wait - 如果两个都为空,Linux 可查
/etc/alternatives/editor(符号链接),macOS 可试open -t作为兜底命令 - 注意:环境变量值可能是带参数的完整命令(如
code --wait),不要盲目拼接文件路径
Windows 上不能只查注册表,EDITOR 环境变量仍有效
Windows 用户确实常通过注册表设置默认文本编辑器(比如 HKEY_LOCAL_MACHINESOFTWAREmicrosoftWindowsCurrentVersionApp PathsNotepad++.exe),但很多跨平台工具(如 git、Cargo)会主动尊重 EDITOR 环境变量。硬切注册表反而绕过用户显式意图。
- 优先检查
getenv("EDITOR"),Windows CMD/PowerShell/WSL 都支持它 - 若为空,再查注册表:推荐从
HKEY_CURRENT_USERSOFTWAREMicrosoftWindowsCurrentVersionExplorerFileExts.txtOpenWithList或更通用的App Paths键,但注意权限和 32/64 位视图差异 - 注册表值可能是纯文件名(
notepad++.exe)或带路径,需用FindExecutable()或ShellExecuteEx()验证是否真能打开文本文件 - 别假设注册表一定存在——精简版 Windows 或企业锁屏环境可能根本没写这些键
std::system() 启动编辑器前必须做路径和参数分离
直接拼接 std::system(editor_cmd + " " + file_path) 在所有平台都危险:路径含空格、shell 元字符(如 &、|、$())、Windows 反斜杠转义都会导致命令失败或执行意外程序。
- Unix-like:用
fork() + execvp()更安全,把命令拆成argv数组,避免 shell 解析 - Windows:优先用
CreateProcess(),传入完整路径和独立参数数组;若用std::system(),必须对file_path做双引号包裹(且内部引号要转义) - 别依赖编辑器自动识别文件编码——
code --wait和vim对 bom、UTF-8-without-BOM 行为不一致,提前转换或加参数(如vim -c ":set encoding=utf-8") - 启动后需等待进程退出(尤其
--wait类参数),否则主程序可能继续执行未保存内容
测试时最容易漏掉的三个真实场景
本地开发跑通不等于上线可靠,这三个点一漏就卡住 CI 或普通用户:
立即学习“C++免费学习笔记(深入)”;
- WSL 环境下,
EDITOR=code实际要调用 Windows 版 VS Code,但code命令可能不在 WSL 的$PATH里——得查/mnt/c/Users/*/AppData/Local/Programs/Microsoft VS Code/bin/code - macOS 上用户用 Homebrew 安装的
vim默认不带+clipboard,而EDITOR=vim启动后无法粘贴,应提示或 fallback 到nvim - Windows 企业域环境下,组策略可能禁用
cmd.exe,导致std::system()直接返回 -1;此时必须用CreateProcess()绕过 shell
跨平台编辑器探测真正的难点不在“怎么读”,而在“读到之后怎么安全、一致地启动它”——环境变量、注册表、实际可执行性、参数语义,四层都要验,缺一不可。