# ETAF ETAF 是构建在独立 [Ebox](../ebox) 布局与渲染引擎之上的小型文本应用框架。 完整的公共模型是: ```text Component(props, Scope) → View → Renderer → Ebox Node → Emacs buffer ``` 所有可见结构都使用一种形式: ```elisp (name :property value ... child ...) ``` 子节点中唯一的计算桥接是 `expr :value`;属性值则是普通 Elisp 表达式。 ```elisp (etaf-view (column (text :font-weight 'bold "Hello") (text :color "#687386" (expr :value (if ready "Ready" "Waiting"))))) ``` 定义 Component: ```elisp (etaf-define-component status-label (&key label) "Render a status label." :view (text :font-weight 'bold (expr :value label))) (etaf-mount "*etaf-demo*" (etaf-view (status-label :label "Connected"))) ``` `etaf-view` 是唯一的公共 View 构造入口。结构 form 不使用 quote;quote 仍然是普通 Elisp 数据语法,例如 `'bold`。普通 Elisp 返回 View 时,必须在 `expr` 中显式使用 `(etaf-view ...)` 构造它。 ## 性能记录面板 ETAF 提供一个独立、按需加载、与具体应用无关的性能记录器。它消费 Runtime 公共 observer 报告,不使用 advice 或私有跨包探针。Event、Action、mount、flush 和 unmount 等 Runtime operation 会自动记录;同一 operation 内的 Ebox、TP、Data、 Resource 和 SQLite 等 provider 阶段按 sequence 关联到同一条记录。 ```elisp (require 'etaf-performance) ;; 在已挂载 ETAF Runtime 的 buffer 中: (etaf-performance-mode 1) ;; 正常操作任意已挂载的 ETAF 应用。 (etaf-performance-show) ``` 交互采集时先执行 `M-x etaf-performance-clear`,复现一组操作后,在面板按 `c`(或执行 `M-x etaf-performance-copy-report`)即可把完整报告复制到剪贴板; 按 `w`(或执行 `M-x etaf-performance-export`)可保存为 `.eld` 文件。报告包含 Emacs/显示环境、电源来源、低功耗模式、native JIT 状态、系统负载、分组 p50/p95/max、每次 operation、GC 增量和有序 provider 阶段;面板 header 也显示 同一环境信息,避免把整机降频误判成某个包的热点。 `*ETAF Performance*` 面板会显示 operation ID、generation 变化、总耗时、GC 增量,以及 flat provider 阶段的顺序和各自耗时。provider 阶段可能重叠,因此 不会伪装成 exclusive/self 时间。记录数量由 `etaf-performance-max-records` 限制;关闭 mode 只会解除当前 Runtime 的 observer,不修改任何函数。 `etaf-performance-summary` 会按需计算 operation 的 p50/p95/max, `etaf-performance-operation-stage-summary` 则按 provider category 汇总单次 operation 的 flat 阶段。`etaf-performance-records` 返回 operation/stage 的防御性 快照,调用方修改返回值不会改写已保留的历史。 没有内置公共边界的任意操作,可以使用 `etaf-performance-call-operation` 或 `etaf-performance-with-operation` 包裹;它们直接委托同一个 Runtime operation 边界,不建立第二套计时器。 ## 可执行示例 [`examples/`](examples/README.zh-CN.md) 目录包含三个只依赖 core 的最佳实践应用:保留式状态与 Action、Data Controller 所有权,以及 Resource 错误/清理 lifecycle。`make check` 会编译它们,并通过已挂载的公开事件路径驱动交互。 ```elisp (add-to-list 'load-path "/path/to/github/etaf/examples") (require 'etaf-counter-example) (etaf-counter-example-open) ``` ## 文档 - [English Architecture](docs/architecture.en.md) · [中文架构](docs/architecture.zh.md) - [English User Guide](docs/user-guide.en.md) · [中文用户指南](docs/user-guide.zh.md) - [English Implementation Plan](docs/implementation-plan.en.md) · [中文实施计划](docs/implementation-plan.zh.md) - [Module-boundary proposal (unimplemented)](docs/proposals/module-boundaries.en.md) · [模块边界提案(未实现)](docs/proposals/module-boundaries.zh.md) - [English Best-practice Examples](examples/README.md) · [中文示例](examples/README.zh-CN.md) ## 独立包 | 包 | 职责 | | --- | --- | | [`etaf-ui`](../etaf-ui/README.md) | 官方 Component 目录:Button、Checkbox、Label、Panel 和 DataGrid。 | | [`etaf-sqlite`](../etaf-sqlite/README.md) | 具体 SQLite Data Source;Data Controller 仍属于 ETAF core。 | | [`etaf-playground`](../etaf-playground/README.md) | ETAF 示例;只有请求官方目录示例时才加载 UI 包。 | | [`ebox-playground`](../ebox-playground/README.md) | 只使用 Ebox 的布局示例,与 ETAF 独立。 | 没有单独需要安装的 `etaf-data`:Data 是 ETAF 核心能力。也没有笼统的 `etaf-adapters` 包:其他数据库、服务、文件或 ORM 应使用明确名称的具体 Data Source 包实现同一契约。 ## 加载与验证 ECSS 0.1.0 与 TP 1.0.1 是互相独立的包,安装顺序任意;两者都安装后再安装 Ebox 2.0.1,最后安装 ETAF 0.1.1。ETAF 会直接声明 TP 依赖,因为 Host final-accept authority 使用 TP transaction contract;渲染仍只使用 Ebox 2.0 的公共契约。 ETAF 默认选择 Ebox framework SPI v2 port。若要立即按进程完整回退旧 render/Host port,必须在加载 ETAF 前把 `etaf-render-port-selection-policy` 设为 `v1`。该选择在当前 Emacs 进程中不可 变;切换时需要重启 Emacs。这个回退不会创建第二个 generation owner:semantic CAS、单向投影的兼容 stores、retirement 和 scheduler authority 仍保持统一,因此 两个 render port 的 generation、token 与 store-version outcome 完全一致。 开发时先把同级 Ebox 检出目录加入 `load-path`: ```elisp (add-to-list 'load-path "/path/to/github/ebox") (add-to-list 'load-path "/path/to/github/etaf") (require 'etaf) ``` 运行完整本地门禁: ```sh make check EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs ``` 核心门禁会编译实现、运行 core/Data/Resource 测试,并检查文档和 API 边界。还应在同级 `etaf-ui`、`etaf-sqlite`、`etaf-playground` 和 `ebox-playground` 仓库分别运行 `make check`;它们都不会被 core facade 自动加载。