+\f
+;; Word search
+
+(defun word-search-regexp (string &optional lax)
+ "Return a regexp which matches words, ignoring punctuation.
+Given STRING, a string of words separated by word delimiters,
+compute a regexp that matches those exact words separated by
+arbitrary punctuation. If LAX is non-nil, the end of the string
+need not match a word boundary unless it ends in whitespace.
+
+Used in `word-search-forward', `word-search-backward',
+`word-search-forward-lax', `word-search-backward-lax'."
+ (if (string-match-p "^\\W*$" string)
+ ""
+ (concat
+ "\\b"
+ (mapconcat 'identity (split-string string "\\W+" t) "\\W+")
+ (if (or (not lax) (string-match-p "\\W$" string)) "\\b"))))
+
+(defun word-search-backward (string &optional bound noerror count)
+ "Search backward from point for STRING, ignoring differences in punctuation.
+Set point to the beginning of the occurrence found, and return point.
+An optional second argument bounds the search; it is a buffer position.
+The match found must not extend before that position.
+Optional third argument, if t, means if fail just return nil (no error).
+ If not nil and not t, move to limit of search and return nil.
+Optional fourth argument is repeat count--search for successive occurrences.
+
+Relies on the function `word-search-regexp' to convert a sequence
+of words in STRING to a regexp used to search words without regard
+to punctuation."
+ (interactive "sWord search backward: ")
+ (re-search-backward (word-search-regexp string nil) bound noerror count))
+
+(defun word-search-forward (string &optional bound noerror count)
+ "Search forward from point for STRING, ignoring differences in punctuation.
+Set point to the end of the occurrence found, and return point.
+An optional second argument bounds the search; it is a buffer position.
+The match found must not extend after that position.
+Optional third argument, if t, means if fail just return nil (no error).
+ If not nil and not t, move to limit of search and return nil.
+Optional fourth argument is repeat count--search for successive occurrences.
+
+Relies on the function `word-search-regexp' to convert a sequence
+of words in STRING to a regexp used to search words without regard
+to punctuation."
+ (interactive "sWord search: ")
+ (re-search-forward (word-search-regexp string nil) bound noerror count))
+
+(defun word-search-backward-lax (string &optional bound noerror count)
+ "Search backward from point for STRING, ignoring differences in punctuation.
+Set point to the beginning of the occurrence found, and return point.
+
+Unlike `word-search-backward', the end of STRING need not match a word
+boundary, unless STRING ends in whitespace.
+
+An optional second argument bounds the search; it is a buffer position.
+The match found must not extend before that position.
+Optional third argument, if t, means if fail just return nil (no error).
+ If not nil and not t, move to limit of search and return nil.
+Optional fourth argument is repeat count--search for successive occurrences.
+
+Relies on the function `word-search-regexp' to convert a sequence
+of words in STRING to a regexp used to search words without regard
+to punctuation."
+ (interactive "sWord search backward: ")
+ (re-search-backward (word-search-regexp string t) bound noerror count))
+
+(defun word-search-forward-lax (string &optional bound noerror count)
+ "Search forward from point for STRING, ignoring differences in punctuation.
+Set point to the end of the occurrence found, and return point.
+
+Unlike `word-search-forward', the end of STRING need not match a word
+boundary, unless STRING ends in whitespace.
+
+An optional second argument bounds the search; it is a buffer position.
+The match found must not extend after that position.
+Optional third argument, if t, means if fail just return nil (no error).
+ If not nil and not t, move to limit of search and return nil.
+Optional fourth argument is repeat count--search for successive occurrences.
+
+Relies on the function `word-search-regexp' to convert a sequence
+of words in STRING to a regexp used to search words without regard
+to punctuation."
+ (interactive "sWord search: ")
+ (re-search-forward (word-search-regexp string t) bound noerror count))
+
+;; Symbol search
+
+(defun isearch-symbol-regexp (string &optional lax)
+ "Return a regexp which matches STRING as a symbol.
+Creates a regexp where STRING is surrounded by symbol delimiters \\_< and \\_>.
+If LAX is non-nil, the end of the string need not match a symbol boundary."
+ (concat "\\_<" (regexp-quote string) (unless lax "\\_>")))
+
+(put 'isearch-symbol-regexp 'isearch-message-prefix "symbol ")
+
+;; Search with lax whitespace
+
+(defun search-forward-lax-whitespace (string &optional bound noerror count)
+ "Search forward for STRING, matching a sequence of whitespace chars."
+ (let ((search-spaces-regexp search-whitespace-regexp))
+ (re-search-forward (regexp-quote string) bound noerror count)))
+
+(defun search-backward-lax-whitespace (string &optional bound noerror count)
+ "Search backward for STRING, matching a sequence of whitespace chars."
+ (let ((search-spaces-regexp search-whitespace-regexp))
+ (re-search-backward (regexp-quote string) bound noerror count)))
+
+(defun re-search-forward-lax-whitespace (regexp &optional bound noerror count)
+ "Search forward for REGEXP, matching a sequence of whitespace chars."
+ (let ((search-spaces-regexp search-whitespace-regexp))
+ (re-search-forward regexp bound noerror count)))
+
+(defun re-search-backward-lax-whitespace (regexp &optional bound noerror count)
+ "Search backward for REGEXP, matching a sequence of whitespace chars."
+ (let ((search-spaces-regexp search-whitespace-regexp))
+ (re-search-backward regexp bound noerror count)))
+
+\f