gnu-emacs-sources
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

replace+.el - extensions to GNU `replace.el'


From: Drew Adams
Subject: replace+.el - extensions to GNU `replace.el'
Date: Tue, 16 Jan 2001 21:35:20 -0500

;;; replace+.el --- Extensions to `replace.el'.
;; 
;; Filename: replace+.el
;; Description: Extensions to `replace.el'.
;; Author: Drew Adams
;; Maintainer: Drew Adams
;; Copyright (C) 1996-2001, Drew Adams, all rights reserved.
;; Created: Tue Jan 30 15:01:06 1996
;; Version: $Id: replace+.el,v 1.6 2001/01/09 22:12:25 dadams Exp $
;; Last-Updated: Tue Jan  9 14:12:14 2001
;;           By: dadams
;;     Update #: 571
;; Keywords: matching, help, internal, tools, local
;; Compatibility: GNU Emacs 20.x
;; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 
;;; Commentary: 
;; 
;;    Extensions to `replace.el'.
;;
;;  New functions here:
;;
;;    `query-replace-w-options', `toggle-replace-w-completion'.
;;
;;  New user options (variables) here:
;;
;;    `list-matching-lines-face', `replace-w-completion',
;;    `search/replace-default-fn'.
;;
;;  Other variable defined here: `occur-regexp'.
;;
;;
;;  ***** NOTE: The following functions defined in `replace.el' have
;;              been REDEFINED HERE:
;;
;;  `flush-lines' - 1. The prompt has been changed, to mention that
;;                     only lines after point are affected.
;;                  2. The default regexp is provided by
;;                     `search/replace-default-fn'.
;;                  3. An in-progress message has been added.
;;  `how-many' - 1. Prompt changed: lines after point are affected.
;;               2. Default regexp: `search/replace-default-fn'.
;;               3. An in-progress message has been added.
;;  `keep-lines' - Same as `flush-lines'.
;;  `occur' - Default regexp is given by `search/replace-default-fn'.
;;  `occur-mode-goto-occurrence' - Highlights regexp in source buffer.
;;  `occur-mode-mouse-goto' - Highlights regexp in source buffer.
;;  `query-replace-read-args' - 1. Uses `completing-read' if
;;                                 `replace-w-completion' is non-nil.
;;                              2. Default regexps are obtained via
;;                                 `search/replace-default-fn'.
;;
;;
;;  This file should be loaded after loading the standard GNU file
;;  `replace.el'.  So, in your `~/.emacs' file, do this:
;;  (eval-after-load "replace" '(progn (require 'replace+)))
;; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 
;;; Change log:
;; 
;; RCS $Log: replace+.el,v $
;; RCS Revision 1.6  2001/01/09 22:12:25  dadams
;; RCS Adapted file header for Emacs Lisp Archive.
;; RCS
;; RCS Revision 1.5  2001/01/03 17:44:29  dadams
;; RCS *** empty log message ***
;; RCS
;; RCS Revision 1.4  2001/01/03 01:05:53  dadams
;; RCS *** empty log message ***
;; RCS
;; RCS Revision 1.3  2000/12/07 19:52:25  dadams
;; RCS Added require of shrink-fit.el.
;; RCS
;; RCS Revision 1.2  2000/11/28 20:31:12  dadams
;; RCS Optional require's via 3rd arg=t now.
;; RCS
;; RCS Revision 1.1  2000/09/14 17:23:42  dadams
;; RCS Initial revision
;; RCS
; Revision 1.1  1997/03/20  14:32:29  dadams
; Initial revision
;
; Revision 1.21  1996/07/01  13:21:23  dadams
; (trivial)
;
; Revision 1.20  1996/06/20  12:02:54  dadams
; flush-lines, keep-lines: Default regexp from search/replace-default-fn.
;
; Revision 1.19  1996/06/14  12:26:19  dadams
; 1. Added: replace-w-completion, toggle-replace-w-completion.
; 2. query-replace-read-args, query-replace-w-options: Now sensitive to
;    replace-w-completion.
;
; Revision 1.18  1996/06/06  14:34:38  dadams
; 1. Require font-lock+.el and frame-cmds.el. (show-a-frame-on is a defsubst)
; 2. Update of file dependency comments (e.g. "Autoloaded from...").
;
; Revision 1.17  1996/04/26  09:59:18  dadams
; Put escaped newlines on long-line strings.
;
; Revision 1.16  1996/04/22  09:25:18  dadams
; Added: flush-lines, keep-lines.
;
; Revision 1.15  1996/04/15  08:15:18  dadams
; occur: Explicitly call shrink-frame-to-fit each time, after displaying.
;
; Revision 1.14  1996/04/05  14:34:11  dadams
; Improved Commentary:  List redefinitions.
;
; Revision 1.13  1996/03/26  16:03:37  dadams
; 1. Added redefinition of query-replace-read-args.
; 2. perform-replace: cond -> case.
; 3. query-replace-w-options: message -> display-in-minibuffer (STRING).
;
; Revision 1.12  1996/03/20  17:55:27  dadams
; 1. perform-replace: Added msgs for leaving recursive edit.
; 2. query-replace-w-options: Defaults for new and old are the same.
;
; Revision 1.11  1996/03/20  09:52:18  dadams
; 1. Added search/replace-default-fn.
; 2. query-replace-w-options, occur:
;    symbol-name-nearest-point -> search/replace-default-fn.
;
; Revision 1.10  1996/03/14  10:21:10  dadams
; Added perform-replace: When change markers to numbers, ensure markerp.
;
; Revision 1.9  1996/03/08  14:01:00  dadams
; 1. Copyright.
; 2. drew-faces.el -> std-faces.el, drew-window-cmds.el -> frame-cmds.el,
;    drew-strings.el -> thingatpt+.el plus strings.el.
;
; Revision 1.8  1996/02/28  16:49:00  dadams
; Renamed query-replace -> query-replace-w-options.  It calls query-replace,
; not perform-replace (was bugged when unread-command-events).
;
; Revision 1.7  1996/02/15  14:41:40  dadams
; occur: Minor correction of last change.
;
; Revision 1.6  1996/02/15  14:27:23  dadams
; occur: Don't raise Occur frame if no occurrences.
;
; Revision 1.5  1996/02/14  17:56:35  dadams
; symbol-around-point -> symbol-name-nearest-point
;
; Revision 1.4  1996/02/12  10:04:56  dadams
; Updated header keywords (for finder).
;
; Revision 1.3  1996/02/06  11:02:58  dadams
; (trivial)
;
; Revision 1.2  1996/02/05  15:56:25  dadams
; occur-mode-goto-occurrence, occur-mode-mouse-goto:
;    Highlight last goto lineno.
;
; Revision 1.1  1996/02/05  15:23:30  dadams
; Initial revision
;; 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 
;;; Code: 

;; Cannot do (require 'replace), because `replace.el' does no `provide'.
;; Don't want to do a (load-library "replace") either, because it wouldn't
;; allow doing (eval-after-load "replace" '(progn (require 'replace+)))

(require 'cl) ;; when, unless, incf, push, pop

(require 'thingatpt nil t) ;; (no error if not found): word-at-point
(require 'thingatpt+ nil t) ;; (no error if not found): 
symbol-name-nearest-point
(require 'strings nil t) ;; (no error if not found): display-in-minibuffer
(require 'frame-cmds nil t) ;; (no error if not found): show-a-frame-on
(require 'frame-fns nil t) ;; (no error if not found): get-a-frame
(require 'shrink-fit nil t) ;; (no error if not found): shrink-frame-to-fit
(require 'highlight nil t) ;; (no error if not found): highlight-regexp-region

;; Get macro `define-face-const' when this is compiled,
;; or run interpreted, but not when the compiled code is loaded.
(eval-when-compile (require 'def-face-const))


(provide 'replace+)

;;;;;;;;;;;;;;;;;;;;;


;;;###autoload
(defvar replace-w-completion nil
  "*Non-nil <=> Use minibuffer completion for replacement commands
such as `query-replace'. With completion, to insert a SPC or TAB char,
you will need to preceed it by `\\[quoted-insert]'.  If this is
inconvenient, set this variable to nil.")

;;;###autoload
(defun toggle-replace-w-completion (force-p)
  "Toggle whether to use minibuffer completion for replacement commands
such as `query-replace'.  (This just sets var `replace-w-completion'.)
Non-nil prefix arg FORCE-P => Use completion iff FORCE-P >= 0.

Note that with completion, to insert a SPC or TAB character you will
need to preceed it by `\\[quoted-insert]'."
  (interactive "P")
  (if force-p                           ; Force.
      (if (natnump (prefix-numeric-value force-p))
          (setq replace-w-completion t)
        (setq replace-w-completion nil))
    (setq replace-w-completion (not replace-w-completion)))) ; Toggle.


;;;###autoload
(defvar search/replace-default-fn
  (if (fboundp 'symbol-name-nearest-point)
      'symbol-name-nearest-point
    'word-at-point)
  "*Fn of 0 args called to provide default input for search/replacement
functions such as \\[query-replace-w-options] and \\[occur].

Some reasonable choices are defined in `thingatpt+.el':
`word-nearest-point', `symbol-name-nearest-point', `sexp-nearest-point'")



;; REPLACES ORIGINAL in `replace.el'.
;; 1. Uses `completing-read' if `replace-w-completion' is non-nil.
;; 2. The default regexps are provided by `search/replace-default-fn'.
;;;###autoload
(defun query-replace-read-args (string regexp-flag)
  "Read arguments for replacement functions such as `\\[query-replace]'.
The variable `replace-w-completion', if non-nil, provides for
minibuffer completion while you type the arguments.  In that case, to
insert a SPC or TAB character, you will need to preceed it by \
`\\[quoted-insert]'."
  (let* ((default (if (fboundp search/replace-default-fn)
                      (funcall search/replace-default-fn)
                    (car regexp-history)))
         (old-prompt (concat string ".   OLD (to be replaced): "))
         (oldx (if replace-w-completion
                   (completing-read old-prompt obarray nil nil default
                                    query-replace-from-history-variable default 
t)
                 (if query-replace-interactive
                     (car (if regexp-flag regexp-search-ring search-ring))
                   (read-from-minibuffer old-prompt default nil nil
                                         query-replace-from-history-variable 
default t))))
         (new-prompt (format "NEW (replacing %s): " oldx))
         (newx (if replace-w-completion
                   (completing-read new-prompt obarray nil nil default
                                    query-replace-to-history-variable default t)
                 (read-from-minibuffer new-prompt default nil nil
                                       query-replace-to-history-variable 
default t))))
    (list oldx newx current-prefix-arg)))
      


;; The main difference between this and `query-replace' is in the
;; treatment of the PREFIX arg.  Only a positive (or nil) PREFIX value
;; gives the same behavior.  A negative PREFIX value does a regexp
;; query replace.
;; Also, unlike the standard GNU `query-replace', this has the same
;; behavior as the version of `query-replace-read-args' defined here:
;;    1. It uses `completing-read' if `replace-w-completion' is non-nil.
;;    2. The default regexps are provided by `search/replace-default-fn'.
;;;###autoload
(defun query-replace-w-options (old new &optional prefix display-msgs)
  "Replace some occurrences of OLD text with NEW one.

No PREFIX arg (nil) => replace literal string matches.
Positive PREFIX arg => replace word matches.
Negative PREFIX arg => replace regexp matches.

As each match is found, you type a character saying what to do.
For more info, type \\[help-command] at that time.

Preserves case in each replacement if variables `case-replace' and
`case-fold-search' are non-nil and OLD has no uppercase letters.

Fourth arg DISPLAY-MSGS non-nil (interactive-p) =>
      Display an in-progress msg.

To customize possible responses, change `query-replace-map' \"bindings\".

The variable `replace-w-completion', if non-nil, provides for
minibuffer completion while you type OLD and NEW.  In that case, to
insert a SPC or TAB character, you will need to preceed it by \
`\\[quoted-insert]'."
  (interactive
   (let* ((kind (and current-prefix-arg
                     (if (natnump (prefix-numeric-value current-prefix-arg))
                         "WORD "
                       "REGEXP ")))
          (default (if (fboundp search/replace-default-fn)
                       (funcall search/replace-default-fn)
                     (car regexp-history)))
          (old-prompt (concat "OLD  (" kind "to be replaced) : "))
          (oldx (if replace-w-completion
                    (completing-read old-prompt obarray nil nil default
                                     query-replace-from-history-variable)
                  (if query-replace-interactive
                      (car
                       (if (and prefix
                                (not (natnump (prefix-numeric-value
                                               current-prefix-arg))))
                           regexp-search-ring
                         search-ring))
                    (read-from-minibuffer old-prompt default nil nil
                                          
query-replace-from-history-variable))))
          (new-prompt (format "NEW (replacing %s): " oldx))
          (newx (if replace-w-completion
                    (completing-read new-prompt obarray nil nil default
                                     query-replace-to-history-variable)
                  (read-from-minibuffer new-prompt default nil nil
                                        query-replace-to-history-variable))))
     (list oldx newx current-prefix-arg 'display-msgs)))

  (let ((face (and (fboundp 'display-in-minibuffer)
                   (or (and (boundp 'blue-foreground-face)
                            blue-foreground-face)
                       (define-face-const "Blue" nil)))))
    (if prefix
        (cond ((natnump (prefix-numeric-value prefix))
               (when face
                 (display-in-minibuffer
                  1 "(" (list face "WORD") " replacement.)"))
               (query-replace old new t))
              (t
               (when face
                 (display-in-minibuffer
                  1 "(" (list face "REGEXP") " replacement.)"))
               (query-replace-regexp old new)))
      (when face
        (display-in-minibuffer 1 "(" (list face "STRING")
                               " replacement.)"))
      (query-replace old new))
    (when display-msgs                  ; interactive-p
      (if face
          (display-in-minibuffer 'event "query-replace `"
                                 (list face old) "' by `"
                                 (list face new) "' ... done.")
        (message "query-replace `%s' by `%s' ... done." old new)))))

;;;###autoload
(defalias 'delete-non-matching-lines 'keep-lines)
;; REPLACES ORIGINAL in `replace.el':
;; 1. Prompt changed, to mention that lines after point are affected.
;; 2. The default regexp is provided by `search/replace-default-fn'.
;; 3. An in-progress message has been added.
;;;###autoload
(defun keep-lines (regexp)
  "Delete all lines after point except those with a match for REGEXP.
A match split across lines preserves all the lines it lies in.
Note that the lines are deleted, not killed to the kill-ring.

If REGEXP contains upper case characters (excluding those preceded by `\\'),
the matching is case-sensitive."
  (interactive
   (list (read-from-minibuffer
          "Keep lines after cursor that contain a match for REGEXP: "
          (if (fboundp search/replace-default-fn)
              (funcall search/replace-default-fn)
            (car regexp-history))
          nil nil 'regexp-history nil t)))
  (when (interactive-p) (message "Deleting non-matching lines ..."))
  (save-excursion
    (unless (bolp) (forward-line 1))
    (let ((start (point))
          (case-fold-search  (and case-fold-search
                                  (isearch-no-upper-case-p regexp t))))
      (while (not (eobp))
        ;; Start is first char not preserved by previous match.
        (if (not (re-search-forward regexp nil 'move))
            (delete-region start (point-max))
          (let ((end (save-excursion (goto-char (match-beginning 0))
                                     (beginning-of-line) (point))))
            ;; Now end is first char preserved by the new match.
            (when (< 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 (not (eobp)) (= (match-beginning 0) (match-end 0))
             (forward-char 1)))))
  (when (interactive-p) (message "Deleting non-matching lines ... done.")))

;;;###autoload
(defalias 'delete-matching-lines 'flush-lines)
;; REPLACES ORIGINAL in `replace.el':
;; 1. Prompt changed, to mention that lines after point are affected.
;; 2. The default regexp is provided by `search/replace-default-fn'.
;; 3. An in-progress message has been added.
;;;###autoload
(defun flush-lines (regexp)
  "Delete lines after point that contain a match for REGEXP.
If a match is split across lines, all the lines it lies in are deleted.
Note that the lines are deleted, not killed to the kill-ring.

If REGEXP contains upper case characters (excluding those preceded by `\\'),
the matching is case-sensitive."
  (interactive
   (list (read-from-minibuffer
          "Delete lines after cursor that contain a match for REGEXP: "
          (if (fboundp search/replace-default-fn)
              (funcall search/replace-default-fn)
            (car regexp-history))
          nil nil 'regexp-history nil t)))
  (when (interactive-p) (message "Deleting matching lines ..."))
  (let ((case-fold-search (and case-fold-search
                               (isearch-no-upper-case-p regexp t))))
    (save-excursion
      (while (and (not (eobp)) (re-search-forward regexp nil t))
        (delete-region (save-excursion (goto-char (match-beginning 0))
                                       (beginning-of-line) (point))
                       (progn (forward-line 1) (point))))))
  (when (interactive-p) (message "Deleting matching lines ... done.")))

;;;###autoload
(defalias 'count-matches 'how-many)
;; REPLACES ORIGINAL in `replace.el':
;; 1. Prompt changed, to mention that lines after point are affected.
;; 2. The default regexp is provided by `search/replace-default-fn'.
;; 3. An in-progress message has been added.
;;;###autoload
(defun how-many (regexp)
  "Print number of matches for REGEXP following point.

If REGEXP contains upper case characters (excluding those preceded by `\\'),
the matching is case-sensitive."
  (interactive (list (read-from-minibuffer
                      "Count matches after point for REGEXP: "
                      (if (fboundp search/replace-default-fn)
                          (funcall search/replace-default-fn)
                        (car regexp-history)) nil nil 'regexp-history nil t)))
  (when (interactive-p) (message "Counting matches after point ..."))
  (let ((count 0)
        (case-fold-search  (and case-fold-search
                                (isearch-no-upper-case-p regexp t)))
        opoint)
    (save-excursion
      (while (and (not (eobp))
                  (progn (setq opoint (point))
                         (re-search-forward regexp nil t)))
        (if (= opoint (point))
            (forward-char 1)
          (setq count (1+ count))))
      (message "%d matches after point." count))))

(defconst list-matching-lines-face
  (or (and (boundp 'skyblue-background-face)
           skyblue-background-face)
      (define-face-const nil "SkyBlue"))
  "*Face used by `list-matching-lines' to show text matching regexp.
If nil, matches are not highlighted.")

;;;###autoload
(defvar occur-regexp nil "Search pattern used by `occur' command.")


;;;###autoload
(defalias 'list-matching-lines 'occur)

;; REPLACES ORIGINAL in `replace.el':
;; The default regexp is provided by `search/replace-default-fn'.
;;;###autoload
(defun occur (regexp &optional nlines)
  "Show all lines in the current buffer containing a match for REGEXP.

If a match spreads across multiple lines, all those lines are shown.

Each line is displayed with NLINES lines before and after,
or -NLINES before if NLINES is negative.  NLINES defaults to
`list-matching-lines-default-context-lines'.
Interactively it is the prefix arg.

The lines are shown in a buffer named `*Occur*'.  This serves as a
menu to find any of the occurrences in the current buffer.
\\<occur-mode-map>\\[describe-mode] in the `*Occur*' buffer will explain how.

If REGEXP contains upper case characters (excluding those preceded by `\\'),
the matching is case-sensitive."
  (interactive
   (list (let ((default (if (fboundp search/replace-default-fn)
                            (funcall search/replace-default-fn)
                          (car regexp-history))))
           (read-from-minibuffer
            "List lines matching regexp: "
            default nil nil 'regexp-history default t))
         current-prefix-arg))
  (setq occur-regexp regexp)            ; Save for highlighting.
  (let ((nlines (if nlines
                    (prefix-numeric-value nlines)
                  list-matching-lines-default-context-lines))
        (first t)
        ;;flag to prevent printing separator for first match
        (occur-num-matches 0)
        (buffer (current-buffer))
        (dir default-directory)
        (linenum 1)
        (prevpos 
         ;;position of most recent match
         (point-min))
        (case-fold-search  (and case-fold-search
                                (isearch-no-upper-case-p regexp t)))
        (final-context-start
         ;; Marker to the start of context immediately following
         ;; the matched text in *Occur*.
         (make-marker)))
;;;     (save-excursion
;;;       (beginning-of-line)
;;;       (setq linenum (1+ (count-lines (point-min) (point))))
;;;       (setq prevpos (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)))
          (when (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
                      ;;start point of text in source buffer to be put
                      ;;into *Occur*
                      (save-excursion
                        (goto-char (match-beginning 0))
                        (forward-line (if (< nlines 0) nlines (- nlines)))
                        (point)))
                     (end
                      ;; end point of text in source buffer to be put
                      ;; into *Occur*
                      (save-excursion 
                        (goto-char (match-end 0))
                        (if (> nlines 0)
                            (forward-line (1+ nlines))
                          (forward-line 1))
                        (point)))
                     (match-beg
                      ;; Amount of context before matching text
                      (- (match-beginning 0) start))
                     (match-len         
                      ;; Length of matching text
                      (- (match-end 0) (match-beginning 0)))
                     (tag (format "%5d" linenum))
                     (empty (make-string (length tag) ?\ ))
                     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)
                  
                  ;; 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.
                  (when 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)
                      (when (null tag)
                        (setq tag (format "%5d" this-linenum)))
                      (insert tag ?:)
;;;                       ;; DDA: Add mouse-face to line
;;;                       (put-text-property (save-excursion
;;;                                            (beginning-of-line) (point))
;;;                                          (save-excursion (end-of-line) 
(point))
;;;                                          'mouse-face 'underline)
;;;                       ;; DDA: Highlight `grep-pattern' in compilation 
buffer, if possible.
;;;                       (when (fboundp 'highlight-regexp-region)
;;;                         (highlight-regexp-region
;;;                          (save-excursion (beginning-of-line) (point))
;;;                          (save-excursion (end-of-line) (point))
;;;                          occur-regexp list-matching-lines-face))
                      (forward-line 1)
                      (setq tag nil)
                      (incf 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)
                                     'mouse-face 'underline)
                  (put-text-property (marker-position text-beg)
                                     (marker-position text-end)
                                     'occur occur-marker)
                  (goto-char (point-max)))
                (forward-line 1)))
            (set-buffer standard-output)
            ;; Go back to top of *Occur* and finish off by printing the
            ;; number of matching lines.
            (goto-char (point-min))
            (let ((message-string
                   (if (= occur-num-matches 1)
                       "1 line"
                     (format "%d lines" occur-num-matches))))
              (insert message-string)
              (when (interactive-p)
                (message "%s matched" message-string)))
            (setq buffer-read-only t)))
        (when (fboundp 'show-a-frame-on) ; Defined in `frame-cmds.el'.
          (show-a-frame-on "*Occur*"))
        (let ((fr (and (fboundp 'get-a-frame) ; Defined in `frame-fns.el'.
                       (get-a-frame "*Occur*"))))
          (when (and fr (fboundp 'shrink-frame-to-fit)) ; Defined in 
`shrink-fit.el'.
            (shrink-frame-to-fit fr)))))))



;; REPLACES ORIGINAL in `replace.el':
;; Highlights regexp in source buffer.
;;;###autoload
(defun occur-mode-mouse-goto (event)
  "In Occur mode, go to the occurrence whose line you click on."
  (interactive "e")
  (let (buffer pos)
    (save-excursion
      (set-buffer (window-buffer (posn-window (event-end event))))
      (save-excursion
        (goto-char (posn-point (event-end event)))
        (when (fboundp 'highlight-regexp-region) ; Highlight goto lineno.
          (let ((bol (save-excursion (beginning-of-line) (point))))
            (highlight-regexp-region
             bol
             (save-excursion (beginning-of-line) (search-forward ":" (+ bol 20) 
t) (point))
             "[0-9]+:"
             (or (and (boundp 'red-foreground-face)
                      red-foreground-face)
                 (define-face-const "Red" nil)))))
        (setq pos (occur-mode-find-occurrence))
        (setq buffer occur-buffer)))
    (pop-to-buffer buffer)
    (goto-char (marker-position pos)))
  (when (fboundp 'highlight-regexp-region)
    (highlight-regexp-region (save-excursion (beginning-of-line) (point))
                             (save-excursion (end-of-line) (point))
                             occur-regexp list-matching-lines-face)))



;; REPLACES ORIGINAL in `replace.el':
;; Highlights regexp in source buffer.
;;;###autoload
(defun occur-mode-goto-occurrence ()
  "Go to the occurrence the current line describes."
  (interactive)
  (when (fboundp 'highlight-regexp-region) ; Highlight goto lineno.
    (let ((bol (save-excursion (beginning-of-line) (point))))
      (highlight-regexp-region
       bol
       (save-excursion (beginning-of-line) (search-forward ":" (+ bol 20) t) 
(point))
       "[0-9]+:"
       (or (and (boundp 'red-foreground-face)
                red-foreground-face)
           (define-face-const "Red" nil)))))
  (let ((pos (occur-mode-find-occurrence)))
    (pop-to-buffer occur-buffer)
    (goto-char (marker-position pos)))
  ;; If possible, highlight regexp in buffer, and lineno in *Occur* buffer.
  (when (fboundp 'highlight-regexp-region)
    (highlight-regexp-region (save-excursion (beginning-of-line) (point))
                             (save-excursion (end-of-line) (point))
                             occur-regexp list-matching-lines-face)))



;;;@@@Emacs20 ;; REPLACES ORIGINAL in `replace.el':
;;;@@@Emacs20 ;; When change markers to numbers (after query loop), ensure they 
are markers.
;;;@@@Emacs20 ;;;###autoload
;;;@@@Emacs20 (defun perform-replace (from-string replacements query-flag 
regexp-flag
;;;@@@Emacs20                                     delimited-flag &optional 
repeat-count map)
;;;@@@Emacs20   "Subroutine of `query-replace'.  Its complexity handles 
interactive queries.
;;;@@@Emacs20 Don't use this in your own program unless you want to query and 
set the mark
;;;@@@Emacs20 just as `query-replace' does.  Instead, write a simple loop like 
this:
;;;@@@Emacs20   (while (re-search-forward \"foo[ \t]+bar\" nil t)
;;;@@@Emacs20     (replace-match \"foobar\" nil nil))
;;;@@@Emacs20 which will run faster and probably do what you want."
;;;@@@Emacs20   (unless map (setq map query-replace-map))
;;;@@@Emacs20   (let ((nocasify (not (and case-fold-search case-replace
;;;@@@Emacs20                             (string-equal from-string
;;;@@@Emacs20                                           (downcase 
from-string)))))
;;;@@@Emacs20         (literal (not regexp-flag))
;;;@@@Emacs20         (search-function (if regexp-flag 're-search-forward 
'search-forward))
;;;@@@Emacs20         (search-string from-string)
;;;@@@Emacs20         (real-match-data nil)           ; The match data for the 
current match.
;;;@@@Emacs20         (next-replacement nil)
;;;@@@Emacs20         (replacement-index 0)
;;;@@@Emacs20         (keep-going t)
;;;@@@Emacs20         (stack nil)
;;;@@@Emacs20         (next-rotate-count 0)
;;;@@@Emacs20         (replace-count 0)
;;;@@@Emacs20         (lastrepl nil)                  ; Position after last 
match considered.
;;;@@@Emacs20         (match-again t)
;;;@@@Emacs20         (message (and query-flag (substitute-command-keys "Query 
replacing %s \
;;;@@@Emacs20 with %s: (\\<query-replace-map>\\[help] for help) "))))
;;;@@@Emacs20     (if (stringp replacements)
;;;@@@Emacs20         (setq next-replacement replacements)
;;;@@@Emacs20       (unless repeat-count (setq repeat-count 1)))
;;;@@@Emacs20     (when delimited-flag
;;;@@@Emacs20       (setq search-function 're-search-forward)
;;;@@@Emacs20       (setq search-string (concat "\\b" (if regexp-flag
;;;@@@Emacs20                                             from-string
;;;@@@Emacs20                                           (regexp-quote 
from-string))
;;;@@@Emacs20                                   "\\b")))
;;;@@@Emacs20     (push-mark)
;;;@@@Emacs20     (undo-boundary)
;;;@@@Emacs20     (unwind-protect
;;;@@@Emacs20         ;; Loop finding occurrences that perhaps should be 
replaced.
;;;@@@Emacs20         (while (and keep-going
;;;@@@Emacs20                     (not (eobp))
;;;@@@Emacs20                     (funcall search-function search-string nil t)
;;;@@@Emacs20                     ;; If the search string matches immediately 
after
;;;@@@Emacs20                     ;; the previous match, but it did not match 
there
;;;@@@Emacs20                     ;; before the replacement was done, ignore 
the match.
;;;@@@Emacs20                     (or (not (or (eq lastrepl (point))
;;;@@@Emacs20                                  (and regexp-flag
;;;@@@Emacs20                                       (eq lastrepl 
(match-beginning 0))
;;;@@@Emacs20                                       (not match-again))))
;;;@@@Emacs20                         (and (not (eobp))
;;;@@@Emacs20                              ;; Don't replace the null string 
;;;@@@Emacs20                              ;; right after end of previous 
replacement.
;;;@@@Emacs20                              (progn (forward-char 1)
;;;@@@Emacs20                                     (funcall search-function 
search-string
;;;@@@Emacs20                                              nil t)))))
;;;@@@Emacs20           ;; Save the data associated with the real match.
;;;@@@Emacs20           (setq real-match-data (match-data))
;;;@@@Emacs20           ;; Before we make the replacement, decide whether the 
search string
;;;@@@Emacs20           ;; can match again just after this match.
;;;@@@Emacs20           (when regexp-flag (setq match-again (looking-at 
search-string)))
;;;@@@Emacs20           ;; If time for a change, advance to next replacement 
string.
;;;@@@Emacs20           (when (and (listp replacements) (= next-rotate-count 
replace-count))
;;;@@@Emacs20             (incf next-rotate-count repeat-count)
;;;@@@Emacs20             (setq next-replacement (nth replacement-index 
replacements))
;;;@@@Emacs20             (setq replacement-index (% (1+ replacement-index)
;;;@@@Emacs20                                        (length replacements))))
;;;@@@Emacs20           (if (not query-flag)
;;;@@@Emacs20               (progn (store-match-data real-match-data)
;;;@@@Emacs20                      (replace-match next-replacement nocasify 
literal)
;;;@@@Emacs20                      (incf replace-count))
;;;@@@Emacs20             (undo-boundary)
;;;@@@Emacs20             (let (done replaced key def)
;;;@@@Emacs20               ;; Loop reading commands until one of them sets 
DONE,
;;;@@@Emacs20               ;; which means it has finished handling this 
occurrence.
;;;@@@Emacs20               (while (not done)
;;;@@@Emacs20                 (store-match-data real-match-data)
;;;@@@Emacs20                 (replace-highlight (match-beginning 0) (match-end 
0))
;;;@@@Emacs20           ;; Bind message-log-max so we don't fill up the message 
log
;;;@@@Emacs20           ;; with a bunch of identical messages.
;;;@@@Emacs20           (let ((message-log-max nil))
;;;@@@Emacs20             (message message from-string next-replacement))
;;;@@@Emacs20           (setq key (read-event))
;;;@@@Emacs20           (setq key (vector key))
;;;@@@Emacs20           (setq def (lookup-key map key))
;;;@@@Emacs20           ;; Restore the match data while we process the command.
;;;@@@Emacs20           (cond ((eq def 'help)
;;;@@@Emacs20                  (with-output-to-temp-buffer "*Help*"
;;;@@@Emacs20                    (princ
;;;@@@Emacs20                     (concat "Query replacing "
;;;@@@Emacs20                             (if regexp-flag "regexp " "")
;;;@@@Emacs20                             from-string " by "
;;;@@@Emacs20                             next-replacement ".\n\n"
;;;@@@Emacs20                             (substitute-command-keys
;;;@@@Emacs20                              query-replace-help)))
;;;@@@Emacs20                    (save-excursion
;;;@@@Emacs20                      (set-buffer standard-output)
;;;@@@Emacs20                      (help-mode))))
;;;@@@Emacs20                 ((eq def 'exit)
;;;@@@Emacs20                  (setq keep-going nil)
;;;@@@Emacs20                  (setq done t))
;;;@@@Emacs20                 ((eq def 'backup)
;;;@@@Emacs20                  (if stack
;;;@@@Emacs20                      (let ((elt (car stack)))
;;;@@@Emacs20                        (goto-char (car elt))
;;;@@@Emacs20                        (setq replaced (eq t (cdr elt)))
;;;@@@Emacs20                        (unless replaced
;;;@@@Emacs20                                (store-match-data (cdr elt)))
;;;@@@Emacs20                        (pop stack))
;;;@@@Emacs20                    (message "No previous match")
;;;@@@Emacs20                    (ding 'no-terminate)
;;;@@@Emacs20                    (sit-for 1)))
;;;@@@Emacs20                 ((eq def 'act)
;;;@@@Emacs20                  (unless replaced
;;;@@@Emacs20                          (replace-match next-replacement nocasify 
literal))
;;;@@@Emacs20                  (setq done t) (setq replaced t))
;;;@@@Emacs20                 ((eq def 'act-and-exit)
;;;@@@Emacs20                  (unless replaced
;;;@@@Emacs20                      (replace-match next-replacement nocasify 
literal))
;;;@@@Emacs20                  (setq keep-going nil)
;;;@@@Emacs20                  (setq done t) (setq replaced t))
;;;@@@Emacs20                 ((eq def 'act-and-show)
;;;@@@Emacs20                  (unless replaced
;;;@@@Emacs20                          (replace-match next-replacement nocasify 
literal)
;;;@@@Emacs20                          (setq replaced t)))
;;;@@@Emacs20                 ((eq def 'automatic)
;;;@@@Emacs20                  (unless replaced
;;;@@@Emacs20                          (replace-match next-replacement nocasify 
literal))
;;;@@@Emacs20                  (setq done t)
;;;@@@Emacs20                        (setq query-flag nil)
;;;@@@Emacs20                        (setq replaced t))
;;;@@@Emacs20                 ((eq def 'skip)
;;;@@@Emacs20                  (setq done t))
;;;@@@Emacs20                 ((eq def 'recenter)
;;;@@@Emacs20                  (recenter nil))
;;;@@@Emacs20                 ((eq def 'edit)
;;;@@@Emacs20                        (message (substitute-command-keys
;;;@@@Emacs20                                  "Recursive edit.  Type 
\\[exit-recursive-edit] \
;;;@@@Emacs20 to return to top level."))
;;;@@@Emacs20                  (store-match-data
;;;@@@Emacs20                   (prog1 (match-data)
;;;@@@Emacs20                     (save-excursion (recursive-edit))))
;;;@@@Emacs20                  ;; Before we make the replacement,
;;;@@@Emacs20                  ;; decide whether the search string
;;;@@@Emacs20                  ;; can match again just after this match.
;;;@@@Emacs20                  (when regexp-flag
;;;@@@Emacs20                          (setq match-again (looking-at 
search-string))))
;;;@@@Emacs20                 ((eq def 'delete-and-edit)
;;;@@@Emacs20                        (message (substitute-command-keys
;;;@@@Emacs20                                  "Recursive edit.  Type 
\\[exit-recursive-edit] \
;;;@@@Emacs20 to return to top level."))
;;;@@@Emacs20                  (delete-region (match-beginning 0) (match-end 0))
;;;@@@Emacs20                  (store-match-data
;;;@@@Emacs20                   (prog1 (match-data)
;;;@@@Emacs20                     (save-excursion (recursive-edit))))
;;;@@@Emacs20                  (setq replaced t))
;;;@@@Emacs20                 ;; Note: we do not need to treat `exit-prefix'
;;;@@@Emacs20                 ;; specially here, since we reread
;;;@@@Emacs20                 ;; any unrecognized character.
;;;@@@Emacs20                 (t
;;;@@@Emacs20                  (setq this-command 'mode-exited)
;;;@@@Emacs20                  (setq keep-going nil)
;;;@@@Emacs20                  (setq unread-command-events
;;;@@@Emacs20                        (append (listify-key-sequence key)
;;;@@@Emacs20                                unread-command-events))
;;;@@@Emacs20                  (setq done t))))
;;;@@@Emacs20         ;; Record previous position for ^ when we move on.
;;;@@@Emacs20         ;; Change markers to numbers in the match data
;;;@@@Emacs20         ;; since lots of markers slow down editing.
;;;@@@Emacs20         (push (cons (point)
;;;@@@Emacs20                           (or replaced
;;;@@@Emacs20                               (mapcar (lambda (elt)
;;;@@@Emacs20                                         (and (markerp elt)
;;;@@@Emacs20                                              (prog1 
(marker-position elt)
;;;@@@Emacs20                                                (set-marker elt 
nil))))
;;;@@@Emacs20                                       (match-data))))
;;;@@@Emacs20                     stack)
;;;@@@Emacs20         (when replaced (incf replace-count))))
;;;@@@Emacs20     (setq lastrepl (point)))
;;;@@@Emacs20       (replace-dehighlight))
;;;@@@Emacs20     (or unread-command-events
;;;@@@Emacs20   (message "Replaced %d occurrence%s"
;;;@@@Emacs20            replace-count
;;;@@@Emacs20            (if (= replace-count 1) "" "s")))
;;;@@@Emacs20     (and keep-going stack)))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; `replace+.el' ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]