ebox/README.zh-CN.md

10 KiB
Raw Permalink Blame History

Ebox

Ebox 是一个独立的 Emacs Text/Box 布局引擎负责文本测量、Box 几何、 row/column/flex/Grid 布局、retained 渲染和增量 buffer 发布。应用还需要 Component、响应式状态、behavior 或生命周期时,使用同级 ETAF 包。

安装

源码仓库为 geekinney/ebox。 当前 3.0.0 更新日志仍标记为未发布;源码 checkout 不代表已经发布的包归档或稳定版本 tag。

依赖 使用条件
Emacs 29.1 或更高版本 所有 Ebox 使用场景。
ECSS 0.1.0 或更高版本 样式计算和选择器语义;即使不使用样式表也需要。
TP 2.0.0 或更高版本 retained 发布、原生属性策略与事务;加载 Ebox 时需要。
EKP 1.0.0 或更高版本 可选,仅使用 :wrap-mode kp 时需要。

ECSS 与 TP 是包声明的必需依赖。EKP 保持可选,普通 wordcharnone 换行不需要它。 使用同级源码 checkout 时,把必需的目录加入 load-path 后加载 Ebox

(add-to-list 'load-path "/path/to/ecss")
(add-to-list 'load-path "/path/to/tp")
(add-to-list 'load-path "/path/to/ebox")
(require 'ebox)

加载 Ebox 不会创建 buffer也不会构建 native 模块。

使用 KnuthPlass 段落排版时,先额外将 EKP 源码目录加入 load-path,或安装它的包, 然后在 Box 上设置 :wrap-mode kp

(add-to-list 'load-path "/path/to/ekp")
(ebox-render
 (ebox-build '(box :width (ch 40) :wrap-mode kp :overflow hidden
                   "A paragraph laid out with KnuthPlass line breaking.")))

Ebox 在使用该换行模式时加载 EKP。EKP 缺失或不兼容时会提示安装或更新;请安装 EKP 或显式选择其他换行模式。Ebox 不会静默改用 word。EKP 自己的可选加速器与 Ebox 的可选 Rust 模块是两回事。

构建并验证可安装归档

在本仓库中运行:

make release-check EMACS=emacs RELEASE_DIR=/tmp/ebox-release-3.0.0

该入口按 release-dependencies.json 获取精确的依赖提交, 构建可重复的 package.el 源码归档,在临时干净配置中安装并验证渲染、更新和选择器。 归档目录与 manifest.json 会保留,其中记录校验和、源码提交及工作区是否有修改; 它不会发布归档或修改你的 Emacs 配置。每次使用新的输出目录,不覆盖已有目录。

需要同时包含并测试可选 KP 排版时,换一个输出目录并加上 RELEASE_OPTIONS=--with-ekp。 归档验证通过后,可以作为本地包归档安装:

(require 'package)
(add-to-list 'package-archives '("ebox-local" . "/tmp/ebox-release-3.0.0/"))
(package-refresh-contents)
(package-install 'ebox)
;; 可选,仅当归档构建时使用了 --with-ekp
;; (package-install 'ekp)

工具输入、清理、离线复用与 native 验证见 维护者指南

第一次渲染

普通用户只需理解七个 author 入口:字符串、textboxrowcolumnflexgrid。子节点直接嵌套,不存在第二套 field-based child 语法。

(require 'ebox)

(ebox-render-to-buffer
 "*Ebox Example*"
 (ebox-build
  '(column :padding ((lh 1) (ch 2))
           :border ((px 1) solid "#8A93A6")
           (text :color "#263244" "Hello Ebox")
           (row :item-gap (ch 1)
                (box "Left")
                (box "Right")))))

普通 author DSL 统一通过 ebox-build。框架集成可以用一个 ebox-source-builder 组合 typed node再把 forest 与同一代 source facts 封装为一个 CanonicalEboxInput;这个 evaluated API 不是第二套 author 语法。

已求值的 Box 构造包含 ebox-child-range 时,通过 :source-builder 显式传入开放的 builder。它必须拥有 Box 及所有直接子节点的 source handle 空 Range 同样需要开放的 builder。builder 只参与构造,不保留在节点中。 组合已有 canonical input 时,使用 ebox-canonical-input-rootsebox-canonical-input-import-roots,框架不应读取私有字段或绑定私有动态上下文。

如何选择布局

  • box 创建普通视觉盒子;
  • rowcolumn 用于简单的一维组合;
  • flex 用于空间分配和换行;
  • grid 用于二维轨道与放置;
  • 裸字符串是 (text "...") 的简写。

Flex/Grid participation property 直接属于子 box,不需要额外 wrapper 节点。

Box 几何统一写成 (单位 数值),支持 px%vwvhchlh。 例如 :width (ch 80) 表示 80 个 0 字形的前进宽度, :height (calc (- (vh 100) (lh 1))) 表示视口高度减一个行高。 calcminmaxclamp 在布局时组合长度;auto、裸 fit-content 等 尺寸关键词仍直接写符号。旧的裸长度、单元素像素列表和视口关键词会报错。 构造时按属性方向检查单位,包括尺寸函数的所有分支。允许的组合、关键词默认值、 百分比参照及纵向行粒度限制见统一单位约束表。 空 Box 的自动内容高度为零;需要一行空白时写 (box :height (lh 1))

原生交互

Text 与所有 Box form 都接受四种显式节点能力::help-echo 提供字符串或原生帮助 函数,:pointer 选择原生鼠标指针形状,:hover-style 设置受限的颜色与文本装饰 绘制,:keymap 接收原生 Emacs keymap。Box 的帮助、指针和 keymap 范围包含内容、 padding 和 border不包含该 Box 的 margin 和结构性换行符。悬停在文字与 padding 间共享声明节点的绘制,不包含物理左右边框。嵌套节点的显式值覆盖外层能力; 显式 nil 清除对应能力。

使用 ebox-help-create 将零参数业务函数适配为原生帮助,并提供悬停 buffer 上下文。 使用 ebox-keymap-create 将普通零参数回调绑定到激活键或自定义按键;鼠标命令会 自动在被点击窗口的 buffer 中运行。ebox-region-update 可以使用当前已挂载 buffer 中的语义 ID或显式 region handle替换或清除节点能力。原生 keymap 可用于 独立的 Ebox 交互;可选的 ebox-next-interactionebox-previous-interaction 命令 在渲染后的 keymap owner 之间移动 point不添加默认按键绑定。应用状态与命令行为 由作者管理。参见 交互指南和 Playground 的 交互实验室

渲染与更新

  • ebox-render 返回带属性文本,不发布 live buffer
  • ebox-render-to-buffer 挂载 retained surface
  • ebox-display-buffer 先完成渲染,再按 Emacs 显示规则与可选 action 显示结果,返回 buffer
  • ebox-commit 原子发布重新构建的 canonical input
  • ebox-buffer-update-report 返回最近一次成功更新报告;
  • ebox-rerender-buffer-with-context 应用显式 viewport 变化。
  • ebox-surface-buffer-snapshot 显式导出当前提交的 :input:revision:mount-id,以一个 plist 返回。

Ebox 会在分配 runtime identity 前复制 canonical input因此同一个 built value 可以 挂载到多个 buffer而不会共享 live ownership。

快照只在显式查询时遍历导出数据和 TP 最近的诊断报告,普通更新不会创建快照。其 canonical input 在后续 更新、卸载后仍可使用;节点中的可变数据与交互 keymap 独立复制,不可变 source facts 与不透明能力回调、record保留身份。快照不冻结显示环境或外部能力。TP 事务期间、 卸载后查询会报错。识别提交版本时同时比较 mount ID 与 revision避免重新挂载后 revision 从头计数导致混淆。

Ebox 只通过 TP 2.0.0 的公开 structured participant API 与最终 v2 协议注册可回滚状态。 旧的过渡版本不具备本版本要求的原生属性所有权与 hover identity 保证。structured participant capability 缺失或格式错误时Ebox 会停止加载,不会选择兼容 writer。

可选 native 模块

Rust 模块只加速符合条件的 reflow它不是正确性的依赖并有完全等价的 Elisp fallback。Ebox 加载时不会自动构建它。

(ebox-native-status)
(ebox-native-build)

显示与文本边界

每个已挂载 buffer 只有一套视口布局。同一个 buffer 同时出现在不同宽度的两个窗口中, 不会产生两套独立布局。需要各自宽度时,分别挂载到不同 buffer同一份 canonical input 可以挂载多次。

纵向几何按完整行生成。文本处理保留常见组合音标、变体选择符、Emoji 修饰符、ZWJ 与 旗帜序列,但不实现完整 Unicode 字素分段,也不承诺浏览器级字体排版和双向布局。 可用字体、原生指针和帮助显示由 Emacs 与窗口系统决定;终端输出无法复现全部 GUI 像素或指针效果。

:overflow hidden 将内容限制在盒子测量后的宽度与完整行高度内,保留自身 padding 和 边框。横向裁剪保留完整的受支持文本簇,用空白补齐剩余像素,不显示半个字形,也不 添加省略号。scroll 仍是纵向滚动。

CI 配置覆盖 Linux 上的 Emacs 29.1、30.2,以及 Linux、macOS、Windows 上使用 Emacs 30.2 的源码包安装和 native 模块加载、执行。这些任务定义验证矩阵,不代表 所有平台的 GUI 渲染都已做视觉实测;请查看待安装提交对应的 workflow 结果。

验证

make load EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
make compile EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
make docs-contract-tests EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
make interaction-tests EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
make c1b-contract-tests EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
make check EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
make native-rust-tests

继续阅读用户指南公共 API 参考,以及同级 ebox-playground 示例。

许可证

Ebox 自有代码按 GPL-3.0-or-later 分发,详见 LICENSE。第三方文件保留各自的 许可证声明。