aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/replace.el
diff options
context:
space:
mode:
authorStefan Monnier2018-10-09 10:47:13 -0400
committerStefan Monnier2018-10-09 10:47:13 -0400
commit5d1fbe25d48ba3ab663afcfe8ee8d5236e8f4cb5 (patch)
tree43669a4c66f831ebf20a510515d7823a9f56a003 /lisp/replace.el
parent333f0bfe766185c66952c6fbd4796c6bb97c868d (diff)
downloademacs-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.
Diffstat (limited to 'lisp/replace.el')
-rw-r--r--lisp/replace.el204
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.
1104See `occur-revert-function'.") 1104See `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."
1130Alternatively, click \\[occur-mode-mouse-goto] on an item to go to it. 1129Alternatively, 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
1155To return to ordinary Occur mode, use \\[occur-cease-edit]." 1154To 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).
1211BEG and END define the region.
1212ORIG-LINE and BUFFER are the line and the buffer from which
1213the 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"