- (with-output-to-temp-buffer "*Occur*"
- (save-excursion
- (set-buffer standard-output)
- (setq default-directory dir)
- ;; We will insert the number of lines, and "lines", later.
- (insert " matching ")
- (let ((print-escape-newlines t))
- (prin1 regexp))
- (insert " in buffer " (buffer-name buffer) ?. ?\n)
- (occur-mode)
- (setq occur-buffer buffer)
- (setq occur-nlines nlines)
- (setq occur-pos-list ()))
- (if (eq buffer standard-output)
- (goto-char (point-max)))
- (save-excursion
- (beginning-of-buffer)
- ;; Find next match, but give up if prev match was at end of buffer.
- (while (and (not (= prevpos (point-max)))
- (re-search-forward regexp nil t))
- (goto-char (match-beginning 0))
- (beginning-of-line)
- (save-match-data
- (setq linenum (+ linenum (count-lines prevpos (point)))))
- (setq prevpos (point))
- (goto-char (match-end 0))
- (let* ((start (save-excursion
- (goto-char (match-beginning 0))
- (forward-line (if (< nlines 0) nlines (- nlines)))
- (point)))
- (end (save-excursion
- (goto-char (match-end 0))
- (if (> nlines 0)
- (forward-line (1+ nlines))
- (forward-line 1))
- (point)))
- (tag (format "%5d" linenum))
- (empty (make-string (length tag) ?\ ))
- tem)
- (save-excursion
- (setq tem (make-marker))
- (set-marker tem (point))
- (set-buffer standard-output)
- (setq occur-pos-list (cons tem occur-pos-list))
- (or first (zerop nlines)
- (insert "--------\n"))
- (setq first nil)
- (insert-buffer-substring buffer start end)
- (backward-char (- end start))
- (setq tem nlines)
- (while (> tem 0)
- (insert empty ?:)
- (forward-line 1)
- (setq tem (1- tem)))
- (let ((this-linenum linenum))
- (set-marker final-context-start
- (+ (point) (- (match-end 0) (match-beginning 0))))
- (while (< (point) final-context-start)
- (if (null tag)
- (setq tag (format "%5d" this-linenum)))
- (insert tag ?:)
- (put-text-property (save-excursion
- (beginning-of-line)
- (point))
- (save-excursion
- (end-of-line)
- (point))
+ (save-excursion
+ (goto-char (point-min))
+ ;; Check first whether there are any matches at all.
+ (if (not (re-search-forward regexp nil t))
+ (message "No matches for `%s'" regexp)
+ ;; Back up, so the search loop below will find the first match.
+ (goto-char (match-beginning 0))
+ (with-output-to-temp-buffer "*Occur*"
+ (save-excursion
+ (set-buffer standard-output)
+ (setq default-directory dir)
+ ;; We will insert the number of lines, and "lines", later.
+ (insert " matching ")
+ (let ((print-escape-newlines t))
+ (prin1 regexp))
+ (insert " in buffer " (buffer-name buffer) ?. ?\n)
+ (occur-mode)
+ (setq occur-buffer buffer)
+ (setq occur-nlines nlines)
+ (setq occur-command-arguments
+ (list regexp nlines)))
+ (if (eq buffer standard-output)
+ (goto-char (point-max)))
+ (save-excursion
+ ;; Find next match, but give up if prev match was at end of buffer.
+ (while (and (not (= prevpos (point-max)))
+ (re-search-forward regexp nil t))
+ (goto-char (match-beginning 0))
+ (beginning-of-line)
+ (save-match-data
+ (setq linenum (+ linenum (count-lines prevpos (point)))))
+ (setq prevpos (point))
+ (goto-char (match-end 0))
+ (let* (;;start point of text in source buffer to be put
+ ;;into *Occur*
+ (start (save-excursion
+ (goto-char (match-beginning 0))
+ (forward-line (if (< nlines 0)
+ nlines
+ (- nlines)))
+ (point)))
+ ;; end point of text in source buffer to be put
+ ;; into *Occur*
+ (end (save-excursion
+ (goto-char (match-end 0))
+ (if (> nlines 0)
+ (forward-line (1+ nlines))
+ (forward-line 1))
+ (point)))
+ ;; Amount of context before matching text
+ (match-beg (- (match-beginning 0) start))
+ ;; Length of matching text
+ (match-len (- (match-end 0) (match-beginning 0)))
+ (tag (format line-number-format linenum))
+ tem
+ insertion-start
+ ;; Number of lines of context to show for current match.
+ occur-marker
+ ;; Marker pointing to end of match in source buffer.
+ (text-beg
+ ;; Marker pointing to start of text for one
+ ;; match in *Occur*.
+ (make-marker))
+ (text-end
+ ;; Marker pointing to end of text for one match
+ ;; in *Occur*.
+ (make-marker)))
+ (save-excursion
+ (setq occur-marker (make-marker))
+ (set-marker occur-marker (point))
+ (set-buffer standard-output)
+ (setq occur-num-matches (1+ occur-num-matches))
+ (or first (zerop nlines)
+ (insert "--------\n"))
+ (setq first nil)
+ (save-excursion
+ (set-buffer "*Occur*")
+ (setq tab-width current-tab-width))
+
+ ;; Insert matching text including context lines from
+ ;; source buffer into *Occur*
+ (set-marker text-beg (point))
+ (setq insertion-start (point))
+ (insert-buffer-substring buffer start end)
+ (or (and (/= (+ start match-beg) end)
+ (with-current-buffer buffer
+ (eq (char-before end) ?\n)))
+ (insert "\n"))
+ (set-marker final-context-start
+ (+ (- (point) (- end (match-end 0)))
+ (if (save-excursion
+ (set-buffer buffer)
+ (save-excursion
+ (goto-char (match-end 0))
+ (end-of-line)
+ (bolp)))
+ 1 0)))
+ (set-marker text-end (point))
+
+ ;; Highlight text that was matched.
+ (if list-matching-lines-face
+ (put-text-property
+ (+ (marker-position text-beg) match-beg)
+ (+ (marker-position text-beg) match-beg match-len)
+ 'face list-matching-lines-face))
+
+ ;; `occur-point' property is used by occur-next and
+ ;; occur-prev to move between matching lines.
+ (put-text-property
+ (+ (marker-position text-beg) match-beg match-len)
+ (+ (marker-position text-beg) match-beg match-len 1)
+ 'occur-point t)
+
+ ;; Now go back to the start of the matching text
+ ;; adding the space and colon to the start of each line.
+ (goto-char insertion-start)
+ ;; Insert space and colon for lines of context before match.
+ (setq tem (if (< linenum nlines)
+ (- nlines linenum)
+ nlines))
+ (while (> tem 0)
+ (insert empty ?:)
+ (forward-line 1)
+ (setq tem (1- tem)))
+
+ ;; Insert line number and colon for the lines of
+ ;; matching text.
+ (let ((this-linenum linenum))
+ (while (< (point) final-context-start)
+ (if (null tag)
+ (setq tag (format line-number-format this-linenum)))
+ (insert tag ?:)
+ (forward-line 1)
+ (setq tag nil)
+ (setq this-linenum (1+ this-linenum)))
+ (while (and (not (eobp)) (<= (point) final-context-start))
+ (insert empty ?:)
+ (forward-line 1)
+ (setq this-linenum (1+ this-linenum))))
+
+ ;; Insert space and colon for lines of context after match.
+ (while (and (< (point) (point-max)) (< tem nlines))
+ (insert empty ?:)
+ (forward-line 1)
+ (setq tem (1+ tem)))
+
+ ;; Add text properties. The `occur' prop is used to
+ ;; store the marker of the matching text in the
+ ;; source buffer.
+ (put-text-property (marker-position text-beg)
+ (- (marker-position text-end) 1)