ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

WezTerm `user-var-changed` 事件:利用 OSC 1337 用户变量实现 pane 与 Lua 配置的双向通信

WezTerm `user-var-changed` 事件:利用 OSC 1337 用户变量实现 pane 与 Lua 配置的双向通信 WezTermuser-var-changed事件利用 OSC 1337 用户变量实现 pane 与 Lua 配置的双向通信【免费下载链接】weztermA GPU-accelerated cross-platform terminal emulator and multiplexer written by wez and implemented in Rust项目地址: https://gitcode.com/GitHub_Trending/we/weztermuser-var-changed是 WezTerm一款基于 Rust 实现的 GPU 加速跨平台终端模拟器与多路复用器提供的窗口级 Lua 事件。当终端 pane 内的程序通过OSC 1337 转义序列设置或更新用户变量user var时该事件会在对应的 GUI 窗口中被触发允许你的.wezterm.lua配置直接感知 pane 内部状态并作出响应。阅读本文后你将掌握用户变量的完整协议与发送方式、user-var-changed事件的注册与回调参数用法、相关的pane:get_user_vars()读取 API以及结合format-tab-title、update-status等事件构建动态标签栏与状态栏的实战方案。user-var-changed事件自版本20220903-194523-3bb1ed612022-09-03 构建起可用。本节内容对应 user-var-changed.md。用户变量User Vars是什么用户变量是一组与特定 pane 关联的键值对它由 iterm2 提出、WezTerm 同样识别与实现。与普通环境变量相比用户变量有两个显著差异作用域不同环境变量属于进程而用户变量属于终端 pane即一个标签页/分屏窗口由 WezTerm 统一维护读写方向不同pane 内运行的程序通常是 shell只能通过转义序列“写入”用户变量无法反向读取它们——它是 pane 向 WezTerm 配置层单向、主动传递信息的通道。WezTerm 官方文档在 docs/shell-integration.md 中明确说明OSC 1337转义序列用于设置用户变量以追踪额外的 shell 状态而在 docs/recipes/passing-data.md 中用户变量被定位为“从 pane 向 Lua 传递数据”的第一推荐方案它不依赖本地进程嗅探即使在 SSH 远程会话中也能工作因为信息是通过终端字节流传送的。从 pane 中设置用户变量OSC 1337 协议用户变量通过OSC 1337Operating System Command 1337即 iTerm2 专有扩展转义序列设置。原始文档给出的最小示例为printf \033]1337;SetUserVar%s%s\007 foo echo -n bar | base64这一条命令将名为foo的用户变量设置为值bar。其协议要点为序列格式为\033]1337;SetUserVar名称Base64编码后的值\007值必须经过 Base64 编码名称不需要编码WezTerm 收到后会解码还原序列以\007BEL或\033\\ST作为终止符WezTerm 两者均接受变量没有显式的生命周期——它由 pane 持有直到被再次覆盖或 pane 关闭。base64 换行的注意事项!!! note 某些系统上的base64命令默认在输出达到一定字符数后会进行换行包装从而限制用户变量值的最大长度。如果遇到这种情况可以加上-w 0之类的参数来禁用换行例如printf \033]1337;SetUserVar%s%s\007 foo echo -n bar | base64 -w 0这样可确保值能够完整传递。这是原文档中特别提醒的实用陷阱。供 shell 复用的辅助函数WezTerm 的 shell 集成脚本 assets/shell-integration/wezterm.sh 内置了__wezterm_set_user_var()函数见该文件 L435 附近它同时处理了非 tmux 与 tmux 两种环境下的发送方式建议直接在你的 shell 配置中复用__wezterm_set_user_var() { if hash base64 2/dev/null ; then if [[ -z ${TMUX} ]] ; then printf \033]1337;SetUserVar%s%s\007 $1 echo -n $2 | base64 else # tmux 直通转义序列同时需要在 tmux.conf 中设置 set -g allow-passthrough on printf \033Ptmux;\033\033]1337;SetUserVar%s%s\007\033\\ $1 echo -n $2 | base64 fi fi }其中 tmux 分支使用了\033Ptmux;...\033\\包裹的直通passthrough转义序列让用户变量可以穿越 tmux 到达真实终端。tmux 用户必须同时在~/.tmux.conf中设置set -g allow-passthrough on否则序列会被 tmux 吞掉。协议底层实现从转义序列解析到事件分发WezTerm 对 OSC 1337 用户变量的解析位于 wezterm-escape-parser/src/osc.rs。从源码可以看到解析器匹配1337关键字SetUserVar后将名称Base64值字符串用splitn(2, )切分并对值执行base64_decode还原见 L1267-L1280若 OSC 参数恰好为两段且关键字为SetUserVar则解析出name与value值部分必须合法 Base64解码失败则整个序列被拒绝解析结果被封装为ITermProprietary::SetUserVar变体。随后在 term/src/terminalstate/performer.rsL833-L836中ITermProprietary::SetUserVar被转换为Alert::SetUserVar { name, value }告警并派发给 handler最终在 GUI 侧wezterm-gui/src/termwindow/mod.rsL1203、L1912-L1949的emit_user_var_event()负责真正触发 Lua 事件先通过window_contains_pane()检查 pane 是否属于当前窗口确保事件只派发给包含该 pane 的窗口构造(window, pane, name, value)四元参数调用config::lua::emit_event(lua, (user-var-changed, args))事件回调执行完成后窗口还会触发update_title()刷新标题与标签栏。此外事件会经多路复用器Mux广播——wezterm-client/src/pane/clientpane.rsL185处理远程 pane 的Alert::SetUserVar因此用户变量变更事件会传播到所有已连接的多路复用客户端包括远程连接与 tmux 直通场景。在 Lua 配置中注册user-var-changed事件在你的.wezterm.lua中注册事件处理函数即可在用户变量被设置/变更时收到通知local wezterm require wezterm wezterm.on(user-var-changed, function(window, pane, name, value) wezterm.log_info(var, name, value) end) return {}回调参数说明事件回调依次接收四个参数参数类型说明windowWindow 对象包含该 pane 的 WezTerm 窗口可用于window:set_right_status()等窗口级操作panePane 对象用户变量所属的 panenamestring被设置/更新的用户变量名称例如foovaluestring设置/更新后的值已由 WezTerm 完成 Base64 解码例如bar沿用开头的命令设置foobar后回调将以name foo、value bar被调用。事件注册机制与format-tab-title、update-status等一样均由 config/src/lua.rs 中的wezterm.on()统一管理多个同名回调会按注册顺序依次执行。读取当前全部用户变量pane:get_user_vars()除了监听变更事件你也可以随时查询 pane 当前的完整用户变量集合。pane:get_user_vars()方法自版本20210502-130208-bff6815d起可用返回一个包含该 pane 所有已赋值用户变量的 Lua 表wezterm.log_info(foo var is .. pane:get_user_vars().foo)该方法对应 docs/config/lua/pane/get_user_vars.md 的说明。其底层实现在 mux/src/localpane.rsL222-L224中直接克隆终端状态中的user_vars哈希表返回给 Lua 层。同样的数据也可以通过PaneInformation结构体的user_vars字段访问——见 wezterm-gui/src/termwindow/mod.rsL273、L3452以及tab.active_pane.user_vars的用法。该 API 最早自 2021-05 版本即已存在说明用户变量机制与事件模型在 WezTerm 中已沉淀多年。实战用用户变量驱动标签栏与状态栏用户变量最常见的落地场景是shell 在关键时刻写入状态WezTerm 在标签栏/状态栏中展示。官方在 docs/recipes/passing-data.md 中给出了完整示例。shell 侧记录正在执行的程序借助前面定义的__wezterm_set_user_var可以包装常用命令实时记录当前执行的程序名# 设置 PROG 为正在运行的程序程序退出时清空 function _run_prog() { __wezterm_set_user_var PROG $1 trap __wezterm_set_user_var PROG EXIT command $ } alias vim_run_prog vim alias tmux_run_prog tmux alias nvim_run_prog nvimWezTerm 侧动态格式化标签标题local wezterm require wezterm wezterm.on(format-tab-title, function(tab) local prog tab.active_pane.user_vars.PROG return tab.active_pane.title .. [ .. (prog or ) .. ] end) return {}当用户执行vim时标签页标题会实时追加[vim]退出后 PROG 被清空后缀随之消失。这里直接通过PaneInformation.user_vars读取无需显式注册user-var-changed——用户变量本身会随每次设置/更新自动刷新标签栏与状态栏原文档与get_user_vars文档均确认设置用户变量会触发窗口内的事件生成、update-status事件以及标题/标签栏区域的更新见 docs/shell-integration.md。内置的用户变量与 shell 集成安装 WezTerm 的 shell 集成脚本即 assets/shell-integration/wezterm.sh后WezTerm 会自动为每个 pane 维护一组内置用户变量并在每次提示符显示与命令执行前更新变量名内容说明WEZTERM_PROG当前正在执行的命令行提示符显示及命令执行前更新WEZTERM_USERid -un的输出当前用户名WEZTERM_HOST主机名依次尝试/proc/sys/kernel/hostname、hostname、hostnamectl hostname失败则置为unknown也可用WEZTERM_HOSTNAME环境变量覆盖WEZTERM_IN_TMUX1或0shell 是否运行在 tmux 内在 assets/shell-integration/wezterm.sh 中可以看到这些内置变量的实际写入逻辑L509-L539例如__wezterm_set_user_var WEZTERM_USER $(id -un) if [[ -z ${WEZTERM_HOSTNAME} ]]; then __wezterm_set_user_var WEZTERM_HOST $(cat /proc/sys/kernel/hostname) ... fi __wezterm_set_user_var WEZTERM_IN_TMUX 1 # 或 0你可以据此判断 pane 的远程主机、当前用户或在标签标题中展示会话上下文比如用WEZTERM_IN_TMUX区分本地与 tmux 会话。常见问题与限制值长度受限某些平台的base64默认按宽度换行导致长值被截断——使用-w 0GNU coreutils或等价参数禁用换行tmux 嵌套在 tmux 内发送用户变量必须使用 tmux 直通序列且需在~/.tmux.conf中开启set -g allow-passthrough on否则事件不会到达 WezTerm事件作用域user-var-changed仅在包含对应 pane 的窗口中触发由源码中的window_contains_pane()校验保证其他窗口不会收到无关 pane 的事件写入者要求用户变量只能由 pane 内程序通过转义序列写入WezTerm 配置侧的 Lua 无法反向“注入”变量到 pane 内版本前提user-var-changed事件要求 WezTerm 版本不低于20220903-194523-3bb1ed61pane:get_user_vars()则要求不低于20210502-130208-bff6815d。小结user-var-changed事件把“终端字节流”与“Lua 配置层”连接起来shell 通过一行printf转义序列即可把任意结构化信息当前程序、工作目录、主机、自定义状态写入 paneWezTerm 则在 GUI 窗口内广播变更、刷新标题与状态栏并允许你在.wezterm.lua中订阅处理。配合pane:get_user_vars()与 shell 集成内置的WEZTERM_*变量你可以在不依赖进程嗅探的情况下构建跨 SSH、跨 tmux、跨多路复用连接的自定义标签与状态展示逻辑。相关文档可继续阅读pane:get_user_vars()shell 集成说明从 pane 向 Lua 传递数据完整实战示例update-status 事件【免费下载链接】weztermA GPU-accelerated cross-platform terminal emulator and multiplexer written by wez and implemented in Rust项目地址: https://gitcode.com/GitHub_Trending/we/wezterm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表