From c3ba26872ad048bcee0f3202a9e89677a33da5e6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Dec 2025 13:24:31 +0000 Subject: [PATCH] Simplify pattern matching API to (PATTERN PLIST &optional OBJECT) format Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com> --- README.md | 46 +++++++++----------- README_CN.md | 46 +++++++++----------- tp-tests.el | 16 +++---- tp.el | 121 ++++++++++++++++++--------------------------------- 4 files changed, 90 insertions(+), 139 deletions(-) diff --git a/README.md b/README.md index c72fc43..65a9f04 100644 --- a/README.md +++ b/README.md @@ -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) ``` --- diff --git a/README_CN.md b/README_CN.md index fd960a3..af754a9 100644 --- a/README_CN.md +++ b/README_CN.md @@ -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) ``` --- diff --git a/tp-tests.el b/tp-tests.el index 0aec3ef..d2458b9 100644 --- a/tp-tests.el +++ b/tp-tests.el @@ -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")))) diff --git a/tp.el b/tp.el index c2cfd07..391b4e6 100644 --- a/tp.el +++ b/tp.el @@ -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))