diff options
| author | Stefan Monnier | 2018-10-09 10:47:13 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2018-10-09 10:47:13 -0400 |
| commit | 5d1fbe25d48ba3ab663afcfe8ee8d5236e8f4cb5 (patch) | |
| tree | 43669a4c66f831ebf20a510515d7823a9f56a003 | |
| parent | 333f0bfe766185c66952c6fbd4796c6bb97c868d (diff) | |
| download | emacs-5d1fbe25d48ba3ab663afcfe8ee8d5236e8f4cb5.tar.gz emacs-5d1fbe25d48ba3ab663afcfe8ee8d5236e8f4cb5.zip | |
* lisp/replace.el: Rework implementation of the occur region
Put the region info in the "list of buffers" used for multi-occur.
(occur--parse-occur-buffer): Remove.
(occur): Pass the region to occur-1 as an overlay.
(occur-1): 'bufs' is now a list of buffers or overlays.
(occur-engine): 'buffers' is now a list of buffers or overlays.
| -rw-r--r-- | lisp/replace.el | 204 |
1 files changed, 92 insertions, 112 deletions
diff --git a/lisp/replace.el b/lisp/replace.el index 00b2ceee356..a134e4e3e58 100644 --- a/lisp/replace.el +++ b/lisp/replace.el | |||
| @@ -1099,10 +1099,9 @@ a previously found match." | |||
| 1099 | map) | 1099 | map) |
| 1100 | "Keymap for `occur-mode'.") | 1100 | "Keymap for `occur-mode'.") |
| 1101 | 1101 | ||
| 1102 | (defvar occur-revert-arguments nil | 1102 | (defvar-local occur-revert-arguments nil |
| 1103 | "Arguments to pass to `occur-1' to revert an Occur mode buffer. | 1103 | "Arguments to pass to `occur-1' to revert an Occur mode buffer. |
| 1104 | See `occur-revert-function'.") | 1104 | See `occur-revert-function'.") |
| 1105 | (make-variable-buffer-local 'occur-revert-arguments) | ||
| 1106 | (put 'occur-revert-arguments 'permanent-local t) | 1105 | (put 'occur-revert-arguments 'permanent-local t) |
| 1107 | 1106 | ||
| 1108 | (defcustom occur-mode-hook '(turn-on-font-lock) | 1107 | (defcustom occur-mode-hook '(turn-on-font-lock) |
| @@ -1130,8 +1129,8 @@ for this is to reveal context in an outline-mode when the occurrence is hidden." | |||
| 1130 | Alternatively, click \\[occur-mode-mouse-goto] on an item to go to it. | 1129 | Alternatively, click \\[occur-mode-mouse-goto] on an item to go to it. |
| 1131 | 1130 | ||
| 1132 | \\{occur-mode-map}" | 1131 | \\{occur-mode-map}" |
| 1133 | (set (make-local-variable 'revert-buffer-function) 'occur-revert-function) | 1132 | (setq-local revert-buffer-function #'occur-revert-function) |
| 1134 | (setq next-error-function 'occur-next-error)) | 1133 | (setq next-error-function #'occur-next-error)) |
| 1135 | 1134 | ||
| 1136 | 1135 | ||
| 1137 | ;;; Occur Edit mode | 1136 | ;;; Occur Edit mode |
| @@ -1154,7 +1153,7 @@ the originating buffer. | |||
| 1154 | 1153 | ||
| 1155 | To return to ordinary Occur mode, use \\[occur-cease-edit]." | 1154 | To return to ordinary Occur mode, use \\[occur-cease-edit]." |
| 1156 | (setq buffer-read-only nil) | 1155 | (setq buffer-read-only nil) |
| 1157 | (add-hook 'after-change-functions 'occur-after-change-function nil t) | 1156 | (add-hook 'after-change-functions #'occur-after-change-function nil t) |
| 1158 | (message (substitute-command-keys | 1157 | (message (substitute-command-keys |
| 1159 | "Editing: Type \\[occur-cease-edit] to return to Occur mode."))) | 1158 | "Editing: Type \\[occur-cease-edit] to return to Occur mode."))) |
| 1160 | 1159 | ||
| @@ -1206,34 +1205,9 @@ To return to ordinary Occur mode, use \\[occur-cease-edit]." | |||
| 1206 | (move-to-column col))))))) | 1205 | (move-to-column col))))))) |
| 1207 | 1206 | ||
| 1208 | 1207 | ||
| 1209 | (defun occur--parse-occur-buffer() | ||
| 1210 | "Retrieve a list of the form (BEG END ORIG-LINE BUFFER). | ||
| 1211 | BEG and END define the region. | ||
| 1212 | ORIG-LINE and BUFFER are the line and the buffer from which | ||
| 1213 | the user called `occur'." | ||
| 1214 | (save-excursion | ||
| 1215 | (goto-char (point-min)) | ||
| 1216 | (let ((buffer (get-text-property (point) 'occur-title)) | ||
| 1217 | (beg-pos (get-text-property (point) 'region-start)) | ||
| 1218 | (end-pos (get-text-property (point) 'region-end)) | ||
| 1219 | (orig-line (get-text-property (point) 'current-line))) | ||
| 1220 | (list beg-pos end-pos orig-line buffer)))) | ||
| 1221 | |||
| 1222 | (defun occur-revert-function (_ignore1 _ignore2) | 1208 | (defun occur-revert-function (_ignore1 _ignore2) |
| 1223 | "Handle `revert-buffer' for Occur mode buffers." | 1209 | "Handle `revert-buffer' for Occur mode buffers." |
| 1224 | (if (cdr (nth 2 occur-revert-arguments)) ; multi-occur | 1210 | (apply #'occur-1 (append occur-revert-arguments (list (buffer-name))))) |
| 1225 | (apply 'occur-1 (append occur-revert-arguments (list (buffer-name)))) | ||
| 1226 | (pcase-let ((`(,region-start ,region-end ,orig-line ,buffer) | ||
| 1227 | (occur--parse-occur-buffer)) | ||
| 1228 | (regexp (car occur-revert-arguments))) | ||
| 1229 | (with-current-buffer buffer | ||
| 1230 | (when (wholenump orig-line) | ||
| 1231 | (goto-char (point-min)) | ||
| 1232 | (forward-line (1- orig-line))) | ||
| 1233 | (save-excursion | ||
| 1234 | (if (or region-start region-end) | ||
| 1235 | (occur regexp nil (list (cons region-start region-end))) | ||
| 1236 | (apply 'occur-1 (append occur-revert-arguments (list (buffer-name)))))))))) | ||
| 1237 | 1211 | ||
| 1238 | (defun occur-mode-find-occurrence () | 1212 | (defun occur-mode-find-occurrence () |
| 1239 | (let ((pos (get-text-property (point) 'occur-target))) | 1213 | (let ((pos (get-text-property (point) 'occur-target))) |
| @@ -1487,23 +1461,14 @@ is not modified." | |||
| 1487 | (and (use-region-p) (list (region-bounds))))) | 1461 | (and (use-region-p) (list (region-bounds))))) |
| 1488 | (let* ((start (and (caar region) (max (caar region) (point-min)))) | 1462 | (let* ((start (and (caar region) (max (caar region) (point-min)))) |
| 1489 | (end (and (cdar region) (min (cdar region) (point-max)))) | 1463 | (end (and (cdar region) (min (cdar region) (point-max)))) |
| 1490 | (in-region-p (or start end))) | 1464 | (in-region (or start end)) |
| 1491 | (when in-region-p | 1465 | (bufs (if (not in-region) (list (current-buffer)) |
| 1492 | (or start (setq start (point-min))) | 1466 | (let ((ol (make-overlay |
| 1493 | (or end (setq end (point-max)))) | 1467 | (or start (point-min)) |
| 1494 | (let ((occur--region-start start) | 1468 | (or end (point-max))))) |
| 1495 | (occur--region-end end) | 1469 | (overlay-put ol 'occur--orig-point (point)) |
| 1496 | (occur--region-start-line | 1470 | (list ol))))) |
| 1497 | (and in-region-p | 1471 | (occur-1 regexp nlines bufs))) |
| 1498 | (line-number-at-pos (min start end)))) | ||
| 1499 | (occur--orig-line | ||
| 1500 | (line-number-at-pos (point)))) | ||
| 1501 | (save-excursion ; If no matches `occur-1' doesn't restore the point. | ||
| 1502 | (and in-region-p (narrow-to-region | ||
| 1503 | (save-excursion (goto-char start) (line-beginning-position)) | ||
| 1504 | (save-excursion (goto-char end) (line-end-position)))) | ||
| 1505 | (occur-1 regexp nlines (list (current-buffer))) | ||
| 1506 | (and in-region-p (widen)))))) | ||
| 1507 | 1472 | ||
| 1508 | (defvar ido-ignore-item-temp-list) | 1473 | (defvar ido-ignore-item-temp-list) |
| 1509 | 1474 | ||
| @@ -1574,17 +1539,27 @@ See also `multi-occur'." | |||
| 1574 | (query-replace-descr regexp)))) | 1539 | (query-replace-descr regexp)))) |
| 1575 | 1540 | ||
| 1576 | (defun occur-1 (regexp nlines bufs &optional buf-name) | 1541 | (defun occur-1 (regexp nlines bufs &optional buf-name) |
| 1542 | ;; BUFS is a list of buffer-or-overlay! | ||
| 1577 | (unless (and regexp (not (equal regexp ""))) | 1543 | (unless (and regexp (not (equal regexp ""))) |
| 1578 | (error "Occur doesn't work with the empty regexp")) | 1544 | (error "Occur doesn't work with the empty regexp")) |
| 1579 | (unless buf-name | 1545 | (unless buf-name |
| 1580 | (setq buf-name "*Occur*")) | 1546 | (setq buf-name "*Occur*")) |
| 1581 | (let (occur-buf | 1547 | (let (occur-buf |
| 1582 | (active-bufs (delq nil (mapcar #'(lambda (buf) | 1548 | (active-bufs |
| 1583 | (when (buffer-live-p buf) buf)) | 1549 | (delq nil (mapcar (lambda (boo) |
| 1584 | bufs)))) | 1550 | (when (or (buffer-live-p boo) |
| 1551 | (and (overlayp boo) | ||
| 1552 | (overlay-buffer boo))) | ||
| 1553 | boo)) | ||
| 1554 | bufs)))) | ||
| 1585 | ;; Handle the case where one of the buffers we're searching is the | 1555 | ;; Handle the case where one of the buffers we're searching is the |
| 1586 | ;; output buffer. Just rename it. | 1556 | ;; output buffer. Just rename it. |
| 1587 | (when (member buf-name (mapcar 'buffer-name active-bufs)) | 1557 | (when (member buf-name |
| 1558 | ;; FIXME: Use cl-exists. | ||
| 1559 | (mapcar | ||
| 1560 | (lambda (boo) | ||
| 1561 | (buffer-name (if (overlayp boo) (overlay-buffer boo) boo))) | ||
| 1562 | active-bufs)) | ||
| 1588 | (with-current-buffer (get-buffer buf-name) | 1563 | (with-current-buffer (get-buffer buf-name) |
| 1589 | (rename-uniquely))) | 1564 | (rename-uniquely))) |
| 1590 | 1565 | ||
| @@ -1604,22 +1579,24 @@ See also `multi-occur'." | |||
| 1604 | (let ((count | 1579 | (let ((count |
| 1605 | (if (stringp nlines) | 1580 | (if (stringp nlines) |
| 1606 | ;; Treat nlines as a regexp to collect. | 1581 | ;; Treat nlines as a regexp to collect. |
| 1607 | (let ((bufs active-bufs) | 1582 | (let ((count 0)) |
| 1608 | (count 0)) | 1583 | (dolist (boo active-bufs) |
| 1609 | (while bufs | 1584 | (with-current-buffer |
| 1610 | (with-current-buffer (car bufs) | 1585 | (if (overlayp boo) (overlay-buffer boo) boo) |
| 1611 | (save-excursion | 1586 | (save-excursion |
| 1612 | (goto-char (point-min)) | 1587 | (goto-char |
| 1613 | (while (re-search-forward regexp nil t) | 1588 | (if (overlayp boo) (overlay-start boo) (point-min))) |
| 1614 | ;; Insert the replacement regexp. | 1589 | (let ((end (if (overlayp boo) (overlay-end boo)))) |
| 1615 | (let ((str (match-substitute-replacement nlines))) | 1590 | (while (re-search-forward regexp end t) |
| 1616 | (if str | 1591 | ;; Insert the replacement regexp. |
| 1617 | (with-current-buffer occur-buf | 1592 | (let ((str (match-substitute-replacement |
| 1618 | (insert str) | 1593 | nlines))) |
| 1619 | (setq count (1+ count)) | 1594 | (if str |
| 1620 | (or (zerop (current-column)) | 1595 | (with-current-buffer occur-buf |
| 1621 | (insert "\n")))))))) | 1596 | (insert str) |
| 1622 | (setq bufs (cdr bufs))) | 1597 | (setq count (1+ count)) |
| 1598 | (or (zerop (current-column)) | ||
| 1599 | (insert "\n")))))))))) | ||
| 1623 | count) | 1600 | count) |
| 1624 | ;; Perform normal occur. | 1601 | ;; Perform normal occur. |
| 1625 | (occur-engine | 1602 | (occur-engine |
| @@ -1662,49 +1639,54 @@ See also `multi-occur'." | |||
| 1662 | 1639 | ||
| 1663 | (defun occur-engine (regexp buffers out-buf nlines case-fold | 1640 | (defun occur-engine (regexp buffers out-buf nlines case-fold |
| 1664 | title-face prefix-face match-face keep-props) | 1641 | title-face prefix-face match-face keep-props) |
| 1642 | ;; BUFFERS is a list of buffer-or-overlay! | ||
| 1665 | (with-current-buffer out-buf | 1643 | (with-current-buffer out-buf |
| 1666 | (let ((global-lines 0) ;; total count of matching lines | 1644 | (let ((global-lines 0) ;; total count of matching lines |
| 1667 | (global-matches 0) ;; total count of matches | 1645 | (global-matches 0) ;; total count of matches |
| 1668 | (coding nil) | 1646 | (coding nil) |
| 1669 | (case-fold-search case-fold) | 1647 | (case-fold-search case-fold) |
| 1670 | (in-region-p (and occur--region-start occur--region-end)) | ||
| 1671 | (multi-occur-p (cdr buffers))) | 1648 | (multi-occur-p (cdr buffers))) |
| 1672 | ;; Map over all the buffers | 1649 | ;; Map over all the buffers |
| 1673 | (dolist (buf buffers) | 1650 | (dolist (boo buffers) |
| 1674 | (when (buffer-live-p buf) | 1651 | (when (if (overlayp boo) (overlay-buffer boo) (buffer-live-p boo)) |
| 1675 | (let ((lines 0) ;; count of matching lines | 1652 | (with-current-buffer (if (overlayp boo) (overlay-buffer boo) boo) |
| 1676 | (matches 0) ;; count of matches | 1653 | (let ((inhibit-field-text-motion t) |
| 1677 | (curr-line ;; line count | 1654 | (lines 0) ; count of matching lines |
| 1678 | (or occur--region-start-line 1)) | 1655 | (matches 0) ; count of matches |
| 1679 | (orig-line (or occur--orig-line 1)) | 1656 | (headerpt (with-current-buffer out-buf (point))) |
| 1680 | (orig-line-shown-p) | 1657 | ) |
| 1681 | (prev-line nil) ;; line number of prev match endpt | 1658 | (save-excursion |
| 1682 | (prev-after-lines nil) ;; context lines of prev match | 1659 | ;; begin searching in the buffer |
| 1683 | (matchbeg 0) | 1660 | (goto-char (if (overlayp boo) (overlay-start boo) (point-min))) |
| 1684 | (origpt nil) | 1661 | (forward-line 0) |
| 1685 | (begpt nil) | 1662 | (let ((limit (if (overlayp boo) (overlay-end boo) (point-max))) |
| 1686 | (endpt nil) | 1663 | (curr-line (line-number-at-pos)) ; line count |
| 1687 | (marker nil) | 1664 | (orig-line (if (not (overlayp boo)) 1 |
| 1688 | (curstring "") | 1665 | (line-number-at-pos |
| 1689 | (ret nil) | 1666 | (overlay-get boo 'occur--orig-point)))) |
| 1690 | (inhibit-field-text-motion t) | 1667 | (orig-line-shown-p) |
| 1691 | (headerpt (with-current-buffer out-buf (point)))) | 1668 | (prev-line nil) ; line number of prev match endpt |
| 1692 | (with-current-buffer buf | 1669 | (prev-after-lines nil) ; context lines of prev match |
| 1693 | ;; The following binding is for when case-fold-search | 1670 | (matchbeg 0) |
| 1694 | ;; has a local binding in the original buffer, in which | 1671 | (origpt nil) |
| 1695 | ;; case we cannot bind it globally and let that have | 1672 | (begpt nil) |
| 1696 | ;; effect in every buffer we search. | 1673 | (endpt nil) |
| 1697 | (let ((case-fold-search case-fold)) | 1674 | (marker nil) |
| 1698 | (or coding | 1675 | (curstring "") |
| 1699 | ;; Set CODING only if the current buffer locally | 1676 | (ret nil) |
| 1700 | ;; binds buffer-file-coding-system. | 1677 | ;; The following binding is for when case-fold-search |
| 1701 | (not (local-variable-p 'buffer-file-coding-system)) | 1678 | ;; has a local binding in the original buffer, in which |
| 1702 | (setq coding buffer-file-coding-system)) | 1679 | ;; case we cannot bind it globally and let that have |
| 1703 | (save-excursion | 1680 | ;; effect in every buffer we search. |
| 1704 | (goto-char (point-min)) ;; begin searching in the buffer | 1681 | (case-fold-search case-fold)) |
| 1705 | (while (not (eobp)) | 1682 | (or coding |
| 1683 | ;; Set CODING only if the current buffer locally | ||
| 1684 | ;; binds buffer-file-coding-system. | ||
| 1685 | (not (local-variable-p 'buffer-file-coding-system)) | ||
| 1686 | (setq coding buffer-file-coding-system)) | ||
| 1687 | (while (< (point) limit) | ||
| 1706 | (setq origpt (point)) | 1688 | (setq origpt (point)) |
| 1707 | (when (setq endpt (re-search-forward regexp nil t)) | 1689 | (when (setq endpt (re-search-forward regexp limit t)) |
| 1708 | (setq lines (1+ lines)) ;; increment matching lines count | 1690 | (setq lines (1+ lines)) ;; increment matching lines count |
| 1709 | (setq matchbeg (match-beginning 0)) | 1691 | (setq matchbeg (match-beginning 0)) |
| 1710 | ;; Get beginning of first match line and end of the last. | 1692 | ;; Get beginning of first match line and end of the last. |
| @@ -1878,17 +1860,14 @@ See also `multi-occur'." | |||
| 1878 | ;; Don't display regexp for multi-buffer. | 1860 | ;; Don't display regexp for multi-buffer. |
| 1879 | (if (> (length buffers) 1) | 1861 | (if (> (length buffers) 1) |
| 1880 | "" (occur-regexp-descr regexp)) | 1862 | "" (occur-regexp-descr regexp)) |
| 1881 | (buffer-name buf) | 1863 | (buffer-name (if (overlayp boo) (overlay-buffer boo) boo)) |
| 1882 | (if in-region-p | 1864 | (if (overlayp boo) |
| 1883 | (format " within region: %d-%d" | 1865 | (format " within region: %d-%d" |
| 1884 | occur--region-start | 1866 | (overlay-start boo) |
| 1885 | occur--region-end) | 1867 | (overlay-end boo)) |
| 1886 | "")) | 1868 | "")) |
| 1887 | 'read-only t)) | 1869 | 'read-only t)) |
| 1888 | (setq end (point)) | 1870 | (setq end (point)) |
| 1889 | (add-text-properties beg end `(occur-title ,buf current-line ,orig-line | ||
| 1890 | region-start ,occur--region-start | ||
| 1891 | region-end ,occur--region-end)) | ||
| 1892 | (when title-face | 1871 | (when title-face |
| 1893 | (add-face-text-property beg end title-face)) | 1872 | (add-face-text-property beg end title-face)) |
| 1894 | (goto-char (if (and list-matching-lines-jump-to-current-line | 1873 | (goto-char (if (and list-matching-lines-jump-to-current-line |
| @@ -2425,7 +2404,7 @@ characters." | |||
| 2425 | 2404 | ||
| 2426 | (message | 2405 | (message |
| 2427 | (if query-flag | 2406 | (if query-flag |
| 2428 | (apply 'propertize | 2407 | (apply #'propertize |
| 2429 | (concat "Query replacing " | 2408 | (concat "Query replacing " |
| 2430 | (if backward "backward " "") | 2409 | (if backward "backward " "") |
| 2431 | (if delimited-flag | 2410 | (if delimited-flag |
| @@ -2880,10 +2859,11 @@ characters." | |||
| 2880 | (if (= replace-count 1) "" "s") | 2859 | (if (= replace-count 1) "" "s") |
| 2881 | (if (> (+ skip-read-only-count | 2860 | (if (> (+ skip-read-only-count |
| 2882 | skip-filtered-count | 2861 | skip-filtered-count |
| 2883 | skip-invisible-count) 0) | 2862 | skip-invisible-count) |
| 2863 | 0) | ||
| 2884 | (format " (skipped %s)" | 2864 | (format " (skipped %s)" |
| 2885 | (mapconcat | 2865 | (mapconcat |
| 2886 | 'identity | 2866 | #'identity |
| 2887 | (delq nil (list | 2867 | (delq nil (list |
| 2888 | (if (> skip-read-only-count 0) | 2868 | (if (> skip-read-only-count 0) |
| 2889 | (format "%s read-only" | 2869 | (format "%s read-only" |