Skip to content

fix(desktop): LSP 日志改为普通编辑器页签,⌘W 关闭选中页签(仅 macOS 默认) - #1873

Merged
xiaoyumuxi merged 3 commits into
previewfrom
fix/desktop-lsp-log-editor-tab
Nov 13, 2026
Merged

xiaoyumuxi merged 3 commits into
previewfrom
fix/desktop-lsp-log-editor-tab

Conversation

@xiaoyumuxi

Copy link
Copy Markdown
Collaborator

关联 Issue / Linked issue

PR 类型 / Type

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

改动说明 / What changes

背景 / Why

在旧 macOS 客户端里,语言服务器日志是编辑器区的一个普通“LSP 日志”页签。Viva 桌面端(desktop/)把它做成了模态弹窗,会挡住编辑器,也不能和文件并排看。另外 Viva 的快捷键目录里没有“关闭标签页”,macOS 上按 ⌘W 没有反应;“文件”菜单的“关闭标签页”也只在选中文件时出现,选中 Diff、查看器或日志页签时无法关闭。

这个 PR 把日志恢复成普通页签,并让“关闭标签页”对任何选中的页签都有效。macOS 默认绑定 ⌘W;其他平台不设默认值,用户可以在快捷键设置页自己绑定。

改动 / Changes

LSP 日志改为普通编辑器页签(lsp_status.go、app.go、root.go)

  • 点击状态栏的 LSP 状态项,会在文件默认打开的编辑组里打开“LSP 日志”页签;项目里已经有这个页签时只切换过去。每个项目最多一个(成员 ID lsp:log),可以像文件页签一样切换、拖动、分屏和关闭。关闭后再打开,之前收到的日志仍在。
  • 删除模态弹窗 lspLogPopup 及 a.editor.lsp.open 的打开方式。
  • 选中“LSP 日志”页签时,状态栏显示页签中那个服务器的状态,而不是变成空白。

日志页签的查看体验(用户授权在“不影响查看”的前提下自行优化)

  • 顶栏:选择服务器的下拉框、文本筛选、服务器状态,以及“清空视图”“停止”“重启”按钮。停止和重启沿用原弹窗的流程。
  • 停在末尾时,新日志自动滚到底部;向上翻看时不会被打断(用 logsAdded 计数判断有没有新行)。
  • 按事件级别着色:错误用主题的危险色,警告用警告色,调试和跟踪行用弱化色。日志行改为带级别的 lspLogLine。
  • “清空视图”复用已有词条 native.clearLogView,只清空页签中的显示,不影响日志文件。

关闭选中页签(commands.go、root.go、shortcuts.go)

  • “文件”菜单和 Find Action 的 tab.close 关闭编辑组当前选中的页签,文件、Diff、查看器、LSP 日志都可以,效果和点页签上的关闭按钮一样。原来只在选中文件时提供,现在不再限制类型。另存为、丢弃草稿两项的条件不变,只是挪到前面单独判断。
  • 快捷键目录新增 shortcuts.CloseTab = "tab.close"(“项目”分组,放在“关闭项目”之后)。closeTabDefaults() 只在 darwin 上返回 ⌘W,其他平台返回空,所以 Windows 默认不绑定,快捷键设置页会自动列出这个动作供用户绑定。
  • 焦点在终端时,快捷键关闭这个终端页签,不会关闭编辑器里的文件。为此 windowShortcuts 额外读出聚焦的终端,runShortcut 签名改为 (id, view, term)。

页签公共代码(difftab.go、viewer.go、tabstrip.go、tabdrag.go、terminals.go、editor_view.go)

  • 把 Diff 用的 placeDiff 改为通用的 placeEditorMember(p, member),并返回所在的编辑组。Diff、查看器、LSP 日志都用它,删掉 openViewer 里复制的同一段逻辑。
  • shownTab 新增 lsp,页签栏、拖动预览、分屏放置(dropTab)和编辑组正文(groupBody)都能处理 LSP 日志页签。
  • 顺带修复:拖动查看器页签时,预览固定显示图片图标。现在和页签栏一致,用 tabLabel/tabIcon,十六进制查看器等也显示自己的图标。

i18n(shared/i18n/、desktop/internal/i18n/shared.generated.go)

  • 删除只给弹窗用的 desktop.lsp.logTitle。
  • logs.language.tabTitle(“LSP 日志”)和 native.clearLogView 的平台范围加上 desktop,并重新生成。

功能矩阵

  • lsp-status-logs.json:notes 改写为页签行为,证据加上 tabstrip.go、editor_view.go。
  • editor-text-tabs.json:notes 写明关闭选中页签的范围、macOS 默认 ⌘W、其他平台可自行绑定,以及终端里的行为;证据加上 commands.go、root.go、shortcuts.go、close_tab_shortcut_test.go。
  • 状态字段未改。

过时路径(机械修正)

  • .github/pull_request_template.md、.agents/skills/develop-lithe/SKILL.md 两处、.agents/notes/proposed/architecture/2026-11-12-plugin-authored-settings-content.md 中的 scripts/macos/verify/verify-runtime-bundle-immutability.sh 改为实际存在的 scripts/desktop/verify/verify-runtime-bundle-immutability.sh。旧路径已不存在。

测试

  • 新增 close_tab_shortcut_test.go:
    • TestCloseTabDefaultsToCommandWOnlyOnMacOS
    • TestCloseTabShortcutClosesTheSelectedEditorTab:非 macOS 上先确认未绑定时 Ctrl-W 不关闭,再按设置页的方式绑定后验证。
    • TestCloseTabShortcutClosesTheFocusedTerminal
  • lsp_status_test.go 改写或新增:
    • TestLSPStatusFollowsStateAndLogOpensAsAnEditorTab
    • TestLSPLogTabSplitsOffAndCloses
    • TestLSPLogFollowsTheNewestLineUntilScrolledAway
    • TestLSPLogLineColorFollowsTheEventLevel
  • git_gutter_test.go 跟随 runShortcut 的新签名。

不在本 PR 范围内 / Out of scope


类型专属:fix

复现与根因

  • 复现步骤、实际结果、期望结果:
    1. 在 Viva 桌面端打开项目,打开一个由插件语言服务器负责的文件,等待状态栏显示 LSP 就绪,然后点击状态项。实际结果:弹出模态窗口。期望结果:编辑器区打开“LSP 日志”页签。
    2. 选中文件页签按 ⌘W。实际结果:没有反应。期望结果:关闭该页签。
    3. 选中 Diff、查看器页签打开“文件”菜单。实际结果:没有“关闭标签页”。期望结果:可以关闭。
  • 根因:lspLogPopup(ui.ModalWith)以及 tab.close 只在 selectedDocument != nil 时添加,都来自 Viva 迁移提交 0faecba(Epic(0.7.0): 基于 Viva 框架的跨平台方案的迁移(#1794) #1799,git log -S lspLogPopup / git log -S '"tab.close"');迁移时快捷键目录没有登记 Close Tab。
  • 影响平台:Viva 桌面端 macOS 与 Windows 共用这段代码。macOS 两个问题都有;Windows 有弹窗问题和非文件页签无法关闭的问题。按需求 Windows 不默认绑定快捷键。

检查项

  • 已先写回归测试,确认它在修复前失败、修复后通过。测试路径:desktop/internal/workbench/close_tab_shortcut_test.go、desktop/internal/workbench/lsp_status_test.go。在 preview(cc403726a)上用等价的临时检查测试运行,失败输出:
    zz_prefix_check_test.go:13: Close Tab is not in the shortcut catalog
    zz_prefix_check_test.go:25: the LSP log did not open as an editor tab
    
  • [N/A] 无法自动化时,已写明手动复现与验证步骤:上述行为都有自动化测试覆盖。
  • 已搜索被修改函数、类型、契约字段的全部调用方:runShortcut 只有 root.go 和 git_gutter_test.go 调用。placeDiff 只有 difftab.go 调用,已改名。"tab.close" 只在 commands.go、shortcuts.go 和测试中出现。lspLogPopup、desktop.lsp.logTitle 已无引用。不涉及契约字段、插件、SDK 或脚本。
  • 已检查另一平台是否有同类缺陷:Viva 桌面端两个平台共用同一份代码,本 PR 同时修复两端;Windows 按需求不设默认快捷键。旧 macOS 客户端本来就是页签。
  • 只改了修复所需的代码。顺带修复了拖动查看器页签时的图标(同一处 tabLook),把 placeDiff 合并为 placeEditorMember(日志页签需要复用),并修正过时的脚本路径。发现的既有问题已提交 Issue:[Feature] Viva LSP 日志页签自存 500 行并在 Go 里筛选:改为通过 Core 查询统一 v2 日志,删除平台层缓冲与 filterLogLines #1869、[Feature] Viva 桌面端快捷键目录的默认值、解析与冲突检测改用 Rust Core keymap #1871。
  • [N/A] 修复改变了行为约束或容易复发,已在 .agents/notes/implemented/bug-fix/ 记录:没有新增需要长期记住的取舍。“日志是普通页签”和“⌘W 只在 macOS 默认”由上面的回归测试和功能矩阵 notes 固定。

范围检查 / Scope checks

功能矩阵 / Feature matrix

  • 已更新 shared/platform-feature-matrix/features/lsp-status-logs.json、editor-text-tabs.json 的 notes 和证据路径。两端的实现状态、验证状态没有改,Windows 未实机验证,保持原状态。
  • 已运行 ./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] 没有更新矩阵的理由:已更新。

统一日志系统 / Structured logging

  • 已接入统一日志系统:新的用户操作都走已声明的 app.action.performed 事件,点击状态项记 lsp.log.open(surface button),快捷键关闭终端记 command.tab.close(surface shortcut),没有新事件 ID 或直接输出。
  • 一个操作只有一条终态;没有新增失败路径,也没有高频的 INFO 输出。
  • 没有记录日志内容、源码或路径,只记录操作 ID 和来源。
  • 已运行 node scripts/logging/generate-log-events.mjs --check 和 node scripts/logging/verify-log-usage.mjs:未完成。scripts/logging/ 下的门禁脚本已被移除,无法运行;按 develop-lithe 的 logging 参考页,恢复前这一项标为未完成,恢复工作由 [Feature] 恢复 Viva 日志事件类型生成和目录使用门禁 #1802 跟踪。

界面文案 / i18n

  • 文案都走共享 i18n:没有新增文案,只复用 logs.language.tabTitle、native.clearLogView(平台范围加上 desktop),删除 desktop.lsp.logTitle,并用 node scripts/i18n/generate-i18n.mjs 重新生成;没有手改生成文件。
  • 已运行 node scripts/i18n/verify-app-language-localization.mjs 和 node scripts/i18n/generate-i18n.mjs --check,都通过;没有放宽脚本或扩大豁免名单。

逻辑归属 / Logic placement

性能与内存 / Performance and memory

  • 日志页签打开时才渲染,没有新增空闲轮询。日志缓冲仍是每个服务器 500 行,自动跟随只比较一个计数。关闭页签只释放视图状态,日志行保留在服务器对象中,服务器结束时一起释放,这与原弹窗相同。
  • 主线程上没有新增文件读写、目录遍历或进程启动。
  • [N/A] 性能基线:没有改动 Viva 编辑器模块(desktop/internal/editor/**、editorview/**),也没有新增依赖。

设置 / Settings

N/A:没有新增或修改设置项。快捷键设置页按目录自动列出新动作“关闭标签页”,页面代码没有改。

插件契约 / Plugin contract

N/A:不涉及插件契约、能力版本、插件函数协议或宿主方法。

发行包与资源 / Bundle and resources

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

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


验证 / Verification

命令或操作 平台 结果
gofmt -l(改动的 Go 文件) macOS arm64 无输出
scripts/desktop/desktop-go.sh vet ./internal/workbench/ ./internal/shortcuts/ ./internal/settingswindow/ macOS arm64 通过
scripts/desktop/desktop-go.sh test ./internal/workbench/ ./internal/settingswindow/(合入最新 preview cc40372 之后重跑) macOS arm64 全部通过
回归测试在 preview 上先失败(输出见上方“检查项”) macOS arm64 修复前失败,修复后通过
.agents/skills/write-stable-tests/scripts/test-stability-macos.sh --package ./internal/workbench --filter '<本 PR 新增和改写的测试>'(静态检查加计时运行) macOS arm64 通过,共 16 个测试,最长 330ms
./scripts/platform-feature-matrix/verify-platform-feature-matrix.sh macOS arm64 通过
./scripts/platform-feature-matrix/verify-platform-feature-matrix-change.sh origin/preview HEAD macOS arm64 通过
node scripts/i18n/verify-app-language-localization.mjs macOS arm64 通过
node scripts/i18n/generate-i18n.mjs --check macOS arm64 通过
./scripts/desktop/verify/verify-runtime-bundle-immutability.sh macOS arm64 通过
./scripts/agent-notes/verify-agent-notes.sh(改了一份 proposed Note 中的路径) macOS arm64 通过

未能执行的检查和原因:

  • Windows 构建与实机验证:当前只有 macOS 机器。Windows 上的行为(没有默认快捷键、可在设置页绑定)只由 runtime.GOOS 分支和测试中的非 darwin 分支覆盖,没有在 Windows 上运行。
  • 统一日志门禁(scripts/logging/*):脚本已被移除,见 [Feature] 恢复 Viva 日志事件类型生成和目录使用门禁 #1802。
  • 整机 GUI 验收、截图(明暗主题、中英文):没有启动打包后的应用,只运行了工作台的组件和交互测试(测试驱动的点击、快捷键、拖放)。

提交前确认 / Final checks

  • 分支从最新的 preview 创建,并已合入当前的 origin/preview(cc403726a);目标分支为 preview。
  • 以 Draft 提交,本地验证通过后才标记 ready。
  • 没有无关改动,没有提交 .build/、target/、dist/、.artifacts/ 等产物,没有凭据、个人路径和未脱敏的日志或截图。
  • 本次没有启动 Lithe 应用;测试进程都已结束,没有进程残留。

- 状态栏“LSP 日志”不再弹出模态窗口,改为在编辑组中打开唯一的“LSP 日志”页签,可切换、拖动、分屏和关闭;会话不保存该页签
- 页签一次显示一个服务器(下拉选择):停在末尾时自动跟随新日志,按级别着色,文本筛选,无匹配时有提示,按服务器清空视图,停止/重启按钮
- 选中日志页签时,状态栏显示该页签所示服务器的状态
- 文件菜单与 Find Action 的“关闭标签页”(tab.close) 改为关闭编辑组当前选中的任意页签(文件、Diff、查看器、LSP 日志)
- 快捷键目录新增 tab.close:macOS 默认 ⌘W,其他平台不设默认,可在快捷键页自行绑定;焦点在终端时关闭该终端页签,运行中进程沿用确认
- 抽出 placeEditorMember 去掉 Diff/查看器/日志页签的重复放置代码;修正十六进制查看器拖动时的页签图标
- 更新 lsp-status-logs、editor-text-tabs 功能矩阵条目
- 既有债:LSP 日志页签平台层缓冲与筛选迁入 Core 见 #1869
PR 模板、develop-lithe Skill 和插件设置内容提案 Note 仍引用已移除的 scripts/macos/verify/verify-runtime-bundle-immutability.sh,改为现存的 scripts/desktop/verify/verify-runtime-bundle-immutability.sh。
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