Skip to content

feat(desktop): Run 窗口按 IDEA 样式为每次执行开标签,控制台按 ANSI 转义着色 - #1932

Merged
xiaoyumuxi merged 2 commits into
previewfrom
feat/desktop-run-window-idea
Nov 14, 2026
Merged

xiaoyumuxi merged 2 commits into
previewfrom
feat/desktop-run-window-idea

Conversation

@xiaoyumuxi

Copy link
Copy Markdown
Collaborator

关联 Issue / Linked issue

PR 类型 / Type

  • feat:新功能或用户可见的改进
  • fix:缺陷修复
  • docs:文档、Agent Note、Skill 等规则文件
  • release:稳定版发布准备

改动说明 / What changes

背景 / Why

原来 Build 窗口执行的任务和运行配置的输出挤在一个共享的控制台里,看不出每次执行的结果和耗时;输出里的 ANSI 转义要么原样显示成乱码,要么颜色全丢(例如构建工具强制彩色输出时的 [INFO]、WARNING、BUILD SUCCESS)。这个 PR 把 Run 窗口改成 IntelliJ IDEA 的样子:每次执行一个标签,左边是执行的状态和耗时,右边是带颜色的控制台。

改动 / Changes

Run 窗口(run_view.go,新文件;build_view.go 删掉原来的运行视图)

  • 窗口标题“运行”后面,每次执行一个标签:状态图标(运行中、成功、失败、已停止)、名称;结束后显示 ×,点 × 关闭,运行中的标签不能关。关闭当前标签后选中顶替它位置的相邻标签(runs.go 的 closeRunSession)。
  • 左侧竖排工具栏:绿色的“再次运行”和红色的“停止”。宿主自己的执行只在没有其他执行时能再次运行;正在停止时停止按钮变成“强制停止”。Viva 的图标按钮不能给图标着色,所以用 runToolButton 自己画。
  • 执行树:根行是状态图标、粗体名称、紧跟的“: 在 <开始时间>”和右对齐的耗时,下一行是结果说明;无障碍名称是“名称, 状态, 耗时”。执行树和控制台之间是可拖动的分隔条(runpanels.go 的 runSplit,键盘调整在 editor_view.go 接入)。
  • 控制台右侧竖排工具栏:滚动到末尾、清空(复用 git.console.scrollToEnd、git.console.clear 词条,git.console.clear 的平台加上 desktop)。
  • 标签放进工具窗口标题栏(shell_view.go,和终端标签同一处)。
  • Build 窗口不再内嵌运行输出;showBuildConsole 改为把 Run 窗口带到前面并选中正在运行的那次执行。

执行会话(runs.go、build.go、runconfig.go、ide_api_dispatch.go)

  • 宿主的构建任务、运行配置和插件经 lithe/host/run/start 发起的运行,都是 Run 窗口里的一个会话:beginBuildOperation 新增 restart 参数(再次运行时调用),每次执行有自己的有界控制台(4000 行、4 MiB)。同名的已结束会话让位给新会话;最多保留 8 个,超出时去掉最旧的已结束会话。
  • 原来所有执行共用的 p.build.output 删除;IDE API 读一次执行的输出(ideAPIOperationText)改为读该会话自己的控制台,读到的是去掉转义的纯文本,被裁掉的行仍由 Core 报告不连续。
  • 运行配置保存未保存文档失败时,原来手动清空 p.build.status,现在统一走 endBuildOperation。

控制台着色(core/output_style.go、workbench/output_style.go、outputlinks_view.go、termview/palette.go)

  • Core 客户端新增 DecodeOutputStyle,Kernel 接口同步。
  • outputDecoder 在读取输出的 goroutine 上按 256 KiB 分片调用 outputStyle.decode,带上一次的状态,补齐被切开的 UTF-8 字符;同一个控制台的块按解码顺序交给界面线程。Core 失败时记一次 operation_failed(output_style),该控制台其余输出按原样分行显示。
  • outputBuffer 保存纯文本行和样式区间,按行数和字节数上限裁剪,sequence 单调递增;复制、搜索、输出链接、快照和 IDE API 都只读纯文本。
  • 绘制:一行按样式切成若干段,和输出链接的区间合并(原来 outputlinks.go 的 splitUTF16、utf16Tail 改成按段切分的 outputSegments)。0–15 号颜色用 termview 新导出的 Look.ANSI(),和终端同一套配色(含 Terminal.app 描述文件导入与对比度回退);粗体的 8 个基本色取亮色;支持反显、暗淡、隐藏、下划线、删除线、背景色。
  • 控制台跟随最新输出(ui.List(...).Follow(true)),用户向上滚动后不再跳动;运行、构建、测试三个控制台都一样。

测试窗口(tests.go、tests_view.go)

  • 测试输出也走解码器和有界控制台(2000 行),显示最后 12 行并带颜色。

文案(shared/i18n/、desktop/internal/i18n/run_messages.go)

  • 新增 desktop.run.*:关闭、开始时间“: 在 {time}”、四种状态、耗时(毫秒;秒+毫秒;分+秒;时+分)。耗时接口参数是整数毫秒,符合目录检查只允许 string/int/bool 参数的规则。

其他

  • PINNED_CORE_REVISION 升到 Lithe-core-rust#44 的 cdc0258,注释补上 [Bug] 双Shift搜索列表无法下拉 #44 并把 [Feature] 关闭项目类似IDEA一样 回退到欢迎页面 #43 改为已 squash 合入。
  • 功能矩阵:新增 run-window-execution-tabs、run-console-ansi-styles;run-output-snapshot、debug-performance、plugin-backend-run-start 的证据路径从 build_view.go 改为 run_view.go,plugin-backend-run-start 的说明从“Build 面板里的运行视图”改为“Run 窗口中这次运行自己的标签”。
  • 测试适配:beginBuildOperation 五参数、feedBuildOutput 辅助函数、各测试改用有界控制台;run_panels_test.go 改为断言控制台停在末尾。

不在本 PR 范围内 / Out of scope

  • 构建工具默认不输出颜色:工具是否强制彩色由提供它的插件在命令参数里决定,宿主不加任何工具特判。Maven 插件加 -Dstyle.color=always 在插件仓库另提 PR;它要先确认测试结果解码读的原始输出能处理转义。
  • IDEA 控制台右侧的软换行、打印、过滤等按钮,以及执行树按构建阶段展开子节点,这次没做。
  • macOS 整机和 Windows 真机验收还没做,功能矩阵两端保持 pending。

类型专属:feat

多平台对齐

  • 两端都具备:Viva 桌面端共享实现,macOS 与 Windows 同一份代码(desktop/internal/**),Core 命令两端共用。
  • 只实现了 macOS:已为 Windows 提交跟进 Issue:#
  • 只实现了 Windows:已为 macOS 提交跟进 Issue:#
  • 刻意只属于某个平台(功能矩阵中另一端记为 platform-specific),理由:

范围检查 / Scope checks

功能矩阵 / Feature matrix

  • 已更新 shared/platform-feature-matrix/features/<id>.json:新增两条,改三条证据路径;两端 implemented / pending,证据路径、owner、验证动作都如实填写
  • 已运行 ./scripts/platform-feature-matrix/verify-platform-feature-matrix.sh 和 ./scripts/platform-feature-matrix/verify-platform-feature-matrix-change.sh origin/preview HEAD
  • 没有提交 .artifacts/ 下生成的矩阵视图
  • [N/A] 已更新矩阵,不需要豁免

插件归属 / Plugin ownership

  • 已在仓库根目录运行 develop-lithe 第三节“插件归属与宿主零依赖”的自查命令,结果为空
  • 新增或修改的测试只使用宿主自己的执行和合成输出,没有读取具体插件,没有使用真实插件 ID,没有“缺少插件时跳过”的测试(视觉测试里的彩色输出是测试内联的合成文本)
  • 新的矩阵条目只记录宿主的 Run 窗口和控制台能力,证据和验证动作不引用插件
  • 没有插件文案或插件构建内容进入宿主
  • [N/A] 没有修改插件可见的扩展点:lithe/host/run/* 的参数、返回值和通知不变,插件的运行只是换到 Run 窗口的标签里显示

统一日志系统 / Structured logging

  • 解码失败复用已有的 operation_failed 事件(字段 output_style),每个控制台只记一次;没有新增事件 ID,没有直接写 stderr
  • 一个操作只有一条终态;输出解码这条高频路径不打 INFO
  • 没有记录命令输出内容,只记录错误
  • [N/A] 旧日志脚本:本 PR 不涉及

界面文案 / i18n

  • 宿主文案都走共享 i18n:shared/i18n/ 补齐中英词条,已运行 node scripts/i18n/generate-i18n.mjs 并提交生成结果;Viva 代码通过 desktop/internal/i18n/ 读取
  • [N/A] 插件文字:本 PR 不涉及
  • 已运行 node scripts/i18n/verify-app-language-localization.mjs 和 node scripts/i18n/generate-i18n.mjs --check,没有放宽脚本或扩大豁免名单

逻辑归属 / Logic placement

  • ANSI 转义解析在 Rust Core(Lithe-core-rust#44,契约和 fixture 先于接入);桌面端只做分片调用、配色和绘制
  • [N/A] 平台层没有其他可共享逻辑需要迁移
  • 宿主和 Core 没有按工具名加分支;构建工具是否输出颜色由插件决定

性能与内存 / Performance and memory

  • 每个控制台有行数和字节数上限(运行 4000 行 / 4 MiB,测试 2000 行),会话最多 8 个;关闭标签即释放它的控制台;没有新增轮询或定时器
  • 解码在读取输出的 goroutine 上进行,不在界面线程;每次调用最多 256 KiB,跨 C ABI 只传这一块和 Core 的状态
  • 长输出改动前后的性能基线:没有测。改动前长输出也是逐行进入有界缓冲;现在每块多一次 Core 调用,但不在界面线程。需要时可以补测

设置 / Settings

N/A:没有新增或修改设置。

插件契约 / Plugin contract

N/A:不涉及插件契约、能力版本、插件函数协议或宿主方法;Core 新命令只是宿主内部命令。PINNED_CORE_REVISION 已按上面说明升到 cdc0258。

发行包与资源 / Bundle and resources

  • 运行时不向已安装的 app bundle 或安装目录写入;没有新增资源路径;已运行 ./scripts/desktop/verify/verify-runtime-bundle-immutability.sh,通过
  • [N/A] 没有新增下载、解压、生成或缓存资源

无用代码与重构 / Dead code and refactoring

  • 本次改动导致变成无用的代码已删除:共享的 p.build.output、Build 窗口里的运行视图、splitUTF16 / utf16Tail、测试视图里不再用的 strings 导入
  • [N/A] 这次没有发现之前就存在、需要另建单的无用代码

验证 / Verification

命令或操作 平台 结果
LITHE_CORE_RUST_DIR=<Core #44 检出> scripts/desktop/desktop-go.sh test ./... macOS 通过(rebase 到最新 preview 后重跑)
scripts/desktop/desktop-go.sh test -race ./internal/workbench/ ./internal/core/ ./internal/i18n/ ./internal/termview/ macOS 通过
scripts/desktop/desktop-go.sh vet ./...,以及 -tags vivahead,lithevisual 的 workbench macOS 通过
gofmt -l desktop/internal macOS 无输出
新测试 TestRunWindowGivesEachExecutionATab(两个标签、选中最新、执行树状态与耗时、切换标签、控制台无转义、× 关闭并选中相邻标签) macOS 通过
新测试 TestRunDurationPicksTheLargestTwoUnits(中英文的毫秒、秒、分、时四档和负值) macOS 通过
LITHE_VISUAL_OUTPUT_DIR=… desktop-go.sh test -tags vivahead,lithevisual -run TestVisualBuildPanels ./internal/workbench/:build-and-run 场景用合成的彩色构建输出截图,明暗主题、中英文 macOS(headless) 截图与 IDEA 布局一致:“运行”标题、“✓ package ×”标签、绿色再次运行、灰色停止、执行树“package: 在 … 0毫秒”和“构建成功”、彩色控制台与右侧按钮
node scripts/i18n/verify-app-language-localization.mjs、node scripts/i18n/generate-i18n.mjs --check、node --test scripts/i18n/test-i18n.mjs macOS 通过
verify-platform-feature-matrix.sh、verify-platform-feature-matrix-change.sh origin/preview HEAD macOS 通过
.agents/skills/write-stable-tests/scripts/verify-test-stability.sh macOS 通过
scripts/desktop/verify/verify-runtime-bundle-immutability.sh macOS 通过
插件零依赖自查命令 macOS 无输出
Core #44:cargo test -p lithe-terminal -p lithe-core、cargo fmt --check、cargo clippy -D warnings macOS 通过

未能执行的检查和原因:

  • 没有启动打包后的 Lithe 做整机验收(真实构建工具的彩色输出、拖动分隔条、长时间输出),只做了 headless 截图;Windows 没有在真机上跑。功能矩阵两端保持 pending。
  • 长输出的性能基线没有测(见上文)。

提交前确认 / Final checks

Run 窗口改成 IntelliJ IDEA 的布局:标题“运行”后面是每次执行一个标签(状态图标、名称、结束后的关闭按钮),
左侧竖排工具栏是绿色的再次运行和红色的停止,执行树显示状态、粗体名称、开始时间和右对齐耗时,右侧控制台
带滚动到末尾和清空。宿主构建任务、运行配置和插件发起的运行都进 Run 窗口,Build 窗口不再内嵌运行输出。

控制台输出经 Rust Core 的 outputStyle.decode 解码为纯文本行和着色区间,在读取输出的 goroutine 上分片调用;
纯文本供复制、搜索、输出链接、快照和 IDE API,样式按终端同一套 16 色配色绘制。运行、构建和测试控制台跟随
最新输出,向上滚动后停止跟随。Core 固定到 Lithe-core-rust #44 的 cdc0258(合入后改为 main 上的 commit)。
@ghfind-review ghfind-review Bot added the review: high ghfind author score; see https://ghfind.com label Nov 14, 2026
@xiaoyumuxi
xiaoyumuxi marked this pull request as ready for review November 14, 2026 15:57
@xiaoyumuxi
xiaoyumuxi merged commit a277694 into preview Nov 14, 2026
6 of 12 checks passed
xiaoyumuxi added a commit that referenced this pull request Nov 14, 2026
#1932 也改了 Core 固定版本。两边改的 #44、#45 都已合入 Core main,固定改为 main 上的 40711b1(即 #45 测过的 c7213c2 加上 #44),注释合并两条说明。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review: high ghfind author score; see https://ghfind.com

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant