Add: (link) predicate
This commit is contained in:
parent
5d720b9fc3
commit
9a56141f6c
5 changed files with 204 additions and 22 deletions
|
|
@ -198,6 +198,7 @@ Arguments are listed next to predicate names, where applicable.
|
||||||
+ =heading (&rest regexps)= :: Return non-nil if current entry's heading matches all ~REGEXPS~ (regexp strings).
|
+ =heading (&rest regexps)= :: Return non-nil if current entry's heading matches all ~REGEXPS~ (regexp strings).
|
||||||
- Aliases: =h=.
|
- Aliases: =h=.
|
||||||
+ =level (level-or-comparator &optional level)= :: Return non-nil if current heading's outline level matches arguments. The following forms are accepted: ~(level NUMBER)~: Matches if heading level is ~NUMBER~. ~(level NUMBER NUMBER)~: Matches if heading level is equal to or between NUMBERs. ~(level COMPARATOR NUMBER)~: Matches if heading level compares to ~NUMBER~ with ~COMPARATOR~. ~COMPARATOR~ may be ~<~, ~<=~, ~>~, or ~>=~.
|
+ =level (level-or-comparator &optional level)= :: Return non-nil if current heading's outline level matches arguments. The following forms are accepted: ~(level NUMBER)~: Matches if heading level is ~NUMBER~. ~(level NUMBER NUMBER)~: Matches if heading level is equal to or between NUMBERs. ~(level COMPARATOR NUMBER)~: Matches if heading level compares to ~NUMBER~ with ~COMPARATOR~. ~COMPARATOR~ may be ~<~, ~<=~, ~>~, or ~>=~.
|
||||||
|
+ =link (&optional description-or-target &key description target regexp-p)= :: Return non-nil if current heading contains a link matching arguments. ~DESCRIPTION-OR-TARGET~ is matched against the link's description and target. Alternatively, one or both of ~DESCRIPTION~ and ~TARGET~ may be matched separately. Without arguments, return non-nil if any link is found.
|
||||||
+ =outline-path (&rest strings)= :: Return non-nil if current node's outline path matches all of ~STRINGS~. Each string may appear as a substring in any part of the node's outline path. For example, the path =Food/Fruits/Grapes= would match ~(olp "Fruit" "Grape")~.
|
+ =outline-path (&rest strings)= :: Return non-nil if current node's outline path matches all of ~STRINGS~. Each string may appear as a substring in any part of the node's outline path. For example, the path =Food/Fruits/Grapes= would match ~(olp "Fruit" "Grape")~.
|
||||||
- Aliases: ~olp~.
|
- Aliases: ~olp~.
|
||||||
+ =outline-path-segment (&rest strings)= :: Return non-nil if current node's outline path matches ~STRINGS~. Matches ~STRINGS~ as a contiguous segment of the outline path. Each string is compared as a substring. For example the path ~Food/Fruits/Grapes~ would match ~(olps "Fruit" "Grape")~ but not ~(olps "Food" "Grape")~.
|
+ =outline-path-segment (&rest strings)= :: Return non-nil if current node's outline path matches ~STRINGS~. Matches ~STRINGS~ as a contiguous segment of the outline path. Each string is compared as a substring. For example the path ~Food/Fruits/Grapes~ would match ~(olps "Fruit" "Grape")~ but not ~(olps "Food" "Grape")~.
|
||||||
|
|
@ -404,6 +405,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience
|
||||||
|
|
||||||
*Added*
|
*Added*
|
||||||
+ View dispatcher using =transient.el= (like Magit), bound to =v= in search/view buffers.
|
+ View dispatcher using =transient.el= (like Magit), bound to =v= in search/view buffers.
|
||||||
|
+ Predicate =link=, which matches descriptions and targets in Org links.
|
||||||
|
|
||||||
*Changed*
|
*Changed*
|
||||||
+ Binding to refresh search/view buffers changed to =r=.
|
+ Binding to refresh search/view buffers changed to =r=.
|
||||||
|
|
|
||||||
141
org-ql.el
141
org-ql.el
|
|
@ -3,7 +3,7 @@
|
||||||
;; Author: Adam Porter <adam@alphapapa.net>
|
;; Author: Adam Porter <adam@alphapapa.net>
|
||||||
;; Url: https://github.com/alphapapa/org-ql
|
;; Url: https://github.com/alphapapa/org-ql
|
||||||
;; Version: 0.5-pre
|
;; Version: 0.5-pre
|
||||||
;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (transient "0.1") (ts "0.2-pre"))
|
;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (map "2.1") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (transient "0.1") (ts "0.2-pre"))
|
||||||
;; Keywords: hypermedia, outlines, Org, agenda
|
;; Keywords: hypermedia, outlines, Org, agenda
|
||||||
|
|
||||||
;;; Commentary:
|
;;; Commentary:
|
||||||
|
|
@ -73,6 +73,25 @@ That is, \"CLOSED:\", \"DEADLINE:\", or \"SCHEDULED:\".")
|
||||||
Tags are stored in match group 1. Match group 2 stores the tags
|
Tags are stored in match group 1. Match group 2 stores the tags
|
||||||
without the enclosing colons.")
|
without the enclosing colons.")
|
||||||
|
|
||||||
|
(defconst org-ql-link-regexp
|
||||||
|
(if (bound-and-true-p org-link-bracket-re)
|
||||||
|
org-link-bracket-re
|
||||||
|
org-bracket-link-regexp)
|
||||||
|
"Regexp used to match Org bracket links.
|
||||||
|
Necessary because of changes in Org 9.something.")
|
||||||
|
|
||||||
|
(defconst org-ql-link-description-group
|
||||||
|
(if (bound-and-true-p org-link-bracket-re)
|
||||||
|
2
|
||||||
|
3)
|
||||||
|
;; I wish Org would not introduce backward-incompatible changes like this in
|
||||||
|
;; minor releases. It requires awkward workarounds to be maintained for years.
|
||||||
|
"Regexp match group used to extract description from Org bracket links.
|
||||||
|
Necessary because of backward-incompatible changes in Org
|
||||||
|
9.something: when `org-link-bracket-re' was added,
|
||||||
|
`org-bracket-link-regexp' was marked as an obsolete alias for it,
|
||||||
|
but the match groups were changed, so they are not compatible.")
|
||||||
|
|
||||||
;;;; Variables
|
;;;; Variables
|
||||||
|
|
||||||
(defvar org-ql--today nil)
|
(defvar org-ql--today nil)
|
||||||
|
|
@ -727,6 +746,40 @@ replace the clause with a preamble."
|
||||||
(setq org-ql-preamble (rx-to-string `(seq bol (repeat ,num "*") " ") t))
|
(setq org-ql-preamble (rx-to-string `(seq bol (repeat ,num "*") " ") t))
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
|
;; Links. Always return nil, because we
|
||||||
|
;; shouldn't need to test the predicate.
|
||||||
|
(`(link)
|
||||||
|
(setq org-ql-preamble
|
||||||
|
;; 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)))
|
||||||
|
nil)
|
||||||
|
;; NOTE: I would use the form "(map :regexp-p)", or at least
|
||||||
|
;; "(map (:regexp-p regexp))" but they require map versions from
|
||||||
|
;; ELPA. That would be fine, except that I can't automatically
|
||||||
|
;; install those versions with makem.sh into a sandbox, because
|
||||||
|
;; `package-install' doesn't accept a version argument. So I
|
||||||
|
;; have to use `plist-get' here for now. Maybe when we drop
|
||||||
|
;; support for Emacs <28...
|
||||||
|
(`(link ,(and description-or-target
|
||||||
|
(guard (not (keywordp description-or-target)))))
|
||||||
|
(setq org-ql-preamble
|
||||||
|
(org-ql--link-regexp :description-or-target
|
||||||
|
(regexp-quote description-or-target)))
|
||||||
|
nil)
|
||||||
|
(`(link . ,plist)
|
||||||
|
(setq org-ql-preamble
|
||||||
|
(org-ql--link-regexp
|
||||||
|
:description
|
||||||
|
(when (plist-get plist :description)
|
||||||
|
(regexp-quote (plist-get plist :description)))
|
||||||
|
:target (when (plist-get plist :target)
|
||||||
|
(regexp-quote (plist-get plist :target)))))
|
||||||
|
nil)
|
||||||
|
|
||||||
;; Planning lines.
|
;; Planning lines.
|
||||||
(`(planning . ,_)
|
(`(planning . ,_)
|
||||||
(setq org-ql-preamble org-ql-planning-regexp)
|
(setq org-ql-preamble org-ql-planning-regexp)
|
||||||
|
|
@ -838,6 +891,47 @@ replace the clause with a preamble."
|
||||||
(query (-flatten-n 1 query))))
|
(query (-flatten-n 1 query))))
|
||||||
(list :query query :preamble org-ql-preamble :preamble-case-fold preamble-case-fold))))))
|
(list :query query :preamble org-ql-preamble :preamble-case-fold preamble-case-fold))))))
|
||||||
|
|
||||||
|
(cl-defun org-ql--link-regexp (&key description-or-target description target)
|
||||||
|
"Return a regexp matching Org links according to arguments.
|
||||||
|
Each argument is treated as a regexp (so non-regexp strings
|
||||||
|
should be quoted before being passed to this function). If
|
||||||
|
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."
|
||||||
|
(cl-labels
|
||||||
|
((no-desc
|
||||||
|
(match) (rx-to-string `(seq (or bol (1+ blank))
|
||||||
|
"[[" (0+ (not (any "]"))) (regexp ,match) (0+ (not (any "]")))
|
||||||
|
"]]")))
|
||||||
|
(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 "]")))
|
||||||
|
"]]")))
|
||||||
|
;; 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 "]")))
|
||||||
|
"]]")))
|
||||||
|
(match-target
|
||||||
|
(match) (rx-to-string `(seq (or bol (1+ blank))
|
||||||
|
"[[" (0+ (not (any "]"))) (regexp ,match) (0+ (not (any "]")))
|
||||||
|
"][" (0+ (not (any "]")))
|
||||||
|
"]]"))))
|
||||||
|
(cond (description-or-target
|
||||||
|
(rx-to-string `(or (regexp ,(no-desc description-or-target))
|
||||||
|
(regexp ,(match-desc description-or-target))
|
||||||
|
(regexp ,(match-target description-or-target)))))
|
||||||
|
((and description target)
|
||||||
|
(match-both description target))
|
||||||
|
(description (match-desc description))
|
||||||
|
(target (rx-to-string `(or (regexp ,(no-desc target))
|
||||||
|
(regexp ,(match-target target))))))))
|
||||||
|
|
||||||
(defun org-ql--format-src-block-regexp (&optional lang)
|
(defun org-ql--format-src-block-regexp (&optional lang)
|
||||||
"Return regexp equivalent to `org-babel-src-block-regexp' with LANG filled in."
|
"Return regexp equivalent to `org-babel-src-block-regexp' with LANG filled in."
|
||||||
;; I couldn't find a way to match block contents without the regexp
|
;; I couldn't find a way to match block contents without the regexp
|
||||||
|
|
@ -1073,6 +1167,51 @@ COMPARATOR may be `<', `<=', `>', or `>='."
|
||||||
((pred symbolp) ;; Compare with function
|
((pred symbolp) ;; Compare with function
|
||||||
(funcall level-or-comparator outline-level level)))))
|
(funcall level-or-comparator outline-level level)))))
|
||||||
|
|
||||||
|
(org-ql--defpred link (&rest args)
|
||||||
|
;; User-facing argument form: (&optional description-or-target &key description target regexp-p).
|
||||||
|
"Return non-nil if current heading contains a link matching arguments.
|
||||||
|
DESCRIPTION-OR-TARGET is matched against the link's description
|
||||||
|
and target. Alternatively, one or both of DESCRIPTION and TARGET
|
||||||
|
may be matched separately. Without arguments, return non-nil if
|
||||||
|
any link is found."
|
||||||
|
;; NOTE: It would be preferable to avoid this manual argument parsing every time the predicate
|
||||||
|
;; is called, but pre-processing it to a normal form gets complicated with the preamble and
|
||||||
|
;; pre-processing, because we don't want to display a query like "(link :description-or-target
|
||||||
|
;; "FOO")" in the view header, which would be ugly. So, since preambles are expected to be
|
||||||
|
;; 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.
|
||||||
|
(let* (plist description-or-target description target regexp-p)
|
||||||
|
(if (not (keywordp (car args)))
|
||||||
|
(setf description-or-target (car args)
|
||||||
|
plist (cdr args))
|
||||||
|
(setf plist args))
|
||||||
|
(setf description (plist-get plist :description)
|
||||||
|
target (plist-get plist :description)
|
||||||
|
regexp-p (plist-get plist :regexp-p))
|
||||||
|
(unless regexp-p
|
||||||
|
;; NOTE: It would also be preferable to avoid regexp-quoting every time this predicate
|
||||||
|
;; is called. Ideally that would be handled in the query pre-processing step. However,
|
||||||
|
;; handling that properly, in combination with preparing the query preamble and whether
|
||||||
|
;; REGEXP-P is enabled, is also complicated, so let's not.
|
||||||
|
(when description-or-target
|
||||||
|
(setf description-or-target (regexp-quote description-or-target)))
|
||||||
|
(when description
|
||||||
|
(setf description (regexp-quote description)))
|
||||||
|
(when target
|
||||||
|
(setf target (regexp-quote target))))
|
||||||
|
(when (re-search-forward org-ql-link-regexp (org-entry-end-position) t)
|
||||||
|
(pcase description-or-target
|
||||||
|
('nil (and (or (null target)
|
||||||
|
(string-match-p target (match-string 1)))
|
||||||
|
(or (null description)
|
||||||
|
(string-match-p description (match-string org-ql-link-description-group)))))
|
||||||
|
(_ (if (and description target)
|
||||||
|
(and (string-match-p target (match-string 1))
|
||||||
|
(string-match-p description (match-string org-ql-link-description-group)))
|
||||||
|
(or (string-match-p description-or-target (match-string 1))
|
||||||
|
(string-match-p description-or-target
|
||||||
|
(match-string org-ql-link-description-group)))))))))
|
||||||
|
|
||||||
(org-ql--defpred priority (&rest args)
|
(org-ql--defpred priority (&rest args)
|
||||||
"Return non-nil if current heading has a certain priority.
|
"Return non-nil if current heading has a certain priority.
|
||||||
ARGS may be either a list of one or more priority letters as
|
ARGS may be either a list of one or more priority letters as
|
||||||
|
|
|
||||||
50
org-ql.info
50
org-ql.info
|
|
@ -381,6 +381,12 @@ Arguments are listed next to predicate names, where applicable.
|
||||||
Matches if heading level is equal to or between NUMBERs. ‘(level
|
Matches if heading level is equal to or between NUMBERs. ‘(level
|
||||||
COMPARATOR NUMBER)’: Matches if heading level compares to ‘NUMBER’
|
COMPARATOR NUMBER)’: Matches if heading level compares to ‘NUMBER’
|
||||||
with ‘COMPARATOR’. ‘COMPARATOR’ may be ‘<’, ‘<=’, ‘>’, or ‘>=’.
|
with ‘COMPARATOR’. ‘COMPARATOR’ may be ‘<’, ‘<=’, ‘>’, or ‘>=’.
|
||||||
|
‘link (&optional description-or-target &key description target regexp-p)’
|
||||||
|
Return non-nil if current heading contains a link matching
|
||||||
|
arguments. ‘DESCRIPTION-OR-TARGET’ is matched against the link’s
|
||||||
|
description and target. Alternatively, one or both of
|
||||||
|
‘DESCRIPTION’ and ‘TARGET’ may be matched separately. Without
|
||||||
|
arguments, return non-nil if any link is found.
|
||||||
‘outline-path (&rest strings)’
|
‘outline-path (&rest strings)’
|
||||||
Return non-nil if current node’s outline path matches all of
|
Return non-nil if current node’s outline path matches all of
|
||||||
‘STRINGS’. Each string may appear as a substring in any part of
|
‘STRINGS’. Each string may appear as a substring in any part of
|
||||||
|
|
@ -732,6 +738,8 @@ File: README.info, Node: 05-pre, Next: 041, Up: Changelog
|
||||||
*Added*
|
*Added*
|
||||||
• View dispatcher using transient.el (like Magit), bound to v in
|
• View dispatcher using transient.el (like Magit), bound to v in
|
||||||
search/view buffers.
|
search/view buffers.
|
||||||
|
• Predicate link, which matches descriptions and targets in Org
|
||||||
|
links.
|
||||||
|
|
||||||
*Changed*
|
*Changed*
|
||||||
• Binding to refresh search/view buffers changed to r.
|
• Binding to refresh search/view buffers changed to r.
|
||||||
|
|
@ -1105,27 +1113,27 @@ Node: org-ql-sparse-tree7044
|
||||||
Node: Queries7844
|
Node: Queries7844
|
||||||
Node: Non-sexp query syntax8752
|
Node: Non-sexp query syntax8752
|
||||||
Node: General predicates10459
|
Node: General predicates10459
|
||||||
Node: Ancestor/descendant predicates15266
|
Node: Ancestor/descendant predicates15674
|
||||||
Node: Date/time predicates16394
|
Node: Date/time predicates16802
|
||||||
Node: Functions / Macros19049
|
Node: Functions / Macros19457
|
||||||
Node: Agenda-like views19282
|
Node: Agenda-like views19690
|
||||||
Node: Listing / acting-on results20687
|
Node: Listing / acting-on results21095
|
||||||
Node: Changelog25289
|
Node: Changelog25697
|
||||||
Node: 05-pre25853
|
Node: 05-pre26261
|
||||||
Node: 04126121
|
Node: 04126610
|
||||||
Node: 0426363
|
Node: 0426852
|
||||||
Node: 03230294
|
Node: 03230783
|
||||||
Node: 03130671
|
Node: 03131160
|
||||||
Node: 0330866
|
Node: 0331355
|
||||||
Node: 02333839
|
Node: 02334328
|
||||||
Node: 02234065
|
Node: 02234554
|
||||||
Node: 02134331
|
Node: 02134820
|
||||||
Node: 0234528
|
Node: 0235017
|
||||||
Node: 0138563
|
Node: 0139052
|
||||||
Node: Notes38664
|
Node: Notes39153
|
||||||
Node: Comparison with Org Agenda searches38826
|
Node: Comparison with Org Agenda searches39315
|
||||||
Node: org-sidebar39698
|
Node: org-sidebar40187
|
||||||
Node: License39977
|
Node: License40466
|
||||||
|
|
||||||
End Tag Table
|
End Tag Table
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,8 @@ Gotta buy one first, though.
|
||||||
** CHECK /r/emacs :website:Emacs:
|
** CHECK /r/emacs :website:Emacs:
|
||||||
DEADLINE: <2017-07-05 Wed +1w>
|
DEADLINE: <2017-07-05 Wed +1w>
|
||||||
|
|
||||||
|
+ [[http://reddit.com/r/emacs][Link to /r/emacs]]
|
||||||
|
|
||||||
** TODO Shop for groceries :food:shopping:@town:
|
** TODO Shop for groceries :food:shopping:@town:
|
||||||
SCHEDULED: <2017-07-05 Wed +1w>
|
SCHEDULED: <2017-07-05 Wed +1w>
|
||||||
:PROPERTIES:
|
:PROPERTIES:
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,7 @@ RESULTS should be a list of strings as returned by
|
||||||
:to-equal org-ql-test-num-headings)))
|
:to-equal org-ql-test-num-headings)))
|
||||||
|
|
||||||
(describe "Query pre-processing"
|
(describe "Query pre-processing"
|
||||||
|
|
||||||
(it "level:"
|
(it "level:"
|
||||||
(expect (org-ql--pre-process-query '(level "1"))
|
(expect (org-ql--pre-process-query '(level "1"))
|
||||||
:to-equal '(level 1))
|
:to-equal '(level 1))
|
||||||
|
|
@ -225,6 +226,19 @@ RESULTS should be a list of strings as returned by
|
||||||
(expect (org-ql--pre-process-query '(level ">" "1"))
|
(expect (org-ql--pre-process-query '(level ">" "1"))
|
||||||
:to-equal '(level > 1)))
|
:to-equal '(level > 1)))
|
||||||
|
|
||||||
|
(describe "(link)"
|
||||||
|
(it "with one argument"
|
||||||
|
(expect (org-ql--pre-process-query '(link "DESC-OR-TARGET"))
|
||||||
|
:to-equal '(link "DESC-OR-TARGET")))
|
||||||
|
(it "with one argument and :regexp-p"
|
||||||
|
(expect (org-ql--pre-process-query '(link "DESC-OR-TARGET" :regexp-p t))
|
||||||
|
:to-equal '(link "DESC-OR-TARGET" :regexp-p t)))
|
||||||
|
(it "with keyword arguments"
|
||||||
|
(expect (org-ql--pre-process-query '(link :description "DESCRIPTION" :target "TARGET"
|
||||||
|
:regexp-p t))
|
||||||
|
:to-equal '(link :description "DESCRIPTION" :target "TARGET"
|
||||||
|
:regexp-p t))))
|
||||||
|
|
||||||
(expect (org-ql--pre-process-query '(and "string1" "string2"))
|
(expect (org-ql--pre-process-query '(and "string1" "string2"))
|
||||||
:to-equal '(and (regexp "string1") (regexp "string2")))
|
:to-equal '(and (regexp "string1") (regexp "string2")))
|
||||||
(expect (org-ql--pre-process-query '(or "string1" "string2"))
|
(expect (org-ql--pre-process-query '(or "string1" "string2"))
|
||||||
|
|
@ -575,6 +589,23 @@ RESULTS should be a list of strings as returned by
|
||||||
(org-ql-expect ((heading "Take over" "world"))
|
(org-ql-expect ((heading "Take over" "world"))
|
||||||
'("Take over the world"))))
|
'("Take over the world"))))
|
||||||
|
|
||||||
|
(describe "(link)"
|
||||||
|
(org-ql-it "without arguments"
|
||||||
|
(org-ql-expect ((link))
|
||||||
|
'("/r/emacs")))
|
||||||
|
(org-ql-it "with description-or-target"
|
||||||
|
(org-ql-expect ((link "emacs"))
|
||||||
|
'("/r/emacs")))
|
||||||
|
(org-ql-it "with :description"
|
||||||
|
(org-ql-expect ((link :description "emacs"))
|
||||||
|
'("/r/emacs")))
|
||||||
|
(org-ql-it "with :target"
|
||||||
|
(org-ql-expect ((link :target "reddit.com"))
|
||||||
|
'("/r/emacs")))
|
||||||
|
(org-ql-it "with :description and :target"
|
||||||
|
(org-ql-expect ((link :description "emacs" :target "reddit.com"))
|
||||||
|
'("/r/emacs"))))
|
||||||
|
|
||||||
(describe "(outline-path)"
|
(describe "(outline-path)"
|
||||||
(org-ql-it "with one argument"
|
(org-ql-it "with one argument"
|
||||||
(org-ql-expect ((outline-path "symphony"))
|
(org-ql-expect ((outline-path "symphony"))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue