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),仅供参考
企业数字化 ERP 产品动态
相关推荐
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:54
企业级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:53
企业网站做电脑营销多少钱?揭秘防黑挂马的底层逻辑 企业网站做电脑营销多少钱?揭秘防黑挂马的底层逻辑 网站突然被黑,首页挂满赌博广告,后台密码怎么改都没用,这种绝望感做过站的都懂。很多老板第一反应是问:“清理一次病毒多少钱?”或者“换个服务器多少钱?”但真相往往扎心:单纯清理病毒的费用可能只要几百块,但重建信任、修复SEO权重、补全安全漏洞的成本,往… · 2026/9/21 8:03:27
3步搞定做品管圈网站从零搭建到上线避坑指南 3步搞定做品管圈网站从零搭建到上线避坑指南 不会写代码,但想给团队搭个品管圈展示平台?别慌。 很多河南的创业老板都卡在这一步:手里有现成的QCC成果,想做个官网放上去,结果一搜全是“前端开发教程”,看得头大。 做品管圈网站 这事儿,真没你想的那么玄乎。只要路子对,零基础也能 从零搭建… · 2026/9/21 7:45:56
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:58
Lightweight Charts v3 到 v4 迁移指南:破坏性变更逐项分析与实战改造方案 Lightweight Charts v3 到 v4 迁移指南:破坏性变更逐项分析与实战改造方案 【免费下载链接】lightweight-charts Performant financial charts built with HTML5 canvas 项目地址: https://gitcode.com/gh_mirrors/li/lightweight-charts
本指南以 Lightweig… · 2026/9/21 7:41:58
Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化 直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡… · 2026/9/21 0:02:39
Word表格编号全攻略:从列表编号到题注交叉引用 写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技… · 2026/9/21 0:02:39
从第一个站到第二个站:独立开发者的静态网站选型与落地实践 1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&… · 2026/9/20 0:00:41
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:18
gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析 gin-vue-admin 前端工具函数全景指南:src/utils 复用规范与源码级解析 【免费下载链接】gin-vue-admin 🚀ViteVue3Gin拥有AI辅助的基础开发平台,企业级业务AI开发解决方案,内置mcp辅助服务,内置skills管理,… · 2026/9/21 0:00:18