Simplify pattern matching API to (PATTERN PLIST &optional OBJECT) format

Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2025-12-15 13:24:31 +00:00
parent 8d1d721bad
commit c3ba26872a
4 changed files with 90 additions and 139 deletions

View File

@ -529,20 +529,13 @@ Clear all text properties from a region.
#### `tp-match-set` - Match String
```elisp
;; Single pattern - Buffer
(tp-match-set PATTERN '(PROPERTY VALUE ...))
;; Single pattern - String or Buffer object
(tp-match-set PATTERN OBJECT '(PROPERTY VALUE ...))
;; Multiple patterns - apply to all matches of all patterns
(tp-match-set '(PATTERN1 PATTERN2 ...) '(PROPERTY VALUE ...))
(tp-match-set '(PATTERN1 PATTERN2 ...) '(PROPERTY VALUE ...) OBJECT)
(tp-match-set PATTERN PLIST &optional OBJECT)
```
Set properties on all occurrences of a string pattern.
PATTERN can be a string (single pattern) or a list of strings (multiple patterns).
When multiple patterns are provided, each is matched and has properties applied.
PLIST is a property list like `'(face bold help-echo "tip")`.
OBJECT is a buffer or string; nil means current buffer.
**Examples:**
@ -552,7 +545,7 @@ When multiple patterns are provided, each is matched and has properties applied.
;; => ((10 . 14) (50 . 54) ...)
;; On string - returns modified string
(tp-match-set "o" "Hello World" '(face bold))
(tp-match-set "o" '(face bold) "Hello World")
;; => #("Hello World" 4 5 (face bold) 7 8 (face bold))
;; Multiple patterns - match both "world" and "Hello"
@ -570,9 +563,11 @@ When multiple patterns are provided, each is matched and has properties applied.
Reset (completely replace) all properties on matches.
PATTERN can be a string or list of strings (multiple patterns).
PLIST is a property list like `'(face bold help-echo "tip")`.
OBJECT is a buffer or string; nil means current buffer.
```elisp
(tp-match-reset PATTERN '(PROPERTY VALUE ...) &optional OBJECT)
(tp-match-reset PATTERN PLIST &optional OBJECT)
```
**Examples:**
@ -592,9 +587,11 @@ PATTERN can be a string or list of strings (multiple patterns).
Add/merge properties on matches with deep merge support.
PATTERN can be a string or list of strings (multiple patterns).
PLIST is a property list like `'(face bold help-echo "tip")`.
OBJECT is a buffer or string; nil means current buffer.
```elisp
(tp-match-add PATTERN '(PROPERTY VALUE ...) &optional OBJECT)
(tp-match-add PATTERN PLIST &optional OBJECT)
```
**Examples:**
@ -613,20 +610,13 @@ PATTERN can be a string or list of strings (multiple patterns).
#### `tp-regexp-set` - Match Regexp
```elisp
;; Single regexp - Buffer
(tp-regexp-set PATTERN '(PROPERTY VALUE ...))
;; Single regexp - String or Buffer object
(tp-regexp-set PATTERN OBJECT '(PROPERTY VALUE ...))
;; Multiple regexps - apply to all matches of all regexps
(tp-regexp-set '(REGEXP1 REGEXP2 ...) '(PROPERTY VALUE ...))
(tp-regexp-set '(REGEXP1 REGEXP2 ...) '(PROPERTY VALUE ...) OBJECT)
(tp-regexp-set PATTERN PLIST &optional OBJECT)
```
Set properties on all matches of a regular expression.
PATTERN can be a string (single regexp) or a list of strings (multiple regexps).
When multiple patterns are provided, each is matched and has properties applied.
PLIST is a property list like `'(face bold help-echo "tip")`.
OBJECT is a buffer or string; nil means current buffer.
**Examples:**
@ -635,7 +625,7 @@ When multiple patterns are provided, each is matched and has properties applied.
(tp-regexp-set "[0-9]+" '(face font-lock-number-face))
;; On string
(tp-regexp-set "[A-Z]+" "Hello WORLD" '(face bold))
(tp-regexp-set "[A-Z]+" '(face bold) "Hello WORLD")
;; => #("Hello WORLD" 6 11 (face bold))
;; Multiple regexps - match both numbers and uppercase letters
@ -649,9 +639,11 @@ When multiple patterns are provided, each is matched and has properties applied.
Reset (completely replace) all properties on regexp matches.
PATTERN can be a string or list of strings (multiple regexps).
PLIST is a property list like `'(face bold help-echo "tip")`.
OBJECT is a buffer or string; nil means current buffer.
```elisp
(tp-regexp-reset PATTERN '(PROPERTY VALUE ...) &optional OBJECT)
(tp-regexp-reset PATTERN PLIST &optional OBJECT)
```
---
@ -660,9 +652,11 @@ PATTERN can be a string or list of strings (multiple regexps).
Add/merge properties on regexp matches with deep merge support.
PATTERN can be a string or list of strings (multiple regexps).
PLIST is a property list like `'(face bold help-echo "tip")`.
OBJECT is a buffer or string; nil means current buffer.
```elisp
(tp-regexp-add PATTERN '(PROPERTY VALUE ...) &optional OBJECT)
(tp-regexp-add PATTERN PLIST &optional OBJECT)
```
---

View File

@ -528,20 +528,13 @@ tp.el 所有函数按类别组织的完整概览:
#### `tp-match-set` - 匹配字符串
```elisp
;; 单个模式 - 缓冲区
(tp-match-set PATTERN '(PROPERTY VALUE ...))
;; 单个模式 - 字符串或缓冲区对象
(tp-match-set PATTERN OBJECT '(PROPERTY VALUE ...))
;; 多个模式 - 对所有模式的所有匹配应用属性
(tp-match-set '(PATTERN1 PATTERN2 ...) '(PROPERTY VALUE ...))
(tp-match-set '(PATTERN1 PATTERN2 ...) '(PROPERTY VALUE ...) OBJECT)
(tp-match-set PATTERN PLIST &optional OBJECT)
```
在所有字符串模式匹配处设置属性。
PATTERN 可以是字符串(单个模式)或字符串列表(多个模式)。
当提供多个模式时,每个模式都会被匹配并应用属性。
PLIST 是属性列表,如 `'(face bold help-echo "tip")`
OBJECT 是缓冲区或字符串nil 表示当前缓冲区。
**示例:**
@ -551,7 +544,7 @@ PATTERN 可以是字符串(单个模式)或字符串列表(多个模式)
;; => ((10 . 14) (50 . 54) ...)
;; 在字符串上 - 返回修改后的字符串
(tp-match-set "o" "Hello World" '(face bold))
(tp-match-set "o" '(face bold) "Hello World")
;; => #("Hello World" 4 5 (face bold) 7 8 (face bold))
;; 多个模式 - 同时匹配 "world" 和 "Hello"
@ -569,9 +562,11 @@ PATTERN 可以是字符串(单个模式)或字符串列表(多个模式)
重置(完全替换)匹配处的所有属性。
PATTERN 可以是字符串或字符串列表(多个模式)。
PLIST 是属性列表,如 `'(face bold help-echo "tip")`
OBJECT 是缓冲区或字符串nil 表示当前缓冲区。
```elisp
(tp-match-reset PATTERN '(PROPERTY VALUE ...) &optional OBJECT)
(tp-match-reset PATTERN PLIST &optional OBJECT)
```
**示例:**
@ -591,9 +586,11 @@ PATTERN 可以是字符串或字符串列表(多个模式)。
在匹配处添加/合并属性,支持深度合并。
PATTERN 可以是字符串或字符串列表(多个模式)。
PLIST 是属性列表,如 `'(face bold help-echo "tip")`
OBJECT 是缓冲区或字符串nil 表示当前缓冲区。
```elisp
(tp-match-add PATTERN '(PROPERTY VALUE ...) &optional OBJECT)
(tp-match-add PATTERN PLIST &optional OBJECT)
```
**示例:**
@ -612,20 +609,13 @@ PATTERN 可以是字符串或字符串列表(多个模式)。
#### `tp-regexp-set` - 匹配正则表达式
```elisp
;; 单个正则 - 缓冲区
(tp-regexp-set PATTERN '(PROPERTY VALUE ...))
;; 单个正则 - 字符串或缓冲区对象
(tp-regexp-set PATTERN OBJECT '(PROPERTY VALUE ...))
;; 多个正则 - 对所有正则的所有匹配应用属性
(tp-regexp-set '(REGEXP1 REGEXP2 ...) '(PROPERTY VALUE ...))
(tp-regexp-set '(REGEXP1 REGEXP2 ...) '(PROPERTY VALUE ...) OBJECT)
(tp-regexp-set PATTERN PLIST &optional OBJECT)
```
在所有正则表达式匹配处设置属性。
PATTERN 可以是字符串(单个正则)或字符串列表(多个正则)。
当提供多个模式时,每个模式都会被匹配并应用属性。
PLIST 是属性列表,如 `'(face bold help-echo "tip")`
OBJECT 是缓冲区或字符串nil 表示当前缓冲区。
**示例:**
@ -634,7 +624,7 @@ PATTERN 可以是字符串(单个正则)或字符串列表(多个正则)
(tp-regexp-set "[0-9]+" '(face font-lock-number-face))
;; 在字符串上
(tp-regexp-set "[A-Z]+" "Hello WORLD" '(face bold))
(tp-regexp-set "[A-Z]+" '(face bold) "Hello WORLD")
;; => #("Hello WORLD" 6 11 (face bold))
;; 多个正则 - 同时匹配数字和大写字母
@ -648,9 +638,11 @@ PATTERN 可以是字符串(单个正则)或字符串列表(多个正则)
重置(完全替换)正则匹配处的所有属性。
PATTERN 可以是字符串或字符串列表(多个正则)。
PLIST 是属性列表,如 `'(face bold help-echo "tip")`
OBJECT 是缓冲区或字符串nil 表示当前缓冲区。
```elisp
(tp-regexp-reset PATTERN '(PROPERTY VALUE ...) &optional OBJECT)
(tp-regexp-reset PATTERN PLIST &optional OBJECT)
```
---
@ -659,9 +651,11 @@ PATTERN 可以是字符串或字符串列表(多个正则)。
在正则匹配处添加/合并属性,支持深度合并。
PATTERN 可以是字符串或字符串列表(多个正则)。
PLIST 是属性列表,如 `'(face bold help-echo "tip")`
OBJECT 是缓冲区或字符串nil 表示当前缓冲区。
```elisp
(tp-regexp-add PATTERN '(PROPERTY VALUE ...) &optional OBJECT)
(tp-regexp-add PATTERN PLIST &optional OBJECT)
```
---

View File

@ -549,7 +549,7 @@
"Test tp-match-set sets properties on string matches."
(tp-test-with-temp-buffer
(insert "Hello World Hello")
(let ((regions (tp-match-set "Hello" 'face 'bold)))
(let ((regions (tp-match-set "Hello" '(face bold))))
(should (= (length regions) 2))
(should (eq (tp-at 1 'face) 'bold))
(should (eq (tp-at 13 'face) 'bold)))))
@ -558,7 +558,7 @@
"Test tp-match-set returns correct region pairs."
(tp-test-with-temp-buffer
(insert "Hello World Hello")
(let ((regions (tp-match-set "Hello")))
(let ((regions (tp-match-set "Hello" nil)))
(should (= (length regions) 2))
(should (equal (car regions) '(1 . 6)))
(should (equal (cadr regions) '(13 . 18))))))
@ -567,7 +567,7 @@
"Test tp-regexp-set sets properties on regexp matches."
(tp-test-with-temp-buffer
(insert "abc 123 def 456")
(let ((regions (tp-regexp-set "[0-9]+" 'face 'bold)))
(let ((regions (tp-regexp-set "[0-9]+" '(face bold))))
(should (= (length regions) 2))
(should (eq (tp-at 5 'face) 'bold))
(should (eq (tp-at 13 'face) 'bold)))))
@ -576,7 +576,7 @@
"Test tp-regexp-set returns correct region pairs."
(tp-test-with-temp-buffer
(insert "abc 123 def 456")
(let ((regions (tp-regexp-set "[0-9]+")))
(let ((regions (tp-regexp-set "[0-9]+" nil)))
(should (= (length regions) 2)))))
;;; ============================================================
@ -945,7 +945,7 @@
(ert-deftest tp-test-match-set-on-string ()
"Test tp-match-set works on string objects."
(let* ((str (copy-sequence "Hello World Hello"))
(result (tp-match-set "Hello" str 'face 'bold)))
(result (tp-match-set "Hello" '(face bold) str)))
(should (stringp result))
(should (eq (get-text-property 0 'face result) 'bold))
(should (eq (get-text-property 12 'face result) 'bold))
@ -954,7 +954,7 @@
(ert-deftest tp-test-regexp-set-on-string ()
"Test tp-regexp-set works on string objects."
(let* ((str (copy-sequence "abc 123 def 456"))
(result (tp-regexp-set "[0-9]+" str 'face 'bold)))
(result (tp-regexp-set "[0-9]+" '(face bold) str)))
(should (stringp result))
(should (eq (get-text-property 4 'face result) 'bold))
(should (eq (get-text-property 12 'face result) 'bold))
@ -1194,7 +1194,7 @@ Returns list of (START END VALUE) intervals."
(ert-deftest tp-test-match-reset-on-string ()
"Test tp-match-reset on string."
(let* ((str (copy-sequence "Hello World Hello"))
(result (tp-match-reset "Hello" str '(face bold))))
(result (tp-match-reset "Hello" '(face bold) str)))
(should (eq (get-text-property 0 'face result) 'bold))
(should (eq (get-text-property 12 'face result) 'bold))))
@ -1202,7 +1202,7 @@ Returns list of (START END VALUE) intervals."
"Test tp-regexp-add on string."
(let ((str (copy-sequence "abc 123 def 456")))
(tp-set 4 7 '(help-echo "original") str)
(tp-regexp-add "[0-9]+" str '(face bold))
(tp-regexp-add "[0-9]+" '(face bold) str)
(should (eq (get-text-property 4 'face str) 'bold))
(should (equal (get-text-property 4 'help-echo str) "original"))))

121
tp.el
View File

@ -817,47 +817,12 @@ Returns modified object or list of regions."
(defun tp--parse-match-args (args)
"Parse match/regexp function ARGS.
Returns (OBJECT . PROPERTIES).
Handles two calling conventions:
1. (OBJECT PROPERTY VALUE ...) or (OBJECT \\='(PROPERTY VALUE ...))
2. (\\='(PROPERTY VALUE ...) OBJECT) or (PROPERTY VALUE ... OBJECT)"
(let (object properties)
(cond
;; First arg is a string - it's the object
((and args (stringp (car args)))
(setq object (car args)
properties (cdr args)))
;; First arg is a buffer - it's the object
((and args (bufferp (car args)))
(setq object (car args)
properties (cdr args)))
;; First arg is a list (properties) and last arg might be object
((and args (listp (car args)))
(let ((last-arg (car (last args))))
(if (or (stringp last-arg) (bufferp last-arg))
;; Last arg is object: '(props) object
(setq object last-arg
properties (car args))
;; No object, just properties
(setq object nil
properties (car args)))))
;; Check if last arg is an object (for flat property args)
((and args (>= (length args) 2))
(let ((last-arg (car (last args))))
(if (or (stringp last-arg) (bufferp last-arg))
;; Last arg is object: prop val ... object
(setq object last-arg
properties (butlast args))
;; No object, all are properties
(setq object nil
properties args))))
;; No object specified
(t
(setq object nil
properties args)))
;; Handle properties as a list (normalize)
(when (and (listp (car-safe properties)) (= (length properties) 1))
(setq properties (car properties)))
(cons object properties)))
Supports the calling convention:
(PLIST &optional OBJECT)
Where PLIST is a property list and OBJECT is a buffer or string (nil for current buffer)."
(let ((plist (car args))
(object (cadr args)))
(cons object plist)))
(defun tp--deep-merge-apply (start end props obj)
"Apply PROPS to OBJ from START to END with deep merge.
@ -880,24 +845,13 @@ Merges nested plists instead of replacing them."
(defun tp-match-set (pattern &rest args)
"Set properties on all occurrences of PATTERN.
This function supports multiple calling conventions:
1. With OBJECT (string or buffer):
(tp-match-set PATTERN OBJECT PROPERTY VALUE ...)
(tp-match-set PATTERN OBJECT \\='(PROPERTY VALUE ...))
(tp-match-set PATTERN \\='(PROPERTY VALUE ...) OBJECT)
2. Without OBJECT (current buffer):
(tp-match-set PATTERN PROPERTY VALUE ...)
(tp-match-set PATTERN \\='(PROPERTY VALUE ...))
3. Multiple patterns (list of patterns to match):
(tp-match-set \\='(\"pattern1\" \"pattern2\" ...) \\='(PROPERTY VALUE ...))
(tp-match-set \\='(\"pattern1\" \"pattern2\" ...) \\='(PROPERTY VALUE ...) OBJECT)
(tp-match-set PATTERN PLIST &optional OBJECT)
PATTERN is a string (single pattern) or list of strings (multiple patterns).
Each pattern will be matched and have properties applied.
PROPERTIES is a plist of property-value pairs.
PLIST is a property list like \\='(face bold help-echo \"tip\").
OBJECT is a buffer or string; nil means current buffer.
Returns:
- For strings: the modified string
- For buffers: list of (START . END) pairs for all matches."
@ -908,8 +862,13 @@ Returns:
(defun tp-match-reset (pattern &rest args)
"Reset (completely replace) properties on all occurrences of PATTERN.
Same calling conventions as `tp-match-set'.
PATTERN can be a string or list of strings (multiple patterns).
(tp-match-reset PATTERN PLIST &optional OBJECT)
PATTERN is a string (single pattern) or list of strings (multiple patterns).
PLIST is a property list like \\='(face bold help-echo \"tip\").
OBJECT is a buffer or string; nil means current buffer.
Unlike `tp-match-set', this completely replaces all existing properties."
(let* ((parsed (tp--parse-match-args args))
(object (car parsed))
@ -921,8 +880,13 @@ Unlike `tp-match-set', this completely replaces all existing properties."
(defun tp-match-add (pattern &rest args)
"Add/update properties on all occurrences of PATTERN.
Same calling conventions as `tp-match-set'.
PATTERN can be a string or list of strings (multiple patterns).
(tp-match-add PATTERN PLIST &optional OBJECT)
PATTERN is a string (single pattern) or list of strings (multiple patterns).
PLIST is a property list like \\='(face bold help-echo \"tip\").
OBJECT is a buffer or string; nil means current buffer.
Unlike `tp-match-set', this deeply merges nested properties."
(let* ((parsed (tp--parse-match-args args))
(object (car parsed))
@ -932,24 +896,13 @@ Unlike `tp-match-set', this deeply merges nested properties."
(defun tp-regexp-set (pattern &rest args)
"Set properties on all matches of PATTERN (regexp).
This function supports multiple calling conventions:
1. With OBJECT (string or buffer):
(tp-regexp-set PATTERN OBJECT PROPERTY VALUE ...)
(tp-regexp-set PATTERN OBJECT \\='(PROPERTY VALUE ...))
(tp-regexp-set PATTERN \\='(PROPERTY VALUE ...) OBJECT)
2. Without OBJECT (current buffer):
(tp-regexp-set PATTERN PROPERTY VALUE ...)
(tp-regexp-set PATTERN \\='(PROPERTY VALUE ...))
3. Multiple patterns (list of regexps to match):
(tp-regexp-set \\='(\"regexp1\" \"regexp2\" ...) \\='(PROPERTY VALUE ...))
(tp-regexp-set \\='(\"regexp1\" \"regexp2\" ...) \\='(PROPERTY VALUE ...) OBJECT)
(tp-regexp-set PATTERN PLIST &optional OBJECT)
PATTERN is a string (single regexp) or list of strings (multiple regexps).
Each pattern will be matched and have properties applied.
PROPERTIES is a plist of property-value pairs.
PLIST is a property list like \\='(face bold help-echo \"tip\").
OBJECT is a buffer or string; nil means current buffer.
Returns:
- For strings: the modified string
- For buffers: list of (START . END) pairs for all matches."
@ -960,8 +913,13 @@ Returns:
(defun tp-regexp-reset (pattern &rest args)
"Reset (completely replace) properties on all regexp matches of PATTERN.
Same calling conventions as `tp-regexp-set'.
PATTERN can be a string or list of strings (multiple regexps).
(tp-regexp-reset PATTERN PLIST &optional OBJECT)
PATTERN is a string (single regexp) or list of strings (multiple regexps).
PLIST is a property list like \\='(face bold help-echo \"tip\").
OBJECT is a buffer or string; nil means current buffer.
Unlike `tp-regexp-set', this completely replaces all existing properties."
(let* ((parsed (tp--parse-match-args args))
(object (car parsed))
@ -973,8 +931,13 @@ Unlike `tp-regexp-set', this completely replaces all existing properties."
(defun tp-regexp-add (pattern &rest args)
"Add/update properties on all regexp matches of PATTERN.
Same calling conventions as `tp-regexp-set'.
PATTERN can be a string or list of strings (multiple regexps).
(tp-regexp-add PATTERN PLIST &optional OBJECT)
PATTERN is a string (single regexp) or list of strings (multiple regexps).
PLIST is a property list like \\='(face bold help-echo \"tip\").
OBJECT is a buffer or string; nil means current buffer.
Unlike `tp-regexp-set', this deeply merges nested properties."
(let* ((parsed (tp--parse-match-args args))
(object (car parsed))