Function `org-link-search' does exact headline search
* lisp/org.el (org-link-search): Change headline search such that it always does an exact search, ignoring spaces. * testing/lisp/test-org.el (test-org/fuzzy-links): Test exact headline match with spaces and cookies. * doc/org.texi (External links): Cleanup footnote about the `org-link-search-must-match-exact-headline' option for text searches and add a footnote about the effect of the same option for heading searches. * doc/ORG-NEWS: Document changes.
This commit is contained in:
parent
a9a9af030d
commit
6d691e2aa8
12
doc/org.texi
12
doc/org.texi
|
@ -3561,10 +3561,14 @@ file:projects.org::some words @r{text search in Org file}@footnote{
|
|||
The actual behavior of the search will depend on the value of
|
||||
the option @code{org-link-search-must-match-exact-headline}. If its value
|
||||
is @code{nil}, then a fuzzy text search will be done. If it is t, then only the
|
||||
exact headline will be matched. If the value is @code{'query-to-create},
|
||||
then an exact headline will be searched; if it is not found, then the user
|
||||
will be queried to create it.}
|
||||
file:projects.org::*task title @r{heading search in Org file}
|
||||
exact headline will be matched, ignoring spaces and cookies. If the value is
|
||||
@code{query-to-create}, then an exact headline will be searched; if it is not
|
||||
found, then the user will be queried to create it.}
|
||||
file:projects.org::*task title @r{heading search in Org
|
||||
file}@footnote{ Headline searches always match the exact headline, ignoring
|
||||
spaces and cookies. If the headline is not found and the value of the option
|
||||
@code{org-link-search-must-match-exact-headline} is @code{query-to-create},
|
||||
then the user will be queried to create it.}
|
||||
file+sys:/path/to/file @r{open via OS, like double-click}
|
||||
file+emacs:/path/to/file @r{force opening by Emacs}
|
||||
docview:papers/last.pdf::NNN @r{open in doc-view mode at page}
|
||||
|
|
|
@ -218,6 +218,11 @@ The build system has been enhanced to allow test selection with a
|
|||
regular expression by defining =BTEST_RE= during the test invocation.
|
||||
This is especially useful during bisection to find just when a
|
||||
particular test failure was introduced.
|
||||
*** Exact heading search for external links ignore spaces and cookies
|
||||
Exact heading search for links now ignore spaces and cookies. This is
|
||||
the case for links of the form ~file:projects.org::*task title~, as
|
||||
well as links of the form ~file:projects.org::some words~
|
||||
when ~org-link-search-must-match-exact-headline~ is not nil.
|
||||
* Version 8.2
|
||||
|
||||
** Incompatible changes
|
||||
|
|
52
lisp/org.el
52
lisp/org.el
|
@ -11007,8 +11007,7 @@ visibility around point, thus ignoring
|
|||
org-emphasis-alist)
|
||||
"\\|") "\\)"))
|
||||
(pos (point))
|
||||
(pre nil) (post nil)
|
||||
words re0 re1 re2 re3 re4_ re4 re5 re2a re2a_ reall)
|
||||
words re0 re2 re4_ re4 re5 re2a re2a_ reall)
|
||||
(cond
|
||||
;; First check if there are any special search functions
|
||||
((run-hook-with-args-until-success 'org-execute-file-search-functions s))
|
||||
|
@ -11062,14 +11061,34 @@ visibility around point, thus ignoring
|
|||
((derived-mode-p 'org-mode)
|
||||
(org-occur (match-string 1 s)))
|
||||
(t (org-do-occur (match-string 1 s)))))
|
||||
((and (derived-mode-p 'org-mode) org-link-search-must-match-exact-headline)
|
||||
(and (equal (string-to-char s) ?*) (setq s (substring s 1)))
|
||||
((and (derived-mode-p 'org-mode)
|
||||
(or (and (equal (string-to-char s) ?*) (setq s (substring s 1)))
|
||||
org-link-search-must-match-exact-headline))
|
||||
;; Headline search.
|
||||
(goto-char (point-min))
|
||||
(cond
|
||||
((let (case-fold-search)
|
||||
(re-search-forward (format org-complex-heading-regexp-format
|
||||
(regexp-quote s))
|
||||
nil t))
|
||||
(re-search-forward
|
||||
(let* ((wspace "[ \t]")
|
||||
(wspaceopt (concat wspace "*"))
|
||||
(cookie (concat "\\(?:"
|
||||
wspaceopt
|
||||
"\\[[0-9]*\\(?:%\\|/[0-9]*\\)\\]"
|
||||
wspaceopt
|
||||
"\\)"))
|
||||
(sep (concat "\\(?:" wspace "+\\|" cookie "+\\)")))
|
||||
(concat
|
||||
org-outline-regexp-bol
|
||||
"\\(?:" org-todo-regexp "[ \t]+\\)?"
|
||||
"\\(?:\\[#.\\][ \t]+\\)?"
|
||||
sep "*"
|
||||
(mapconcat #'identity
|
||||
(org-split-string (regexp-quote s))
|
||||
(concat sep "+"))
|
||||
sep "*"
|
||||
(org-re "\\(?:[ \t]+:[[:alnum:]_@#%%:]+:\\)?")
|
||||
"[ \t]*$"))
|
||||
nil t))
|
||||
;; OK, found a match
|
||||
(setq type 'dedicated)
|
||||
(goto-char (match-beginning 0)))
|
||||
|
@ -11085,11 +11104,6 @@ visibility around point, thus ignoring
|
|||
(error "No match"))))
|
||||
(t
|
||||
;; A normal search string
|
||||
(when (equal (string-to-char s) ?*)
|
||||
;; Anchor on headlines, post may include tags.
|
||||
(setq pre "^\\*+[ \t]+\\(?:\\sw+\\)?[ \t]*"
|
||||
post (org-re "[ \t]*\\(?:[ \t]+:[[:alnum:]_@#%:+]:[ \t]*\\)?$")
|
||||
s (substring s 1)))
|
||||
(remove-text-properties
|
||||
0 (length s)
|
||||
'(face nil mouse-face nil keymap nil fontified nil) s)
|
||||
|
@ -11106,15 +11120,9 @@ visibility around point, thus ignoring
|
|||
"[^a-zA-Z_\r\n]+") "\\)[^a-zA-Z_]")
|
||||
re4 (concat "[^a-zA-Z_]" re4_)
|
||||
|
||||
re1 (concat pre re2 post)
|
||||
re3 (concat pre (if pre re4_ re4) post)
|
||||
re5 (concat pre ".*" re4)
|
||||
re2 (concat pre re2)
|
||||
re2a (concat pre (if pre re2a_ re2a))
|
||||
re4 (concat pre (if pre re4_ re4))
|
||||
reall (concat "\\(" re0 "\\)\\|\\(" re1 "\\)\\|\\(" re2
|
||||
"\\)\\|\\(" re3 "\\)\\|\\(" re4 "\\)\\|\\("
|
||||
re5 "\\)"))
|
||||
re5 (concat ".*" re4)
|
||||
reall (concat "\\(" re0 "\\)\\|\\(" re2 "\\)\\|\\(" re4
|
||||
"\\)\\|\\(" re5 "\\)"))
|
||||
(cond
|
||||
((eq type 'org-occur) (org-occur reall))
|
||||
((eq type 'occur) (org-do-occur (downcase reall) 'cleanup))
|
||||
|
@ -11122,10 +11130,8 @@ visibility around point, thus ignoring
|
|||
(setq type 'fuzzy)
|
||||
(if (or (and (org-search-not-self 1 re0 nil t)
|
||||
(setq type 'dedicated))
|
||||
(org-search-not-self 1 re1 nil t)
|
||||
(org-search-not-self 1 re2 nil t)
|
||||
(org-search-not-self 1 re2a nil t)
|
||||
(org-search-not-self 1 re3 nil t)
|
||||
(org-search-not-self 1 re4 nil t)
|
||||
(org-search-not-self 1 re5 nil t))
|
||||
(goto-char (match-beginning 1))
|
||||
|
|
|
@ -1331,6 +1331,32 @@
|
|||
(goto-line 3)
|
||||
(org-open-at-point)
|
||||
(looking-at "\\* Test")))
|
||||
;; With a leading star in link, enforce exact heading match, even
|
||||
;; with `org-link-search-must-match-exact-headline' set to nil.
|
||||
(should-error
|
||||
(org-test-with-temp-text "* Test 1\nFoo Bar\n<point>[[*Test]]"
|
||||
(let ((org-link-search-must-match-exact-headline nil))
|
||||
(org-open-at-point))))
|
||||
;; Heading match should not care about spaces, cookies, todo
|
||||
;; keywords, priorities, and tags.
|
||||
(should
|
||||
(let ((first-line
|
||||
"** TODO [#A] [/] Test [1/2] [33%] 1 \t 2 [%] :work:urgent: "))
|
||||
(org-test-with-temp-text
|
||||
(concat first-line "\nFoo Bar\n<point>[[*Test 1 2]]")
|
||||
(let ((org-link-search-must-match-exact-headline nil)
|
||||
(org-todo-regexp "TODO"))
|
||||
(org-open-at-point))
|
||||
(looking-at (regexp-quote first-line)))))
|
||||
;; Heading match should still be exact.
|
||||
(should-error
|
||||
(let ((first-line
|
||||
"** TODO [#A] [/] Test [1/2] [33%] 1 \t 2 [%] :work:urgent: "))
|
||||
(org-test-with-temp-text
|
||||
(concat first-line "\nFoo Bar\n<point>[[*Test 1]]")
|
||||
(let ((org-link-search-must-match-exact-headline nil)
|
||||
(org-todo-regexp "TODO"))
|
||||
(org-open-at-point)))))
|
||||
;; Correctly un-hexify fuzzy links.
|
||||
(should
|
||||
(org-test-with-temp-text "* With space\n[[*With%20space][With space]]"
|
||||
|
|
Loading…
Reference in New Issue