[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
igrep-find-replace.el --- igrep interface for query-replace
From: |
Kevin A. Burton |
Subject: |
igrep-find-replace.el --- igrep interface for query-replace |
Date: |
04 Nov 2001 02:40:41 -0800 |
User-agent: |
Gnus/5.0808 (Gnus v5.8.8) Emacs/21.1 |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
OK... just some small usability fixes.
;; - Wed Oct 31 2001 10:38 PM (address@hidden): overlay-arrow-string
;; must be non-nil. AKA '>'
;;
;; - Wed Oct 31 2001 09:24 AM (address@hidden): need to show the user
;; (somehow) that the replacement was actually done correctly. This is
;; necessary because we need to show the user what is actually happening
;; without any confusion.
;;
;; - now using sit-for to handle this.
;;; igrep-find-replace.el --- igrep interface for query-replace
;; $Id: igrep-find-query-replace.el,v 1.5 2001/11/02 09:43:06 burton Exp $
;; Copyright (C) 2000-2003 Free Software Foundation, Inc.
;; Copyright (C) 2000-2003 Kevin A. Burton (address@hidden)
;; Author: Kevin A. Burton (address@hidden)
;; Maintainer: Kevin A. Burton (address@hidden)
;; Location: http://relativity.yi.org
;; Keywords:
;; Version: 1.0.0
;; This file is [not yet] part of GNU Emacs.
;; 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 of the License, or 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; if not, write to the Free Software Foundation, Inc., 59 Temple
;; Place - Suite 330, Boston, MA 02111-1307, USA.
;;; Commentary:
;;
;; This is a utility for igrep. It allows you to run igrep-find and
;; 'query-replace' within all matched files. This allows you to make major
;; changes to multiple files at once.
;;
;; The interface behaves just like 'igrep' and 'query-replace' and shouldn't
;; confuse the user with any new UI metaphor.
;;
;;; History
;; - Wed Oct 31 2001 10:38 PM (address@hidden): overlay-arrow-string
;; must be non-nil. AKA '>'
;;
;; - Wed Oct 31 2001 09:24 AM (address@hidden): need to show the user
;; (somehow) that the replacement was actually done correctly. This is
;; necessary because we need to show the user what is actually happening
;; without any confusion.
;;
;; - now using sit-for to handle this.
;; - Tue Oct 30 2001 07:26 PM (address@hidden): we now display the
;; process termination event.
;;
;; - Sat Oct 27 2001 08:32 PM (address@hidden): we are now using an
;; 'overlay-arrow' in the igrep buffer.
;;
;; - Sat Oct 27 2001 07:15 PM (address@hidden): message stating that
;; igrep-find-query-will start when igrep finishes.
;;
;; - Thu Oct 25 2001 01:15 AM (address@hidden): need a "y or n" question
;; on the query prompt.
;;
;;; TODO:
;;
;;
;;; HIGH PRIORITY...
;; - when the file buffer (not the *igrep* buffer) shows the match near the end
;; of beginning of the buffer, center the window so that it is more obvious
what
;; we are replacing.
;;
;; - is there an easy function to do this? maybe -recenter or something?
;;
;; - Make sure that the it is obvious what buffer we are in in the *igrep*
;; buffer.
;;
;; - use the secondary selection face to highlight the current line (in the
;; *igrep* buffer) I am replacing.
;;
;; - support the ability to replace multi-line text..
;;
;; - is it possible to stop using the *igrep* buffer and use an
;; *igrep-find-query-replace* buffer instead?
;;; LOW PRIORITY...
;; - implement igrep-query-replace as well as igrep-find-query-replace. Any
;; other functions I should implement?? agrep, fgrep, etc?
;;
;; - for some reason I am getting this error:
;;
;; error in process sentinel: Args out of range: 0, 6 [2 times]
;;
;; - Use an italic overlay to highlight the current line/file.
;;
;; - In long buffers, keep the current line near the top of the buffer.
(require 'igrep)
;;; Code:
(defvar ifqr-from nil "String to search and replace from.")
(make-variable-buffer-local 'ifqr-from)
(defvar ifqr-with nil "String to search and replace with.")
(make-variable-buffer-local 'ifqr-with)
(defvar ifqr-replacement-count 0 "Number of replacements for the last
`query-replace'.")
(defvar ifqr-text-buffer-name "*ifqr-text*" "Buffer used for reading and writing
text/multiline string")
(defvar ifqr-text-replace-from nil "Search for the given text.")
(defvar ifqr-text-replace-with nil "Replace the given text.")
(defvar ifqr-text-replace-var-name nil "Var name to set.")
(defvar ifqr-text-replace-function nil "Function to eval after completion.")
(defface ifqr-line-overlay-face nil "Overlay used to highlight the current
match.")
(set-face-background 'ifqr-line-overlay-face (face-background
'secondary-selection))
(defvar ifqr-line-overlay (make-overlay 0 0) "Overlay used to highlight this
match.")
(defun igrep-find-query-replace(replace-from replace-with files)
"Use igrep-find to query and replace strings within buffers."
(interactive
(let(from to files)
(setq from (read-string "Query replace: "))
(setq to (read-string (format "Query replace %s with: " from )))
(setq files (igrep-read-files))
(list from to files)))
(delete-other-windows)
(let ((igrep-find t)
igrep-args
filename
process)
(setq igrep-args (list "grep" replace-from files))
;;run igrep-find...
(igrep (elt igrep-args 0)
(elt igrep-args 1)
(elt igrep-args 2))
(message "igrep-find-query-replace will start when igrep finishes...")
;;get the process created by igrep
(setq process (get-process "igrep"))
;;if the process is nil... it exited quickly... process the output.
(if process
;; use a process sentinel to find it.
(progn
;;update buffer local variables for from/width
(save-excursion
(set-buffer (process-buffer process))
(setq ifqr-from replace-from)
(setq ifqr-with replace-with))
(set-process-sentinel process 'ifqr-sentinel))
;;this should never happen... I think... maybe we shouldn't signal an
;;error though.
(error "Unable to find process"))))
(defun ifqr-do()
"Do the query/replace after igrep has ran saving. Show the number of
replacements when complete. "
;;reset the count
(setq ifqr-replacement-count 0)
(let(filename line-number replace-from replace-with quit)
(set-buffer "*igrep*")
(display-buffer "*igrep*")
;;get the local replacement vars..
(setq replace-from ifqr-from)
(setq replace-with ifqr-with)
(beginning-of-buffer)
(forward-line 2)
(ifqr-highlight-line (point))
;;navigate forward though the igrep buffer.
(while (and (not quit)
(re-search-forward "\\(^/[^:]+\\):\\([0-9]+\\):" nil t))
(ifqr-highlight-line (point))
(setq filename (match-string 1))
(setq line-number (string-to-number (match-string 2)))
(setq quit (ifqr-do-replace filename line-number replace-from
replace-with))
;;return to the igrep buffer just in case.
(set-buffer "*igrep*")
(forward-line 1)
(beginning-of-line)))
(message "Replaced %i occurrences...done" ifqr-replacement-count))
(defun ifqr-do-replace(filename line-number replace-from replace-with)
"Do a replacement on the given line number, keep doing until we are complete.
If the user select 'q' (for quit) return true, else nil. "
;;valid options are y/n/q
(let(source-buffer result)
(setq source-buffer (find-file-noselect filename))
(set-window-buffer (other-window 0) source-buffer)
(set-buffer source-buffer)
(goto-line line-number)
(beginning-of-buffer)
(assert (search-forward replace-from nil t)
nil (format "Could not find %s" replace-from))
;;highlight the match...
(ifqr-highlight (match-beginning 0) (match-end 0))
;;if an error is signaled... catch it... this can happen from mouse
;;events/etc..
(condition-case nil
(progn
;;should we replace
(if (yes-or-no-p (format "Query replacing '%s' with '%s' in %s: "
replace-from replace-with filename))
(progn
(replace-match replace-with)
(ifqr-highlight-entire-match)
(sit-for .2)
;;increment the match count...
(setq ifqr-replacement-count (1+ ifqr-replacement-count))
;;important to save the buffer when we are done.
(save-buffer))))
nil)
result))
(defun ifqr-highlight(region-start region-end)
"Setup the mark within the given region."
(goto-char region-start)
(push-mark nil t t)
(goto-char region-end))
(defun ifqr-highlight-entire-match()
"Highlight the entire match."
(ifqr-highlight (match-beginning 0) (match-end 0)))
(defun ifqr-sentinel(process event)
"Process sentinel which detects if the igrep process is done."
(if (and (string-equal (process-name process) "igrep")
(string-match "^finished\n$" event))
(ifqr-do)
(progn
;;else somethign happened.
(save-excursion
(set-buffer "*igrep*")
(end-of-buffer)
(insert event))
(message ""))))
(defun igrep-find-query-replace-text()
"Run query replace on long/text strings."
(interactive)
(ifqr-text-step-1))
(defun ifqr-text-step-1()
"Get the from variable."
(ifqr-read-text-string 'ifqr-text-replace-from
'ifqr-text-step-2
"(Step one) Enter the text you would like to search
for."))
(defun ifqr-text-step-2()
(ifqr-read-text-string 'ifqr-text-replace-with
'ifqr-text-do
"(Step two) Enter the text you would like to use as a
replacement."))
(defun ifqr-read-text-string(var-name function message)
"Read a text string from a buffer."
(setq ifqr-text-replace-var-name var-name)
(setq ifqr-text-replace-function function)
(save-excursion
(set-buffer (get-buffer-create ifqr-text-buffer-name))
(erase-buffer)
(insert (format "//REPLACE-TEXT: %s\n" message))
(ifqr-text-entry-mode))
(pop-to-buffer ifqr-text-buffer-name)
(message message))
(defun ifqr-read-text-complete()
"Complete text entry and continue."
(interactive)
(ifqr-text-cleanse-buffer)
(delete-window (get-buffer-window ifqr-text-buffer-name))
(funcall ifqr-text-replace-function))
(defun ifqr-text-cleanse-buffer()
(save-excursion
(set-buffer ifqr-text-buffer-name)
(beginning-of-buffer)
(while (re-search-forward "^//REPLACE-TEXT: .*$" nil t)
(delete-region (match-beginning 0)
(1+ (match-end 0))))))
(defun ifqr-highlight-line(point)
"Highlight the current line so that people know what the heck is going on..."
(interactive
(list
(point)))
(save-excursion
(set-buffer "*igrep*")
(let((begin nil)
(end nil))
(goto-char point)
(setq begin (point-at-bol))
(setq end (1+ (point-at-eol)))
;;update the Emacs 21 arrow...
(let(m)
(setq m (make-marker))
(set-marker m begin)
(make-local-variable 'overlay-arrow-string)
(setq overlay-arrow-string "=>")
(setq overlay-arrow-position m))
(move-overlay ifqr-line-overlay begin end (current-buffer))
(overlay-put ifqr-line-overlay 'face 'ifqr-line-overlay-face)
(overlay-put ifqr-line-overlay 'window (selected-window))
(overlay-put ifqr-line-overlay 'priority 1)
(sit-for .2))))
(define-derived-mode ifqr-text-entry-mode fundamental-mode "IGrepTextEntry"
"Major mode with key bindings to jump to files."
(interactive)
(font-lock-mode 1))
;;comments
(font-lock-add-keywords 'ifqr-text-entry-mode '(("^//.*$"
(0 'font-lock-comment-face
t))))
(define-key ifqr-text-entry-mode-map "\C-c\C-c" 'ifqr-read-text-complete)
(provide 'igrep-find-query-replace)
;;; igrep-find-replace.el ends here
- --
Kevin A. Burton ( address@hidden, address@hidden, address@hidden )
Location - San Francisco, CA, Cell - 415.595.9965
Jabber - address@hidden, Web - http://relativity.yi.org/
Whenever there is a conflict between human rights and property rights, human
rights must prevail.
-- Abraham Lincoln
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: Get my public key at: http://relativity.yi.org/pgpkey.txt
iD8DBQE75RCIAwM6xb2dfE0RAjn+AJ0a9nx+1P9b0X6mYkSqJA/w1aUo9QCgliL3
tWg5RRs7RdILnBh5+SFdkLQ=
=bYpz
-----END PGP SIGNATURE-----
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- igrep-find-replace.el --- igrep interface for query-replace,
Kevin A. Burton <=