tp/docs/ARCHITECTURE.md
Kinneyzhang 07b84b0685 feat(tp): add scoped retained surface updates
Allow callers to authorize one atomic surface update through generic retained object handles while TP remains the sole owner of mount resolution, buffer publication, and rollback.

Verified: byte compilation with warnings as errors; 726 ERT tests; 92 doctests; targeted scoped-update tests; checkdoc; git diff --check.
2026-08-06 06:32:58 +08:00

57 KiB
Raw Blame History

tp 代码架构文档

未来主版本目标TP 将重构为独立 retained/reactive text runtime并可作为 Ebox 等高级 consumer 的通用底层执行器。TP 自身完整、可独立阅读的已批准目标见 TP Retained/Reactive Text Runtime 目标架构English);它不依赖 sibling Ebox checkout。本文描述当前已经落地的实现并明确标出仍处于迁移期的旧 runtime 与 TP 1.0 功能切片。

本文档描述 tp 库的模块分层结构与函数调用层次从底层基础模块到上层功能模块的分层组织。TP 1.0 的纯 style/cascade kernel、exact signal/binding graph 与 retained surface publication 已分别在 tp-style.eltp-reactive.eltp-surface.el 落地;旧 managed façade 尚未切换。

当前 API 的规范契约见 API-SEMANTICS.mdEmacs 原生 文本属性覆盖范围、已确认问题与演进路线见 REPOSITORY-AUDIT.md

自 0.2.0 起,原来的单文件 tp.el 已拆分为分层模块,tp.el 只作为总入口((require 'tp) 依次加载全部模块用户接口不变。0.3.0 进一步收紧了模块边界:tp-text 处理链下沉至 tp-ops、批量更新上收至 tp-render、层栈存储编解码与匿名层机制归位 tp-layer钩子变量从四个减少到两个。Stage 3 新增 tp-query承载原生文本查询/change 封装与修改策略。各变更的缘由见 CHANGELOG.md

目录


架构概述

tp 采用严格的线性分层:每个模块只允许 require 并调用排在它前面的模块,字节编译器强制检查这一依赖顺序。加载顺序即依赖顺序:

tp-core → tp-style → tp-reactive → tp-layer → tp-ops → tp-search
        → tp-render → tp-stack → tp-query → tp-palette → tp-builtins

注意加载顺序是依赖顺序的上界:并非每个模块都依赖它前面的全部模块。各模块实际 require 的 tp- 模块如下(逐一核对自源码头部):

模块 require 的 tp- 模块
tp-core —(仅 cl-lib、dash、seq
tp-style tp-core
tp-reactive tp-core
tp-layer tp-core、tp-style、tp-reactive
tp-ops tp-core、tp-reactive、tp-layer
tp-search tp-core、tp-reactive、tp-layer、tp-ops
tp-render tp-core、tp-reactive、tp-layer、tp-ops、tp-search
tp-stack tp-core、tp-reactive、tp-layer不依赖 tp-ops / tp-search / tp-render
tp-query tp-core
tp-palette —(不依赖任何 tp- 模块,仅 subr-x
tp-builtins tp-core、tp-layer、tp-ops、tp-palette
┌────────────────────────────────────────────────────────────────┐
│  tp.el —— 总入口,按序 require 全部模块                          │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│  tp-builtins.el   内置层tp-link, tp-space, tp-headline …)、   │
│                   tp-palette-show、显示缓冲辅助宏                │
├────────────────────────────────────────────────────────────────┤
│  tp-palette.el    明/暗主题调色板数据、tp-parse-color            │
│                   (独立叶模块,不依赖任何 tp- 模块)             │
├────────────────────────────────────────────────────────────────┤
│  tp-query.el      原生文本 lookup/change 封装、mutation policy   │
├────────────────────────────────────────────────────────────────┤
│  tp-stack.el      层栈操作push/pop/move/hide/show/merge …)    │
├────────────────────────────────────────────────────────────────┤
│  tp-render.el     响应式重渲染引擎、最小差异 tp-text 编辑、       │
│                   批量更新tp-with-batch-updates + flush──┐   │
├─────────────────────────────────────────────────────────── │ ──┤
│  tp-search.el     tp-match-*/tp-regexp-*、tp-search、导航    │   │
├─────────────────────────────────────────────────────────── │ ──┤
│  tp-ops.el        tp-set/reset/add/get/at/remove/clear、    │   │
│                   tp-text 处理链0.3.0 起在此,直接调用)    │   │
├─────────────────────────────────────────────────────────── │ ──┤
│  tp-layer.el      define-tp/define-tps、层注册表与解析、     │   │
│                   层栈存储编解码、匿名层机制与 GC            │   │
│                   ◁╌╌ tp--layer-refresh-function ╌╌╌╌╌╌╌╌╌╌┤   │
├─────────────────────────────────────────────────────────── │ ──┤
│  tp-reactive.el   响应式依赖注册表、变量监听、批量队列、      │   │
│                   层→缓冲区注册表                           │   │
│                   ◁╌╌ tp--reactive-update-function ╌╌╌╌╌╌╌╌╌┘   │
├────────────────────────────────────────────────────────────────┤
│  tp-style.el      property schema、structured selector、       │
│                   cascade、custom property、computed value      │
├────────────────────────────────────────────────────────────────┤
│  tp-core.el       区间遍历、plist/face 合并引擎、               │
│                   调试日志、$var 符号工具(无可变状态)          │
└────────────────────────────────────────────────────────────────┘

实线层级上层模块调用下层模块require 依赖)。
虚线(◁╌╌):钩子变量 —— 下层模块预留的函数变量,
由 tp-render.el 在加载时安装实现(见下文)。

需要"向上调用"的逻辑全部收拢在 tp-render.el(位于 tp-search.el 之上可以直接调用它。0.2.0 时这类反向调用靠四个钩子变量实现0.3.0 把其中两个消除在了代码层面——tp-text 处理链整体下沉进 tp-opstp-set 等直接调用,不再需要 tp--tp-text-handler-function;只加载到 tp-ops 的部分加载也能得到可用的 tp-text 文本替换),批量刷新整体上收进 tp-rendertp--flush-batch-updates 直接调用 tp--reactive-flush-entry,不再需要 tp--reactive-flush-function。剩下的两个钩子对应真正源自下层的事件变量监听器触发tp-reactive与层重定义触发tp-layer


模块分层

Canonical records 与 dataflow

Stage 2 canonical façade 是内部模型,不改变公开入口和历史返回值。五个记录承担模块间的规范数据边界:

记录 所有者 用途
tp--native-range tp-core 目标对象的原生 [START, END) 范围;字符串使用 0-based缓冲区使用原生 buffer position
tp--presence tp-core 区分属性缺失、present nil、present non-nil
tp--request tp-ops 公开重载参数解析后的规范请求:对象、范围、操作、属性/值/谓词、修改策略
tp--match tp-search 搜索内部匹配结果,统一字符串与缓冲区路径
tp--result tp-search 搜索内部结果载体;最终按公开 API 的历史契约适配返回

数据流为:公开入口解析成 tp--requesttp-core 提供对象、native range、presence 与 adaptertp-ops/tp-search/tp-stack 只在 I/O 边界按对象类型分支。内部搜索先产生 canonical tp--match / tp--result,再由公开入口保留旧返回结构;tp-intervals / tp-intervals-map 的缓冲区 relative 默认是显式保留的兼容例外。

tp-core.el基础工具

最底层模块,不依赖任何其他 tp 模块提供区间遍历、合并引擎与调试能力。0.3.0 起 tp-core 不再持有任何可变状态(匿名层计数器已迁至 tp-layer仅剩 tp-debug-mode / tp-debug-echo 两个 defcustom 用户选项)。

区间操作

函数 描述 主要调用者
tp-intervals 获取区域内文本属性区间列表(裁剪到 [START, END);可选 ABSOLUTE 参数返回缓冲区原生坐标,默认仍为相对坐标) tp-intervals-map, tp-get
tp-intervals-map 对区间应用函数(同样支持 ABSOLUTE 多个属性/层操作函数
tp--map-intervals 共享的裁剪式区间遍历引擎 tp-intervals-map, tp-ops/tp-stack 的区域操作, tp-reactive 的缓冲区扫描
tp-plist 获取区域中合并后的所有属性 用户 API
tp-empty-p 检查对象是否没有文本属性 用户 API

plist / face 合并引擎

函数 描述 主要调用者
tp--deep-merge-plist 深度合并两个 plist tp-add, tp--prepend-face 等
tp--prepend-face face 家族属性的合并逻辑 tp-add, tp-match-add
tp--merge-face-values 合并两个 face 值 合并引擎内部
tp--merge-duplicate-keys 合并 plist 中的重复键 tp--parse-args
tp--parse-face-list 解析 face 列表 合并引擎内部
tp--get-nested 按路径获取嵌套属性值 tp-get, tp-at

tp-face-properties(常量,'(face font-lock-face mouse-face))定义参与 face 感知合并的属性家族。

$var 符号工具

函数 描述
tp--reactive-symbol-p 检查是否为 $var 响应式符号
tp--reactive-var-symbol $var 符号转变量符号
tp--collect-reactive-symbols 收集表达式中所有 $var 符号
tp--resolve-reactive-symbols $var 解析为当前值(支持覆盖表)
tp--extract-reactive-props 提取引用特定变量的属性

调试工具

变量/函数 描述
tp-debug-mode 启用/禁用调试模式
tp-debug-echo 是否在 minibuffer 显示调试信息
tp-debug-log 记录调试信息
tp-debug-show 显示 tp-debug 缓冲区
tp-debug-clear 清除调试日志

另有辅助宏 tp-with-current-buffer


tp-style.el纯 schema 与 cascade kernel

只依赖 tp-core不接触 buffer、marker、mount 或订阅。它拥有 namespaced property schema、structured subject/selector、origin/importance/layer/specificity/scope/source-order cascade、逐属性继承、tagged CSS-wide values、custom property/tp-var、显式 tp-computed、named style、provenance 和最终 Emacs property projection。

普通 function value 保持 literal只有 tp-computed 才会求值一次。schema/rule 注册先完整校验再原子替换。shorthand 在进入候选集前展开一次,计算结果随后经过 variable/wide-value resolution、normalizer 和 validator。该模块提供后续 signal/binding 与 retained surface 共用的唯一 style 语义,不建立第二套 renderer。


tp-reactive.el响应式基础设施

只依赖 tp-core。文件上半部是 TP 1.0 的唯一新响应式执行语义global/buffer-scoped signal、owner+key binding identity、dynamic dependency collection、binding→binding graph、transaction-local candidate signal values、dirty dedupe/topological lazy flush、nested write stabilization、rollback-capable transaction participant、cycle path、owner disposal、variable adapter 和 public counters。participant 在全部 surface side state 发布后、source commit 前晋升 client-owned opaque state失败时按逆序撤销它不解释 client state。正常新热路径只从 source subscriber set 到 dirty binding不读取 buffer-list、文本上的 tp-name/tp-layers 或 layer→buffer registry。

文件下半部仍暂存 0.3 façade 所需的变量→layer watcher、batch queue 和 layer→buffer registry以保持旧测试在 retained surface 建成前可运行;它们没有被新 graph 调用,并将在最终 cutover phase 与 tp-render.el 扫描路径一起删除。这个暂存区不是第二套长期 public runtime。

tp-surface.elretained publication owner

该模块拥有 surface/object identity、marker-backed mount index、range anchor、properties ledger、buffer diff、publication journal 与 revision。tp-surface-update-scoped 复用同一完整 candidate prepare 和同一事务发布器,只把 live object handles 解析成当前事务的授权范围;它不是子树 renderer也不接受 Ebox owner、dirty kind、layout patch 或 raw marker。范围外输出变化在 prepare 阶段拒绝,显式 root fallback 除外。

只依赖 tp-coretp-styletp-reactive。它集中拥有 prepare context、candidate/live object identity、pure surface plan、content/properties capability、range anchor、logical object→多个 marker-backed mounts、object-keyed mount index、position→object side index、properties contribution ledger、text/property diff、multi-buffer change group、silent-property inverse journal、opaque client state、revision、generic report 和 buffer-kill lifecycle。没有可见字符的 logical object 必须显式 retain不连续输出通过 prepare-only object→plan-fragment attachment 建立plan 本身仍没有 handle 或 position。normal update 从 binding owner 直接取得 prepared surface再从 object 直接取得 mounts不读取 buffer-list,也不按 tp-nametp-layers 或显示文本反查 identity。

content mount 可以替换其拥有的 disjoint span外部字符编辑会使 mount stale。properties mount 只能修改 attached anchor 上声明的 direct properties同一 surface 内重叠 contribution 通过 native property schema 合成。外部值与 TP last-published value 不同时prepare 报 tp-property-conflict,调用者必须 tp-range-rebase 或 unmount。独立 surfaces 的字符范围当前必须不重叠,以保持单一、可证明的 ownership journal。

tp-propertizetp-applytp-style projection 加 tp-ops mutation primitive 的 one-shot 组合,不创建 runtime state。tp-watch 只把 range anchor、object binding 和 properties surface 组合成普通用户入口;它没有独立 scheduler、diff 或 publication path。

依赖注册与管理

函数/变量 描述
tp-reactive-deps 变量 → 依赖它的层及属性 的注册表
tp--register-reactive-deps 注册响应式依赖
tp--unregister-reactive-deps 取消注册依赖(含 watchers/computed/data并移除该层的缓冲区注册表条目
tp--layer-has-reactive-deps-p 层是否有响应式依赖
tp--register-layer-watchers / tp--unregister-layer-watchers 注册/清除 :watch 回调
tp--register-layer-computed / tp--unregister-layer-computed 注册/清除 :compute 计算属性
tp--register-layer-data / tp--unregister-layer-data 注册/清除 :data 变量
tp--apply-initial-computed 计算 :compute 的初始值
tp--ensure-reactive-variables 确保 $var 对应的变量已定义
tp-reactive-reset 重置全部响应式注册表(含批量队列与层→缓冲区注册表)

层→缓冲区注册表0.3.0

响应式更新不再全量扫描 (buffer-list):每条会写入 tp-name 的缓冲区路径tp-set 家族、栈变更函数、match/regexp 应用器)都把目标缓冲区登记到注册表,更新时只访问登记过的缓冲区。

函数/变量 描述
tp--layer-buffers 哈希表(:test equal):层名 → 展示该层的缓冲区列表。键存在但值为空表示"已知:无缓冲区展示该层",与键不存在(unknown)严格区分
tp-reactive--register-layer-buffer 幂等登记公开写入口tp-ops/tp-search/tp-stack 各自的注册助手最终都调用它);首次使用时安装 kill-buffer-hook 清理器
tp-reactive-layer-buffers 查询某层的已登记存活缓冲区,或返回符号 unknown;惰性剔除已死缓冲区
tp-reactive--buffer-layer-names 栈感知的缓冲区扫描:直接 tp-nametp-layers 栈存储内的层(被覆盖或被隐藏)都算在场。tp-reactive-track-buffer 与匿名层 GC 的存活检查共用它
tp-reactive-track-buffer 交互命令:扫描缓冲区并登记其中的全部层。用于弥补"插入已带属性的字符串"绕过登记路径的已知缺口
tp-reactive--prune-killed-buffer / tp-reactive--install-kill-buffer-hook kill-buffer 时从注册表剔除死缓冲区(条目保留为空列表,即"已知:无"

unknowntp-render 的更新走一次学习性全扫描并登记实际找到的缓冲区;一处都没找到的层刻意保持 unknown,以便之后经非登记路径(如字符串插入)出现时仍能被下次扫描发现。

变量监听与批量队列

函数 描述
tp--reactive-variable-watcher add-variable-watcher 回调;调用 :watch 后经 tp--reactive-update-function 委托重渲染
tp--invoke-layer-watchers 调用层的 :watch 回调
tp--queue-batch-update 将更新加入待处理队列 tp--batch-update-pending(刷新在 tp-render

钩子变量:tp--reactive-update-function(定义于此,由 tp-render.el 安装)。


tp-layer.el层定义、解析与层栈存储

依赖 tp-core、tp-reactive。提供 define-tp / define-tps 宏、层注册表、层名解析,以及 0.3.0 归位至此的层栈存储编解码匿名层完整生命周期铸造、驻留、注销、GC

层定义

函数/宏 描述 依赖
define-tp 定义单个自定义文本属性(层);别名 tp-define-layer tp--define-layer-internal
define-tps 定义自定义文本属性组(层组);别名 define-tp-grouptp-define-group tp--define-layer-group-internal
tp--define-layer-internal 层定义的运行时实现 tp--parse-define-layer-args, tp--collect-reactive-symbols, tp--ensure-reactive-variables, tp--register-*, tp--layer-refresh
tp--parse-define-layer-args 解析 :props / :data / :compute / :watch / :transform -
tp--parse-layer-group-element 解析层组元素 tp--layer-group-element-format
tp--define-layer-from-parsed 从解析结果定义层 (与 define-tp 类似的依赖)
tp--check-layer-cycle 检测循环层引用并报错 tp--layer-expansion-stack

0.3.0 起参数化层/层组的 ARGLIST 可以声明任意个参数(此前仅限一个);(LAYER ARG1 ... ARGN) 与包裹形式 (LAYER (ARG1 ... ARGN))tp-settp-put-layer 规格中均可用,实参数量不匹配会报出点名该层与两个数量的清晰错误。

注册表与查询

函数/变量 描述
tp-layer-alist / tp-layer-groups / tp-layer-transforms 层、层组、转换函数注册表
tp--group-generated-layers 层组 → 其定义生成的层 的注册表(组重定义/注销时随之清理)
tp--set-layer-props / tp--set-group-layers 写入注册表
tp-layer-props / tp-group-props 获取层/层组属性(&optional INCLUDE-TP-NAME,默认不含 tp-name;返回副本)
tp-layer-props-with-arg / tp-group-props-with-arg 单参数形式0.3.0 起是 -with-args 的薄封装)
tp-layer-props-with-args / tp-group-props-with-args 多参数形式ARGS 按位置绑定到层参数
tp-layer-arglist 返回参数化层的形参表副本(非参数化层返回 nil
tp-layer-parameterized-p / tp-group-parameterized-p 是否参数化
tp-describe-layer 交互命令:在 help 缓冲区展示层的存储格式、形参表、原始定义体、展开属性、响应式依赖、transform 与所属层组(数据采集在 tp--describe-layer-data
tp-layer-reset 重置层系统(连带调用 tp-reactive-reset;见可变状态清单
tp-undefine-layer / tp-undefine-group 删除层/层组(含其响应式依赖、转换与匿名层注册表条目)

属性解析

函数 描述 依赖
tp--resolve-props 解析属性(展开层名、多参数规格、$var、注册依赖、驻留匿名层) tp-layer-props(-with-args), tp--collect-reactive-symbols, tp--resolve-reactive-symbols, tp--anonymous-layer-name-for, tp--register-reactive-deps
tp--expand-layer-in-plist 展开 plist 中的层名键 tp--is-layer-name-p

匿名层机制与 GC0.3.0 归位/新增)

函数/变量 描述
tp--anonymous-layer-counter 匿名层名计数器。刻意不被任何 reset 清零:脱离缓冲区的字符串可能仍携带旧的 tp-anon-N 属性值,计数器单调递增保证新铸名字永不与之混淆
tp--generate-anonymous-layer-name 生成唯一的 tp-anon-N 符号
tp--anonymous-layer-registry 匿名响应式层驻留表:equal 的 props 规格复用既有注册项
tp--anonymous-layer-name-for 驻留查询/铸造入口
tp--buffer-has-layer-region-p 栈感知的存活检查:直接 tp-nametp-layers 内(被覆盖/被隐藏)皆算存活
tp-gc-anonymous-layers 交互命令:回收已无任何已登记存活缓冲区展示的匿名层;注册表状态为 unknown 的层(可能仅被游离字符串引用)保守保留

层栈存储编解码

层栈在原始文本属性上的编码/解码知识集中在这里tp-stack栈操作与 tp-render响应式写穿都向下调用它互不 require。

函数 描述
tp--normalize-layer-spec 规范化层规格(含多参数 (LAYER ARG1 ... ARGN)
tp--build-layer-props / tp--layer-stack-to-list 旧式编解码原语(无隐藏层语义)
tp--stack-hidden-p 层 plist 是否带 tp-hidden 标志
tp--plist-equivalent-p / tp--assert-hidden-render-cache 普通栈解码时验证完整存储的直接渲染缓存;无刷新上下文的不一致在改写前发出 tp-layer-conflict
tp--stack-props-to-list 原始属性 → 有序层列表(顶层在前,含隐藏层)。完整存储模式下 tp-layers 持有完整栈直接属性只是最顶可见层的渲染缓存并在普通解码时执行冲突检查definition/reactive refresh 由 tp-render 在明确可见 entry 上协调外部编辑
tp--stack-build-props 有序层列表 → 原始属性。单层栈不携带 tp-layers;含隐藏层时切换为"完整栈 + 渲染缓存"存储模式(全部隐藏时不渲染任何层属性)
tp--get-layer-by-idx-or-name 通过索引或名称查找层

钩子变量:tp--layer-refresh-function(定义于此,由 tp-render.el 安装为 tp--update-layer-regionstp--layer-refresh 是它的调用入口,非参数化 层重定义后把 old props 一并传给渲染层,触发已挂载区域的 old/new 所有权协调。


tp-ops.el核心属性操作与 tp-text 处理链

依赖 tp-core、tp-reactive、tp-layer。面向用户的核心属性读写函数直接调用 Emacs 原生文本属性 API。0.3.0 起 tp-text 处理链从 tp-render 下沉至此,tp-set同模块直接调用它(不再经钩子变量)——因此只加载到 tp-ops 的部分加载也能得到可用的 tp-text 文本替换。

参数解析

函数 描述 调用者
tp--parse-args 解析灵活的调用格式(整串/区域/层名/多参数层) tp-set, tp-reset, tp-add
tp--apply-props-to-string 字符串路径的属性应用 tp-set, tp-reset, tp-add
tp--ops-register-layer-buffer 应用带 tp-name 的属性到缓冲区后,登记到层→缓冲区注册表 tp-set, tp-reset, tp-add

tp-text 处理链0.3.0 自 tp-render 迁入)

函数 描述
tp--handle-tp-text-property tp-text 属性的总入口:初始化/替换文本、双向同步响应式变量
tp--tp-text-replace 执行文本替换(缓冲区与字符串两条路径)
tp--tp-text-transform 应用层的 :transform(首次渲染同样生效)
tp--find-tp-text-reactive-var 找到层 tp-text 绑定的响应式变量
tp--merge-embedded-props 合并 tp-text 字符串内嵌属性与外部属性
tp--apply-reactive-text-props 把结果属性应用到替换文本(值未变的区段跳过写入,保持 buffer-modified 状态)
tp--put-text-property-unless-equal 仅在值确实变化时写属性

设置属性

函数 描述 依赖 被依赖
tp-set 设置文本属性(保留其他属性) tp--parse-args, tp--handle-tp-text-property, tp--ops-register-layer-buffer tp-match-set, 层操作
tp-reset 完全替换所有文本属性 同上 tp-match-reset
tp-add 深度合并属性 同上 + tp--deep-merge-plist, tp--prepend-face tp-match-add

获取属性

函数 描述 依赖 被依赖
tp-get 获取范围内的属性值(返回区间列表) tp--get-nested 搜索函数
tp-at 获取单个位置的属性值 tp--get-nested 大多数高层函数
tp-member 区分"属性值为 nil"与"属性不存在"plist-member 风格) - 用户 API

删除属性

函数 描述 依赖 被依赖
tp-remove 移除属性或子属性 tp--remove-property, tp--remove-sub, tp--remove-*-from-string 用户 API
tp-clear 清除所有属性(显式返回 nil - 用户 API

tp-search.el模式匹配与搜索

依赖 tp-core、tp-reactive、tp-layer、tp-ops0.3.0 新增 tp-reactive 依赖:应用器写入缓冲区后经 tp--search-register-layer-buffer 登记层→缓冲区注册表)。提供模式匹配式属性应用、属性搜索与导航。

模式匹配

函数 描述 依赖
tp-match-set / tp-match-reset / tp-match-add 在字符串匹配处设置/重置/合并属性0.3.0 起接受 START/END 界限(视同只存在该部分;颠倒的界限自动交换) tp--match-apply
tp-regexp-set / tp-regexp-reset / tp-regexp-add 在正则匹配处设置/重置/合并属性0.3.0 起额外接受 SUBEXP属性作用于每个匹配的该捕获组超出组数报清晰错误 tp--regexp-apply
tp--match-apply / tp--regexp-apply 字面/正则匹配的入口(含多模式支持) tp--pattern-apply
tp--pattern-apply / tp--pattern-apply-single 共享的模式匹配引擎(空模式/零宽模式安全;承载 START/END/SUBEXP tp-set/tp-reset/tp-add 风格的 apply-fn
tp--deep-merge-apply / tp--reset-apply 传给引擎的合并/重置回调(缓冲区路径顺带登记注册表) tp--deep-merge-plist, tp--search-register-layer-buffer
tp--search-register-layer-buffer 登记助手,转发到 tp-reactive--register-layer-buffer tp-reactive

搜索和导航

函数 描述 依赖
tp-forward 向前搜索 N 次并移动点;省略 VALUE 匹配任意直接存在值,显式 nil 精确匹配 present-nil tp--property-search-forward
tp-backward 向后搜索 N 次并移动点(与向前语义对称,同样新增 PREDICATE/NOT-CURRENT tp--property-search-backward
tp--property-search-forward / tp--property-search-backward 基于统一直接属性 run 的单步搜索引擎 tp--property-matches
tp--property-match-p 谓词归一化(函数优先;否则 tp-any-value 通配,其他值用 equal -
tp--property-matches 字符串/缓冲区共用、presence-aware 的直接属性 run 收集器 text-properties-at, next-property-change
tp-search 收集所有 (START END VALUE) 匹配区间 tp--property-matches
tp-search-forward / tp-search-backward 已废弃0.3.0make-obsolete裸封装原语nil-PREDICATE 默认语义与库内 equal 匹配相悖;请改用 tp-forward / tp-backward,或直接用 Emacs 原语 text-property-search-*

遍历与替换

函数 描述 依赖
tp-forward-do / tp-backward-do 向前/向后搜索并在第 TIMES 个匹配处执行函数(同样透传 PREDICATE/NOT-CURRENT tp--forward-do / tp--backward-do
tp--forward-do / tp--backward-do 单方向遍历的内部实现 tp--replace-match-text
tp-search-map 对所有匹配应用函数FUNCTION 接收 TEXT &optional START END IDX tp--search-do
tp--search-do 搜索遍历的内部实现 tp--replace-match-text
tp--replace-match-text 共享的匹配文本替换助手(缓冲区支持变长替换;字符串变长时报错) -

tp-render.el响应式渲染引擎

依赖 tp-core、tp-reactive、tp-layer、tp-ops、tp-search。这是唯一"知道"渲染如何进行的模块:它直接调用 tp-search-maptp--tp-text-transformtp--apply-reactive-text-props(后两者位于 tp-ops——这条 require 是真实的下行调用,不只是加载顺序),并在加载末尾把自己的入口函数安装进下层模块预留的两个钩子变量。0.3.0 起批量更新宏与刷新逻辑也位于此。

缓冲区遍历0.3.0:注册表驱动)

函数 描述 依赖
tp--render-visit-buffer 单缓冲区访问接缝(测试可包裹它统计访问次数) tp-with-current-buffer
tp--map-layer-buffers 在可能展示该层的缓冲区中执行更新WHERE 为缓冲区setq-local时只走它否则查注册表只访问已登记缓冲区unknown 层回退为一次学习性 (buffer-list) 全扫描并登记实际命中的缓冲区 tp-reactive-layer-buffers, tp--buffer-has-layer-region-p

重渲染

函数 描述 依赖
tp--update-layer-regions 用 old/new 所有权协调重渲染已挂载区域,并写穿tp-layers 栈存储 tp--layer-render-props, tp-search-map, tp--write-layer-through-stack-storage
tp--write-layer-through-stack-storage 先按旧定义移除仍由该层拥有的键,再写入新定义;被覆盖或隐藏的副本也保持最新 tp--stack-props-to-list, tp--stack-build-props [tp-layer]
tp--reconcile-layer-props / tp--reconcile-layer-region 计算和写入 old/new 属性协调;保留不属于旧层或已被外部改写的值 -
tp--update-layer-computed 更新 :compute 计算属性nil 可传播;错误向上抛出) tp--store-computed-value
tp--layer-render-props / tp--layer-reactive-props 求取层的渲染属性 tp-layer-props

响应式文本tp-text

函数 描述 依赖
tp--update-reactive-text 变量变化后更新响应式文本 tp--replace-reactive-text-in-buffer, tp--map-layer-buffers
tp--replace-reactive-text-in-buffer 在缓冲区中替换响应式文本0.3.0最小差异编辑——修剪公共前后缀只编辑差异区段,且先插入后删除,未变文本内的点位与标记不动;文本相同的更新完全不触碰缓冲区) tp--edit-region-minimal-diff
tp--edit-region-minimal-diff 最小差异编辑原语 -
tp--pos-holds-layer-in-storage-only-p 某位置的层是否只存在于栈存储(隐藏/被覆盖,跳过可见文本替换) -

批量更新0.3.0 自 tp-reactive 迁入)

函数/宏 描述
tp-with-batch-updates 批量更新宏BODY 内的多次变量修改合并为一次刷新(队列变量仍在 tp-reactive宏向下 let 绑定它们)
tp--flush-batch-updates 刷新队列,按层去重后直接调用 tp--reactive-flush-entry(不再经钩子)
tp--reactive-flush-entry 单条刷新的工作函数(属性更新或 tp-text 替换)

引擎入口与钩子安装

函数 描述
tp--reactive-apply-update 变量变化的完整处理:更新 computed、合并层定义、重渲染或入批量队列嵌套写入经队列而非递归。尾部刷新置于 unwind-protect 清理段中,重渲染抛错也不会把队列条目困死。安装为 tp--reactive-update-function

加载末尾执行安装(与源码逐字一致):

(setq tp--reactive-update-function #'tp--reactive-apply-update)
(setq tp--layer-refresh-function #'tp--update-layer-regions)

tp-stack.el属性层栈操作

依赖 tp-core、tp-reactive、tp-layer——不依赖 tp-ops0.2.0 的幻影依赖已在 0.3.0 移除,独立字节编译无警告)。所有栈变更函数建立在共享的裁剪式区域遍历之上,区域操作不会影响 [START, END) 之外的文本;栈的存储编解码在 tp-layer向下调用。0.3.0 起所有栈变更函数返回实际修改的属性段数量0 表示无匹配;tp-put-layer/tp-push-layer 例外,仍返回 OBJECT 或 (START . END)),每次改写后经 tp--stack-register-layers 登记层→缓冲区注册表。字符串形式原地修改字符串(与 tp-set 的复制语义不同,各函数 docstring 均有警示)。

内部助手

函数 描述 依赖
tp--parse-layer-args 解析层操作的灵活参数 -
tp--plist-remove 返回去掉某键的 plist 副本 -
tp--stack-map-region 按区间遍历区域内层栈的共享引擎(解码经 tp--stack-props-to-list含隐藏层 tp--map-intervals [tp-core], tp--stack-props-to-list [tp-layer]
tp--stack-register-layers 把新栈中每个带 tp-name 的层(含被覆盖与隐藏的)登记到缓冲区注册表 tp-reactive--register-layer-buffer [tp-reactive]
tp--put-layer-specs 展开层规格(层名/内联 plist/层名列表/参数化/层组) tp--normalize-layer-spec, tp-group-props(-with-arg) [tp-layer]
tp--move-layer-in-stack 在栈中移动层 tp--get-layer-by-idx-or-name
tp--raise-layer-in-stack 在栈中上下移动层 tp--move-layer-in-stack
tp--switch-layers-in-stack 交换两个层的位置 tp--get-layer-by-idx-or-name

层操作(公开 API

函数 描述 依赖
tp-put-layer 在指定索引放置层区域局部0.3.0 新增尾参 NOERROR未定义层名返回 nil 而非报错) tp--put-layer-specs, tp--stack-map-region
tp-push-layer 将层推到顶部(同样支持 NOERROR tp-put-layer
tp-delete-layer 删除层 tp--stack-map-region
tp-pop-layer 弹出顶层 tp-delete-layer
tp-move-layer 移动层到指定位置 tp--move-layer-in-stack, tp--stack-map-region
tp-raise-layer 上移层 tp--raise-layer-in-stack, tp--stack-map-region
tp-lower-layer 下移层0.3.0 新增tp-raise-layer 的镜像) tp--raise-layer-in-stack, tp--stack-map-region
tp-rotate-layer 轮换层0.3.0:规范顺序 (START END DIRECTION [COUNT] [OBJECT]),凭 up/down 符号无歧义分派;旧顺序永久兼容;单趟栈旋转实现) tp--stack-map-region
tp-pin-layer 将层一次性移到栈顶(不阻止后续 push 覆盖) tp-move-layer
tp-switch-layer 交换两个层 tp--switch-layers-in-stack, tp--stack-map-region
tp-hide-layer 隐藏层0.3.0 新增):层留在栈中、继续接收响应式更新但不渲染;隐藏可见顶层则显露下一可见层;全部隐藏时文本仅剩 tp-layers 记账属性 tp--stack-map-region, tp--stack-build-props [tp-layer]
tp-show-layer 取消隐藏0.3.0 新增) 同上
tp-merge-layers 合并多个层(显式 nil 值保留;隐藏的匹配层不贡献属性,全部匹配层均隐藏时合并结果保持隐藏) tp--merge-layer-props, tp--stack-map-region
tp-flatten-layers 扁平化所有层(只合并可见层;全部隐藏时得到裸文本) tp--merge-layer-props, tp--stack-map-region

层查询

函数 描述 依赖
tp-layer-list 列出所有层名称(含隐藏层) tp--stack-map-region
tp-layer-count 计算层数量(含隐藏层) tp--stack-map-region
tp-layer-exists-p 检查层是否存在 tp-layer-list
tp-layer-top 获取顶层名称(覆盖整个请求区域;按栈序报告最顶层,即使它被隐藏) tp--stack-map-region
tp-layer-stack-at 单个位置的完整有序层栈:(NAME . PROPS) 列表,顶层在前,隐藏层以 PROPS 中的 tp-hidden t 标识0.3.0 新增) tp--stack-props-to-list [tp-layer]
tp-region-layer-props 获取区域中特定层的属性 tp--stack-map-region

层属性操作

函数 描述 依赖
tp-add-to-layers 向特定层添加属性 tp--deep-merge-plist, tp--stack-map-region
tp-add-to-all-layers 向所有层添加属性 tp-add-to-layers

Managed lifecycleStage 4

函数/状态 描述 依赖
tp-meta lifecycle metadata保存在 tp-layers 权威存储中;直接渲染属性和 public stack query 会剥离它 tp--managed-render-props, tp--managed-public-layer-props
tp--managed-operation-counter transaction/entry id 的单调计数器 tp--managed-next-operation-id
tp-attach-managed-layers 扫描已有 managed storage、规范化 metadata、登记发现的层并返回层名 tp--managed-normalize-stack, tp-reactive--register-layer-buffer
tp-detach-managed-layers 移除 managed storageKEEP-RENDERED 时保留当前可见渲染属性 tp--managed-detached-props
tp-managed-layer-diagnostics 只读层诊断entries、args、registry、buffers、errors tp--managed-buffer-diagnostic-data
tp-managed-buffer-diagnostics 只读缓冲区诊断 tp--managed-buffer-diagnostic-data
tp-managed-diagnostics 全局只读诊断,含 theme diagnostics tp--managed-theme-diagnostics
tp-layer-transaction managed transaction失败恢复原文本/属性快照,默认发出 tp-layer-transaction-error tp--transaction-*

只要 layer stack entry 携带 tp-meta,即使只有一个 managed layer也使用 tp-layers 保存权威 stack storage。参数化 mounted entry 保存 args、arglist 与 definition-version层重定义后通过保存的 args 刷新既有 entry。历史无 metadata entry 作为 legacy entry 保守处理。


tp-query.el原生文本查询与修改策略

只依赖 tp-core。提供 Stage 3/5 原生 façade直接/effective/source-aware text lookup、overlay-aware char lookup、property change/any/not-all 封装,以及显式 modified/read-only 修改策略。overlay lifecycle创建、移动、删除、priority 管理)不属于 tp-query。

查询记录与 lookup

函数/记录 描述 依赖
tp-lookup-result cl-defstruct 结果记录property、value、present-p、source、mode、object、position、overlay -
tp-lookup 按 MODE 查询属性;支持 :text-direct:text-effective:text-source:char:char-source tp--lookup-direct, tp--lookup-effective, tp--lookup-char, tp--lookup-source-cell
tp--lookup-direct 只检查 text-properties-at 的直接 plist区分 explicit nil 与 absent plist-member
tp--lookup-effective 值使用 get-text-propertysource 使用 text-only 解释 tp--lookup-source-cell
tp--lookup-char 使用 get-char-property-and-overlayoverlay 获胜时 source 为 :overlay 且记录 overlay 对象 get-char-property-and-overlay
tp--lookup-source-cell 按 direct → category → alias → default → absent 解释来源 text-properties-at, symbol-plist, char-property-alias-alist, default-text-properties
tp--lookup-alias-cell 查找 char-property-alias-alist 中第一个直接存在的 alias 属性 plist-member

property change 与区域谓词

函数 描述 依赖
tp-property-change :direction :next / :previous;传入 PROPERTY 时走 single-property change省略时走 all-property change next/previous-property-change, next/previous-single-property-change
tp-property-any text-property-any 薄封装 text-property-any
tp-property-not-all text-property-not-all 薄封装 text-property-not-all

修改策略

函数/宏 描述
tp--mutation-policy-modes 校验并归一化 :modified:read-only;拒绝 (:modified :silent :read-only :respect)
tp-with-mutation-policy 三种有效组合ordinary+respect、ordinary+inhibit、silent+inhibit

insert/copy/yank/stickiness/narrowing/indirect buffer 均不在 tp-query 中封装,行为直接委托 Emacs 原生操作。


tp-palette.el调色板数据

不依赖任何 tp- 模块(仅 subr-x是独立的叶模块。明/暗主题双值调色板系统,tp-palette-alist 是唯一数据源。

函数/宏/变量 描述
define-tp-palette 定义调色板(重定义立即生效);别名 tp-define-palette
tp-palette-alist 调色板注册表(唯一数据源)
tp-theme-generation / tp-theme-last-* theme lifecycle diagnosticsgeneration、last hook source、refresh mode、refreshed ranges、errors
tp-theme-change-hook enable-theme / disable-theme 后运行的 hookpalette 只负责事件检测managed renderer 可订阅
tp--palette-after-enable-theme / tp--palette-after-disable-theme theme lifecycle advice递增 generation 并记录来源
tp-parse-color 解析颜色规格(支持 ("light" . "dark") 及单边 cons
tp-theme-dark-p / tp-theme-light-p 当前主题判断
tp-palette-color 通用的主题解析取色器0.3.0 新增的首选查询入口)
tp-palette-has-p 谓词整合入口KIND 取 :fg/:bg/:border/nil0.3.0 新增)
tp-palette-fg-color / tp-palette-bg-color / tp-palette-border-color 取前景/背景/边框色(兼容便捷函数)
tp-palette-p / tp-palette-fg-p / tp-palette-bg-p / tp-palette-fbg-p / tp-palette-border-p 调色板谓词(兼容便捷函数)
tp-palette-pure 取纯色值

tp-builtins.el内置层与辅助工具

最上层模块,依赖 tp-core、tp-layer、tp-ops、tp-palette。提供开箱即用的内置层与展示/缓冲辅助。

定义 描述
内置层 tp-palettetp-fgtp-bgtp-buttontp-underlinetp-deletetp-linktp-spacetp-headlinetp-action 等(define-tp 定义;tp-link 的颜色在应用时解析,主题切换即时生效)
tp-pop-to-buffer / tp-switch-to-buffer 显示带属性文本的缓冲辅助宏q 绑定在缓冲区局部 minor-mode keymap 中)
tp-palette-show 展示所有调色板
tp--suffix-symbol 符号加后缀助手0.3.0 起转为私有;tp-suffix-symbol 保留为废弃兼容别名)

钩子变量:唯一许可的反向调用

分层规则的唯一例外是两个钩子变量:下层模块声明变量并在需要时 funcall,实现由 tp-render.el 在加载时安装。这样下层模块不必 require 上层模块,依赖图保持严格单向;而在未加载 tp-render 时,下层模块依然可用(钩子为 nil 时优雅降级:层可以定义与应用,只是没有自动重渲染)。

钩子变量 声明于 安装的实现tp-render.el 用途
tp--reactive-update-function tp-reactive.el tp--reactive-apply-update 变量监听器触发的重计算与重渲染
tp--layer-refresh-function tp-layer.el tp--update-layer-regions 层重定义后刷新已应用区域

0.2.0 时钩子有四个0.3.0 删掉了其中两个,代之以真实的模块内/下行调用:

  • tp--tp-text-handler-function(原声明于 tp-ops整条 tp-text 处理链移入 tp-opstp-set 等直接调用 tp--handle-tp-text-property。副产品:只加载 tp-ops 的部分加载也能完成 tp-text 文本替换。
  • tp--reactive-flush-function(原声明于 tp-reactivetp-with-batch-updatestp--flush-batch-updates 移入 tp-render刷新直接调用 tp--reactive-flush-entry。副产品:部分加载下批量刷新不再被静默丢弃,而是诚实地报 void-function。

留下的两个钩子对应真正源自下层的事件(变量被 set、层被重定义无法在不打破分层的前提下改写为下行调用。


可变状态清单

各模块持有的可变运行时状态及其清理入口0.3.0 全面核对):

模块 状态 描述 清理
tp-core —— 无可变状态(仅 tp-debug-mode/tp-debug-echo 两个用户选项;调试日志写入 tp-debug 缓冲区,由 tp-debug-clear 清除) -
tp-style schema、named style、stylesheet rule、cascade layer/source order registries 纯 style definition 和 rule 状态;不保存 object、buffer 或 mount tp-style-reset / tp-style-reset-rules
tp-reactive signals、owner bindings、dependency subscriber sets、variable adapters、transaction-local scheduler state、public counters TP 1.0 exact reactive graphnormal update 不扫描 buffer tp-reactive-resetbuffer-scoped signal 随 buffer kill
tp-surface buffer-local surfaces、object/mount/index、range anchors、property ledgers、root/scoped publication、plan/client-state/revision/report TP 1.0 retained publicationglobal registry 仅 weak-reference tp-surface-unmountbuffer kill authoritative teardown
tp-reactive tp-reactive-deps 变量 → 依赖层 注册表 tp-reactive-reset
tp-reactive tp-layer-watchers / tp-layer-computed / tp-layer-data / tp-reactive-observer-errors :watch / :compute / :data 注册表与结构化 observer 错误 tp-reactive-reset
tp-reactive tp--batch-update-pending 批量更新队列0.3.0 起也被 reset 清空,防止残留条目对新定义的层重放) tp-reactive-reset
tp-reactive tp--layer-buffers 层→缓冲区注册表哈希表0.3.0 新增) tp-reactive-resetclrhash单层条目随 tp-undefine-layer/层重定义移除;死缓冲区经 kill-buffer-hook 与惰性访问剔除
tp-reactive tp--batch-update-active / tp--reactive-updating 动态标志let 绑定,非持久状态) 随作用域退出
tp-layer tp-layer-alist / tp-layer-groups / tp-layer-transforms 层、层组、转换注册表 tp-layer-reset
tp-layer tp--group-generated-layers 层组生成的层 tp-layer-reset
tp-layer tp--anonymous-layer-registry 匿名层驻留表 tp-layer-reset;单条随 tp-undefine-layer / tp-gc-anonymous-layers
tp-layer tp--anonymous-layer-counter 匿名层名计数器——刻意不清零(任何 reset 都不动它):游离字符串上残留的 tp-anon-N 名字永远不能与新铸层重名 从不

tp-reactive-reset 移除全部变量监听器并清空上表 tp-reactive 各行;tp-layer-reset 先调用 tp-reactive-reset,再清空 tp-layer 各注册表(计数器除外)。


函数调用关系图

(标注 [模块] 表示函数所在文件;╌╌▷ 表示经钩子变量的间接调用。)

tp-set 调用链

tp-set [tp-ops]
  ├── tp--parse-args [tp-ops]
  │     ├── tp--merge-duplicate-keys [tp-core]
  │     └── tp--resolve-props [tp-layer]
  │           ├── tp-layer-props / tp-layer-props-with-args [tp-layer]
  │           ├── tp--collect-reactive-symbols [tp-core]
  │           ├── tp--resolve-reactive-symbols [tp-core]
  │           ├── tp--anonymous-layer-name-for [tp-layer]$var 匿名层驻留)
  │           └── tp--register-reactive-deps [tp-reactive]
  ├── tp--handle-tp-text-property [tp-ops]0.3.0 起同模块直接调用,不再经钩子)
  │     └── tp--tp-text-transform / tp--tp-text-replace [tp-ops]
  ├── tp--apply-props-to-string [tp-ops](整串形式,返回新字符串)
  ├── set-text-properties / put-text-propertyEmacs 原生,区域形式)
  └── tp--ops-register-layer-buffer [tp-ops](缓冲区目标)
        └── tp-reactive--register-layer-buffer [tp-reactive]

tp-add 调用链

tp-add [tp-ops]
  ├── tp--parse-args [tp-ops]
  ├── tp--handle-tp-text-property [tp-ops](直接调用)
  ├── text-properties-atEmacs 原生)
  ├── tp--prepend-face [tp-core]face 家族属性)
  │     └── tp--deep-merge-plist [tp-core]
  ├── tp--deep-merge-plist [tp-core](其他嵌套属性)
  ├── put-text-propertyEmacs 原生)
  └── tp--ops-register-layer-buffer [tp-ops]
        └── tp-reactive--register-layer-buffer [tp-reactive]

define-tp 调用链

define-tp [tp-layer](宏)
  └── tp--define-layer-internal [tp-layer]
        ├── tp--parse-define-layer-args [tp-layer]
        ├── tp--collect-reactive-symbols [tp-core]
        ├── tp--unregister-reactive-deps [tp-reactive](连带移除旧的缓冲区注册表条目)
        ├── tp--ensure-reactive-variables [tp-reactive]
        ├── tp--register-layer-data [tp-reactive]
        │     └── add-variable-watcherEmacs 原生)
        ├── tp--register-layer-computed [tp-reactive]
        ├── tp--apply-initial-computed [tp-reactive]
        ├── tp--register-reactive-deps [tp-reactive]
        ├── tp--register-layer-watchers [tp-reactive]
        ├── tp--resolve-reactive-symbols [tp-core]
        ├── tp--set-layer-props [tp-layer]
        └── tp--layer-refresh [tp-layer]
              ╌╌▷ tp--update-layer-regions [tp-render](经钩子)
                    └── tp-search-map [tp-search]
                          └── put-text-property

tp-push-layer 调用链

tp-push-layer [tp-stack]
  ├── tp--parse-layer-args [tp-stack]
  └── tp-put-layer [tp-stack]
        ├── tp--put-layer-specs [tp-stack]
        │     ├── tp--normalize-layer-spec [tp-layer]
        │     │     └── tp-layer-props [tp-layer]
        │     └── tp-group-props / tp-group-props-with-arg [tp-layer]
        └── tp--stack-map-region [tp-stack](裁剪到 [START, END)
              ├── tp--stack-props-to-list [tp-layer](解码既有栈,含隐藏层)
              ├── tp--stack-build-props [tp-layer](编码新栈/渲染缓存)
              ├── set-text-propertiesEmacs 原生)
              └── tp--stack-register-layers [tp-stack]
                    └── tp-reactive--register-layer-buffer [tp-reactive]

响应式更新调用链

(setq some-reactive-var new-value)
  └── tp--reactive-variable-watcher [tp-reactive]
        ├── tp--invoke-layer-watchers [tp-reactive]:watch 回调)
        └── ╌╌▷ tp--reactive-apply-update [tp-render](经钩子)
              ├── tp--update-layer-computed [tp-render]
              │     ├── tp--resolve-reactive-symbols [tp-core]
              │     └── tp--set-layer-props [tp-layer]
              ├── tp--set-layer-props [tp-layer]深合并回层定义setq-local 不写全局)
              ├── tp--update-layer-regions [tp-render](属性更新)
              │     └── tp--map-layer-buffers [tp-render]
              │           │只访问注册表登记的缓冲区unknown 层回退为
              │           │ 一次学习性全扫描并登记命中缓冲区)
              │           ├── tp-reactive-layer-buffers [tp-reactive]
              │           ├── tp--buffer-has-layer-region-p [tp-layer](回退路径)
              │           └── 每缓冲区:
              │                 ├── tp-search-map [tp-search] → put-text-property
              │                 └── tp--write-layer-through-stack-storage [tp-render]
              │                       └── tp--stack-props-to-list /
              │                           tp--stack-build-props [tp-layer]
              │                          (隐藏/被覆盖的层副本同步刷新)
              └── tp--update-reactive-text [tp-render]tp-text 文本替换)
                    └── tp--replace-reactive-text-in-buffer [tp-render]
                          └── tp--edit-region-minimal-diff [tp-render]
                             (最小差异、先插入后删除;文本相同则完全不动缓冲区)

批量模式tp-with-batch-updates [tp-render]/ 更新中的嵌套写入:
  └── tp--queue-batch-update [tp-reactive](入队,不递归)
        └── tp--flush-batch-updates [tp-render](退出批量/最外层更新结束时;
              置于 unwind-protect 清理段,重渲染抛错也会排空队列)
              └── tp--reactive-flush-entry [tp-render]0.3.0 起同模块直接调用,不再经钩子)
                    ├── tp--update-layer-regions
                    └── tp--update-reactive-text

设计原则

  1. 严格分层:模块只允许 require 并调用排在它前面的模块字节编译器强制检查依赖顺序且只声明真实存在的依赖0.3.0 移除了 tp-stack→tp-ops 的幻影依赖tp-palette 不依赖任何 tp- 模块)
  2. 钩子反转:唯一许可的"向上调用"是两个钩子变量(tp--reactive-update-functiontp--layer-refresh-function),由 tp-render.el 统一安装实现能改写为下行调用的反转tp-text 链、批量刷新)已在 0.3.0 改写掉
  3. 单一职责:每个模块(和函数)只负责一件事;一个子系统的完整生命周期住在一个模块里(匿名层的铸造/驻留/注销/GC 全在 tp-layer层栈存储格式知识全在 tp-layer 的编解码器)
  4. 复用优先:共享引擎(tp--map-intervalstp--stack-map-regiontp--pattern-applytp--replace-match-texttp-reactive--buffer-layer-names)承载重复逻辑,高层函数复用而非复制
  5. 统一接口:所有核心属性函数支持相同的调用约定(整串/区域形式、层名、$var、多参数层)
  6. 响应式解耦tp-reactive/tp-layer/tp-ops 不依赖渲染引擎;不加载 tp-render 时钩子为 nil各模块优雅降级tp-text 替换自 0.3.0 起随 tp-ops 即可用);重渲染只访问层→缓冲区注册表登记的缓冲区,未知层才回退全扫描