From: knighten@intel.com (Robert L. Knighten)
Subject: Re: How to search again using forward-search?
Reply-To: knighten@ssd.intel.com (Bob Knighten)
Organization: Intel Supercomputer System Division, Beaverton, OR
Date: Thu, 15 Oct 1992 20:42:17 GMT

Below is the code that I wrote and use for non-incremental searching.  The
basic functions that I bind to keys are:

        RLK-search-forward
        RLK-search-forward-again
        RLK-word-search-forward-again
        RLK-word-search-forward
        RLK-search-backward
        RLK-search-backward-again
        RLK-word-search-backward-again
        RLK-word-search-backward

I use function keys for the "search again" functions and meta with the
function key when I want to start a fresh search.  These functions have a
number of other personal preferences built-in:  search is case sensitive if
the search string contains any upper case letters, but case insensitive
otherwise.  If a search is started in the middle of a region and fails, the
user is asked if a search in the opposite direction is desired.  I believe all
of these features can be easily removed.
------------------------------------------------------------------------------

(setq is-word-search nil)     ; starting value in case search-again is used first

(defun RLK-get-search-string (prompt)
  "Gets the search string (as search-last-string!)"
  (let (string)
; Read the search string
    (setq string (read-string prompt))
; Empty means use previous search string.
    (if (> (length string) 0)
      (setq search-last-string string))))


(defun RLK-actual-forward-search ()
  
"Sets case-fold-search properly, calls appropriate search function and 
positions point at front of string found."

  (if is-word-search
      (message "Searching forward (word) for: %s" search-last-string)
    (message "Searching forward for %s" search-last-string))
  (let ((tmp case-fold-search) ; save case-fold-search so it can be restored
	(starting-position (point) found)) ; save point so we can get back if needed
    (forward-char 1)     ;move off starting position
    (setq case-fold-search  ; set according to presence of caps in search string
	  (string-equal search-last-string (downcase search-last-string)))
 ;now search forward
    (setq found  ; record if found the search string
	  (if is-word-search
	      (word-search-forward search-last-string nil t)
	    (search-forward search-last-string nil t)))
    (if found
	(progn  ; yes, so move to start of the found search string and mark
                ; starting position
	  (search-backward search-last-string)
	  (push-mark starting-position))
      (goto-char starting-position) ; no, so go back to starting position
      (message "\"%s\" not found" search-last-string)
      (ding)
    (sleep-for 1)
    (message ""))
    (setq case-fold-search tmp) ; restore case-fold-search
    (setq found found)))  ; return the value of found


(defun try-backward ()
  "Optionally search backward - called if forward search fails."
  (if (not (bobp))
      (progn
	(sleep-for 1)
	(if (y-or-n-p "Search backward? ")
	    (RLK-search-backward-again)
	  (message "")))))


(defun RLK-search-forward-again ()
  "Search forward using search-last-string"
  (interactive)
  (setq is-word-search nil)
  (if (= 0 (length search-last-string))
      (RLK-search-forward)
    (RLK-actual-forward-search)))

(defun RLK-search-forward ()

"Search forward from point for prompted string.  If the search string is all
lower case then the search is NOT case sensitive.  If the search string
contains any upper case letters, then the search is case sensitive.  The
search string is put into search-last-string for use by search-again."

     (interactive)
     (RLK-get-search-string "Search forward for: ")
     (setq is-word-search nil)
     (if (not (RLK-actual-forward-search))
	 (try-backward)))

(defun RLK-word-search-forward-again ()
  "Search forward for the word in search-last-string"
  (interactive)
  (if (= 0 (length search-last-string))
      (RLK-word-search-forward)
    (setq is-word-search t)
    (RLK-actual-forward-search)
    (message "")))


(defun RLK-word-search-forward ()
  
"Search forward from point for prompted string, delimited as a word.  If the
search string is all lower case then the search is NOT case sensitive.  If the
search string contains any upper case letters, then the search is case
sensitive.  The search string is put into search-last-string for use by
search-again."

     (interactive)
     (RLK-get-search-string "Search forward (word) for: ")
     (setq is-word-search t)
     (if (not (RLK-actual-forward-search))
	 (try-backward)))


(defun RLK-actual-backward-search ()

"Sets case-fold-search properly, calls appropriate search function and 
positions point at front of string found."
  
(message "Searching backward for: %s" search-last-string)
(let (tmp (starting-position (point) found))
  (setq tmp case-fold-search)
  (setq case-fold-search 
	(string-equal search-last-string (downcase search-last-string)))
					;now search backward
  (setq found
	(if is-word-search
	    (word-search-backward search-last-string nil t)
	  (search-backward search-last-string nil t)))
  (if found
      (push-mark starting-position)
    (goto-char starting-position)
    (message "\"%s\" not found" search-last-string)
    (ding)
    (sleep-for 1)
    (message ""))
  (setq case-fold-search tmp)
  (setq found found)))


(defun try-forward ()
  "Optionally search forward - called if backward search fails."
  (if (not (eobp))
      (progn
	(sleep-for 1)
	(if (y-or-n-p "Search forward? ")
	    (RLK-search-forward-again)
	  (message "")))))

(defun RLK-search-backward-again ()
  "Search backward using search-last-string"
  (interactive)
  (if (= 0 (length search-last-string))
      (RLK-search-backward)
    (RLK-actual-backward-search)
    (message "")))


(defun RLK-search-backward ()
     
"Search backward from point for prompted string.  If the search string is
all lower case then the search is NOT case sensitive.  If the search string
search string is put into search-last-string for use by search-again."

(interactive)
(RLK-get-search-string "Search backward for: ")
(setq is-word-search nil)
(if (not (RLK-actual-backward-search))
    (try-forward)))


(defun RLK-word-search-backward-again ()
  "Search backward for the word in search-last-string"
  (interactive)
  (if (= 0 (length search-last-string))
      (RLK-word-search-backward)
    (setq is-word-search t)
    (RLK-actual-backward-search)
    (message "")))


(defun RLK-word-search-backward ()

"Search backward from point for prompted string, delimited as a word.  If the
search string is all lower case then the search is NOT case sensitive.  If the
search string contains any upper case letters, then the search is case
sensitive.  The search string is put into search-last-string for use by
search-again."

(interactive)
(RLK-get-search-string "Search backward (word) for: ")
(setq is-word-search t)
(if (not (RLK-actual-backward-search))
    (try-forward)))
------------------------------------------------------------------------------
--
Robert L. Knighten	             | knighten@ssd.intel.com
Intel Supercomputer Systems Division | 
15201 N.W. Greenbrier Pkwy.	     | (503) 629-4315
Beaverton, Oregon  97006	     | (503) 629-9147 [FAX]
Newsgroups: gnu.emacs.help