Add canonical query semantics, managed metadata and transactions, overlay-aware lookup, reproducible benchmarks, and synchronized API documentation.
4.9 KiB
完整文本属性 facade:把“替代”定义为语义覆盖,而不是重写 Emacs
背景
仓库最初能够便捷地写入、搜索和组合文本属性,但“可以替代所有文本属性操作”仍缺少可验证边界:直接值与有效值混在一起,显式 nil 难以观察,参数化 managed layer 丢失实参,overlay-aware 字符属性没有统一入口,主题变化和多步写入也没有生命周期证据。
本轮没有复制 Emacs 的 interval、overlay、undo、yank 或 stickiness 引擎。目标改为更严格也更可维护的定义:
tp为高频文本属性工作流提供统一 facade;原生语义由 GNU Emacs 执行并以等价测试锁定;overlay 生命周期等不应被包装的能力明确委托。
决策
1. 一个 lookup record,五种明确模式
新增 tp-lookup-result 和 tp-lookup,而没有继续增加 tp-direct-at、tp-char-at 等平行入口。模式区分:
:text-direct:只看直接 text plist;:text-effective:等价于get-text-property;:text-source:报告 direct/category/alias/default/absent;:char:等价于 overlay-awareget-char-property;:char-source:同时报告来源和获胜 overlay。
record 的 present-p 是必要字段,因为 nil 既可能是合法直接值,也可能表示缺失。overlay 只在 overlay 真正提供获胜值时设置。
2. 原生编辑语义优先委托
property change、any/not-all 只做签名统一,直接调用对应 Emacs primitive。copy、substring、insert、insert-and-inherit、kill/yank、stickiness、narrowing 和 indirect buffer 不增加包装层;测试证明 facade 不会破坏这些行为,文档给出委托边界。
with-silent-modifications 原生会绑定 inhibit-read-only。因此 :silent + :respect 无法诚实实现:伪装支持会让策略名与实际行为冲突。本轮只支持 ordinary/respect、ordinary/inhibit、silent/inhibit,并对矛盾组合立即报错。
3. managed metadata 属于存储,不属于渲染属性
managed entry 使用单一保留键 tp-meta 保存 schema、entry id、原始 spec、实参、arglist、定义版本和 entry 版本。没有把这些字段拆成大量普通 text-property key,避免污染用户属性命名空间。
tp-meta 必须保留在 authoritative stack storage 中,但必须从直接渲染属性和公开 stack query 中剥离。冲突比较也只比较渲染投影,否则 metadata 自身会制造假冲突。
参数化 layer 重定义现在可用保存的 args 重新求值。旧 entry 若没有 args,不猜测、不静默套用错误参数;诊断将其标为 legacy limitation。
完整存储模式下的直接属性明确对应第一个可见 entry。definition/reactive refresh 具备 old/new 所有权上下文,因此会先把原生直接编辑协调进该 entry,再刷新定义,以保留外部值;普通 stack decode 没有这层上下文,仍对缓存不一致发出 tp-layer-conflict。所有层都隐藏时出现直接属性同样属于冲突。
4. attach、diagnostics、transaction 是显式生命周期
插入已经带属性的字符串不会经过普通 buffer 写入注册路径,因此提供显式 attach 扫描。detach 可以移除 managed identity/storage,并由调用者选择是否保留当前渲染结果。
诊断 API 必须是只读的:不能移动 point、修改 modified state、undo、文本属性或 registry(清除已死亡 buffer 除外)。
多步 managed 写入通过 opt-in transaction 包装。事务保存受影响范围的精确文本与属性状态;buffer 事务使用 live markers 跟踪范围内的插入和删除,任一步失败都恢复快照。默认重新抛出结构化 tp-layer-transaction-error,只有显式 NOERROR 才把失败转换为结构化返回值。
5. 主题检测与刷新分层
palette 模块只负责检测 enable-theme / disable-theme、递增 generation 并发出 hook;managed renderer 负责刷新。v1 允许保守扫描全部 managed ranges,因为错误地漏刷比多刷一次更危险。诊断记录 hook 来源、generation、刷新模式、范围和错误,为后续 dependency-targeted 优化保留证据。
有意排除
- 不提供 overlay 创建、移动、删除、evaporation 或 priority mutation API;
- 不重写 category、alias、default、undo、yank 或 stickiness 引擎;
- 不引入 compositional layer 语义;
- 不改变现有公共 mutator 的历史返回值;
- 不提高 Emacs 28.1 或 Dash 2.19.1 baseline。
验证标准
完成声明必须同时具备:
- direct/effective/source/char lookup 的原生等价测试;
- managed metadata、参数化刷新、attach/detach、只读诊断、事务回滚和主题 lifecycle 测试;
- 全量 ERT、固定 seed 乱序 ERT、doctest 和 warning-as-error 编译;
- 大文本、碎片 interval、深 stack、reactive fan-out 与主题刷新的可复现实测;
- 中英文 README、API semantics、architecture、audit checklist 和 changelog 同步。