In addition to the bug Hrvoje fixed in isearch, I'd like to propose
the following patch to generalize the behavior of isearch (which is the Right
One) to other searches as well. The point is that when calling interactively a
routine that leads to a search (even basic, non-incremetal, non-regexp ones),
the introduction of an uppercase character in the search srting should switch
back to case-sensitive search, regardless of the value of case-fold-search
(but still taking search-caps-disable-folding). isearch currently behaves this
way, but we'd like to see other functions (like zap-to-char) follow this rule
too.
The following patch generalizes the use of isearch-no-upper-case and
with-caps-disable-folding (moving them away from isearch.el), and corrects the
behavior of the `zap-*-to-char' functions. I'm likely to modify other
functions along with the same lines in the future as they come to my mind.
One important point: there are 2 interface changes in this patch: the
routine isearch-no-upper-case-p is moved away from isearch.el in order to be
used anywhere else, so the isearch- prefixe is removed. The other one is one
more argument (regexp-flag) to the macro with-caps-disable-folding, which is
moved away from isearch too. I think we can afford those changes: they lead to
only 2 other modifications in the core lisp packages, and none of the packages
I have installed (almost all of them) use those functions.
_this patch must be applied on top of hrvoje's previous one_
(<kigyarb68yb.fsf(a)jagor.srce.hr>)
1998-09-23 Didier Verna <verna(a)inf.enst.fr>
* simple.el (search-caps-disable-folding): moved from isearch-mode.el
(no-upper-case-p): moved from isearch-mode.el, plus a regexp flag.
(with-caps-disable-folding): ditto.
(zap-to-char): In interactive mode, do a case-sensitive search if
the character is uppercase.
(zap-up-to-char): ditto.
* replace.el (perform-replace): use the function no-upper-case-p.
* isearch-mode.el (isearch-fix-case): ditto.
* etags.el (find-tag-internal): call `with-caps-disable-folding'
with the regexp flag.
(tags-search): ditto.
(tags-query-replace): ditto.
* info.el (Info-search): ditto.
--- lisp/simple.el.orig Wed Sep 23 10:27:30 1998
+++ lisp/simple.el Wed Sep 23 12:05:51 1998
@@ -94,6 +94,36 @@
:group 'minibuffer)
+(defcustom search-caps-disable-folding t
+ "*If non-nil, upper case chars disable case fold searching.
+This does not apply to \"yanked\" strings."
+ :type 'boolean
+ :group 'editing-basics)
+
+(defun no-upper-case-p (string &optional regexp)
+ "Return t if there are no upper case chars in string.
+If REGEXP is non nil, upper case chars preceded by \\ do not count since they
+have special meaning in a regexp."
+ ;; this incorrectly returns t for "\\\\A"
+ (let ((case-fold-search nil))
+ (if regexp
+ (not (string-match "\\(^\\|[^\\]\\)[A-Z]" string))
+ (not (string-match "[A-Z]" string)))
+ ))
+
+(defmacro with-caps-disable-folding (string regexp &rest body) "\
+Eval BODY with `case-fold-search' let to nil if STRING (either a string or a
+regular expression according to the REGEXP flag) contains uppercase letters
+and `search-caps-disable-folding' is t."
+ `(let ((case-fold-search
+ (if (and case-fold-search search-caps-disable-folding)
+ (no-upper-case-p ,string regexp)
+ case-fold-search)))
+ ,@body))
+(put 'with-caps-disable-folding 'lisp-indent-function 1)
+(put 'with-caps-disable-folding 'edebug-form-spec '(form body))
+
+
(defun newline (&optional arg)
"Insert a newline, and move to left margin of the new line if it's blank.
The newline is marked with the text-property `hard'.
@@ -456,7 +486,12 @@
"Kill up to and including ARG'th occurrence of CHAR.
Goes backward if ARG is negative; error if CHAR not found."
(interactive "*p\ncZap to char: ")
- (kill-region (point) (progn
+ (kill-region (point) (let ((case-fold-search
+ (if (and (interactive-p)
+ case-fold-search
+ search-caps-disable-folding)
+ (no-upper-case-p (char-to-string char))
+ case-fold-search)))
(search-forward (char-to-string char) nil nil arg)
; (goto-char (if (> arg 0) (1- (point)) (1+ (point))))
(point))))
@@ -465,10 +500,15 @@
"Kill up to ARG'th occurrence of CHAR.
Goes backward if ARG is negative; error if CHAR not found."
(interactive "*p\ncZap up to char: ")
- (kill-region (point) (progn
- (search-forward (char-to-string char) nil nil arg)
- (goto-char (if (> arg 0) (1- (point)) (1+ (point))))
- (point))))
+ (kill-region (point) (let ((case-fold-search
+ (if (and (interactive-p)
+ case-fold-search
+ search-caps-disable-folding)
+ (no-upper-case-p (char-to-string char))
+ case-fold-search)))
+ (search-forward (char-to-string char) nil nil arg)
+ (goto-char (if (> arg 0) (1- (point)) (1+ (point))))
+ (point))))
(defun beginning-of-buffer (&optional arg)
"Move point to the beginning of the buffer; leave mark at previous position.
--- lisp/isearch-mode.el.orig Wed Sep 23 10:27:30 1998
+++ lisp/isearch-mode.el Wed Sep 23 11:11:57 1998
@@ -148,12 +148,6 @@
:type 'integer
:group 'isearch)
-(defcustom search-caps-disable-folding t
- "*If non-nil, upper case chars disable case fold searching.
-This does not apply to \"yanked\" strings."
- :type 'boolean
- :group 'isearch)
-
(defcustom search-nonincremental-instead t
"*If non-nil, do a nonincremental search instead if exiting immediately."
:type 'boolean
@@ -938,7 +932,8 @@
(defun isearch-fix-case ()
(if (and isearch-case-fold-search search-caps-disable-folding)
- (setq isearch-case-fold-search (isearch-no-upper-case-p isearch-string)))
+ (setq isearch-case-fold-search
+ (no-upper-case-p isearch-string isearch-regexp)))
(setq isearch-mode (if case-fold-search
(if isearch-case-fold-search
" Isearch" ;As God Intended Mode
@@ -1598,29 +1593,8 @@
; ;; Go ahead and search.
; (if search-caps-disable-folding
; (setq isearch-case-fold-search
-; (isearch-no-upper-case-p isearch-string)))
+; (no-upper-case-p isearch-string isearch-regexp)))
; (let ((case-fold-search isearch-case-fold-search))
; (funcall function isearch-string))))
-
-
-(defun isearch-no-upper-case-p (string)
- "Return t if there are no upper case chars in string.
-But upper case chars preceded by \\ do not count since they
-have special meaning in a regexp."
- ;; this incorrectly returns t for "\\\\A"
- (let ((case-fold-search nil))
- (not (string-match "\\(^\\|[^\\]\\)[A-Z]" string))))
-
-;; Used by etags.el and info.el
-(defmacro with-caps-disable-folding (string &rest body) "\
-Eval BODY with `case-fold-search' let to nil if STRING contains
-uppercase letters and `search-caps-disable-folding' is t."
- `(let ((case-fold-search
- (if (and case-fold-search search-caps-disable-folding)
- (isearch-no-upper-case-p ,string)
- case-fold-search)))
- ,@body))
-(put 'with-caps-disable-folding 'lisp-indent-function 1)
-(put 'with-caps-disable-folding 'edebug-form-spec '(form body))
;;; isearch-mode.el ends here
--- lisp/etags.el.orig Wed Sep 23 10:27:30 1998
+++ lisp/etags.el Wed Sep 23 11:24:19 1998
@@ -662,7 +662,7 @@
syn-tab exact-syntax-table)
(setq tag-target tagname
syn-tab normal-syntax-table))
- (with-caps-disable-folding tag-target
+ (with-caps-disable-folding tag-target t
(while tag-tables
(set-buffer (get-tag-table-buffer (car tag-tables)))
(bury-buffer (current-buffer))
@@ -967,7 +967,7 @@
(null tags-loop-operate))
;; Continue last tags-search as if by `M-,'.
(tags-loop-continue nil)
- (setq tags-loop-scan `(with-caps-disable-folding ,regexp
+ (setq tags-loop-scan `(with-caps-disable-folding ,regexp t
(re-search-forward ,regexp nil t))
tags-loop-operate nil)
(tags-loop-continue (or file-list-form t))))
@@ -982,7 +982,7 @@
See documentation of variable `tag-table-alist'."
(interactive
"sTags query replace (regexp): \nsTags query replace %s by: \nP")
- (setq tags-loop-scan `(with-caps-disable-folding ,from
+ (setq tags-loop-scan `(with-caps-disable-folding ,from t
(if (re-search-forward ,from nil t)
;; When we find a match, move back
;; to the beginning of it so perform-replace
--- lisp/info.el.orig Wed Sep 23 10:27:30 1998
+++ lisp/info.el Wed Sep 23 11:25:03 1998
@@ -1571,7 +1571,7 @@
(if (equal regexp "")
(setq regexp Info-last-search)
(setq Info-last-search regexp))
- (with-caps-disable-folding regexp
+ (with-caps-disable-folding regexp t
(let ((found ())
(onode Info-current-node)
(ofile Info-current-file)
--- lisp/replace.el.orig Wed Sep 23 10:27:30 1998
+++ lisp/replace.el Wed Sep 23 10:56:51 1998
@@ -628,7 +628,7 @@
;; XEmacs addition
(qr-case-fold-search
(if (and case-fold-search search-caps-disable-folding)
- (isearch-no-upper-case-p search-string)
+ (no-upper-case-p search-string regexp-flag)
case-fold-search))
(message
(if query-flag