[gnu.emacs] suggestion for search enhancement

jv@mh.nl (Johan Vromans) (06/14/89)

Once I wrote a small emacs look&feel alike editor, and one of the
users requested me to implemented the following feature, which I
hereby propose to the FSF.

When searching, and case-fold-search is t, temporary switch it to nil
if the search argument contains uppercase letters.

After using this method for a number of years, we never felt the need
to switch case-fold-search by hand again.

	Johan
--
Johan Vromans			 jv@mh.nl via european backbone (mcvax)
Multihouse Automatisering bv		uucp: ..!{mcvax,hp4nl}!mh.nl!jv
Doesburgweg 7					  phone: +31 1820 62944
2803 PL Gouda - The Netherlands			    fax: +31 1820 62500

knighten@pinocchio (Bob Knighten) (06/22/89)

In JV.89Jun13210432@mhres.mh.nl Johan Vromans mentioned the utility of a 
modified version of search that sets the case sensitivity depending on the 
occurance of captial letters in the search string.  Below is a set of functions
that do this among other things.  There are 8 functions that I bind to keys and
use constantly:
	RLK-search-forward-again
	RLK-search-forward
	RLK-search-backward-again
	RLK-search-backward
	RLK-word-search-forward-again
	RLK-word-search-forward
	RLK-word-search-backward
	RLK-word-search-backward-again
Each of these sets case-fold-search to nil (for the duration of the search) if 
the search string contains an upper case letter, otherwise it sets it to 
non-nil.   Each of these positions the cursor at the beginning of the string 
found provided it is found, and each offers to search in the opposite 
direction if the search is unsuccessful.  The search-again variants simply 
search in the prescribed direction for the last search string used.  The word 
search variants just pass the search string to the standard word-search 
functions.

------------------------------------------------------------------------------

(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)
    (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)))