Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
634ed52
feat(linux): 接入 GPUI Kit 实现 Linux 前端与构建流水线
Sep 23, 2026
0bb39ab
feat(linux): 对齐 Tauri/IntelliJ 架构设计与暗色主题 Tab 交互
Sep 23, 2026
65a7ec1
feat(linux): 对齐 macOS UI/UX 体验并将组件翻译为 gpui-kit 原生实现
Sep 23, 2026
c847970
Merge remote-tracking branch 'origin/preview' into linux_front
Sep 24, 2026
8c334ec
feat(linux): 修复编辑器滚动与选中,补齐侧边栏/搜索/设置界面
Sep 24, 2026
93d8a11
feat(linux): 复刻 Tauri 主工作台 UI 框架并接入 XDG 设置持久化
Sep 24, 2026
df39ffa
fix(linux): 浮层卡片点击不再误触发遮罩关闭
Sep 24, 2026
aeb1da3
fix(linux): 紧凑菜单改为横向浮出菜单条,对齐 Tauri
Sep 24, 2026
1d50d05
fix(linux): 删除 Tauri 不存在的顶栏元素
Sep 24, 2026
a191e5f
fix(linux): 左栏去掉 maven、终端跟随主题、项目徽标换真实图标
Sep 24, 2026
b218703
fix(linux): 空编辑器对齐 Tauri EmptyEditorState
Sep 24, 2026
38523f4
fix(linux): 设置分类标题与 Tauri 中文文案逐字对齐
Sep 24, 2026
44688b2
feat(linux): 设置弹窗内容与图标完全对齐 Tauri
Sep 24, 2026
4310252
feat(linux): 菜单栏接入语言功能,菜单项与 Tauri 完全对齐
Sep 24, 2026
e4a131a
feat(linux): Explorer 头部对齐 Tauri(搜索+偏好设置,去掉新建/刷新)
Sep 24, 2026
22bb163
feat(linux): 底部默认隐藏、活动栏对齐 Tauri,删自创 Output/Problems
Sep 24, 2026
3f20c7c
feat(linux): 接入右侧 Maven 导航工具窗口与目标执行
Sep 24, 2026
5d324f7
feat(linux): 全量文案跟随语言,底部/左侧/弹窗/设置对齐 Tauri
Sep 24, 2026
183d422
feat(linux): 新建/打开/克隆仓库功能接入,对齐 Tauri
Sep 24, 2026
6a5fb61
chore(linux): 更新 Cargo.lock(rfd 0.16 依赖)
Sep 24, 2026
cb8ccbe
feat(linux): 最近项目记录展示与分支徽标点击切换,对齐 Tauri
Sep 24, 2026
28efe37
chore(linux): 同步 welcome_screen 重导出(RecentProject 已删)
Sep 24, 2026
a42fef0
feat(linux): 左上功能菜单动作全量接线,对齐 Tauri window-menu-bar
Sep 24, 2026
dc6d2db
feat(linux): 设置弹窗全部分类功能接线,对齐 Tauri/Mac
Sep 24, 2026
00860d3
fix(linux): 隐藏路径输入框改为多行高度(目录 120px/文件 96px)
Sep 24, 2026
6ec22b8
feat(linux): 右侧工具窗口与底部 Run/GitLog 面板,对齐 Tauri
Sep 24, 2026
4d63107
feat(linux): 标题栏搜索对齐 Tauri QuickOpen 分组与计数
Sep 24, 2026
ff24bf3
feat(linux): 复用 Windows lithe 图标集的文件夹与文件彩色图标
Sep 24, 2026
9392c98
feat(linux): 图标切 Windows 默认 idea 套装并启用 tree-sitter 高亮
Sep 24, 2026
58662f3
chore(core): tree-sitter 0.25 升 0.26,与 gpui-kit 高亮特性对齐
Sep 24, 2026
2bcdaf3
feat(linux): Run 面板真实执行链与 Maven/LSP 接线,对齐 Tauri
Sep 24, 2026
97ad639
fix(linux): 右侧工具窗可左右拖动缩放
Sep 24, 2026
18c88ac
feat(linux): 编辑器标签页右键菜单,对齐 Tauri TabContextMenu
Sep 24, 2026
d0e0eb9
fix(linux): 去掉 tab_menu 未使用的 px 导入
Sep 24, 2026
37868f1
fix(linux): 底部终端收进编辑区列宽,对齐 Tauri editor 模式
Sep 24, 2026
abe7491
fix(linux): 运行窗口行为对齐 Tauri
Sep 24, 2026
b1dee2a
feat(linux): 固定标签页与编辑器分屏,对齐 Tauri
Sep 24, 2026
ed49c7b
fix(linux): 插件页对齐 Tauri 扩展侧栏语义
Sep 24, 2026
95cbf60
fix(linux): 点扩展时右侧默认展开到 560
Sep 24, 2026
4910f11
fix(linux): 通知点击与文案对齐 Tauri
Sep 24, 2026
03df5d4
fix(linux): 通知筛选改漏斗下拉,对齐 Tauri 版式
Sep 24, 2026
2a494e5
fix(linux): Maven 展开面板对齐 Tauri 树语义
Sep 24, 2026
f801157
fix(linux): Maven 设置按钮打开项目 JDK 与 Maven 页
Sep 24, 2026
1f5d368
fix(linux): 标签关闭按钮对齐 Tauri 显示规则
Sep 24, 2026
eff87ee
fix(linux): 底部窗格改各窗格按钮头,对齐 Tauri
Sep 24, 2026
2f8e47a
fix(linux): 终端显示与输入对齐可用状态
Sep 24, 2026
28ca208
feat(linux): 终端改 IDEA 式字符直输(vte 真解析)
Sep 24, 2026
64a90ad
feat(linux): 终端换 alacritty_terminal 网格
Sep 25, 2026
f835656
fix(linux): 终端光标整行只画一次
Sep 25, 2026
6bf80b2
feat(linux): 运行输出跟随末尾与自动换行对齐 Tauri
Sep 25, 2026
164aa2e
fix(windows): normalize persisted display language
Sep 25, 2026
1af5796
Revert "fix(windows): normalize persisted display language"
Sep 25, 2026
d30b862
fix(linux): normalize display language setting
Sep 25, 2026
4197276
feat(linux): replicate diagnostics panel behavior
Sep 25, 2026
526dd81
feat(linux): 接入语言服务器并输出诊断面板数据
Sep 25, 2026
0c96cfc
feat(linux): LSP 集成与 Run 配置重构
Sep 25, 2026
c9f766e
feat(linux): 接入菜单派生的全局快捷键与双击 Shift 搜索
Sep 25, 2026
72e2ef4
feat(linux): 接入 JDT LS 的 Java 项目准备与 Run 直启
Sep 25, 2026
b566790
feat(linux): 终端改为复用 alacritty_terminal 引擎并补齐交互
Sep 25, 2026
4c54eca
feat(linux): 去掉设置里的配色主题行
Sep 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,24 @@ classpath/module-path;随后 Run 模块只启动一次项目 JDK。Maven 仍
4. Rust Core 接收结构化 `javaLaunch`,生成 `project-jdk` 直启计划;
5. macOS/Windows 宿主按各自路径分隔符拼接参数并启动一个 JVM。

Linux 第二阶段已经接入同一 Java 项目准备能力:`linux/src/lsp.rs` 只解析
JDT LS 直启资源、Core workspace fingerprint 和请求形状;Workbench 持有唯一的
`java` Core session,并把 `ServiceReady` 与 `projectPreparation.blocksRun` 快照
交给 Run。Linux 路径优先使用 `LITHE_JDTLS_ROOT` / `LITHE_JDK_ROOT`,默认从
工作区 `.artifacts/jdtls-linux` 与 `.artifacts/jdk-linux` 解析;正式资源目录
存在但不完整时直接报可操作错误,外部 `jdtls` wrapper 只作为兼容回退。

`bottom_panel.rs` 对 Maven-backed `java.main` 和带 Java 入口的 Spring Boot 配置
先等待对应 session ready,再按 Core `javaEntrypoints` →
`vscode.java.buildWorkspace` → `vscode.java.resolveClasspath` 顺序准备目标,
最后把 JDT 返回的 `{mainClass, projectName, classPaths, modulePaths}` 作为
`javaLaunch` 传给 `runConfig.createLaunchPlan`。Linux 不扫描源码决定入口,也
不在 UI 拼接 classpath;构建失败保留 Core 的 build diagnostics,阻止主进程,
并通过再次 Run 重试。没有 JDT 元数据时,framework Maven goal 与独立 Java
`javac -> java` 仍沿用第一阶段 Core 计划,Maven-backed `java.main` 明确显示等待
或准备失败。Linux 仍不读取旧 `name/type/mainClass` 文档作为主路径,不用源码
正则补入口,也不在计划失败后伪造 `mvn compile`。

Run 和 Debug 共用同一套 Java 项目准备逻辑。配置中的 Maven 信息仍用于 JDT LS
导入、Profile、settings.xml 和项目模型;Maven 工具窗口、框架 goal、测试与显式
Maven 任务仍走 Maven 启动计划。
Expand Down Expand Up @@ -176,6 +194,9 @@ Run 控件,也不在 `java-run-launch` 或平台 adapter 再做一次 `blocksR
- 点击运行可能需要等待 Java 语言服务 ready;构建失败会保留真实诊断,并在目标路径
仍可解析时暂停等待用户决定,而不是永久阻止启动。
- 独立 Java 文件仍遵循“`javac` 编译再运行”的既有方案,不依赖语言服务。
- Linux Run 只把 Core 计划解析成 Linux 进程;Core 或配置失败会保留真实错误,
不再退化为只执行 `compile`。Maven 项目里的 Java 入口在 JDT 准备完成前不会
启动,Linux 也不会维护第二套源码扫描结果。
- 打开大型 Maven 项目后立即点击运行,可能要先等 JDT 的项目更新结束;等待原因
会写入日志(`Java project build is waiting`),不会再因 30 秒期限而半路失败。
Windows 运行面板在准备期间先显示一行“正在等待 Java 语言服务更新并构建项目”,
Expand All @@ -202,6 +223,12 @@ Run 控件,也不在 `java-run-launch` 或平台 adapter 再做一次 `blocksR
终态测试覆盖同一次启动继续、按工作区记忆选择和索引恢复。
- Windows:Run Store 把准备结果传入 Core,并分别用 `;` 拼 classpath/module-path;
Run/Debug 共用的 Store 测试覆盖同一次启动继续、取消、记忆选择和索引恢复。
- Linux:`cargo test --manifest-path linux/Cargo.toml --lib --bins` 覆盖 Core
process/Spring Boot 计划、`javac -> java`、POSIX classpath、工具链映射、
JDT 资源排序与 payload、入口/classpath/build 结果解析、Core Java provider 门禁、
过期 session/sequence、pre-launch 失败门禁与完整进程组停止;测试不依赖本机
Maven/JDK/网络。资源解析测试只创建临时目录和 fixture
JSON。
- 共享契约:`shared/contracts/rust-core-api.md` 与
`shared/contracts/application-boundary.md`,跨平台样例为
`shared/fixtures/lsp/java-build-report-v1.json`。
Expand All @@ -213,5 +240,7 @@ Run 控件,也不在 `java-run-launch` 或平台 adapter 再做一次 `blocksR
`rust/lithe-core/src/lsp/interface/engine.rs`
- macOS:`LanguageToolingSessionManager`、`AppModel+RunConfiguration`、`RunService`
- Windows:`java-run-launch.ts`、`lsp-core-adapter.ts`、`run.store.ts`
- Linux:`linux/src/lsp.rs`、`linux/src/workbench/view.rs`、
`linux/src/workbench/bottom_panel.rs`、`linux/src/workbench/run/`
- 相关笔记:
`.agents/notes/implemented/feature/2026-09-17-standalone-java-compile-then-run.md`
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Agent 笔记:Linux GPUI 终端的引擎复用边界

状态:已实现

## 先说结论

Linux 原生 GPUI 版终端不自己实现终端语义,只复用成熟上游 `alacritty_terminal`
作为“终端引擎”(负责解析 ANSI 转义序列、维护字符网格、回滚、选择、搜索),
再由本仓库把它投影成 GPUI 元素。原因是 GPUI 生态不存在可复用的成熟终端
控件,唯一成熟且可合法分发的上游是引擎层。开发者要记住:**终端行为(滚动、
选择、搜索、随窗缩放、reflow)只能调用 `alacritty_terminal` 的既有 API,
禁止在 `terminal.rs` 里手写第二套终端语义。**

## 问题

Linux 版工作台使用 GPUI Kit 构建,底部面板需要一个嵌入式终端。
Windows 版同类能力由前端 xterm.js 承担,xterm.js 是完整的成熟终端控件
(自带网格渲染、滚动、选择、搜索)。GPUI 没有 DOM,无法复用 xterm.js。

早期实现虽然在依赖里引了 `alacritty_terminal`,但只把它当解析器使用:
渲染固定 120×30、不随窗缩放,且完全没接上游已经提供的回滚滚动、
文本选择、复制、搜索 API。结果是终端“能跑但不好用”,并被迫在文件头
声明“多标签、搜索、复制粘贴、随窗缩放暂不支持”。

## 决策

### 复用边界

- `alacritty_terminal` 0.26 是 Linux 终端的唯一引擎。解析、网格状态、
回滚缓冲、选择模型、正则搜索、resize/reflow 全部由它提供。
- `linux/src/workbench/terminal.rs` 只做三件事:
1. 用 `portable-pty` 起 PTY 会话并转发字节;
2. 调用上游 API(`Term::resize`、`Term::scroll_display`、
`Selection`、`RegexSearch`、`Term::renderable_content`);
3. 把网格投影成 GPUI 元素并处理鼠标/键盘事件。
- 渲染层实现成“固定字符单元格”排版:单元格宽度由上游
`WindowTextSystem::em_layout_width` 按当前字号实测,行高按字号倍率换算。
鼠标坐标换算、PTY 行列数、网格 `cols/rows` 三者必须使用同一套
`CellMetrics`,否则选择与点击会出现半格偏移。

### 正确做法

- 需要滚动时调用 `term.scroll_display(Scroll::Delta / Bottom)`,不要
自己维护偏移量。
- 需要复制时调用 `term.selection_to_string()`,不要自己遍历网格拼字符串。
- 需要搜索时用 `term::search::RegexSearch` + `Term::search_next`,不要
自己写匹配循环。
- 容器尺寸变化时用 `Term::resize(TermDims)` 并把 `cols/rows` 同步给 PTY;
reflow 由上游完成。
- 鼠标命中用 `viewport_to_grid_point(局部坐标, CellMetrics, TermDims, display_offset)`
换算,回滚偏移必须叠加,保证上滚后仍命中用户看到的同一行。

### 不要这样做

- 不要在 `terminal.rs` 里手写 ANSI 解析、换行、光标移动或滚动缓冲。
- 不要固定网格行列数;固定尺寸会让全屏 TUI(如 vim、top)拿不到正确
窗口大小,也无法随窗缩放。
- 不要用渲染文本的视觉长度代替单元格数换算鼠标列号;宽字符和样式分段
会让两者不一致。
- 不要为了“加个功能”把终端语义下沉到 `bottom_panel.rs` 或 `view.rs`;
宿主只负责切换标签、转发命令和生命周期。

## 考虑过的备选方案

### 备选方案一:引入 GPUI 生态的终端控件

如果存在成熟的 GPUI 终端控件,可以像 xterm.js 一样整体复用,工作量最小。
但实际盘点后不存在:本地 Cargo registry 与可访问上游都没有
`gpui-term`、`gpui_term`、`terminal-gpui` 这类 crate;Alacritty 自身的
渲染在 `alacritty` 二进制 crate 中,基于 OpenGL/winit,与 GPUI 的
`Element`/`Render` 体系不兼容,无法直接嵌入。

### 备选方案二:复用 `viml` / `wezterm-term` / `termwiz` 引擎

这些是其他终端模拟器的引擎,成熟度也够。但它们与 `alacritty_terminal`
能力重叠,且现有实现已经在用 `alacritty_terminal`。为同一目标引入第二个
引擎会增加依赖体积和双份语义,收益为零,因此不采用。

### 备选方案三:继续维护现有固定尺寸实现

改动最小,但无法满足“和 Windows/Tauri 终端一致”的产品目标:固定
120×30、无回滚、无选择、无搜索、无缩放,属于明确的能力缺口,不是可接受
的长期状态。

## 后果

- 收益:滚动、选择、复制粘贴、搜索、随窗缩放、reflow 全部由上游保证,
本仓库代码量显著下降,缺陷面收敛到“投影与事件接线”。
- 收益:单元格度量、命中换算、PTY 尺寸三处共用同一来源,跨窗口大小与
字体缩放行为一致。
- 代价:渲染仍需自绘(上游无 GPUI 渲染器),固定单元格排版要求等宽
字体,非等宽字体下对齐会退化。
- 代价:多标签、横向分屏、超链接点击、图形协议(Sixel/Kitty)仍未接入,
需后续按需扩展;这些属于产品编排,不属于引擎边界。

## 验证

- `cargo test --manifest-path linux/Cargo.toml -p lithe-linux --lib`
覆盖:`viewport_to_grid_point` 的边界/内边距/回滚偏移换算、256 色与
加粗高亮解算,以及引擎联通性(解析输出入网格、回滚 `display_offset`、
选择导出字符串、`resize` 改变列数)。
- `cargo build --manifest-path linux/Cargo.toml -p lithe-linux` 通过。
- `./.agents/skills/write-stable-tests/scripts/verify-test-stability.sh` 通过。

## 适用范围

- `linux/src/workbench/terminal.rs`:Linux 终端的引擎调用、渲染投影与事件接线。
- `linux/src/i18n.rs`:终端搜索栏等新增文案键。
- 不适用于 Windows 产品;Windows 终端由
`windows/tauri/src/features/terminal/`(xterm.js)与
`windows/tauri/crates/terminal/`(`portable-pty`)承担。
80 changes: 80 additions & 0 deletions .github/workflows/ci-linux.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: Linux CI

on:
pull_request:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read

concurrency:
group: linux-ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build-and-test:
name: Build & Package Linux Frontend
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- name: Check out source
uses: actions/checkout@v7

- name: Install system dependencies for GPUI
run: |
sudo apt-get update
sudo apt-get install -y \
libxkbcommon-dev \
libxkbcommon-x11-dev \
libxcb-xkb-dev \
libfontconfig1-dev \
libfreetype6-dev \
libx11-dev \
libxcb1-dev \
libx11-xcb-dev \
libssl-dev \
pkg-config

- name: Set up Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt

- name: Restore Cargo dependencies
uses: actions/cache@v6
with:
path: |
~/.cargo/git
~/.cargo/registry
target
key: cargo-linux-${{ runner.os }}-${{ hashFiles('linux/Cargo.toml', 'rust/Cargo.lock') }}
restore-keys: |
cargo-linux-${{ runner.os }}-

- name: Check formatting
run: |
cargo fmt --manifest-path linux/Cargo.toml -- --check

- name: Check lithe-linux compilation
run: |
cargo check --manifest-path linux/Cargo.toml

- name: Build lithe-linux binary
run: |
./scripts/build-linux.sh --release

- name: Package Linux application
run: |
./scripts/package-linux.sh --release

- name: Upload Linux artifact
uses: actions/upload-artifact@v4
with:
name: lithe-linux-dist
path: dist/*.tar.gz
if-no-files-found: error
retention-days: 14
10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
.DS_Store
.build/
rust/target/
target/
.swiftpm/
.idea/
.vscode/
DerivedData/
/windows/build*/
dist/
Expand All @@ -15,4 +16,11 @@ docs/visual-qa/
.reasonix/
reasonix.toml
.codex/
.codegraph/
/node_modules/
*.swp
*.swo
*~
*.tar.gz
*.deb
*.AppImage
Loading
Loading