From f67ae7ed53e6a90cf4f97ac1bba9498b5d58e6dc Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Tue, 27 Jan 2015 14:08:01 -0200 Subject: [PATCH] (isearch-search-fun-default): Implement group folding in isearch. Use `isearch-fold-groups', `isearch-groups-alist', and `isearch--replace-groups-in-string'. --- lisp/isearch.el | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/lisp/isearch.el b/lisp/isearch.el index 99ca73f..accfb72 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -58,6 +58,7 @@ ;;; Code: (eval-when-compile (require 'cl-lib)) +(eval-when-compile (require 'subr-x)) ;; Some additional options and constants. @@ -272,6 +273,23 @@ Default value, nil, means edit the string instead." :version "23.1" :group 'isearch) +(defcustom isearch-fold-groups t + "Whether regular isearch should do group folding. +This means some characters will match entire groups of charactes, +such as \" matching ”, for instance." + :type 'boolean + :group 'isearch + :version "25.1") + +(defvar isearch-groups-alist + ;; FIXME: Add all the latin accented letters like Ã. + '((?\" . "[\""“””„⹂〞‟‟❞❝❠“„〝〟🙷🙶🙸❮❯«»‹›󠀢]") + (?' . "[`'❟❛❜‘’’‚‛‛‚‘󠀢❮❯«»‹›]") + ;; `isearch-fold-groups' doesn't interact with + ;; `isearch-lax-whitespace' yet. So we need to add this here. + (?\s . "[ \r\n]+")) + "Alist of groups to use when `isearch-fold-groups' is non-nil.") + (defcustom isearch-lazy-highlight t "Controls the lazy-highlighting during incremental search. When non-nil, all text in the buffer matching the current search @@ -2565,6 +2583,18 @@ search for the first occurrence of STRING or its translation.") Can be changed via `isearch-search-fun-function' for special needs." (funcall (or isearch-search-fun-function 'isearch-search-fun-default))) +(defun isearch--replace-groups-in-string (string) + "Return a group-folded regexp version of STRING. +Any character that has an entry in `isearch-groups-alist' is +replaced with the cdr of that entry (which should be a regexp). +Other characters are `regexp-quote'd." + (apply #'concat + (mapcar (lambda (c) + (if-let ((entry (assq c isearch-groups-alist))) + (cdr entry) + (regexp-quote (string c)))) + string))) + (defun isearch-search-fun-default () "Return default functions to use for the search." (cond @@ -2591,6 +2621,13 @@ Can be changed via `isearch-search-fun-function' for special needs." 're-search-backward-lax-whitespace)) (isearch-regexp (if isearch-forward 're-search-forward 're-search-backward)) + ;; `isearch-regexp' is essentially a superset of + ;; `isearch-fold-groups'. So fold-groups comes after it. + (isearch-fold-groups + (lambda (string &optional bound noerror count) + (funcall (if isearch-forward #'re-search-forward #'re-search-backward) + (isearch--replace-groups-in-string string) + bound noerror count))) ((and isearch-lax-whitespace search-whitespace-regexp) (if isearch-forward 'search-forward-lax-whitespace -- 2.2.2