Fix: (link) Allow brackets in description

Org 9.3 stopped replacing brackets in link descriptions with braces
and started escaping them instead.

Fixes #283.  Thanks to Daniel Borchmann (@exot) for reporting.
This commit is contained in:
Adam Porter 2023-03-10 05:52:06 -06:00
parent 3c73888b98
commit 9e14f9eefa
5 changed files with 115 additions and 68 deletions

View file

@ -560,6 +560,7 @@ Simple links may also be written manually in either sexp or non-sexp form, like:
+ Command ~org-ql-sparse-tree~ accepts both string and sexp queries. (Thanks to [[https://github.com/akirak][Akira Komamura]].)
*Fixed*
+ Predicate ~link~ matches links whose descriptions contain escaped brackets (changed in Org 9.3). (Thanks to [[https://github.com/exot][Daniel Borchmann]] for reporting.)
+ Predicate ~src~'s matching of begin/end block lines, normalization of arguments, and handling in non-sexp queries. (Thanks to [[https://github.com/akirak][Akira Komamura]] for reporting.)
+ Predicate ~src~'s behavior with various arguments.
+ Various compilation warnings.

View file

@ -794,28 +794,33 @@ DESCRIPTION-OR-TARGET, match it in either description or target.
If DESCRIPTION, match it in the description. If TARGET, match it
in the target. If both DESCRIPTION and TARGET, match both,
respectively."
;; This `rx' part is borrowed from `org-make-link-regexps'. It matches the interior of an
;; Org link target (i.e. the parts between the brackets, including any escaped brackets).
(let ((link-target-part '(0+ (or (not (any "[]\\"))
(and "\\" (0+ "\\\\") (any "[]"))
(and (1+ "\\") (not (any "[]")))))))
(cl-labels
((no-desc
(match) (rx-to-string `(seq (or bol (1+ blank))
"[[" (0+ (not (any "]"))) (regexp ,match) (0+ (not (any "]")))
"[[" ,link-target-part (regexp ,match) ,link-target-part
"]]")))
(match-both
(description target)
(rx-to-string `(seq (or bol (1+ blank))
"[[" (0+ (not (any "]"))) (regexp ,target) (0+ (not (any "]")))
"][" (0+ (not (any "]"))) (regexp ,description) (0+ (not (any "]")))
"[[" ,link-target-part (regexp ,target) ,link-target-part
"][" (*? anything) (regexp ,description) (*? anything)
"]]")))
;; Note that these actually allow empty descriptions
;; or targets, depending on what they are matching.
(match-desc
(match) (rx-to-string `(seq (or bol (1+ blank))
"[[" (0+ (not (any "]")))
"][" (0+ (not (any "]"))) (regexp ,match) (0+ (not (any "]")))
"[[" ,link-target-part
"][" (*? anything) (regexp ,match) (*? anything)
"]]")))
(match-target
(match) (rx-to-string `(seq (or bol (1+ blank))
"[[" (0+ (not (any "]"))) (regexp ,match) (0+ (not (any "]")))
"][" (0+ (not (any "]")))
"[[" ,link-target-part (regexp ,match) ,link-target-part
"][" (*? anything)
"]]"))))
(cond (description-or-target
(rx-to-string `(or (regexp ,(no-desc description-or-target))
@ -825,7 +830,7 @@ respectively."
(match-both description target))
(description (match-desc description))
(target (rx-to-string `(or (regexp ,(no-desc target))
(regexp ,(match-target target))))))))
(regexp ,(match-target target)))))))))
(defun org-ql--format-src-block-regexp (&optional lang)
"Return regexp equivalent to `org-babel-src-block-regexp' with LANG filled in."
@ -1563,12 +1568,8 @@ any link is found."
;; enabled nearly all of the time, in which case this function won't be called anyway, it's
;; probably not worth rewriting code all over the place to fix this.
:preambles ((`(,predicate-names)
(list :regexp ;; Match a link with a target and optionally a description.
(rx (or bol (1+ blank))
"[[" (1+ (not (any "]"))) "]"
(optional (seq "[" (0+ (not (any "]"))) "]"))
"]"
(or eol blank))))
;; Match a link with a target and optionally a description.
(list :regexp (org-ql--link-regexp :target ".*")))
(`(,predicate-names ,(and description-or-target
(guard (not (keywordp description-or-target))))
. ,plist)

View file

@ -1055,6 +1055,9 @@ File: README.info, Node: 07-pre, Next: 063, Up: Changelog
(Thanks to Akira Komamura (https://github.com/akirak).)
*Fixed*
• Predicate link matches links whose descriptions contain escaped
brackets (changed in Org 9.3). (Thanks to Daniel Borchmann
(https://github.com/exot) for reporting.)
• Predicate srcs matching of begin/end block lines, normalization
of arguments, and handling in non-sexp queries. (Thanks to Akira
Komamura (https://github.com/akirak) for reporting.)
@ -1735,35 +1738,35 @@ Node: Links37255
Node: Tips37942
Node: Changelog38266
Node: 07-pre39049
Node: 06341784
Node: 06242319
Node: 06142624
Node: 0643192
Node: 05246246
Node: 05146546
Node: 0546969
Node: 04948498
Node: 04848778
Node: 04749127
Node: 04649536
Node: 04549944
Node: 04450305
Node: 04350664
Node: 04250867
Node: 04151028
Node: 0451275
Node: 03255376
Node: 03155779
Node: 0355976
Node: 02359276
Node: 02259510
Node: 02159790
Node: 0259995
Node: 0164073
Node: Notes64174
Node: Comparison with Org Agenda searches64336
Node: org-sidebar65225
Node: License65504
Node: 06341973
Node: 06242508
Node: 06142813
Node: 0643381
Node: 05246435
Node: 05146735
Node: 0547158
Node: 04948687
Node: 04848967
Node: 04749316
Node: 04649725
Node: 04550133
Node: 04450494
Node: 04350853
Node: 04251056
Node: 04151217
Node: 0451464
Node: 03255565
Node: 03155968
Node: 0356165
Node: 02359465
Node: 02259699
Node: 02159979
Node: 0260184
Node: 0164262
Node: Notes64363
Node: Comparison with Org Agenda searches64525
Node: org-sidebar65414
Node: License65693

End Tag Table

10
tests/data-links.org Normal file
View file

@ -0,0 +1,10 @@
* Alpha
Let us link to: [[id:74d357ac-fb9c-40d1-a63f-eca8a227321d][Bravo [a phrase in brackets]]].
* Bravo [a phrase in brackets]
:PROPERTIES:
:ID: 74d357ac-fb9c-40d1-a63f-eca8a227321d
:END:
* Charlie

View file

@ -1141,7 +1141,39 @@ with keyword arg NOW in PLIST."
'("/r/emacs")))
(org-ql-it "with :description and :target regexp"
(org-ql-expect ('(link :description "em.cs" :target "em.cs" :regexp-p t))
'("/r/emacs"))))
'("/r/emacs")))
(describe "matches links whose descriptions contain brackets"
(before-each
(setq org-ql-test-buffer (org-ql-test-data-buffer "data-links.org")))
(org-ql-it "without arguments"
(org-ql-expect ('(link))
'("Alpha")))
(org-ql-it "with description-or-target"
(org-ql-expect ('(link "phrase"))
'("Alpha")))
(org-ql-it "with :description"
(org-ql-expect ('(link :description "phrase"))
'("Alpha")))
(org-ql-it "with :target"
(org-ql-expect ('(link :target "id:"))
'("Alpha")))
(org-ql-it "with :description and :target"
(org-ql-expect ('(link :description "phrase" :target "id"))
'("Alpha")))
(org-ql-it "with description-or-target regexp"
(org-ql-expect ('(link "id:.*" :regexp-p t))
'("Alpha")))
(org-ql-it "with :description regexp"
(org-ql-expect ('(link :description "phr.se" :regexp-p t))
'("Alpha")))
(org-ql-it "with :target regexp"
(org-ql-expect ('(link :target "id:.*" :regexp-p t))
'("Alpha")))
(org-ql-it "with :description and :target regexp"
(org-ql-expect ('(link :description "phr.se" :target "id:.*" :regexp-p t))
'("Alpha")))))
(describe "(outline-path)"
(org-ql-it "with one argument"