diff options
| author | F. Jason Park | 2023-10-03 23:15:40 -0700 |
|---|---|---|
| committer | F. Jason Park | 2023-10-13 07:47:01 -0700 |
| commit | a4bae965e06c982871cf01bb0fc3afc43c915bc5 (patch) | |
| tree | 628df10ab9e00382967881485b2617f737945828 | |
| parent | f97fdf5e50ebf1aab236b4b8bbd09c203a56aac5 (diff) | |
| download | emacs-a4bae965e06c982871cf01bb0fc3afc43c915bc5.tar.gz emacs-a4bae965e06c982871cf01bb0fc3afc43c915bc5.zip | |
Easily excise list-valued text prop members in ERC
* lisp/erc/erc.el (erc--remove-from-prop-value-list): New function for
removing `invisible' and `face' prop members cleanly.
* test/lisp/erc/erc-tests.el (erc--remove-from-prop-value-list,
erc--remove-from-prop-value-list/many): New tests. (Bug#60936)
| -rw-r--r-- | lisp/erc/erc.el | 24 | ||||
| -rw-r--r-- | test/lisp/erc/erc-tests.el | 169 |
2 files changed, 193 insertions, 0 deletions
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 3a0337eae9a..c3312000ffd 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el | |||
| @@ -3079,6 +3079,30 @@ value. See also `erc-button-add-face'." | |||
| 3079 | old (get-text-property pos prop object) | 3079 | old (get-text-property pos prop object) |
| 3080 | end (next-single-property-change pos prop object to))))) | 3080 | end (next-single-property-change pos prop object to))))) |
| 3081 | 3081 | ||
| 3082 | (defun erc--remove-from-prop-value-list (from to prop val &optional object) | ||
| 3083 | "Remove VAL from text prop value between FROM and TO. | ||
| 3084 | If current value is VAL itself, remove the property entirely. | ||
| 3085 | When VAL is a list, act as if this function were called | ||
| 3086 | repeatedly with VAL set to each of VAL's members." | ||
| 3087 | (let ((old (get-text-property from prop object)) | ||
| 3088 | (pos from) | ||
| 3089 | (end (next-single-property-change from prop object to)) | ||
| 3090 | new) | ||
| 3091 | (while (< pos to) | ||
| 3092 | (when old | ||
| 3093 | (if (setq new (and (consp old) (if (consp val) | ||
| 3094 | (seq-difference old val) | ||
| 3095 | (remq val old)))) | ||
| 3096 | (put-text-property pos end prop | ||
| 3097 | (if (cdr new) new (car new)) object) | ||
| 3098 | (when (pcase val | ||
| 3099 | ((pred consp) (or (consp old) (memq old val))) | ||
| 3100 | (_ (if (consp old) (memq val old) (eq old val)))) | ||
| 3101 | (remove-text-properties pos end (list prop nil) object)))) | ||
| 3102 | (setq pos end | ||
| 3103 | old (get-text-property pos prop object) | ||
| 3104 | end (next-single-property-change pos prop object to))))) | ||
| 3105 | |||
| 3082 | (defvar erc-legacy-invisible-bounds-p nil | 3106 | (defvar erc-legacy-invisible-bounds-p nil |
| 3083 | "Whether to hide trailing rather than preceding newlines. | 3107 | "Whether to hide trailing rather than preceding newlines. |
| 3084 | Beginning in ERC 5.6, invisibility extends from a message's | 3108 | Beginning in ERC 5.6, invisibility extends from a message's |
diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 0b88ad9cfa9..ed89fd01d93 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el | |||
| @@ -1475,6 +1475,175 @@ | |||
| 1475 | (when noninteractive | 1475 | (when noninteractive |
| 1476 | (kill-buffer)))) | 1476 | (kill-buffer)))) |
| 1477 | 1477 | ||
| 1478 | (ert-deftest erc--remove-from-prop-value-list () | ||
| 1479 | (with-current-buffer (get-buffer-create "*erc-test*") | ||
| 1480 | ;; Non-list match. | ||
| 1481 | (insert "abc\n") | ||
| 1482 | (put-text-property 1 2 'erc-test 'a) | ||
| 1483 | (put-text-property 2 3 'erc-test 'b) | ||
| 1484 | (put-text-property 3 4 'erc-test 'c) | ||
| 1485 | (should (erc-tests--equal-including-properties | ||
| 1486 | (buffer-substring 1 4) #("abc" | ||
| 1487 | 0 1 (erc-test a) | ||
| 1488 | 1 2 (erc-test b) | ||
| 1489 | 2 3 (erc-test c)))) | ||
| 1490 | |||
| 1491 | (erc--remove-from-prop-value-list 1 4 'erc-test 'b) | ||
| 1492 | (should (erc-tests--equal-including-properties | ||
| 1493 | (buffer-substring 1 4) #("abc" | ||
| 1494 | 0 1 (erc-test a) | ||
| 1495 | 2 3 (erc-test c)))) | ||
| 1496 | (erc--remove-from-prop-value-list 1 4 'erc-test 'a) | ||
| 1497 | (should (erc-tests--equal-including-properties | ||
| 1498 | (buffer-substring 1 4) #("abc" 2 3 (erc-test c)))) | ||
| 1499 | (erc--remove-from-prop-value-list 1 4 'erc-test 'c) | ||
| 1500 | (should (erc-tests--equal-including-properties | ||
| 1501 | (buffer-substring 1 4) "abc")) | ||
| 1502 | |||
| 1503 | ;; List match. | ||
| 1504 | (goto-char (point-min)) | ||
| 1505 | (insert "def\n") | ||
| 1506 | (put-text-property 1 2 'erc-test '(d x)) | ||
| 1507 | (put-text-property 2 3 'erc-test '(e y)) | ||
| 1508 | (put-text-property 3 4 'erc-test '(f z)) | ||
| 1509 | (should (erc-tests--equal-including-properties | ||
| 1510 | (buffer-substring 1 4) #("def" | ||
| 1511 | 0 1 (erc-test (d x)) | ||
| 1512 | 1 2 (erc-test (e y)) | ||
| 1513 | 2 3 (erc-test (f z))))) | ||
| 1514 | (erc--remove-from-prop-value-list 1 4 'erc-test 'y) | ||
| 1515 | (should (erc-tests--equal-including-properties | ||
| 1516 | (buffer-substring 1 4) #("def" | ||
| 1517 | 0 1 (erc-test (d x)) | ||
| 1518 | 1 2 (erc-test e) | ||
| 1519 | 2 3 (erc-test (f z))))) | ||
| 1520 | (erc--remove-from-prop-value-list 1 4 'erc-test 'd) | ||
| 1521 | (erc--remove-from-prop-value-list 1 4 'erc-test 'f) | ||
| 1522 | (should (erc-tests--equal-including-properties | ||
| 1523 | (buffer-substring 1 4) #("def" | ||
| 1524 | 0 1 (erc-test x) | ||
| 1525 | 1 2 (erc-test e) | ||
| 1526 | 2 3 (erc-test z)))) | ||
| 1527 | (erc--remove-from-prop-value-list 1 4 'erc-test 'e) | ||
| 1528 | (erc--remove-from-prop-value-list 1 4 'erc-test 'z) | ||
| 1529 | (erc--remove-from-prop-value-list 1 4 'erc-test 'x) | ||
| 1530 | (should (erc-tests--equal-including-properties | ||
| 1531 | (buffer-substring 1 4) "def")) | ||
| 1532 | |||
| 1533 | ;; List match. | ||
| 1534 | (goto-char (point-min)) | ||
| 1535 | (insert "ghi\n") | ||
| 1536 | (put-text-property 1 2 'erc-test '(g x)) | ||
| 1537 | (put-text-property 2 3 'erc-test '(h x)) | ||
| 1538 | (put-text-property 3 4 'erc-test '(i y)) | ||
| 1539 | (should (erc-tests--equal-including-properties | ||
| 1540 | (buffer-substring 1 4) #("ghi" | ||
| 1541 | 0 1 (erc-test (g x)) | ||
| 1542 | 1 2 (erc-test (h x)) | ||
| 1543 | 2 3 (erc-test (i y))))) | ||
| 1544 | (erc--remove-from-prop-value-list 1 4 'erc-test 'x) | ||
| 1545 | (should (erc-tests--equal-including-properties | ||
| 1546 | (buffer-substring 1 4) #("ghi" | ||
| 1547 | 0 1 (erc-test g) | ||
| 1548 | 1 2 (erc-test h) | ||
| 1549 | 2 3 (erc-test (i y))))) | ||
| 1550 | (erc--remove-from-prop-value-list 1 2 'erc-test 'g) ; narrowed | ||
| 1551 | (erc--remove-from-prop-value-list 3 4 'erc-test 'i) ; narrowed | ||
| 1552 | (should (erc-tests--equal-including-properties | ||
| 1553 | (buffer-substring 1 4) #("ghi" | ||
| 1554 | 1 2 (erc-test h) | ||
| 1555 | 2 3 (erc-test y)))) | ||
| 1556 | |||
| 1557 | ;; Pathological (,c) case (hopefully not created by ERC) | ||
| 1558 | (goto-char (point-min)) | ||
| 1559 | (insert "jkl\n") | ||
| 1560 | (put-text-property 1 2 'erc-test '(j x)) | ||
| 1561 | (put-text-property 2 3 'erc-test '(k)) | ||
| 1562 | (put-text-property 3 4 'erc-test '(k)) | ||
| 1563 | (erc--remove-from-prop-value-list 1 4 'erc-test 'k) | ||
| 1564 | (should (erc-tests--equal-including-properties | ||
| 1565 | (buffer-substring 1 4) #("jkl" 0 1 (erc-test (j x))))) | ||
| 1566 | |||
| 1567 | (when noninteractive | ||
| 1568 | (kill-buffer)))) | ||
| 1569 | |||
| 1570 | (ert-deftest erc--remove-from-prop-value-list/many () | ||
| 1571 | (with-current-buffer (get-buffer-create "*erc-test*") | ||
| 1572 | ;; Non-list match. | ||
| 1573 | (insert "abc\n") | ||
| 1574 | (put-text-property 1 2 'erc-test 'a) | ||
| 1575 | (put-text-property 2 3 'erc-test 'b) | ||
| 1576 | (put-text-property 3 4 'erc-test 'c) | ||
| 1577 | (should (erc-tests--equal-including-properties | ||
| 1578 | (buffer-substring 1 4) #("abc" | ||
| 1579 | 0 1 (erc-test a) | ||
| 1580 | 1 2 (erc-test b) | ||
| 1581 | 2 3 (erc-test c)))) | ||
| 1582 | |||
| 1583 | (erc--remove-from-prop-value-list 1 4 'erc-test '(a b)) | ||
| 1584 | (should (erc-tests--equal-including-properties | ||
| 1585 | (buffer-substring 1 4) #("abc" 2 3 (erc-test c)))) | ||
| 1586 | (erc--remove-from-prop-value-list 1 4 'erc-test 'a) | ||
| 1587 | (should (erc-tests--equal-including-properties | ||
| 1588 | (buffer-substring 1 4) #("abc" 2 3 (erc-test c)))) | ||
| 1589 | (erc--remove-from-prop-value-list 1 4 'erc-test '(c)) | ||
| 1590 | (should (erc-tests--equal-including-properties | ||
| 1591 | (buffer-substring 1 4) "abc")) | ||
| 1592 | |||
| 1593 | ;; List match. | ||
| 1594 | (goto-char (point-min)) | ||
| 1595 | (insert "def\n") | ||
| 1596 | (put-text-property 1 2 'erc-test '(d x y)) | ||
| 1597 | (put-text-property 2 3 'erc-test '(e y)) | ||
| 1598 | (put-text-property 3 4 'erc-test '(f z)) | ||
| 1599 | (should (erc-tests--equal-including-properties | ||
| 1600 | (buffer-substring 1 4) #("def" | ||
| 1601 | 0 1 (erc-test (d x y)) | ||
| 1602 | 1 2 (erc-test (e y)) | ||
| 1603 | 2 3 (erc-test (f z))))) | ||
| 1604 | (erc--remove-from-prop-value-list 1 4 'erc-test '(d y f)) | ||
| 1605 | (should (erc-tests--equal-including-properties | ||
| 1606 | (buffer-substring 1 4) #("def" | ||
| 1607 | 0 1 (erc-test x) | ||
| 1608 | 1 2 (erc-test e) | ||
| 1609 | 2 3 (erc-test z)))) | ||
| 1610 | (erc--remove-from-prop-value-list 1 4 'erc-test '(e z x)) | ||
| 1611 | (should (erc-tests--equal-including-properties | ||
| 1612 | (buffer-substring 1 4) "def")) | ||
| 1613 | |||
| 1614 | ;; Narrowed beg. | ||
| 1615 | (goto-char (point-min)) | ||
| 1616 | (insert "ghi\n") | ||
| 1617 | (put-text-property 1 2 'erc-test '(g x)) | ||
| 1618 | (put-text-property 2 3 'erc-test '(h x)) | ||
| 1619 | (put-text-property 3 4 'erc-test '(i x)) | ||
| 1620 | (should (erc-tests--equal-including-properties | ||
| 1621 | (buffer-substring 1 4) #("ghi" | ||
| 1622 | 0 1 (erc-test (g x)) | ||
| 1623 | 1 2 (erc-test (h x)) | ||
| 1624 | 2 3 (erc-test (i x))))) | ||
| 1625 | (erc--remove-from-prop-value-list 1 3 'erc-test '(x g i)) | ||
| 1626 | (should (erc-tests--equal-including-properties | ||
| 1627 | (buffer-substring 1 4) #("ghi" | ||
| 1628 | 1 2 (erc-test h) | ||
| 1629 | 2 3 (erc-test (i x))))) | ||
| 1630 | |||
| 1631 | ;; Narrowed middle. | ||
| 1632 | (goto-char (point-min)) | ||
| 1633 | (insert "jkl\n") | ||
| 1634 | (put-text-property 1 2 'erc-test '(j x)) | ||
| 1635 | (put-text-property 2 3 'erc-test '(k)) | ||
| 1636 | (put-text-property 3 4 'erc-test '(l y z)) | ||
| 1637 | (erc--remove-from-prop-value-list 3 4 'erc-test '(k x y z)) | ||
| 1638 | (should (erc-tests--equal-including-properties | ||
| 1639 | (buffer-substring 1 4) #("jkl" | ||
| 1640 | 0 1 (erc-test (j x)) | ||
| 1641 | 1 2 (erc-test (k)) | ||
| 1642 | 2 3 (erc-test l)))) | ||
| 1643 | |||
| 1644 | (when noninteractive | ||
| 1645 | (kill-buffer)))) | ||
| 1646 | |||
| 1478 | (ert-deftest erc--split-string-shell-cmd () | 1647 | (ert-deftest erc--split-string-shell-cmd () |
| 1479 | 1648 | ||
| 1480 | ;; Leading and trailing space | 1649 | ;; Leading and trailing space |