+\f
+;;; Toggles for `isearch-regexp-function' and `search-default-mode'.
+(defmacro isearch-define-mode-toggle (mode key function &optional docstring &rest body)
+ "Define a command called `isearch-toggle-MODE' and bind it to `M-s KEY'.
+The first line of the command's docstring is auto-generated, the
+remainder may be provided in DOCSTRING.
+If FUNCTION is a symbol, this command first toggles the value of
+`isearch-regexp-function' between nil and FUNCTION. Also set the
+`isearch-message-prefix' property of FUNCTION.
+The command then executes BODY and updates the isearch prompt."
+ (declare (indent defun))
+ (let ((command-name (intern (format "isearch-toggle-%s" mode)))
+ (key (concat "\M-s" key)))
+ `(progn
+ (defun ,command-name ()
+ ,(format "Toggle %s searching on or off.%s" mode
+ (if docstring (concat "\n" docstring) ""))
+ (interactive)
+ ,@(when function
+ `((setq isearch-regexp-function
+ (unless (eq isearch-regexp-function #',function)
+ #',function))
+ (setq isearch-regexp nil)))
+ ,@body
+ (setq isearch-success t isearch-adjusted t)
+ (isearch-update))
+ (define-key isearch-mode-map ,key #',command-name)
+ ,@(when (and function (symbolp function))
+ `((put ',function 'isearch-message-prefix ,(format "%s " mode))
+ (put ',function :advertised-binding ,key)
+ (cl-callf (lambda (types) (cons 'choice
+ (cons '(const :tag ,(capitalize (format "%s search" mode)) ,function)
+ (cdr types))))
+ (get 'search-default-mode 'custom-type)))))))
+
+(isearch-define-mode-toggle word "w" word-search-regexp "\
+Turning on word search turns off regexp mode.")
+(isearch-define-mode-toggle symbol "_" isearch-symbol-regexp "\
+Turning on symbol search turns off regexp mode.")
+(isearch-define-mode-toggle char-fold "'" char-fold-to-regexp "\
+Turning on character-folding turns off regexp mode.")
+(put 'char-fold-to-regexp 'isearch-message-prefix "char-fold ")
+
+(isearch-define-mode-toggle regexp "r" nil nil