16 KiB
tp.el - Emacs 文本属性操作库
一个功能强大的文本属性操作库,具有创新的图层系统
功能特性 • 安装 • 快速开始 • API 参考 • 图层系统
tp.el 提供了一个便捷统一的 API 来操作 Emacs 文本属性。灵感来自用于叠加层的 ov.el,tp.el 提供:
- 统一 API:所有属性设置函数同时支持 字符串 和 缓冲区
- 图层系统:在同一文本区域上堆叠多组属性
- 模式匹配:将属性应用到匹配字符串或正则表达式的文本
功能特性
- ✅ 统一对象支持:
tp-put、tp-match、tp-regexp等函数同时支持字符串和缓冲区 - ✅ 创新图层系统:堆叠、轮换和管理多层属性
- ✅ 图层组:定义可复用的相关图层集合
- ✅ 搜索和导航:查找并导航带属性的文本
- ✅ 模式匹配:将属性应用到字符串/正则匹配
- ✅ 简洁 API:一致的命名和调用约定
系统要求
- Emacs 28.1+(使用
object-intervals函数) - dash.el(列表操作工具库)
安装
;; 添加到 load-path
(add-to-list 'load-path "/path/to/tp")
(require 'tp)
或使用 use-package:
(use-package tp
:load-path "/path/to/tp")
快速开始
设置属性
;; 在当前缓冲区(属性作为列表)
(tp-put 1 10 '(face bold help-echo "Hello!"))
;; 在特定缓冲区
(tp-put 1 10 '(face bold) some-buffer)
;; 在字符串上(0 索引)
(tp-put 0 5 '(face bold) "Hello World")
;; => #("Hello World" 0 5 (face bold))
;; 在整个字符串上(平铺属性)
(tp-put "Hello World" 'face 'bold 'help-echo "test")
;; => #("Hello World" 0 11 (face bold help-echo "test"))
获取属性
;; 获取特定位置的属性
(tp-get 5 'face) ; => bold
;; 获取范围内的特定属性
(tp-get 1 10 'face) ; => bold
;; 获取范围内的所有属性
(tp-get 1 10) ; => (face bold help-echo "Hello!")
;; 获取该位置的所有属性
(tp-at 5) ; => (face bold help-echo "Hello!")
细粒度属性操作
;; 获取 face 的子属性
(tp-get-sub 1 'face :foreground) ; => "red"
;; 设置 face 的子属性
(tp-put-sub 1 6 'face :foreground "blue")
;; 移除 face 的子属性
(tp-remove-sub 1 6 'face :foreground)
模式匹配
;; 将属性应用到缓冲区中所有 "TODO" 出现的位置
(tp-match "TODO" 'face 'warning)
;; 应用到字符串
(tp-match "world" "Hello world world" 'face 'bold)
;; => #("Hello world world" 6 11 (face bold) 12 17 (face bold))
;; 使用正则表达式
(tp-regexp "\\b[0-9]+\\b" 'face 'font-lock-number-face)
API 参考
核心属性函数
tp-put - 设置文本属性
在字符串或缓冲区区域上设置文本属性。
;; 当前缓冲区(属性作为列表)
(tp-put START END '(PROPERTY VALUE ...))
;; 特定缓冲区或字符串
(tp-put START END '(PROPERTY VALUE ...) OBJECT)
;; 整个字符串(平铺属性)
(tp-put STRING PROPERTY VALUE ...)
示例:
;; 在缓冲区区域设置 face
(tp-put 1 10 '(face bold)) ; => (1 . 10)
;; 设置多个属性
(tp-put 1 10 '(face bold help-echo "Click me"))
;; 在特定缓冲区设置
(tp-put 1 10 '(face italic) my-buffer)
;; 在字符串上设置属性(0 索引)
(setq my-string (tp-put 0 5 '(face italic) "Hello World"))
;; => #("Hello World" 0 5 (face italic))
;; 在整个字符串上设置属性
(tp-put "Hello" 'face 'bold 'mouse-face 'highlight)
;; => #("Hello" 0 5 (face bold mouse-face highlight))
tp-get - 获取属性值
从位置或范围获取属性值。
;; 单个位置
(tp-get POSITION PROPERTY)
(tp-get POSITION PROPERTY OBJECT)
;; 范围 - 特定属性
(tp-get START END PROPERTY)
(tp-get START END PROPERTY OBJECT)
;; 范围 - 所有属性
(tp-get START END)
(tp-get START END OBJECT)
示例:
;; 从当前缓冲区获取
(tp-get 5 'face) ; => bold
;; 从字符串获取(0 索引)
(tp-get 0 'face my-string) ; => italic
;; 从范围获取
(tp-get 1 10 'face) ; => bold
;; 获取范围内的所有属性
(tp-get 1 10) ; => (face bold help-echo "test")
细粒度属性函数
用于操作复杂属性(如 face 或 display)内的子属性:
;; 获取子属性
(tp-get-sub POSITION PROPERTY SUB-PROPERTY &optional OBJECT)
;; 设置子属性
(tp-put-sub START END PROPERTY SUB-PROPERTY VALUE &optional OBJECT)
;; 移除子属性
(tp-remove-sub START END PROPERTY SUB-PROPERTY &optional OBJECT)
示例:
;; 获取 face 的 :foreground
(tp-get-sub 1 'face :foreground) ; => "red"
;; 设置 face 的 :weight
(tp-put-sub 1 6 'face :weight 'bold)
;; 移除 face 的 :background
(tp-remove-sub 1 6 'face :background)
tp-at - 获取所有属性
(tp-at &optional POINT OBJECT)
获取 POINT 位置的所有文本属性,返回属性列表。
示例:
(tp-at 5) ; => (face bold help-echo "test")
(tp-at 0 my-string) ; 从字符串获取
tp-remove - 移除属性
(tp-remove START END PROPERTY &optional OBJECT)
从区域中移除特定属性。
示例:
(tp-remove 1 10 'face) ; 移除 face 属性
tp-remove-list - 移除多个属性
(tp-remove-list START END PROPERTIES &optional OBJECT)
一次移除多个属性。
示例:
(tp-remove-list 1 10 '(face help-echo mouse-face))
tp-clear - 清除所有属性
(tp-clear &optional START END OBJECT)
清除区域中的所有文本属性。
示例:
(tp-clear 1 10) ; 清除区域
(tp-clear) ; 清除整个缓冲区
属性化函数
tp-propertize - 创建带属性的字符串
;; 创建带属性的字符串
(tp-propertize STRING PROPERTY VALUE ...)
(tp-propertize STRING '(PROPERTY VALUE ...))
;; 应用到对象的区域
(tp-propertize OBJECT START END PROPERTY VALUE ...)
示例:
;; 简单用法 - 返回带属性的字符串
(tp-propertize "Hello" 'face 'bold)
;; => #("Hello" 0 5 (face bold))
;; 使用属性列表
(tp-propertize "World" '(face italic help-echo "greeting"))
;; 应用到子字符串
(tp-propertize "Hello World" 6 11 'face 'underline)
tp-layer-propertize - 将图层应用到对象
(tp-layer-propertize OBJECT LAYER &optional START END)
将预定义图层的属性应用到对象。
示例:
;; 首先定义一个图层
(tp-layer-define highlight '(face (:background "yellow")))
;; 应用到字符串
(tp-layer-propertize "Important" 'highlight)
;; 应用到子字符串
(tp-layer-propertize "Hello World" 'highlight 0 5)
;; 应用到缓冲区区域
(tp-layer-propertize (current-buffer) 'highlight 1 10)
tp-group-propertize - 应用图层组
(tp-group-propertize OBJECT LAYER-GROUP &optional START END)
将图层组中的所有图层应用到对象。
模式匹配函数
tp-match - 匹配字符串
;; 缓冲区
(tp-match PATTERN PROPERTY VALUE ...)
;; 字符串或缓冲区对象
(tp-match PATTERN OBJECT PROPERTY VALUE ...)
在所有字符串模式匹配处设置属性。
示例:
;; 在缓冲区中 - 返回 (START . END) 对的列表
(tp-match "TODO" 'face 'warning)
;; => ((10 . 14) (50 . 54) ...)
;; 在字符串上 - 返回修改后的字符串
(tp-match "o" "Hello World" 'face 'bold)
;; => #("Hello World" 4 5 (face bold) 7 8 (face bold))
tp-regexp - 匹配正则表达式
;; 缓冲区
(tp-regexp PATTERN PROPERTY VALUE ...)
;; 字符串或缓冲区对象
(tp-regexp PATTERN OBJECT PROPERTY VALUE ...)
在所有正则表达式匹配处设置属性。
示例:
;; 高亮缓冲区中的所有数字
(tp-regexp "[0-9]+" 'face 'font-lock-number-face)
;; 在字符串上
(tp-regexp "[A-Z]+" "Hello WORLD" 'face 'bold)
;; => #("Hello WORLD" 6 11 (face bold))
搜索和导航函数
tp-forward / tp-backward
(tp-forward PROPERTY &optional VALUE PREDICATE NOT-CURRENT)
(tp-backward PROPERTY &optional VALUE PREDICATE NOT-CURRENT)
向前/向后搜索具有 PROPERTY 的文本。
示例:
;; 查找下一个具有 'marker 属性的文本
(tp-forward 'marker)
;; 查找下一个 'type 等于 'heading 的文本
(tp-forward 'type 'heading)
tp-next / tp-prev
(tp-next &optional POINT PROPERTY VALUE)
(tp-prev &optional POINT PROPERTY VALUE)
获取下一个/上一个具有文本属性的位置。
tp-goto-next / tp-goto-prev
(tp-goto-next &optional PROPERTY VALUE)
(tp-goto-prev &optional PROPERTY VALUE)
将光标移动到下一个/上一个具有 PROPERTY 的文本。
tp-regions-map / tp-strings-map
(tp-regions-map FUNCTION PROPERTY &optional VALUE PREDICATE COLLECT)
(tp-strings-map FUNCTION PROPERTY &optional VALUE PREDICATE COLLECT)
对所有具有 PROPERTY 的区域/字符串应用函数。
示例:
;; 处理所有标记的文本
(tp-strings-map
(lambda (str idx)
(message "找到: %s,索引 %d" str idx))
'marker)
查询函数
tp-in - 查找具有属性的区域
(tp-in PROPERTY &optional VALUE START END)
获取当前缓冲区中所有具有 PROPERTY 的区域。
示例:
;; 获取所有具有 'marker 属性的区域
(tp-in 'marker)
;; => ((1 5 (marker t ...)) (10 15 (marker t ...)))
;; 按值过滤
(tp-in 'type 'heading)
tp-all - 获取所有带属性的区域
(tp-all &optional START END)
获取所有具有任何文本属性的区域。
tp-intervals - 获取属性区间
(tp-intervals START END &optional OBJECT)
获取区域中所有文本属性区间。
tp-empty-p - 检查属性
(tp-empty-p OBJECT)
如果 OBJECT 没有文本属性则返回 t。
tp-plist - 获取合并的属性
(tp-plist START END &optional OBJECT)
获取区域中所有属性的合并属性列表。
图层系统
图层系统是 tp.el 的创新功能,允许在同一文本区域上堆叠多组属性。只有顶层可见,但下层会被保留,可以通过轮换或置顶来显示。
图层概念
┌─────────────────────────────┐
│ 顶层(可见) │ ← 你看到的
├─────────────────────────────┤
│ 中间层(隐藏) │ ← 被保留
├─────────────────────────────┤
│ 底层(隐藏) │ ← 被保留
└─────────────────────────────┘
图层定义函数
tp-layer-define - 定义图层
(tp-layer-define NAME PROPERTIES)
定义一个带属性的命名图层。
示例:
(tp-layer-define highlight
'(face (:background "yellow" :foreground "black")))
(tp-layer-define error
'(face (:background "red" :foreground "white")
help-echo "错误!"))
(tp-layer-define info
'(face (:background "blue" :foreground "white")))
tp-group-define - 定义图层组
(tp-group-define NAME
LAYER1 PROPERTIES1
LAYER2 PROPERTIES2
...)
定义一组相关的图层。
示例:
(tp-group-define status-colors
status-ok '(face (:foreground "green"))
status-warning '(face (:foreground "orange"))
status-error '(face (:foreground "red")))
tp-layer-props / tp-group-props
(tp-layer-props LAYER-NAME)
(tp-group-props GROUP-NAME)
获取图层或图层组中所有图层的属性。
tp-layer-undefine / tp-group-undefine
(tp-layer-undefine NAME)
(tp-group-undefine NAME)
移除图层或图层组定义。
tp-layer-reset
(tp-layer-reset)
清除所有图层和图层组定义。
图层操作函数
tp-layer-push - 添加图层
(tp-layer-push START END NAME &optional OBJECT)
将图层推到堆栈顶部。
示例:
(tp-layer-define base '(face default))
(tp-layer-define highlight '(face (:background "yellow")))
;; 首先推入 base 图层
(tp-layer-push 1 10 'base)
;; 将 highlight 推到顶部(现在可见)
(tp-layer-push 1 10 'highlight)
tp-layer-delete - 删除图层
(tp-layer-delete START END NAME &optional OBJECT)
从堆栈任何位置删除图层。
示例:
;; 删除 highlight 图层
(tp-layer-delete 1 10 'highlight)
;; base 图层现在可见
tp-layer-rotate - 轮换图层
(tp-layer-rotate START END &optional OBJECT)
轮换图层 - 顶层移到底部,下一层变为可见。
示例:
;; 堆栈: highlight (顶) -> base (底)
(tp-layer-rotate 1 10)
;; 堆栈: base (顶) -> highlight (底)
tp-layer-pin - 将图层置顶
(tp-layer-pin START END NAME &optional OBJECT)
将特定图层移到顶部。
示例:
;; 将 'base 设为顶层
(tp-layer-pin 1 10 'base)
tp-layer-hide / tp-layer-show
(tp-layer-hide START END NAME &optional OBJECT)
(tp-layer-show START END NAME &optional OBJECT)
隐藏图层(移到底部)或显示图层(移到顶部)。
tp-layer-merge
(tp-layer-merge START END LAYER1 LAYER2 NEW-NAME &optional OBJECT)
将两个图层合并为一个新图层。
图层查询函数
tp-layer-list - 列出所有图层
(tp-layer-list START END &optional OBJECT)
获取区域中所有图层名称的列表。
示例:
(tp-layer-list 1 10) ; => (highlight base)
tp-layer-count
(tp-layer-count START END &optional OBJECT)
计算区域中的图层数量。
tp-layer-exists-p
(tp-layer-exists-p START END NAME &optional OBJECT)
检查区域中是否存在某图层。
tp-layer-top
(tp-layer-top START END &optional OBJECT)
获取顶层(可见)图层的名称。
实用示例
多图层语法高亮
;; 为不同高亮目的定义图层
(tp-layer-define code-base
'(face font-lock-keyword-face))
(tp-layer-define code-error
'(face (:underline (:color "red" :style wave))
help-echo "语法错误"))
(tp-layer-define code-debug
'(face (:background "dark blue")))
;; 应用基础高亮
(tp-layer-push 1 100 'code-base)
;; 在有问题的代码上添加错误高亮
(tp-layer-push 50 60 'code-error)
;; 在错误和正常视图之间切换
(defun toggle-error-view ()
(interactive)
(tp-layer-rotate 50 60))
状态指示器
(tp-group-define task-status
status-todo '(face (:foreground "gray"))
status-progress '(face (:foreground "yellow"))
status-done '(face (:foreground "green")))
;; 循环切换状态
(defun cycle-task-status ()
(interactive)
(tp-layer-rotate (line-beginning-position) (line-end-position)))
临时高亮
(tp-layer-define temp-highlight
'(face (:background "yellow")))
(defun flash-region (start end)
"临时闪烁一个区域。"
(tp-layer-push start end 'temp-highlight)
(run-with-timer 0.5 nil
(lambda ()
(tp-layer-delete start end 'temp-highlight))))
别名
为方便使用,tp.el 提供以下别名:
| 别名 | 原函数 |
|---|---|
tp-set |
tp-put |
tp-layer-properties |
tp-layer-props |
tp-layer-group-define |
tp-group-define |
tp-layer-group-properties |
tp-group-props |
tp-layer-group-propertize |
tp-group-propertize |
tp-layer-group-undefine |
tp-group-undefine |
许可证
GNU 通用公共许可证 v2 或更高版本。
贡献
欢迎贡献!请随时提交 issues 或 pull requests。
tp.el - 让文本属性变得强大且易用