string is used as FROM-STRING--you don't have to specify it with the
minibuffer.
-Replacement transfers the case of the old text to the new text,
-if `case-replace' and `case-fold-search'
-are non-nil and FROM-STRING has no uppercase letters.
-\(Preserving case means that if the string matched is all caps, or capitalized,
-then its replacement is upcased or capitalized.)
+Matching is independent of case if `case-fold-search' is non-nil and
+FROM-STRING has no uppercase letters. Replacement transfers the case
+pattern of the old text to the new text, if `case-replace' and
+`case-fold-search' are non-nil and FROM-STRING has no uppercase
+letters. \(Transferring the case pattern means that if the old text
+matched is all caps, or capitalized, then its replacement is upcased
+or capitalized.)
Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace
only matches surrounded by word boundaries.
regexp is used as REGEXP--you don't have to specify it with the
minibuffer.
-Preserves case in each replacement if `case-replace' and `case-fold-search'
-are non-nil and REGEXP has no uppercase letters.
+Matching is independent of case if `case-fold-search' is non-nil and
+REGEXP has no uppercase letters. Replacement transfers the case
+pattern of the old text to the new text, if `case-replace' and
+`case-fold-search' are non-nil and REGEXP has no uppercase letters.
+\(Transferring the case pattern means that if the old text matched is
+all caps, or capitalized, then its replacement is upcased or
+capitalized.)
Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace
only matches surrounded by word boundaries.
end of the buffer."
(interactive
- (keep-lines-read-args "Keep lines (containing match for regexp): "))
+ (progn
+ (barf-if-buffer-read-only)
+ (keep-lines-read-args "Keep lines (containing match for regexp): ")))
(if rstart
- (goto-char (min rstart rend))
+ (progn
+ (goto-char (min rstart rend))
+ (setq rend (copy-marker (max rstart rend))))
(if (and transient-mark-mode mark-active)
(setq rstart (region-beginning)
rend (copy-marker (region-end)))
;; Now end is first char preserved by the new match.
(if (< start end)
(delete-region start end))))
-
+
(setq start (save-excursion (forward-line 1) (point)))
;; If the match was empty, avoid matching again at same place.
(and (< (point) rend)
end of the buffer."
(interactive
- (keep-lines-read-args "Flush lines (containing match for regexp): "))
+ (progn
+ (barf-if-buffer-read-only)
+ (keep-lines-read-args "Flush lines (containing match for regexp): ")))
(if rstart
- (goto-char (min rstart rend))
+ (progn
+ (goto-char (min rstart rend))
+ (setq rend (copy-marker (max rstart rend))))
(if (and transient-mark-mode mark-active)
(setq rstart (region-beginning)
rend (copy-marker (region-end)))
(define-key map "\C-o" 'occur-mode-display-occurrence)
(define-key map "\M-n" 'occur-next)
(define-key map "\M-p" 'occur-prev)
+ (define-key map "r" 'occur-rename-buffer)
+ (define-key map "c" 'clone-buffer)
(define-key map "g" 'revert-buffer)
- (define-key map "q" 'delete-window)
+ (define-key map "q" 'quit-window)
+ (define-key map "z" 'kill-this-buffer)
map)
"Keymap for `occur-mode'.")
See `occur-revert-function'.")
(defcustom occur-mode-hook '(turn-on-font-lock)
- "Hooks run when `occur' is called."
+ "Hook run when entering Occur mode."
+ :type 'hook
+ :group 'matching)
+
+(defcustom occur-hook nil
+ "Hook run when `occur' is called."
:type 'hook
:group 'matching)
Alternatively, click \\[occur-mode-mouse-goto] on an item to go to it.
\\{occur-mode-map}"
+ (interactive)
(kill-all-local-variables)
(use-local-map occur-mode-map)
(setq major-mode 'occur-mode)
(setq mode-name "Occur")
- (make-local-variable 'revert-buffer-function)
- (set (make-local-variable 'font-lock-category-alist)
- `((,(make-symbol "occur-match") . bold)
- (,(make-symbol "occur-title") . underline)))
(set (make-local-variable 'revert-buffer-function) 'occur-revert-function)
(make-local-variable 'occur-revert-arguments)
+ (add-hook 'change-major-mode-hook 'font-lock-defontify nil t)
(run-hooks 'occur-mode-hook))
(defun occur-revert-function (ignore1 ignore2)
(select-window window)
(goto-char pos))))
-(defun occur-next (&optional n)
- "Move to the Nth (default 1) next match in an Occur mode buffer."
- (interactive "p")
+(defun occur-find-match (n search message)
(if (not n) (setq n 1))
(let ((r))
(while (> n 0)
- (if (get-text-property (point) 'occur-point)
- (forward-char 1))
- (setq r (next-single-property-change (point) 'occur-point))
+ (setq r (funcall search (point) 'occur-match))
+ (and r
+ (get-text-property r 'occur-match)
+ (setq r (funcall search r 'occur-match)))
(if r
- (goto-char r)
- (error "No more matches"))
+ (goto-char r)
+ (error message))
(setq n (1- n)))))
+(defun occur-next (&optional n)
+ "Move to the Nth (default 1) next match in an Occur mode buffer."
+ (interactive "p")
+ (occur-find-match n #'next-single-property-change "No more matches"))
+
(defun occur-prev (&optional n)
"Move to the Nth (default 1) previous match in an Occur mode buffer."
(interactive "p")
- (if (not n) (setq n 1))
- (let ((r))
- (while (> n 0)
-
- (setq r (get-text-property (point) 'occur-point))
- (if r (forward-char -1))
-
- (setq r (previous-single-property-change (point) 'occur-point))
- (if r
- (goto-char (- r 1))
- (error "No earlier matches"))
-
- (setq n (1- n)))))
+ (occur-find-match n #'previous-single-property-change "No earlier matches"))
\f
(defcustom list-matching-lines-default-context-lines 0
"*Default number of context lines included around `list-matching-lines' matches.
(when current-prefix-arg
(prefix-numeric-value current-prefix-arg))))
+(defun occur-rename-buffer (&optional unique-p)
+ "Rename the current *Occur* buffer to *Occur: original-buffer-name*.
+Here `original-buffer-name' is the buffer name were occur was originally run.
+When given the prefix argument, the renaming will not clobber the existing
+buffer(s) of that name, but use `generate-new-buffer-name' instead.
+You can add this to `occur-hook' if you always want a separate *Occur*
+buffer for each buffer where you invoke `occur'."
+ (interactive "P")
+ (with-current-buffer
+ (if (eq major-mode 'occur-mode) (current-buffer) (get-buffer "*Occur*"))
+ (rename-buffer (concat "*Occur: "
+ (mapconcat #'buffer-name
+ (car (cddr occur-revert-arguments)) "/")
+ "*")
+ unique-p)))
+
(defun occur (regexp &optional nlines)
"Show all lines in the current buffer containing a match for REGEXP.
`occur'."
(interactive
(cons
- (let ((bufs (list (read-buffer "First buffer to search: "
- (current-buffer) t)))
- (buf nil))
+ (let* ((bufs (list (read-buffer "First buffer to search: "
+ (current-buffer) t)))
+ (buf nil)
+ (ido-ignore-item-temp-list bufs))
(while (not (string-equal
- (setq buf (read-buffer "Next buffer to search (RET to end): "
- nil t))
+ (setq buf (read-buffer
+ (if (eq read-buffer-function 'ido-read-buffer)
+ "Next buffer to search (C-j to end): "
+ "Next buffer to search (RET to end): ")
+ nil t))
""))
- (push buf bufs))
+ (add-to-list 'bufs buf)
+ (setq ido-ignore-item-temp-list bufs))
(nreverse (mapcar #'get-buffer bufs)))
(occur-read-primary-args)))
(occur-1 regexp nlines bufs))
(or nlines list-matching-lines-default-context-lines)
(and case-fold-search
(isearch-no-upper-case-p regexp t))
- nil nil nil nil)))
- (let* ((diff (- (length bufs) (length active-bufs)))
- (bufcount (- (length bufs) diff))
- (msg (concat
- (format "Searched %d buffer%s" bufcount (if (= bufcount 1) "" "s"))
- "%s; "
- (format "%s match%s for `%s'"
- (if (zerop count)
- "no"
- (format "%d" count))
- (if (= count 1)
- ""
- "es")
- regexp))))
- (message msg (if (zerop diff)
- ""
- (format " (%d killed)" diff))))
+ list-matching-lines-buffer-name-face
+ nil list-matching-lines-face nil)))
+ (let* ((bufcount (length active-bufs))
+ (diff (- (length bufs) bufcount)))
+ (message "Searched %d buffer%s%s; %s match%s for `%s'"
+ bufcount (if (= bufcount 1) "" "s")
+ (if (zerop diff) "" (format " (%d killed)" diff))
+ (if (zerop count) "no" (format "%d" count))
+ (if (= count 1) "" "es")
+ regexp))
;; If we had to make a temporary buffer, make it the *Occur*
;; buffer now.
(when made-temp-buf
buffer-read-only t)
(if (> count 0)
(display-buffer occur-buf)
- (kill-buffer occur-buf))))))
+ (kill-buffer occur-buf)))
+ (run-hooks 'occur-hook))))
(defun occur-engine-add-prefix (lines)
(mapcar
#'(lambda (line)
- (concat " :" line "\n"))
+ (concat " :" line "\n"))
lines))
(defun occur-engine (regexp buffers out-buf nlines case-fold-search
title-face prefix-face match-face keep-props)
(with-current-buffer out-buf
(setq buffer-read-only nil)
- (let ((globalcount 0))
+ (let ((globalcount 0)
+ (coding nil))
;; Map over all the buffers
(dolist (buf buffers)
(when (buffer-live-p buf)
(headerpt (with-current-buffer out-buf (point))))
(save-excursion
(set-buffer buf)
+ (or coding
+ ;; Set CODING only if the current buffer locally
+ ;; binds buffer-file-coding-system.
+ (not (local-variable-p 'buffer-file-coding-system))
+ (setq coding buffer-file-coding-system))
(save-excursion
(goto-char (point-min)) ;; begin searching in the buffer
(while (not (eobp))
;; Depropertize the string, and maybe
;; highlight the matches
(let ((len (length curstring))
- (match-category (with-current-buffer out-buf
- (car (nth 0 font-lock-category-alist))))
(start 0))
(unless keep-props
(set-text-properties 0 len nil curstring))
(add-text-properties (match-beginning 0)
(match-end 0)
(append
- `(occur-match t category ,match-category)
+ `(occur-match t)
(when match-face
- `(face ,match-face)))
+ `(font-lock-face ,match-face)))
curstring)
(setq start (match-end 0))))
;; Generate the string to insert for this match
(let* ((out-line
(concat
- (apply #'propertize (format "%6d:" lines)
+ ;; Using 7 digits aligns tabs properly.
+ (apply #'propertize (format "%7d:" lines)
(append
(when prefix-face
- `(face prefix-face))
+ `(font-lock-face prefix-face))
'(occur-prefix t)))
curstring
"\n"))
(unless (= nlines 0)
(insert "-------\n"))
(add-text-properties
- beg (1- end)
- `(occur-target ,marker
- mouse-face highlight help-echo
- "mouse-2: go to this occurrence")))))
+ beg end
+ `(occur-target ,marker help-echo "mouse-2: go to this occurrence"))
+ ;; We don't put `mouse-face' on the newline,
+ ;; because that loses.
+ (add-text-properties beg (1- end) '(mouse-face highlight)))))
(goto-char endpt))
(if endpt
(progn
(add-text-properties beg end
(append
(when title-face
- `(face ,title-face))
- `(occur-title
- ,buf category
- ,(car (nth 1 font-lock-category-alist))))))
+ `(font-lock-face ,title-face))
+ `(occur-title ,buf))))
(goto-char (point-min)))))))
+ (if coding
+ ;; CODING is buffer-file-coding-system of the first buffer
+ ;; that locally binds it. Let's use it also for the output
+ ;; buffer.
+ (set-buffer-file-coding-system coding))
;; Return the number of matches
globalcount)))
(aset data 2 (if (consp next) next (aref data 3))))))
(car (aref data 2)))
-(defun perform-replace (from-string replacements
+(defun perform-replace (from-string replacements
query-flag regexp-flag delimited-flag
&optional repeat-count map start end)
"Subroutine of `query-replace'. Its complexity handles interactive queries.
which will run faster and probably do exactly what you want. Please
see the documentation of `replace-match' to find out how to simulate
-`case-replace'."
+`case-replace'.
+
+This function returns nil if and only if there were no matches to
+make, or the user didn't cancel the call."
(or map (setq map query-replace-map))
(and query-flag minibuffer-auto-raise
(raise-frame (window-frame (minibuffer-window))))
(setq done t))
((eq def 'backup)
(if stack
- (let ((elt (car stack)))
+ (let ((elt (pop stack)))
(goto-char (car elt))
(setq replaced (eq t (cdr elt)))
(or replaced
- (set-match-data (cdr elt)))
- (setq stack (cdr stack)))
+ (set-match-data (cdr elt))))
(message "No previous match")
(ding 'no-terminate)
(sit-for 1)))
(if (and regexp-flag nonempty-match)
(setq match-again (and (looking-at search-string)
(match-data)))))
-
+
;; Edit replacement.
((eq def 'edit-replacement)
(setq next-replacement
(or replaced
(replace-match next-replacement nocasify literal))
(setq done t))
-
+
((eq def 'delete-and-edit)
(delete-region (match-beginning 0) (match-end 0))
(set-match-data
;; beyond the last replacement. Undo that.
(when (and regexp-flag (not match-again) (> replace-count 0))
(backward-char 1))
-
+
(replace-dehighlight))
(or unread-command-events
(message "Replaced %d occurrence%s"