Add support for deeply nested sub-properties and multiple key extraction in tp-get
Co-authored-by: Kinneyzhang <38454496+Kinneyzhang@users.noreply.github.com>
This commit is contained in:
parent
b31077e486
commit
3f7f8cd9b9
14
README.md
14
README.md
@ -312,6 +312,12 @@ For range and entire string queries, returns a list of `(START END VALUE)` inter
|
||||
(tp-get START END '(PROPERTY) OBJECT)
|
||||
(tp-get START END '(PROPERTY SUB-KEY ...) OBJECT)
|
||||
|
||||
;; Range with deeply nested property path
|
||||
(tp-get START END '(PROPERTY SUB-KEY SUB-SUB-KEY ...) OBJECT)
|
||||
|
||||
;; Range extracting multiple keys from nested property
|
||||
(tp-get START END '(PROPERTY SUB-KEY (KEY1 KEY2 ...)) OBJECT)
|
||||
|
||||
;; Range - all properties (returns list of intervals)
|
||||
(tp-get START END)
|
||||
(tp-get START END OBJECT)
|
||||
@ -320,6 +326,7 @@ For range and entire string queries, returns a list of `(START END VALUE)` inter
|
||||
(tp-get STRING)
|
||||
(tp-get STRING PROPERTY)
|
||||
(tp-get STRING PROPERTY SUB-KEY ...)
|
||||
(tp-get STRING PROPERTY SUB-KEY '(KEY1 KEY2 ...))
|
||||
(tp-get STRING '(PROPERTY SUB-KEY ...))
|
||||
```
|
||||
|
||||
@ -348,6 +355,13 @@ For range and entire string queries, returns a list of `(START END VALUE)` inter
|
||||
;; Get with property path as list
|
||||
(tp-get 5 20 '(face :underline :style) my-string) ; => ((5 20 wave))
|
||||
|
||||
;; Get deeply nested property from entire string
|
||||
(tp-get str 'face :underline :color) ; => ((0 5 "green") (6 11 "yellow"))
|
||||
|
||||
;; Get multiple keys from nested property
|
||||
(tp-get str 'face :underline '(:color :style))
|
||||
;; => ((0 5 (:color "green" :style wave)) (6 11 (:color "yellow" :style line)))
|
||||
|
||||
;; Get all properties from range
|
||||
(tp-get 1 10) ; => ((1 6 (face bold help-echo "test")))
|
||||
|
||||
|
||||
14
README_CN.md
14
README_CN.md
@ -311,6 +311,12 @@ tp.el 提供三个主要的属性设置函数,每个有不同的语义:
|
||||
(tp-get START END '(PROPERTY) OBJECT)
|
||||
(tp-get START END '(PROPERTY SUB-KEY ...) OBJECT)
|
||||
|
||||
;; 范围 - 深层嵌套属性路径
|
||||
(tp-get START END '(PROPERTY SUB-KEY SUB-SUB-KEY ...) OBJECT)
|
||||
|
||||
;; 范围 - 从嵌套属性中提取多个键
|
||||
(tp-get START END '(PROPERTY SUB-KEY (KEY1 KEY2 ...)) OBJECT)
|
||||
|
||||
;; 范围 - 所有属性(返回区间列表)
|
||||
(tp-get START END)
|
||||
(tp-get START END OBJECT)
|
||||
@ -319,6 +325,7 @@ tp.el 提供三个主要的属性设置函数,每个有不同的语义:
|
||||
(tp-get STRING)
|
||||
(tp-get STRING PROPERTY)
|
||||
(tp-get STRING PROPERTY SUB-KEY ...)
|
||||
(tp-get STRING PROPERTY SUB-KEY '(KEY1 KEY2 ...))
|
||||
(tp-get STRING '(PROPERTY SUB-KEY ...))
|
||||
```
|
||||
|
||||
@ -347,6 +354,13 @@ tp.el 提供三个主要的属性设置函数,每个有不同的语义:
|
||||
;; 使用列表形式的属性路径
|
||||
(tp-get 5 20 '(face :underline :style) my-string) ; => ((5 20 wave))
|
||||
|
||||
;; 从整个字符串获取深层嵌套属性
|
||||
(tp-get str 'face :underline :color) ; => ((0 5 "green") (6 11 "yellow"))
|
||||
|
||||
;; 从嵌套属性中获取多个键
|
||||
(tp-get str 'face :underline '(:color :style))
|
||||
;; => ((0 5 (:color "green" :style wave)) (6 11 (:color "yellow" :style line)))
|
||||
|
||||
;; 获取范围内的所有属性
|
||||
(tp-get 1 10) ; => ((1 6 (face bold help-echo "test")))
|
||||
|
||||
|
||||
33
tp-tests.el
33
tp-tests.el
@ -1239,5 +1239,38 @@ Returns list of (START END VALUE) intervals."
|
||||
(should (equal (car intervals) '(0 5 bold)))
|
||||
(should (equal (cadr intervals) '(12 17 italic))))))
|
||||
|
||||
(ert-deftest tp-test-get-deeply-nested-property ()
|
||||
"Test tp-get with deeply nested property path."
|
||||
(let ((str (copy-sequence "Hello World")))
|
||||
(put-text-property 0 5 'face '(:foreground "red" :underline (:color "green" :style wave)) str)
|
||||
(put-text-property 6 11 'face '(:foreground "blue" :underline (:color "yellow" :style line)) str)
|
||||
;; Test deeply nested single key from entire string
|
||||
(let ((intervals (tp-get str 'face :underline :color)))
|
||||
(should (= (length intervals) 2))
|
||||
(should (equal (caddr (car intervals)) "green"))
|
||||
(should (equal (caddr (cadr intervals)) "yellow")))
|
||||
;; Test range with deeply nested key
|
||||
(let ((intervals (tp-get 0 7 '(face :underline :color) str)))
|
||||
(should (= (length intervals) 2))
|
||||
(should (equal (caddr (car intervals)) "green")))))
|
||||
|
||||
(ert-deftest tp-test-get-multiple-nested-keys ()
|
||||
"Test tp-get with multiple keys from nested property."
|
||||
(let ((str (copy-sequence "Hello World")))
|
||||
(put-text-property 0 5 'face '(:foreground "red" :underline (:color "green" :style wave)) str)
|
||||
(put-text-property 6 11 'face '(:foreground "blue" :underline (:color "yellow" :style line)) str)
|
||||
;; Test extracting multiple keys from entire string
|
||||
(let ((intervals (tp-get str 'face :underline '(:color :style))))
|
||||
(should (= (length intervals) 2))
|
||||
(let ((val1 (caddr (car intervals)))
|
||||
(val2 (caddr (cadr intervals))))
|
||||
(should (equal (plist-get val1 :color) "green"))
|
||||
(should (eq (plist-get val1 :style) 'wave))
|
||||
(should (equal (plist-get val2 :color) "yellow"))
|
||||
(should (eq (plist-get val2 :style) 'line))))
|
||||
;; Test range with multiple keys
|
||||
(let ((intervals (tp-get 0 7 '(face :underline (:color :style)) str)))
|
||||
(should (= (length intervals) 2)))))
|
||||
|
||||
(provide 'tp-ert-tests)
|
||||
;;; tp-ert-tests.el ends here
|
||||
|
||||
15
tp.el
15
tp.el
@ -398,13 +398,26 @@ Return the modified object (string) or region (START . END) for buffer."
|
||||
(defun tp--get-nested (value path)
|
||||
"Get nested value from VALUE following PATH.
|
||||
PATH is a list of keys/symbols to traverse nested structures.
|
||||
Supports plists, alists, and special display property formats."
|
||||
Supports plists, alists, and special display property formats.
|
||||
|
||||
If an element in PATH is a list of keys, extract those keys from the
|
||||
current value and return a plist with those keys.
|
||||
Example: (tp--get-nested \\='(:a 1 :b 2 :c 3) \\='((:a :b))) => (:a 1 :b 2)"
|
||||
(if (null path)
|
||||
value
|
||||
(let* ((key (car path))
|
||||
(rest (cdr path))
|
||||
(next-value
|
||||
(cond
|
||||
;; Key is a list of keys - extract multiple keys from value
|
||||
((and (listp key) (not (null key)))
|
||||
(when (and (listp value) (keywordp (car value)))
|
||||
(let ((result nil))
|
||||
(dolist (k (reverse key))
|
||||
(let ((v (plist-get value k)))
|
||||
(when v
|
||||
(setq result (plist-put result k v)))))
|
||||
result)))
|
||||
;; Value is a plist with keyword keys
|
||||
((and (listp value) (keywordp (car value)))
|
||||
(plist-get value key))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user