[COMMIT] Look for cased character classes when deciding on case-fold-search, #'isearch

Aidan Kehoe <[email protected]> Wed, 11 Mar 2015 18:10:08 +0000
Newsgroups gmane.emacs.xemacs.patches
Message-ID <[email protected]>
APPROVE COMMIT

NOTE: This patch has been committed. 

# HG changeset patch
# User Aidan Kehoe <[email protected]>
# Date 1426097175 0
#      Wed Mar 11 18:06:15 2015 +0000
# Node ID 0bddb59072b667153117b8c6407cdedaee4dad3b
# Parent  ccb0cff115d2dc5a0752e3f688a562c48ab90ffc
Look for cased character classes when deciding on case-fold-search, #'isearch

lisp/ChangeLog addition:

2015-03-11  Aidan Kehoe  <[email protected]>

	* isearch-mode.el:
	* isearch-mode.el (isearch-fix-case):
	Use the new #'no-case-regexp-p function if treating ISEARCH-STRING
	as a regular expression; otherwise, use the [[:upper:]] character
	class.
	* isearch-mode.el (isearch-no-upper-case-p): Removed.
	* isearch-mode.el (with-caps-disable-folding): Removed.
	These two haven't been used since 1998.
	* occur.el (occur-1):
	Use #'no-case-regexp-p here.
	* replace.el (perform-replace):
	Don't use #'no-upper-case-p, use #'no-case-regexp-p or
	(string-match "[[:upper:]]" ...) as appropriate.
	* simple.el:
	* simple.el (no-upper-case-p): Removed. This did two different
	things, and its secondary function (examining regular expressions)
	just became much more complicated; move the regular expression
	functionality to its own function, use character classes when
	examining non-regular-expressions instead.
	The code to look for character classes, and the design decision
	that this should be done, are from GNU, thank you Stefan Monnier.
	* simple.el (no-case-regexp-p): New.
	Given a REGEXP, return non-nil if it has nothing to suggest an
	interactive user wants a case-sensitive search.
	* simple.el (with-search-caps-disable-folding):
	* simple.el (with-interactive-search-caps-disable-folding):
	Update both these macros to use #'no-case-regexp-p.

diff -r ccb0cff115d2 -r 0bddb59072b6 lisp/ChangeLog
--- a/lisp/ChangeLog	Wed Mar 11 15:06:05 2015 +0000
+++ b/lisp/ChangeLog	Wed Mar 11 18:06:15 2015 +0000
@@ -1,3 +1,33 @@
+2015-03-11  Aidan Kehoe  <[email protected]>
+
+	* isearch-mode.el:
+	* isearch-mode.el (isearch-fix-case):
+	Use the new #'no-case-regexp-p function if treating ISEARCH-STRING
+	as a regular expression; otherwise, use the [[:upper:]] character
+	class.
+	* isearch-mode.el (isearch-no-upper-case-p): Removed. 
+	* isearch-mode.el (with-caps-disable-folding): Removed.
+	These two haven't been used since 1998.
+	* occur.el (occur-1):
+	Use #'no-case-regexp-p here.
+	* replace.el (perform-replace):
+	Don't use #'no-upper-case-p, use #'no-case-regexp-p or
+	(string-match "[[:upper:]]" ...) as appropriate.
+	* simple.el:
+	* simple.el (no-upper-case-p): Removed. This did two different
+	things, and its secondary function (examining regular expressions)
+	just became much more complicated; move the regular expression
+	functionality to its own function, use character classes when
+	examining non-regular-expressions instead.
+	The code to look for character classes, and the design decision
+	that this should be done, are from GNU, thank you Stefan Monnier.
+	* simple.el (no-case-regexp-p): New.
+	Given a REGEXP, return non-nil if it has nothing to suggest an
+	interactive user wants a case-sensitive search.
+	* simple.el (with-search-caps-disable-folding):
+	* simple.el (with-interactive-search-caps-disable-folding):
+	Update both these macros to use #'no-case-regexp-p.
+
 2015-03-11  Aidan Kehoe  <[email protected]>
 
 	Correct #'clear-message and friends so the START and END supplied
diff -r ccb0cff115d2 -r 0bddb59072b6 lisp/isearch-mode.el
--- a/lisp/isearch-mode.el	Wed Mar 11 15:06:05 2015 +0000
+++ b/lisp/isearch-mode.el	Wed Mar 11 18:06:15 2015 +0000
@@ -1068,7 +1068,11 @@
 	   (not isearch-fixed-case)
 	   search-caps-disable-folding)
       (setq isearch-case-fold-search
-	    (no-upper-case-p isearch-string isearch-regexp)))
+            (if isearch-regexp
+                (no-case-regexp-p isearch-string)
+              (save-match-data
+                (let (case-fold-search)
+                  (not (string-match "[[:upper:]]" isearch-string)))))))
   (setq isearch-mode (if case-fold-search
                          (if isearch-case-fold-search
                              " Isearch"  ;As God Intended Mode
@@ -1856,15 +1860,6 @@
 			 t))
 		     isearch-unhidden-extents)))))
 
-(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))))
-(make-obsolete 'isearch-no-upper-case-p 'no-upper-case-p)
-
 ;; Portability functions to support various Emacs versions.
 
 (defun isearch-char-to-string (c)
@@ -1876,20 +1871,6 @@
 ;  (isearch-char-to-string c))
 
 (define-function 'isearch-text-char-description 'text-char-description)
-
-;; 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))
-(make-obsolete 'with-caps-disable-folding 'with-search-caps-disable-folding)
-(put 'with-caps-disable-folding 'lisp-indent-function 1)
-(put 'with-caps-disable-folding 'edebug-form-spec '(form body))
-
 
 ;;;========================================================
 ;;; Advanced highlighting
diff -r ccb0cff115d2 -r 0bddb59072b6 lisp/occur.el
--- a/lisp/occur.el	Wed Mar 11 15:06:05 2015 +0000
+++ b/lisp/occur.el	Wed Mar 11 18:06:15 2015 +0000
@@ -394,8 +394,7 @@
 	(let ((count (occur-engine
 		      regexp active-bufs occur-buf
 		      (or nlines list-matching-lines-default-context-lines)
-		      (and case-fold-search
-			   (no-upper-case-p regexp t))
+		      (and case-fold-search (no-case-regexp-p regexp))
 		      list-matching-lines-buffer-name-face
 		      nil list-matching-lines-face t)))
 	  (let* ((bufcount (length active-bufs))
diff -r ccb0cff115d2 -r 0bddb59072b6 lisp/replace.el
--- a/lisp/replace.el	Wed Mar 11 15:06:05 2015 +0000
+++ b/lisp/replace.el	Wed Mar 11 18:06:15 2015 +0000
@@ -563,7 +563,11 @@
 	 ;; XEmacs addition
 	 (qr-case-fold-search
 	  (if (and case-fold-search search-caps-disable-folding)
-	      (no-upper-case-p search-string regexp-flag)
+              (if regexp-flag
+                  (no-case-regexp-p search-string)
+                (save-match-data
+                  (let (case-fold-search)
+                    (not (string-match "[[:upper:]]" search-string)))))
 	    case-fold-search))
 	 (message
 	  (if query-flag
diff -r ccb0cff115d2 -r 0bddb59072b6 lisp/simple.el
--- a/lisp/simple.el	Wed Mar 11 15:06:05 2015 +0000
+++ b/lisp/simple.el	Wed Mar 11 18:06:15 2015 +0000
@@ -94,47 +94,70 @@
   "Warnings customizations."
   :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)
 
-;; This is stolen (and slightly modified) from FSF emacs's
-;; `isearch-no-upper-case-p'.
-(defun no-upper-case-p (string &optional regexp-flag)
-  "Return t if there are no upper case chars in STRING.
-If REGEXP-FLAG is non-nil, disregard letters preceded by `\\' (but not `\\\\')
-since they have special meaning in a regexp."
+(defun no-case-regexp-p (regexp)
+  "Return t if there are no case-specific constructs in REGEXP.
+
+Lower case characters are regarded as not case-specific.  Upper case
+characters are usually regarded as case-specific, but upper case characters
+used in special regexp constructs, where they do not match upper case
+characters specifically, are regarded as not case-specific.  In contrast, the
+character classes [:lower:] and [:upper:] are viewed as case-specific.
+
+This is intended to be used by interactive searching code to decide, in a
+do-what-I-mean fashion, whether a given search should be case-sensitive."
   (let ((case-fold-search nil))
-    (not (string-match (if regexp-flag
-			   "\\(^\\|\\\\\\\\\\|[^\\]\\)[A-Z]"
-			 "[A-Z]")
-		       string))
-    ))
-
-(defmacro with-search-caps-disable-folding (string regexp-flag &rest body) "\
-Eval BODY with `case-fold-search' let to nil if `search-caps-disable-folding'
-is non-nil, and if STRING (either a string or a regular expression according
-to REGEXP-FLAG) contains uppercase letters."
+    (save-match-data
+      (not (or (string-match "\\(^\\|\\\\\\\\\\|[^\\]\\)[[:upper:]]" regexp)
+               (and (string-match "\\[:\\(upp\\|low\\)er:]" regexp)
+                    (condition-case err
+                        (progn
+                          (string-match (substring regexp 0
+                                                   (match-beginning 0)) "")
+                          nil)
+                      (invalid-regexp
+                       (equal "Unmatched [ or [^" (cadr err))))))))))
+
+(defmacro* with-search-caps-disable-folding (string regexp-p &body body)
+  "Execute the forms in BODY, respecting `search-caps-disable-folding'.
+
+Within BODY, bind `case-fold-search' to nil if `search-caps-disable-folding'
+is non-nil, REGEXP-P is nil, and if STRING contains any uppercase characters.
+
+If REGEXP-P is non-nil, treat STRING as a regular expression, and bind
+`case-fold-search' to nil if it contains uppercase characters that are
+not special regular expression constructs, or if it contains
+case-specific character classes such as `[[:upper:]]' or
+`[[:lower:]]'.  See `no-case-regexp-p'."
   `(let ((case-fold-search
           (if (and case-fold-search search-caps-disable-folding)
-              (no-upper-case-p ,string ,regexp-flag)
+              (if ,regexp-p
+                  (no-case-regexp-p ,string)
+                (save-match-data
+                  (let (case-fold-search)
+                    (not (string-match "[[:upper:]]" ,string)))))
             case-fold-search)))
      ,@body))
 (put 'with-search-caps-disable-folding 'lisp-indent-function 2)
 (put 'with-search-caps-disable-folding 'edebug-form-spec
      '(sexp sexp &rest form))
 
-(defmacro with-interactive-search-caps-disable-folding (string regexp-flag
-							       &rest body)
-  "Same as `with-search-caps-disable-folding', but only in the case of a
-function called interactively."
+(defmacro* with-interactive-search-caps-disable-folding (string regexp-p
+                                                                &body body)
+  "Like `with-search-caps-disable-folding', but only when interactive."
   `(let ((case-fold-search
-	  (if (and (interactive-p)
-		   case-fold-search search-caps-disable-folding)
-              (no-upper-case-p ,string ,regexp-flag)
+	  (if (and (interactive-p) case-fold-search
+                   search-caps-disable-folding)
+              (if ,regexp-p
+                  (no-case-regexp-p ,string)
+                (save-match-data
+                  (let (case-fold-search)
+                    (not (string-match "[[:upper:]]" ,string)))))
             case-fold-search)))
      ,@body))
 (put 'with-interactive-search-caps-disable-folding 'lisp-indent-function 2)


-- 
‘Tramadol is further fed to cattle […] when working them […] (as draft
animals) so that the animals do not get tired quickly. …’
	— Angewandte Chemie, Sept 2014, describing the social context of
	(synthetic) tramadol having been found in Cameroon tree roots.

_______________________________________________
XEmacs-Patches mailing list
[email protected]
http://lists.xemacs.org/mailman/listinfo/xemacs-patches