iTerm2 Python API 实战:用 copycolor 脚本在分屏时保持标签页颜色同步
iTerm2 Python API 实战用 copycolor 脚本在分屏时保持标签页颜色同步【免费下载链接】iTerm2iTerm2 is a terminal emulator for Mac OS X that does amazing things.项目地址: https://gitcode.com/gh_mirrors/it/iTerm2导读在 iTerm2 中同一标签页Tab内的多个窗格Pane可以来自不同的 Profile如果这些 Profile 定义了不同的标签页颜色分屏后就会出现同一标签页内两个窗格颜色不一致的情况。iTerm2 官方 Python API 示例 copycolor.rst 提供了一段名为 Preserve Tab Color保持标签页颜色的守护脚本它监听新会话的创建自动把标签页内已有会话的标签颜色复制给新窗格并在不改动底层 Profile 的前提下完成这一修改。读完本文你将掌握LocalWriteOnlyProfile、NewSessionMonitor、async_set_profile_properties等核心 API 的用法并能直接部署这段脚本到自己的 iTerm2 环境中。问题背景分屏后标签页颜色为什么会对不上iTerm2 允许每个 Profile 单独配置标签页颜色Tab Color。当你执行用其他 Profile 在此处分割Split with a different profile操作时新窗格会继承该 Profile 的标签页颜色而旧窗格保留原 Profile 的颜色。如果两个 Profile 的颜色不同同一个标签页就会呈现两种颜色视觉上容易被误认为两个独立的标签页。官方示例开篇即点明了这一场景If you split a session using a different profile, you can end up with two panes that have different tab colors. This script copies the old tab color to the new split pane so they stay in sync.解决思路很直接监听新会话创建事件找到它所在的标签页读取该标签页中已经存在的会话的标签颜色再用会话级而非 Profile 级的写操作把颜色应用到新会话上。这段脚本的核心价值在于第二个技巧——如何修改会话的 Profile 属性而不修改底层 Profile因为直接改底层 Profile 会影响所有使用该 Profile 的会话。完整示例代码以下是 copycolor.rst 中的完整脚本约 44 行你可以从仓库的 copycolor.its 下载该脚本的原始版本#!/usr/bin/env python3.7 import iterm2 async def main(connection): async def async_color_in_tab(tab, exclude): Return the tab color of any session that already existed. colors [] for session in tab.sessions: if session exclude: continue profile await session.async_get_profile() if not profile: continue color profile.tab_color if color: return color return None app await iterm2.async_get_app(connection) async with iterm2.NewSessionMonitor(connection) as mon: while True: # Wait for a new session to be created session_id await mon.async_get() session app.get_session_by_id(session_id) if not session: continue window, tab app.get_tab_and_window_for_session(session) if not tab: continue color await async_color_in_tab(tab, session) if not color: continue # Another session had a color in this tab. Change the tab # color property of the new session. Use LocalWriteOnlyProfile # and session.async_set_profile_properties to avoid changing the # underlying profile. change iterm2.LocalWriteOnlyProfile() change.set_tab_color(color) await session.async_set_profile_properties(change) iterm2.run_forever(main)脚本结构清晰自顶向下可以分为四个部分读取已有颜色、监听新会话、查找所属标签页、写入颜色。下面逐段剖析。逐段剖析四个核心步骤1. 读取标签页中已有会话的颜色async def async_color_in_tab(tab, exclude): Return the tab color of any session that already existed. colors [] for session in tab.sessions: if session exclude: continue profile await session.async_get_profile() if not profile: continue color profile.tab_color if color: return color return Noneasync_color_in_tab遍历标签页内的所有会话tab.sessions跳过新创建的那个会话exclude对每个已有会话调用session.async_get_profile()获取其生效的 Profile读取profile.tab_color。一旦找到非空颜色就立即返回全部没有颜色则返回None。两个细节值得注意async_get_profile()返回的 Profile包含会话本地修改。从 session.py 的实现看它通过iterm2.rpc.async_get_profile拉取数据docstring 明确写着including any session-local changes not in the underlying profile包含不在底层 Profile 中的会话本地修改。这意味着即使旧窗格此前已被脚本改过颜色新窗格也能读到最终生效的颜色而不是回退到 Profile 原始值。函数内部声明了colors []但从未使用属于示例代码遗留的冗余变量不影响逻辑可自行删除。2. 监听新会话的创建app await iterm2.async_get_app(connection) async with iterm2.NewSessionMonitor(connection) as mon: while True: # Wait for a new session to be created session_id await mon.async_get() session app.get_session_by_id(session_id) if not session: continueiterm2.async_get_app(connection)获取当前 App 的对象模型包含窗口、标签页、会话的树状结构。NewSessionMonitor是一个异步上下文管理器进入时订阅新会话创建通知退出时自动取消订阅见 lifecycle.py 的实现__aenter__中调用async_subscribe_to_new_session_notification__aexit__中调用async_unsubscribe。mon.async_get()会阻塞等待下一个新会话事件返回新会话的 ID字符串。随后用app.get_session_by_id(session_id)把 ID 解析为Session对象。如果解析失败例如会话已被关闭直接continue等待下一个事件。整个while True循环让脚本变成一个常驻守护进程这正是run_forever入口的意义。3. 定位新会话所属的标签页window, tab app.get_tab_and_window_for_session(session) if not tab: continueget_tab_and_window_for_session返回(Window, Tab)二元组用于找出会话所属的窗口和标签页。值得注意的是从 app.py 的源码注释看这个方法已标记为 Deprecated理由是名字与返回参数顺序不符——它实际返回的是(Window, Tab)而非名字暗示的(Tab, Window)官方建议使用新方法get_window_and_tab_for_session。内部实现是遍历terminal_windows与window.tabs检查session in tab.all_sessions来定位。新代码中可以改用get_window_and_tab_for_session语义更清晰。如果找不到所属标签页例如会话已被关闭跳过本次事件。4. 通过 LocalWriteOnlyProfile 写入颜色color await async_color_in_tab(tab, session) if not color: continue # Another session had a color in this tab. Change the tab # color property of the new session. Use LocalWriteOnlyProfile # and session.async_set_profile_properties to avoid changing the # underlying profile. change iterm2.LocalWriteOnlyProfile() change.set_tab_color(color) await session.async_set_profile_properties(change)这是全脚本最关键的部分不修改底层 Profile只修改这一个会话的生效配置。LocalWriteOnlyProfile是一个可写不可读的临时 Profile 对象从 profile.py 的实现看它的values属性保存着一组(键, JSON 值)对本身并不与任何真实 Profile 绑定。change.set_tab_color(color)会调用_color_set(Tab Color, value)把颜色对象序列化为 JSON 存进values字典。session.async_set_profile_properties(change)负责把这份变更应用到会话。从 session.py 的实现看当连接支持多属性批量设置supports_multiple_set_profile_properties时一次性把所有(key, json_value)打包为 assignments通过async_set_profile_properties_json发送对不支持的老版本3.3.0beta9 及更早则退化为逐条调用async_set_profile_property_json任一属性写入失败都会抛出RPCException。其 docstring 明确说明When you use this function the underlying profile is not modified. The session will keep a copy of its profile with these modifications.使用此函数时底层 Profile 不会被修改会话会保留一份带这些修改的 Profile 副本。这正是脚本能只影响新窗格、不影响其他会话的根本原因。关键 API 源码级剖析LocalWriteOnlyProfile会话级临时配置LocalWriteOnlyProfile是 iTerm2 Python API 中实现局部覆盖的标准工具官方文档在 profile.py 中直接引用本示例作为用法范例。它配合Session.async_set_profile_properties使用相关方法包括方法作用底层键名set_tab_color(color)设置标签页颜色未启用明暗分离颜色时生效Tab Colorset_tab_color_light(color)设置明色模式变体启用明暗分离颜色时生效Tab Color (Light)set_tab_color_dark(color)设置暗色模式变体启用明暗分离颜色时生效Tab Color (Dark)set_use_tab_color(value)是否启用标签页颜色Use Tab Color颜色对象通过_color_set内部的value.get_dict()序列化为 JSON 存储。值得注意的是set_tab_color的 docstring 特别说明它仅在未启用独立明暗模式颜色时使用used only when separate light/dark mode colors are not enabled。如果目标 Profile 启用了Use separate colors for light and dark mode选项标签页颜色实际由Tab Color (Light)/Tab Color (Dark)决定此时应改用set_tab_color_light/set_tab_color_dark才能生效——这是本示例在特定配置下的一个扩展点。Color颜色值的表示iterm2.Color见 color.py以 RGBA 描述颜色r、g、b、a取值均为 0-255a默认 255color_space目前仅支持 sRGB。它还提供from_hex解析#aabbcc或 13 位十六进制与from_cocoa解析 NSKeyedArchiver 编码等工厂方法。本示例中颜色直接取自已有 Profile 的tab_color属性属于Color实例无需自行构造。NewSessionMonitor事件驱动的守护模式NewSessionMonitorlifecycle.py内部使用asyncio.Queue缓存通知async_get()从队列取出新会话 ID 并返回。它与其他 Monitor如SessionTerminationMonitor、LayoutChangeMonitor一样遵循async with上下文管理器协议退出时自动退订。配合iterm2.run_forever(main)入口见 connection.py脚本可以无限期运行这正是官方守护脚本的典型形态。对照实验settabcolor 示例带来的启发同目录下的另一个官方示例 settabcolor.rst 与本脚本形成了很好的对照app await iterm2.async_get_app(connection) session app.current_terminal_window.current_tab.current_session change iterm2.LocalWriteOnlyProfile() color iterm2.Color(255, 128, 128) change.set_tab_color(color) change.set_use_tab_color(True) await session.async_set_profile_properties(change)settabcolor 演示的是主动设置对当前会话写入硬编码颜色并额外调用change.set_use_tab_color(True)开启标签页颜色开关最后用run_until_complete一次性执行。而 copycolor 是被动同步它只复制颜色值本身。对比两者可以得出一个重要结论——copycolor 假设已有会话的标签页颜色已经处于生效状态即旧 Profile 已开启Use Tab Color新窗格沿用相同的颜色值时自然沿用开关状态若旧窗格颜色来自关闭开关的状态即未启用标签颜色则profile.tab_color与渲染结果不一定一致这是使用本脚本时需要了解的边界条件。若需在新窗格上强制开启标签颜色可参考 settabcolor 追加change.set_use_tab_color(True)。安装与运行脚本以#!/usr/bin/env python3.7开头要求 Python 3.7 及以上版本当前 iTerm2 的 Python API 运行时通常内置 Python 3.10兼容无虞。运行方式有两种从仓库下载脚本文件copycolor.its 是该示例的官方可下载版本可以通过 iTerm2 菜单Scripts Manage Import...导入.its 即 iTerm2 Script 文件的扩展名。手动创建脚本新建一个以.py结尾的文件粘贴上文完整代码放入~/Library/Application Support/iTerm2/Scripts/AutoLaunch/目录即可随 iTerm2 启动自动运行或放入Scripts/目录后从Scripts菜单手动启动。由于脚本主体是while True循环 run_forever(main)它属于常驻守护脚本启动后持续监听直到 iTerm2 退出或脚本被手动终止。分屏操作完成后新窗格的标签颜色会自动与同标签页内已有会话对齐之后无需再手动干预。关于 Python API 脚本的更多运行机制普通脚本与守护脚本的区别、调试方法可以继续阅读仓库中的 tutorial/index.rst、running.rst 与 daemons.rst。扩展思路与注意事项颜色继承方向脚本总是优先取tab.sessions中第一个按会话顺序有颜色的会话作为颜色来源。若同一标签页内多个窗格颜色本就不同新窗格会继承最先遇到的那个方向不可配置。明暗分离模式若旧窗格 Profile 启用了独立明暗颜色脚本读取到的tab_color可能为空此时需要改用tab_color_light/tab_color_dark属性并对应调用set_tab_color_light/set_tab_color_dark两者均已在LocalWriteOnlyProfile中提供见 profile.py。临时会话与 tmux 会话脚本通过app.get_session_by_id解析会话对任何新创建会话一视同仁如果session_id无法解析为 Session 对象如会话已关闭脚本会安全跳过不会崩溃。API 版本兼容性async_set_profile_properties内部会自动检测连接能力对不支持批量写入的老版本 iTerm23.3.0beta9 及更早退化为逐条写入因此脚本具备较好的向后兼容性。与新方法的关系get_tab_and_window_for_session已废弃新代码建议改用get_window_and_tab_for_session返回顺序同为(Window, Tab)。总而言之copycolor 脚本是一份麻雀虽小、五脏俱全的官方范例它完整演示了事件监听NewSessionMonitor 对象模型查询async_get_app/get_session_by_id/get_tab_and_window_for_session 局部写入LocalWriteOnlyProfileasync_set_profile_properties这一 iTerm2 Python API 的典型编程范式尤其适合作为学习在不污染底层 Profile 的前提下做会话级定制的入门教材。【免费下载链接】iTerm2iTerm2 is a terminal emulator for Mac OS X that does amazing things.项目地址: https://gitcode.com/gh_mirrors/it/iTerm2创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

SkyReels-V2 AI视频生成入门指南:无限长度视频快速上手教程

SkyReels-V2 AI视频生成入门指南:无限长度视频快速上手教程

SkyReels-V2 AI视频生成入门指南:无限长度视频快速上手教程 【免费下载链接】SkyReels-V2 SkyReels-V2: Infinite-length Film Generative model 项目地址: https://gitcode.com/GitHub_Trending/sk/SkyReels-V2 SkyReels-V2 是一个开源的 AI 视频生成模型&a…

2026/9/21 7:22:36 阅读更多 →
AltTab macOS 人工按键重复定时器(KeyRepeatTimer)的时序守卫设计:可见性锚点与迟到判定规则解析

AltTab macOS 人工按键重复定时器(KeyRepeatTimer)的时序守卫设计:可见性锚点与迟到判定规则解析

AltTab macOS 人工按键重复定时器(KeyRepeatTimer)的时序守卫设计:可见性锚点与迟到判定规则解析 【免费下载链接】alt-tab-macos Windows alt-tab on macOS 项目地址: https://gitcode.com/gh_mirrors/al/alt-tab-macos 导读 AltTa…

2026/9/21 7:22:36 阅读更多 →
企业级AI编程平台如何重构研发基建

企业级AI编程平台如何重构研发基建

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/21 7:21:36 阅读更多 →

最新新闻

3类高危漏洞:网页制作模板中文源码下载安全自查

3类高危漏洞:网页制作模板中文源码下载安全自查

3类高危漏洞:网页制作模板中文源码下载安全自查 域名服务器搞不懂,是无数运营推广人员接手“网页制作模板中文”项目时的噩梦。你手里拿着一个看起来很漂亮的模板,后台却像个黑盒,更别提那些藏在代码深处的安全隐患。…

2026/9/21 8:30:15 阅读更多 →
汽车之家网页版地址排查指南:3步定位挂马源,附前端布局对比评测

汽车之家网页版地址排查指南:3步定位挂马源,附前端布局对比评测

汽车之家网页版地址排查指南:3步定位挂马源,附前端布局对比评测 网站被黑挂马,后台却一片空白,这种绝望感每个运维和前端都懂。别慌,这通常不是代码逻辑错误,而是服务器环境或静态资源被篡改。今天不聊虚的,直接上干货,用 对比评测 的思路,带你从 汽车之家网页版地址…

2026/9/21 8:14:36 阅读更多 →
企业网站做电脑营销避坑指南:选哪家好别只看价格,看这套设计规范

企业网站做电脑营销避坑指南:选哪家好别只看价格,看这套设计规范

企业网站做电脑营销避坑指南:选哪家好别只看价格,看这套设计规范 改个需求建站公司拖一周,这种憋屈事谁没经历过?很多老板找企业网站做电脑营销,问得最多的一句话就是“哪家好”。其实,网站好不好用,营销转不转化,核心不在你付了多少钱,而在前端代码写得够不够规范,设计逻辑是否支撑你的业务目标。…

2026/9/21 8:00:00 阅读更多 →
做品管圈网站哪家好?3步避开被黑挂马陷阱

做品管圈网站哪家好?3步避开被黑挂马陷阱

做品管圈网站哪家好?3步避开被黑挂马陷阱 网站上线三天,后台突然多了个奇怪的脚本,页面弹出一堆博彩广告,SEO排名一夜清零。如果你正面临这种“网站被黑挂马不知道怎么办”的噩梦,先别慌着删库重装。很多站长在找做品管圈网站哪家好时,只盯着价格和功能,却忽略了最底层的代码安全与架构选型。今天咱们不聊虚的,…

2026/9/21 7:44:43 阅读更多 →
Voyager 資料夾管理指南:為 Gemini 與 AI Studio 的 AI 對話打造真正的「檔案系統」

Voyager 資料夾管理指南:為 Gemini 與 AI Studio 的 AI 對話打造真正的「檔案系統」

AI 应用前端 【免费下载链接】voyager Enhancement suite for Gemini, AI Studio, Claude & ChatGPT — plus a prompt manager for any websites, DeepSeek Harness included. / 面向 Gemini、AI Studio、Claude 与 ChatGPT 的增强套件;其中的提示词管理器可用…

2026/9/21 7:41:44 阅读更多 →
gatsby-source-graphql 插件全解析:将任意第三方 GraphQL API 缝合进 Gatsby 数据层

gatsby-source-graphql 插件全解析:将任意第三方 GraphQL API 缝合进 Gatsby 数据层

前端静态站点Web框架 【免费下载链接】gatsby React-based framework with performance, scalability, and security built in. 项目地址: https://gitcode.com/gh_mirrors/ga/gatsby 点击查看 免费下载 本篇技术指南以 gatsby-source-graphql 插件的 CHANGELOG 版…

2026/9/21 7:41:44 阅读更多 →

日新闻

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程

agents-generator 决策矩阵全解析:从项目检测到 AGENTS.md 规则生成的 16 步判定流程 【免费下载链接】agentic-awesome-skills AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and …

2026/9/21 0:00:01 阅读更多 →
gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析

gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析

gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析 【免费下载链接】gin-vue-admin 🚀ViteVue3Gin拥有AI辅助的基础开发平台,企业级业务AI开发解决方案,内置mcp辅助服务,内置skills管理,…

2026/9/21 0:00:01 阅读更多 →
Wox 全功能插件开发实战指南:基于 Python / Node.js 宿主与 WebSocket 的持久化插件体系

Wox 全功能插件开发实战指南:基于 Python / Node.js 宿主与 WebSocket 的持久化插件体系

桌面应用AI 应用插件系统 【免费下载链接】Wox A cross-platform launcher that simply works 项目地址: https://gitcode.com/gh_mirrors/wo/Wox 点击查看 免费下载 全功能插件(Full-featured Plugin)是 Wox 三类插件实现方式中能力最完整的…

2026/9/21 0:00:01 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/21 3:13:20 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/21 2:19:36 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/21 4:51:05 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/19 23:01:36 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/19 17:50:38 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →