Add comprehensive code analysis report for developers
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
This commit is contained in:
parent
ce06c76089
commit
715ceaac1e
778
docs/CODE-ANALYSIS.md
Normal file
778
docs/CODE-ANALYSIS.md
Normal file
@ -0,0 +1,778 @@
|
||||
# tp.el 代码分析报告
|
||||
|
||||
本报告旨在帮助想要参与 tp.el 开发的开发者快速了解项目结构、核心功能实现、以及潜在的优化方向。
|
||||
|
||||
## 目录
|
||||
|
||||
- [项目概述](#项目概述)
|
||||
- [文件结构](#文件结构)
|
||||
- [核心功能函数调用堆栈](#核心功能函数调用堆栈)
|
||||
- [1. 文本属性设置 tp-set](#1-文本属性设置-tp-set)
|
||||
- [2. 深度合并属性 tp-add](#2-深度合并属性-tp-add)
|
||||
- [3. 属性层推送 tp-push-layer](#3-属性层推送-tp-push-layer)
|
||||
- [4. 响应式层定义 define-tp](#4-响应式层定义-define-tp)
|
||||
- [5. 响应式更新触发](#5-响应式更新触发)
|
||||
- [6. 模式匹配 tp-match-set](#6-模式匹配-tp-match-set)
|
||||
- [7. 搜索与遍历 tp-search-map](#7-搜索与遍历-tp-search-map)
|
||||
- [关键数据结构](#关键数据结构)
|
||||
- [潜在问题分析](#潜在问题分析)
|
||||
- [架构优化建议](#架构优化建议)
|
||||
- [开发入门指南](#开发入门指南)
|
||||
|
||||
---
|
||||
|
||||
## 项目概述
|
||||
|
||||
tp.el 是一个 Emacs Lisp 文本属性操作库,采用 **五层架构设计**:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 第五层:高级 API │
|
||||
│ tp-match-set, tp-regexp-set, tp-forward-do, tp-search-map │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 第四层:响应式系统 │
|
||||
│ define-tp, define-tps, tp--reactive-variable-watcher │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 第三层:属性层系统 │
|
||||
│ tp-push-layer, tp-pop-layer, tp-rotate-layer │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 第二层:核心属性操作 │
|
||||
│ tp-set, tp-reset, tp-add, tp-get, tp-at, tp-remove │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ 第一层:基础工具函数 │
|
||||
│ tp--parse-args, tp--deep-merge-plist, tp-intervals │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 文件结构
|
||||
|
||||
```
|
||||
tp/
|
||||
├── tp.el # 核心代码(4863 行)
|
||||
├── tp-palette.el # 预定义颜色调色板层(333 行)
|
||||
├── tp-tests.el # ERT 测试套件(4113 行,100+ 测试用例)
|
||||
├── docs/
|
||||
│ ├── ARCHITECTURE.md # 架构文档
|
||||
│ ├── reactive-text-properties.md # 响应式功能文档(中文)
|
||||
│ ├── reactive-text-properties-en.md # 响应式功能文档(英文)
|
||||
│ ├── reactive-optimization.md # 优化文档(中文)
|
||||
│ └── reactive-optimization-en.md # 优化文档(英文)
|
||||
├── README.md # 英文说明文档
|
||||
└── README_CN.md # 中文说明文档
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 核心功能函数调用堆栈
|
||||
|
||||
### 1. 文本属性设置 tp-set
|
||||
|
||||
`tp-set` 是最核心的属性设置函数,支持三种调用方式。
|
||||
|
||||
#### 调用堆栈
|
||||
|
||||
```
|
||||
tp-set (用户调用入口)
|
||||
│
|
||||
├─→ tp--parse-args (解析参数格式)
|
||||
│ │
|
||||
│ └─→ tp--resolve-props (解析属性,包括层名称)
|
||||
│ │
|
||||
│ ├─→ tp-layer-props (获取层定义的属性)
|
||||
│ ├─→ tp--collect-reactive-symbols (收集 $var 符号)
|
||||
│ ├─→ tp--resolve-reactive-symbols (解析为实际值)
|
||||
│ └─→ tp--register-reactive-deps (注册响应式依赖)
|
||||
│
|
||||
├─→ tp--handle-tp-text-property (处理 tp-text 特殊属性)
|
||||
│ │
|
||||
│ └─→ (替换文本内容,如果 tp-text 存在)
|
||||
│
|
||||
└─→ put-text-property / propertize (Emacs 原生 API)
|
||||
```
|
||||
|
||||
#### 关键代码位置
|
||||
|
||||
| 函数 | 文件位置 | 作用 |
|
||||
|------|----------|------|
|
||||
| `tp-set` | tp.el:1350 | 主入口函数 |
|
||||
| `tp--parse-args` | tp.el:1233 | 解析三种调用格式 |
|
||||
| `tp--resolve-props` | tp.el:3730 | 展开层名称和响应式变量 |
|
||||
| `tp--handle-tp-text-property` | tp.el:1124 | 处理 tp-text 文本替换 |
|
||||
| `tp-add` | tp.el:1522 | 深度合并属性 |
|
||||
| `tp-push-layer` | tp.el:4156 | 推送层到栈顶 |
|
||||
| `tp-put-layer` | tp.el:4071 | 在指定位置放置层 |
|
||||
| `define-tp` | tp.el:3154 | 定义自定义层(宏)|
|
||||
| `define-tps` | tp.el:3448 | 定义层组(宏)|
|
||||
| `tp--reactive-variable-watcher` | tp.el:713 | 响应式变量监听器回调 |
|
||||
| `tp--update-layer-regions` | tp.el:993 | 更新使用层的文本区域 |
|
||||
| `tp-search-map` | tp.el:2918 | 搜索并应用函数 |
|
||||
| `tp--match-apply` | tp.el:2269 | 模式匹配内部实现 |
|
||||
|
||||
---
|
||||
|
||||
### 2. 深度合并属性 tp-add
|
||||
|
||||
`tp-add` 实现属性的深度合并,特别是 face 属性的智能合并。
|
||||
|
||||
#### 调用堆栈
|
||||
|
||||
```
|
||||
tp-add (用户调用入口)
|
||||
│
|
||||
├─→ tp--parse-args (解析参数)
|
||||
│
|
||||
├─→ tp--handle-tp-text-property (处理 tp-text)
|
||||
│
|
||||
├─→ text-properties-at (获取现有属性)
|
||||
│
|
||||
├─→ tp--prepend-face (智能合并 face 属性)
|
||||
│ │
|
||||
│ └─→ tp--deep-merge-plist (递归合并 plist)
|
||||
│
|
||||
├─→ tp--deep-merge-plist (合并其他嵌套属性)
|
||||
│
|
||||
└─→ put-text-property (设置合并后的属性)
|
||||
```
|
||||
|
||||
#### Face 合并逻辑
|
||||
|
||||
```elisp
|
||||
;; 输入
|
||||
(tp-add 1 10 '(face (:foreground "red"))) ; 已存在
|
||||
(tp-add 1 10 '(face bold)) ; 新增
|
||||
|
||||
;; 结果: face 是 (bold (:foreground "red"))
|
||||
;; - 符号 face 被前置到列表
|
||||
;; - plist face 被深度合并
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. 属性层推送 tp-push-layer
|
||||
|
||||
`tp-push-layer` 将属性层推送到栈顶,实现多层属性的堆叠管理。
|
||||
|
||||
#### 调用堆栈
|
||||
|
||||
```
|
||||
tp-push-layer (用户调用入口)
|
||||
│
|
||||
└─→ tp-put-layer (在指定索引放置层)
|
||||
│
|
||||
├─→ tp--normalize-layer-spec (规范化层规格)
|
||||
│ │
|
||||
│ └─→ tp-layer-props (获取层属性,添加 tp-name)
|
||||
│
|
||||
├─→ tp-group-props (如果是层组,获取所有层属性)
|
||||
│
|
||||
├─→ tp-empty-p (检查是否为空)
|
||||
│
|
||||
├─→ tp--get-layer-stack (获取现有层栈)
|
||||
│
|
||||
├─→ tp--build-layer-props (构建包含 tp-layers 的属性)
|
||||
│
|
||||
└─→ tp-intervals-map (遍历区间应用属性)
|
||||
│
|
||||
└─→ set-text-properties / put-text-property
|
||||
```
|
||||
|
||||
#### 层栈存储结构
|
||||
|
||||
```elisp
|
||||
;; 可见层属性直接存储为文本属性
|
||||
;; 隐藏层存储在 tp-layers 属性中
|
||||
|
||||
;; 例如:两层栈
|
||||
'(face (:foreground "red") ; 顶层(可见)属性
|
||||
tp-name layer1 ; 顶层名称
|
||||
tp-layers ; 下层列表
|
||||
((face (:background "blue") ; 第一个隐藏层
|
||||
tp-name layer2)))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. 响应式层定义 define-tp
|
||||
|
||||
`define-tp` 宏定义支持响应式变量的自定义层。
|
||||
|
||||
#### 宏展开流程
|
||||
|
||||
```
|
||||
define-tp (宏调用)
|
||||
│
|
||||
├─→ tp--parse-define-layer-args (解析 :props, :data, :compute, :watch, :transform)
|
||||
│
|
||||
├─→ tp--collect-reactive-symbols (收集所有 $var 符号)
|
||||
│
|
||||
├─→ tp--unregister-reactive-deps (如果重新定义,先清除旧依赖)
|
||||
│
|
||||
├─→ tp--ensure-reactive-variables (确保 $var 对应的变量已定义)
|
||||
│
|
||||
├─→ tp--register-layer-data (注册 :data 变量)
|
||||
│ │
|
||||
│ └─→ add-variable-watcher (为每个变量添加监听器)
|
||||
│
|
||||
├─→ tp--register-layer-computed (注册 :compute 计算属性)
|
||||
│
|
||||
├─→ tp--apply-initial-computed (计算初始值)
|
||||
│
|
||||
├─→ tp--register-reactive-deps (注册响应式依赖)
|
||||
│
|
||||
├─→ tp--register-layer-watchers (注册 :watch 回调)
|
||||
│
|
||||
├─→ tp--resolve-reactive-symbols (解析 $var 为当前值)
|
||||
│
|
||||
└─→ tp--set-layer-props (存储到 tp-layer-alist)
|
||||
```
|
||||
|
||||
#### 关键数据结构
|
||||
|
||||
```elisp
|
||||
;; 层定义存储
|
||||
tp-layer-alist
|
||||
;; => ((layer-name arglist body-form) ...)
|
||||
;; 或 ((layer-name nil resolved-props) ...) ; 非参数化层
|
||||
|
||||
;; 响应式依赖
|
||||
tp-reactive-deps
|
||||
;; => ((my-color . ((my-layer . '(face (:foreground $my-color)))))
|
||||
;; (my-bg . ((my-layer . '(face (:background $my-bg))))))
|
||||
|
||||
;; 计算属性
|
||||
tp-layer-computed
|
||||
;; => ((my-layer . ((full-name . (lambda () (concat first last))))))
|
||||
|
||||
;; 数据变量
|
||||
tp-layer-data
|
||||
;; => ((my-layer . (first-name last-name)))
|
||||
|
||||
;; 监听回调
|
||||
tp-layer-watchers
|
||||
;; => ((my-layer . ((first-name . (lambda (new old layer) ...)))))
|
||||
|
||||
;; 转换函数
|
||||
tp-layer-transforms
|
||||
;; => ((my-layer . (lambda (text) (upcase text))))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. 响应式更新触发
|
||||
|
||||
当响应式变量通过 `setq` 改变时,自动触发更新。
|
||||
|
||||
#### 调用堆栈
|
||||
|
||||
```
|
||||
(setq my-color "blue") ; 用户改变变量
|
||||
│
|
||||
└─→ tp--reactive-variable-watcher (由 add-variable-watcher 注册)
|
||||
│
|
||||
├─→ (检查是否在批量更新模式)
|
||||
│ └─→ 如果是,添加到 tp--batch-update-pending 并返回
|
||||
│
|
||||
├─→ tp--invoke-layer-watchers (调用 :watch 回调)
|
||||
│
|
||||
├─→ tp--update-layer-computed (更新计算属性)
|
||||
│ │
|
||||
│ ├─→ (调用计算函数)
|
||||
│ ├─→ tp--resolve-reactive-symbols (解析新值)
|
||||
│ └─→ tp--set-layer-props (更新层定义)
|
||||
│
|
||||
├─→ tp--update-layer-regions (更新文本区域)
|
||||
│ │
|
||||
│ ├─→ tp-layer-props (获取新属性)
|
||||
│ │
|
||||
│ └─→ tp-search-map (遍历所有使用该层的区域)
|
||||
│ │
|
||||
│ └─→ tp-add (合并新属性)
|
||||
│
|
||||
└─→ tp--update-reactive-text (如果 tp-text 依赖该变量)
|
||||
│
|
||||
└─→ tp--replace-reactive-text-in-buffer
|
||||
│
|
||||
└─→ (删除旧文本,插入新文本)
|
||||
```
|
||||
|
||||
#### 批量更新优化
|
||||
|
||||
```elisp
|
||||
(tp-with-batch-updates
|
||||
(setq my-color "red") ; 不立即更新
|
||||
(setq my-bg "blue")) ; 不立即更新
|
||||
;; 退出时一次性更新所有变化
|
||||
|
||||
;; 内部实现:
|
||||
;; 1. 设置 tp--batch-update-active = t
|
||||
;; 2. 变量变化被记录到 tp--batch-update-pending
|
||||
;; 3. 退出时调用 tp--flush-batch-updates
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 6. 模式匹配 tp-match-set
|
||||
|
||||
`tp-match-set` 在字符串匹配处设置属性。
|
||||
|
||||
#### 调用堆栈
|
||||
|
||||
```
|
||||
tp-match-set (用户调用入口)
|
||||
│
|
||||
└─→ tp--match-apply (内部实现)
|
||||
│
|
||||
├─→ (如果 OBJECT 是字符串,copy-sequence 创建副本)
|
||||
│
|
||||
├─→ (循环搜索 PATTERN)
|
||||
│ │
|
||||
│ ├─→ search-forward / string-match
|
||||
│ │
|
||||
│ └─→ tp-set (在匹配区域设置属性)
|
||||
│
|
||||
└─→ (返回匹配区域列表或带属性字符串)
|
||||
```
|
||||
|
||||
#### 支持多模式
|
||||
|
||||
```elisp
|
||||
(tp-match-set '("TODO" "FIXME") '(face warning))
|
||||
;; => 匹配所有 TODO 和 FIXME
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 7. 搜索与遍历 tp-search-map
|
||||
|
||||
`tp-search-map` 对所有匹配属性的区域应用转换函数。
|
||||
|
||||
#### 调用堆栈
|
||||
|
||||
```
|
||||
tp-search-map (用户调用入口)
|
||||
│
|
||||
└─→ tp--search-do (内部搜索实现)
|
||||
│
|
||||
├─→ (区分字符串和缓冲区处理)
|
||||
│
|
||||
├─→ (对于字符串)
|
||||
│ │
|
||||
│ ├─→ text-property-search-forward (搜索)
|
||||
│ │
|
||||
│ └─→ (调用 FUNCTION,传入 text, start, end, idx)
|
||||
│ │
|
||||
│ └─→ (替换匹配文本为函数返回值)
|
||||
│
|
||||
└─→ (对于缓冲区)
|
||||
│
|
||||
├─→ text-property-search-forward
|
||||
│
|
||||
└─→ (相同处理,但修改缓冲区)
|
||||
```
|
||||
|
||||
#### 函数签名
|
||||
|
||||
```elisp
|
||||
(tp-search-map
|
||||
(lambda (text &optional start end idx)
|
||||
(upcase text)) ; 返回值替换原文本
|
||||
'marker ; 搜索的属性名
|
||||
nil ; 值(nil 表示不匹配值)
|
||||
my-string ; 目标对象
|
||||
0 ; 起始位置(可选)
|
||||
100) ; 结束位置(可选)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 关键数据结构
|
||||
|
||||
### 1. tp-layer-alist
|
||||
|
||||
存储所有层定义。
|
||||
|
||||
```elisp
|
||||
;; 非参数化层
|
||||
((highlight nil '(face (:background "yellow")))
|
||||
(error nil '(face (:foreground "red"))))
|
||||
|
||||
;; 参数化层
|
||||
((tp-space (pixel) `(display (space :width (,pixel)))))
|
||||
```
|
||||
|
||||
### 2. tp-layer-groups
|
||||
|
||||
存储层组定义。
|
||||
|
||||
```elisp
|
||||
((status-colors . (highlight error info))
|
||||
(moon-phases . (moon-phases-new moon-phases-full)))
|
||||
```
|
||||
|
||||
### 3. tp-reactive-deps
|
||||
|
||||
存储响应式依赖关系。
|
||||
|
||||
```elisp
|
||||
;; 变量 -> ((层名 . 使用该变量的属性列表) ...)
|
||||
((my-color . ((my-layer . '(face (:foreground $my-color)))
|
||||
(other-layer . '(face (:background $my-color)))))
|
||||
(my-size . ((size-layer . '(display (space :width $my-size))))))
|
||||
```
|
||||
|
||||
### 4. 层栈结构
|
||||
|
||||
文本区域的层栈通过 `tp-name` 和 `tp-layers` 属性存储。
|
||||
|
||||
```elisp
|
||||
;; 位置 1-10 的属性
|
||||
'(face (:foreground "red") ; 可见属性
|
||||
tp-name layer1 ; 顶层名称
|
||||
help-echo "tip" ; 可见属性
|
||||
tp-layers ; 隐藏层列表
|
||||
((face (:background "blue") tp-name layer2)
|
||||
(face (:underline t) tp-name layer3)))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 潜在问题分析
|
||||
|
||||
### 1. 性能问题
|
||||
|
||||
#### 问题 1.1:响应式更新可能导致性能瓶颈
|
||||
|
||||
**现象**:当一个响应式变量被多个层使用,且这些层被应用到大量文本区域时,变量变化会触发大量更新。
|
||||
|
||||
**代码位置**:`tp--update-layer-regions` 函数
|
||||
|
||||
**问题代码**:
|
||||
```elisp
|
||||
(defun tp--update-layer-regions (var layer-name)
|
||||
;; 遍历所有缓冲区
|
||||
(dolist (buf (buffer-list))
|
||||
;; 在每个缓冲区中搜索所有使用该层的区域
|
||||
(tp-search-map (lambda (txt) ...) 'tp-name layer-name nil buf)))
|
||||
```
|
||||
|
||||
**建议**:
|
||||
- 添加缓冲区级别的响应式依赖跟踪
|
||||
- 只更新实际使用该层的缓冲区
|
||||
- 考虑使用惰性更新策略
|
||||
|
||||
#### 问题 1.2:tp-intervals 可能在大文件中变慢
|
||||
|
||||
**现象**:`object-intervals` 返回整个对象的所有区间,然后过滤。
|
||||
|
||||
**建议**:对于大文件,考虑使用 `next-property-change` 进行增量遍历。
|
||||
|
||||
---
|
||||
|
||||
### 2. 内存问题
|
||||
|
||||
#### 问题 2.1:匿名层名称无限增长
|
||||
|
||||
**现象**:`tp--anonymous-layer-counter` 只增不减,匿名层名称永不重用。
|
||||
|
||||
**代码位置**:`tp--generate-anonymous-layer-name`
|
||||
|
||||
**建议**:
|
||||
- 使用弱引用跟踪匿名层
|
||||
- 当层不再被使用时自动清理
|
||||
|
||||
#### 问题 2.2:响应式依赖可能泄漏
|
||||
|
||||
**现象**:如果缓冲区被杀死,但响应式依赖未清理,可能导致内存泄漏。
|
||||
|
||||
**建议**:
|
||||
- 添加 `kill-buffer-hook` 来清理缓冲区相关的依赖
|
||||
- 定期检查并清理无效依赖
|
||||
|
||||
---
|
||||
|
||||
### 3. 功能问题
|
||||
|
||||
#### 问题 3.1:层栈深度无限制
|
||||
|
||||
**现象**:没有限制层栈的最大深度,可能导致性能问题。
|
||||
|
||||
**建议**:添加可配置的最大深度限制。
|
||||
|
||||
#### 问题 3.2:参数化层的参数验证不足
|
||||
|
||||
**现象**:参数化层不验证传入参数的类型和数量。
|
||||
|
||||
```elisp
|
||||
(define-tp tp-space (pixel)
|
||||
`(display (space :width (,pixel))))
|
||||
|
||||
;; 错误调用不会报错
|
||||
(tp-set "test" 'tp-space) ; 缺少参数
|
||||
```
|
||||
|
||||
**建议**:在层调用时添加参数验证。
|
||||
|
||||
---
|
||||
|
||||
### 4. 代码质量问题
|
||||
|
||||
#### 问题 4.1:部分函数过长
|
||||
|
||||
**现象**:某些函数超过 100 行,如 `tp--parse-args`、`tp-set`。
|
||||
|
||||
**建议**:拆分为更小的辅助函数。
|
||||
|
||||
#### 问题 4.2:文档字符串不一致
|
||||
|
||||
**现象**:部分内部函数缺少文档字符串。
|
||||
|
||||
**建议**:为所有公开函数和重要内部函数添加文档。
|
||||
|
||||
#### 问题 4.3:错误处理不完善
|
||||
|
||||
**现象**:某些边界情况没有清晰的错误消息。
|
||||
|
||||
```elisp
|
||||
;; 调用未定义的层
|
||||
(tp-set 1 10 'undefined-layer)
|
||||
;; 可能静默失败或产生不明确的错误
|
||||
```
|
||||
|
||||
**建议**:添加清晰的错误检查和消息。
|
||||
|
||||
---
|
||||
|
||||
### 5. 测试覆盖问题
|
||||
|
||||
#### 问题 5.1:某些边界情况未测试
|
||||
|
||||
**现象**:测试主要覆盖正常流程,边界情况覆盖不足。
|
||||
|
||||
**需要补充的测试**:
|
||||
- 空字符串/空缓冲区处理
|
||||
- 极端层栈深度
|
||||
- 循环依赖检测
|
||||
- 并发修改场景
|
||||
|
||||
---
|
||||
|
||||
## 架构优化建议
|
||||
|
||||
### 1. 短期优化(低成本高收益)
|
||||
|
||||
#### 1.1 添加错误边界
|
||||
|
||||
```elisp
|
||||
(defun tp-set (...)
|
||||
"..."
|
||||
(condition-case err
|
||||
(tp--set-internal ...)
|
||||
(error
|
||||
(tp-debug-log "Error in tp-set: %s" err)
|
||||
(signal (car err) (cdr err)))))
|
||||
```
|
||||
|
||||
#### 1.2 添加性能日志
|
||||
|
||||
```elisp
|
||||
(defmacro tp--with-timing (name &rest body)
|
||||
"Execute BODY and log timing if tp-debug-mode is enabled."
|
||||
`(let ((start (float-time)))
|
||||
(prog1 (progn ,@body)
|
||||
(when tp-debug-mode
|
||||
(tp-debug-log "%s took %.3fms"
|
||||
,name
|
||||
(* 1000 (- (float-time) start)))))))
|
||||
```
|
||||
|
||||
#### 1.3 参数验证
|
||||
|
||||
```elisp
|
||||
(defun tp-layer-props (name &optional include-tp-name)
|
||||
"Get properties for layer NAME."
|
||||
(unless (symbolp name)
|
||||
(error "Layer name must be a symbol: %S" name))
|
||||
...)
|
||||
```
|
||||
|
||||
### 2. 中期优化(改进用户体验)
|
||||
|
||||
#### 2.1 层定义的本地化
|
||||
|
||||
当前所有层定义是全局的。考虑支持缓冲区本地层:
|
||||
|
||||
```elisp
|
||||
(define-tp-local my-local-layer ()
|
||||
'(face bold))
|
||||
```
|
||||
|
||||
#### 2.2 层的命名空间
|
||||
|
||||
避免层名冲突:
|
||||
|
||||
```elisp
|
||||
(define-tp (my-package . highlight) ()
|
||||
'(face (:background "yellow")))
|
||||
```
|
||||
|
||||
#### 2.3 属性继承
|
||||
|
||||
允许层继承其他层:
|
||||
|
||||
```elisp
|
||||
(define-tp error-highlight ()
|
||||
:inherit 'base-highlight
|
||||
:props '(face (:foreground "red")))
|
||||
```
|
||||
|
||||
### 3. 长期优化(架构改进)
|
||||
|
||||
#### 3.1 响应式系统优化
|
||||
|
||||
考虑采用脏标记 + 批量更新模式:
|
||||
|
||||
```elisp
|
||||
;; 标记脏数据
|
||||
(defvar tp--dirty-layers nil)
|
||||
|
||||
;; 在 idle 时更新
|
||||
(run-with-idle-timer 0.1 t #'tp--flush-dirty-layers)
|
||||
```
|
||||
|
||||
#### 3.2 层栈优化
|
||||
|
||||
使用更高效的数据结构:
|
||||
|
||||
```elisp
|
||||
;; 当前:列表
|
||||
tp-layers -> ((props1) (props2) (props3))
|
||||
|
||||
;; 优化:使用向量
|
||||
tp-layers -> [props1 props2 props3]
|
||||
```
|
||||
|
||||
#### 3.3 增量更新
|
||||
|
||||
对于大区域,考虑增量更新:
|
||||
|
||||
```elisp
|
||||
(defun tp--update-region-incremental (start end new-props)
|
||||
"Update region incrementally using property change boundaries."
|
||||
(let ((pos start))
|
||||
(while (< pos end)
|
||||
(let ((next (next-single-property-change pos 'tp-name nil end)))
|
||||
(tp--update-single-interval pos next new-props)
|
||||
(setq pos next)))))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 开发入门指南
|
||||
|
||||
### 1. 开发环境设置
|
||||
|
||||
```elisp
|
||||
;; 加载开发版本
|
||||
(add-to-list 'load-path "/path/to/tp")
|
||||
(require 'tp)
|
||||
|
||||
;; 启用调试模式
|
||||
(setq tp-debug-mode t)
|
||||
(setq tp-debug-echo t)
|
||||
|
||||
;; 运行测试
|
||||
;; emacs --batch -l tp.el -l tp-tests.el -f ert-run-tests-batch-and-exit
|
||||
```
|
||||
|
||||
### 2. 添加新功能的步骤
|
||||
|
||||
1. **理解分层架构**
|
||||
- 确定新功能属于哪一层
|
||||
- 遵循层间调用规则(只调用下层函数)
|
||||
|
||||
2. **编写测试用例**
|
||||
- 在 `tp-tests.el` 中添加测试
|
||||
- 覆盖正常流程和边界情况
|
||||
|
||||
3. **实现功能**
|
||||
- 添加必要的辅助函数
|
||||
- 添加文档字符串
|
||||
- 处理错误情况
|
||||
|
||||
4. **更新文档**
|
||||
- 更新 README.md / README_CN.md
|
||||
- 如果涉及架构变化,更新 ARCHITECTURE.md
|
||||
|
||||
### 3. 调试技巧
|
||||
|
||||
```elisp
|
||||
;; 查看层定义
|
||||
tp-layer-alist
|
||||
|
||||
;; 查看响应式依赖
|
||||
tp-reactive-deps
|
||||
|
||||
;; 查看位置属性
|
||||
(tp-at 5)
|
||||
(tp-at 5 'face)
|
||||
(tp-at 5 '(face :foreground))
|
||||
|
||||
;; 查看区间
|
||||
(tp-intervals 1 100)
|
||||
|
||||
;; 查看调试日志
|
||||
(tp-debug-show)
|
||||
```
|
||||
|
||||
### 4. 常见开发任务
|
||||
|
||||
#### 添加新的核心属性函数
|
||||
|
||||
1. 在第二层添加函数
|
||||
2. 使用 `tp--parse-args` 解析参数
|
||||
3. 调用 Emacs 原生 API
|
||||
4. 添加测试用例
|
||||
|
||||
#### 添加新的层操作函数
|
||||
|
||||
1. 在第三层添加函数
|
||||
2. 使用 `tp-intervals-map` 遍历区间
|
||||
3. 使用 `tp--get-layer-stack` 获取层栈
|
||||
4. 添加测试用例
|
||||
|
||||
#### 扩展响应式系统
|
||||
|
||||
1. 在第四层添加函数
|
||||
2. 使用 `add-variable-watcher` 注册监听
|
||||
3. 在适当位置调用 `tp--update-layer-regions`
|
||||
4. 添加测试用例
|
||||
|
||||
---
|
||||
|
||||
## 总结
|
||||
|
||||
tp.el 是一个设计精良的文本属性操作库,其核心创新包括:
|
||||
|
||||
1. **统一的 API 设计**:同一函数支持多种调用方式
|
||||
2. **属性层系统**:实现了类似图层的属性管理
|
||||
3. **响应式更新**:借鉴前端框架思想,实现数据驱动 UI
|
||||
|
||||
主要的改进方向:
|
||||
|
||||
1. **性能优化**:响应式更新的效率、大文件处理
|
||||
2. **错误处理**:参数验证、清晰的错误消息
|
||||
3. **代码质量**:函数拆分、文档完善、测试覆盖
|
||||
|
||||
对于想要参与开发的贡献者,建议:
|
||||
|
||||
1. 从理解测试用例开始
|
||||
2. 使用调试模式跟踪执行流程
|
||||
3. 遵循分层架构原则
|
||||
4. 先写测试,后写实现
|
||||
|
||||
---
|
||||
|
||||
*报告生成时间: 2026-01-10*
|
||||
*tp.el 版本: 0.1.0*
|
||||
Loading…
Reference in New Issue
Block a user