From cb1e73d1bc964f61626955e950e660602f2014f5 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 3 May 2020 16:53:53 +0300 Subject: [PATCH] Improve accuracy of apropos commands that search doc strings It is conceptually wrong for apropos commands that search doc strings to look for matches of several words only on the same line, because division of doc strings between lines is ephemeral. * lisp/apropos.el (apropos-parse-pattern): Accept an optional argument MULTILINE-P, and if that is non-nil, produce regexps that match words in the list even if they are separated by line boundaries. (apropos-value, apropos-local-value, apropos-documentation): Use the new optional argument in apropos commands that search multiline text, such as doc strings. * src/search.c (Fposix_looking_at, Fposix_string_match) (Fposix_search_backward, Fposix_search_forward): Make sure Posix appears in the doc strings near REGEXP, for better matches. --- lisp/apropos.el | 21 +++++++++++++++------ src/search.c | 10 +++++----- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/lisp/apropos.el b/lisp/apropos.el index e40f94ccb8c..7cbda3cb678 100644 --- a/lisp/apropos.el +++ b/lisp/apropos.el @@ -373,9 +373,11 @@ kind of objects to search." (user-error "No word list given")) pattern))) -(defun apropos-parse-pattern (pattern) +(defun apropos-parse-pattern (pattern &optional multiline-p) "Rewrite a list of words to a regexp matching all permutations. If PATTERN is a string, that means it is already a regexp. +MULTILINE-P, if non-nil, means produce a regexp that will match +the words even if separated by newlines. This updates variables `apropos-pattern', `apropos-pattern-quoted', `apropos-regexp', `apropos-words', and `apropos-all-words-regexp'." (setq apropos-words nil @@ -386,6 +388,9 @@ This updates variables `apropos-pattern', `apropos-pattern-quoted', ;; any combination of two or more words like this: ;; (a|b|c).*(a|b|c) which may give some false matches, ;; but as long as it also gives the right ones, that's ok. + ;; (Actually, when MULTILINE-P is non-nil, instead of '.' we + ;; use a trick that would find a match even if the words are + ;; on different lines. (let ((words pattern)) (setq apropos-pattern (mapconcat 'identity pattern " ") apropos-pattern-quoted (regexp-quote apropos-pattern)) @@ -402,9 +407,13 @@ This updates variables `apropos-pattern', `apropos-pattern-quoted', (setq apropos-words (cons s apropos-words) apropos-all-words (cons a apropos-all-words)))) (setq apropos-all-words-regexp - (apropos-words-to-regexp apropos-all-words ".+")) + (apropos-words-to-regexp apropos-all-words + ;; The [^b-a] trick matches any + ;; character including a newline. + (if multiline-p "[^b-a]+?" ".+"))) (setq apropos-regexp - (apropos-words-to-regexp apropos-words ".*?"))) + (apropos-words-to-regexp apropos-words + (if multiline-p "[^b-a]*?" ".*?")))) (setq apropos-pattern-quoted (regexp-quote pattern) apropos-all-words-regexp pattern apropos-pattern pattern @@ -787,7 +796,7 @@ Returns list of symbols and values found." (interactive (list (apropos-read-pattern "value") current-prefix-arg)) (setq apropos--current (list #'apropos-value pattern do-all)) - (apropos-parse-pattern pattern) + (apropos-parse-pattern pattern t) (or do-all (setq do-all apropos-do-all)) (setq apropos-accumulator ()) (let (f v p) @@ -827,7 +836,7 @@ Optional arg BUFFER (default: current buffer) is the buffer to check." (interactive (list (apropos-read-pattern "value of buffer-local variable"))) (unless buffer (setq buffer (current-buffer))) (setq apropos--current (list #'apropos-local-value pattern buffer)) - (apropos-parse-pattern pattern) + (apropos-parse-pattern pattern t) (setq apropos-accumulator ()) (let ((var nil)) (mapatoms @@ -869,7 +878,7 @@ Returns list of symbols and documentation found." (interactive (list (apropos-read-pattern "documentation") current-prefix-arg)) (setq apropos--current (list #'apropos-documentation pattern do-all)) - (apropos-parse-pattern pattern) + (apropos-parse-pattern pattern t) (or do-all (setq do-all apropos-do-all)) (setq apropos-accumulator () apropos-files-scanned ()) (let ((standard-input (get-buffer-create " apropos-temp")) diff --git a/src/search.c b/src/search.c index 567270a84cb..ec076c18035 100644 --- a/src/search.c +++ b/src/search.c @@ -353,8 +353,8 @@ data if you want to preserve them. */) } DEFUN ("posix-looking-at", Fposix_looking_at, Sposix_looking_at, 1, 1, 0, - doc: /* Return t if text after point matches regular expression REGEXP. -Find the longest match, in accord with Posix regular expression rules. + doc: /* Return t if text after point matches REGEXP according to Posix rules. +Find the longest match, in accordance with Posix regular expression rules. This function modifies the match data that `match-beginning', `match-end' and `match-data' access; save and restore the match data if you want to preserve them. */) @@ -449,7 +449,7 @@ matched by the parenthesis constructions in REGEXP. */) } DEFUN ("posix-string-match", Fposix_string_match, Sposix_string_match, 2, 3, 0, - doc: /* Return index of start of first match for REGEXP in STRING, or nil. + doc: /* Return index of start of first match for Posix REGEXP in STRING, or nil. Find the longest match, in accord with Posix regular expression rules. Case is ignored if `case-fold-search' is non-nil in the current buffer. If third arg START is non-nil, start search at that index in STRING. @@ -2276,7 +2276,7 @@ and `replace-match'. */) DEFUN ("posix-search-backward", Fposix_search_backward, Sposix_search_backward, 1, 4, "sPosix search backward: ", - doc: /* Search backward from point for match for regular expression REGEXP. + doc: /* Search backward from point for match for REGEXP according to Posix rules. Find the longest match in accord with Posix regular expression rules. Set point to the beginning of the occurrence found, and return point. An optional second argument bounds the search; it is a buffer position. @@ -2304,7 +2304,7 @@ and `replace-match'. */) DEFUN ("posix-search-forward", Fposix_search_forward, Sposix_search_forward, 1, 4, "sPosix search: ", - doc: /* Search forward from point for regular expression REGEXP. + doc: /* Search forward from point for REGEXP according to Posix rules. Find the longest match in accord with Posix regular expression rules. Set point to the end of the occurrence found, and return point. An optional second argument bounds the search; it is a buffer position. -- 2.39.5