Compare commits

..

1 commit

Author SHA1 Message Date
Adam Porter
ea72409f64 WIP: Fix issue 79
See #79.
2024-09-01 14:56:54 -05:00
7 changed files with 209 additions and 365 deletions

View file

@ -233,7 +233,7 @@ Note that the =effort=, =level=, and =priority= predicates do not support compar
Arguments are listed next to predicate names, where applicable. Arguments are listed next to predicate names, where applicable.
+ =blocked= :: Return non-nil if current heading is blocked. Calls ~org-entry-blocked-p~, which see. + =blocked= :: Return non-nil if current heading is blocked. Calls ~org-entry-blocked-p~, which see.
+ =category (&rest categories)= :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). + =category (&optional categories)= :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings).
+ =done= :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~. + =done= :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~.
+ =effort (&optional effort-or-comparator effort)= :: Return non-nil if current heading's effort property matches arguments. The following forms are accepted: ~(effort DURATION)~: Matches if effort is ~DURATION~. ~(effort DURATION DURATION)~: Matches if effort is between DURATIONs, inclusive. ~(effort COMPARATOR DURATION)~: Matches if effort compares to ~DURATION~ with ~COMPARATOR~. ~COMPARATOR~ may be ~<~, ~<=~, ~>~, or ~>=~. ~DURATION~ should be an Org effort string, like =5= or =0:05=. + =effort (&optional effort-or-comparator effort)= :: Return non-nil if current heading's effort property matches arguments. The following forms are accepted: ~(effort DURATION)~: Matches if effort is ~DURATION~. ~(effort DURATION DURATION)~: Matches if effort is between DURATIONs, inclusive. ~(effort COMPARATOR DURATION)~: Matches if effort compares to ~DURATION~ with ~COMPARATOR~. ~COMPARATOR~ may be ~<~, ~<=~, ~>~, or ~>=~. ~DURATION~ should be an Org effort string, like =5= or =0:05=.
+ =habit= :: Return non-nil if entry is a habit. + =habit= :: Return non-nil if entry is a habit.
@ -256,16 +256,16 @@ Arguments are listed next to predicate names, where applicable.
- Aliases: ~smart~. - Aliases: ~smart~.
- *Note:* By default, this is the default predicate used for plain-string query tokens (i.e. given without a specified predicate). This can be customized with the option ~org-ql-default-predicate~. - *Note:* By default, this is the default predicate used for plain-string query tokens (i.e. given without a specified predicate). This can be customized with the option ~org-ql-default-predicate~.
+ ~src (&key lang regexps)~ :: Return non-nil if current entry contains an Org Babel source block. If ~LANG~ is non-nil, match blocks of that language. If ~REGEXPS~ is non-nil, require that block's contents match all regexps. Matching is done case-insensitively. + ~src (&key lang regexps)~ :: Return non-nil if current entry contains an Org Babel source block. If ~LANG~ is non-nil, match blocks of that language. If ~REGEXPS~ is non-nil, require that block's contents match all regexps. Matching is done case-insensitively.
+ =tags (&rest tags)= :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). Tests both inherited and local tags. + =tags (&optional tags)= :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). Tests both inherited and local tags.
+ =tags-inherited (&rest tags)= :: Return non-nil if current heading's inherited tags include one or more of ~TAGS~ (a list of strings). If ~TAGS~ is nil, return non-nil if heading has any inherited tags. + =tags-inherited (&optional tags)= :: Return non-nil if current heading's inherited tags include one or more of ~TAGS~ (a list of strings). If ~TAGS~ is nil, return non-nil if heading has any inherited tags.
- Aliases: ~inherited-tags~, ~tags-i~, ~itags~. - Aliases: ~inherited-tags~, ~tags-i~, ~itags~.
+ =tags-local (&rest tags)= :: Return non-nil if current heading's local tags include one or more of ~TAGS~ (a list of strings). If ~TAGS~ is nil, return non-nil if heading has any local tags. + =tags-local (&optional tags)= :: Return non-nil if current heading's local tags include one or more of ~TAGS~ (a list of strings). If ~TAGS~ is nil, return non-nil if heading has any local tags.
- Aliases: ~local-tags~, ~tags-l~, ~ltags~. - Aliases: ~local-tags~, ~tags-l~, ~ltags~.
+ =tags-all (&rest tags)= :: Return non-nil if current heading includes all of ~TAGS~. Tests both inherited and local tags. + =tags-all (tags)= :: Return non-nil if current heading includes all of ~TAGS~. Tests both inherited and local tags.
- Aliases: ~tags&~. - Aliases: ~tags&~.
+ =tags-regexp (&rest regexps)= :: Return non-nil if current heading has tags matching one or more of ~REGEXPS~. Tests both inherited and local tags. + =tags-regexp (&rest regexps)= :: Return non-nil if current heading has tags matching one or more of ~REGEXPS~. Tests both inherited and local tags.
- Aliases: ~tags*~. - Aliases: ~tags*~.
+ =todo (&rest keywords)= :: Return non-nil if current heading is a ~TODO~ item. With ~KEYWORDS~, return non-nil if its keyword is one of ~KEYWORDS~ (a list of strings). When called without arguments, only matches non-done tasks (i.e. does not match keywords in ~org-done-keywords~). + =todo (&optional keywords)= :: Return non-nil if current heading is a ~TODO~ item. With ~KEYWORDS~, return non-nil if its keyword is one of ~KEYWORDS~ (a list of strings). When called without arguments, only matches non-done tasks (i.e. does not match keywords in ~org-done-keywords~).
*** Ancestor/descendant predicates *** Ancestor/descendant predicates
@ -556,39 +556,17 @@ Simple links may also be written manually in either sexp or non-sexp form, like:
** 0.9-pre ** 0.9-pre
*Additions*
+ Face ~org-ql-view-query~, applied to view queries in header line.
+ Face ~org-ql-view-title~, applied to view titles in header line.
+ Option ~org-ql-view-relative-deadline-prefix~.
*Changes* *Changes*
+ Command ~org-ql-find~ respects narrowing of the current buffer by default, allowing searching within the narrowed region. (Using one ~C-u~ argument widens the current buffer, and using two ~C-u~ arguments prompts for the buffers to search.) + Command ~org-ql-find~ respects narrowing of the current buffer by default, allowing searching within the narrowed region. (Using one ~C-u~ argument widens the current buffer, and using two ~C-u~ arguments prompts for the buffers to search.)
+ Function ~org-ql-completing-read~ accepts a new ~NARROWP~ argument, which is passed to ~org-ql-select~. + Function ~org-ql-completing-read~ accepts a new ~NARROWP~ argument, which is passed to ~org-ql-select~.
*Fixes* *Compatibility*
+ Customization group for face ~org-ql-view-due-date~. + Fix compilation error on Emacs 30. ([[https://github.com/alphapapa/org-ql/issues/433][#433]]. Thanks to [[https://github.com/akirak][Akira Komamura]] and [[https://github.com/monnier][Stefan Monnier]].)
+ Apply Org syntax font-locking to items in ~org-ql-view~ buffers.
*** helm-org-ql *** helm-org-ql
Tagged v0.6.2, fixing a compilation warning. Tagged v0.6.2, fixing a compilation warning.
** 0.8.10
*Fixes*
+ Command ~org-ql-refile~ uses the base buffer when refiling to an indirect buffer. ([[https://github.com/alphapapa/org-ql/issues/466][#466]].)
+ Predicate ~link~ could signal an error when searching text that is mistakenly recognized as an Org link (e.g. Bash double-bracket constructs in a source block). (Thanks to [[https://github.com/jwiegley][John Wiegley]] for reporting.)
** 0.8.9
*Fixes*
+ Predicate ~property~ when called with argument form ~(property "PROPERTY-NAME" :inherit t)~. ([[https://github.com/alphapapa/org-ql/issues/460][#460]]. Thanks to [[https://github.com/Stewmath][Stewmath]] for reporting.)
+ Predicate ~level~'s preamble optimizer allows expressions in place of the numeric argument. (See [[https://github.com/alphapapa/org-ql/issues/460][#460]]. Thanks to [[https://github.com/Stewmath][Stewmath]] for reporting.)
+ Reading of view settings from Org links in upcoming Emacs version. ([[https://github.com/alphapapa/org-ql/issues/461][#461]]. Thanks to [[https://github.com/snogge][Ola Nilsson]] for help debugging, and for maintaining [[https://github.com/jorgenschaefer/emacs-buttercup][Buttercup]].)
*Compatibility*
+ Fix compilation error on Emacs 30. ([[https://github.com/alphapapa/org-ql/issues/433][#433]]. Thanks to [[https://github.com/akirak][Akira Komamura]] and [[https://github.com/monnier][Stefan Monnier]].)
** 0.8.8 ** 0.8.8
*Fixes* *Fixes*

View file

@ -122,20 +122,18 @@ which see (but only the files are used)."
((and (pred listp) files) files))) ((and (pred listp) files) files)))
(list files-spec))))))) (list files-spec)))))))
(list (org-ql-completing-read buffers-files :prompt "Refile to: ")))) (list (org-ql-completing-read buffers-files :prompt "Refile to: "))))
(let ((buffer (or (buffer-base-buffer (marker-buffer marker)) (org-refile nil nil
(marker-buffer marker)))) ;; The RFLOC argument:
(org-refile nil nil (list
;; The RFLOC argument: ;; Name
(list (org-with-point-at marker
;; Name (nth 4 (org-heading-components)))
(org-with-point-at marker ;; File
(nth 4 (org-heading-components))) (buffer-file-name (marker-buffer marker))
;; File ;; nil
(buffer-file-name buffer) nil
;; nil ;; Position
nil marker)))
;; Position
marker))))
;;;###autoload ;;;###autoload
(defun org-ql-find-in-agenda () (defun org-ql-find-in-agenda ()

View file

@ -240,7 +240,7 @@ Like other agenda block commands, it searches files returned by
function `org-agenda-files'. Inserts a newline after the block. function `org-agenda-files'. Inserts a newline after the block.
If `org-ql-block-header' is non-nil, it is used as the header If `org-ql-block-header' is non-nil, it is used as the header
string for the block, otherwise the header is formed string for the block, otherwise a the header is formed
automatically from the query." automatically from the query."
(pcase-let ((`(,query . ,(map :header :sort)) args) (pcase-let ((`(,query . ,(map :header :sort)) args)
(narrow-p) (old-beg) (old-end)) (narrow-p) (old-beg) (old-end))

View file

@ -57,18 +57,7 @@
(defface org-ql-view-due-date (defface org-ql-view-due-date
'((t (:slant italic :weight bold))) '((t (:slant italic :weight bold)))
"Face for due dates in `org-ql-view' views." "Face for due dates in `org-ql-view' views."
:group 'org-ql-view) :group 'org-ql)
(defface org-ql-view-query nil
"View query in header line.
This face is added to the formatted query after font-lock faces
are applied to it. It may be used, e.g. to reduce the height so
more of it is visible."
:group 'org-ql-view)
(defface org-ql-view-title '((t :weight bold))
"View title in header line."
:group 'org-ql-view)
;;;; Variables ;;;; Variables
@ -249,12 +238,6 @@ See info node `(elisp)Cyclic Window Ordering'."
(sexp :tag "org-super-agenda grouping expression") (sexp :tag "org-super-agenda grouping expression")
(variable :tag "Variable holding org-super-agenda grouping expression")))))))) (variable :tag "Variable holding org-super-agenda grouping expression"))))))))
(defcustom org-ql-view-relative-deadline-prefix "due "
;; TODO(v0.9): Add one for scheduled, too.
"Prefix for relative deadlines.
Relative deadlines are, e.g. \"in 5d\", \"5d ago\"."
:type 'string)
;;;; Commands ;;;; Commands
;;;###autoload ;;;###autoload
@ -476,8 +459,7 @@ subsequent refreshing of the buffer: `org-ql-view-buffers-files',
If TITLE, prepend it to the header." If TITLE, prepend it to the header."
(let* ((title (if title (let* ((title (if title
(concat (propertize "View:" 'face 'transient-argument) (concat (propertize "View:" 'face 'transient-argument)
(propertize title 'face 'org-ql-view-title) title " ")
" ")
"")) ""))
(query-formatted (when query (query-formatted (when query
(org-ql-view--format-query query))) (org-ql-view--format-query query)))
@ -496,7 +478,6 @@ If TITLE, prepend it to the header."
(org-ql-view--font-lock-string 'emacs-lisp-mode) (org-ql-view--font-lock-string 'emacs-lisp-mode)
(s-truncate available-width)) (s-truncate available-width))
'help-echo buffers-files-formatted)))) 'help-echo buffers-files-formatted))))
(add-face-text-property 0 (length query-propertized) 'org-ql-view-query 'append query-propertized)
(concat title (concat title
(when query (propertize "Query:" 'face 'transient-argument)) (when query (propertize "Query:" 'face 'transient-argument))
(when query query-propertized) (when query query-propertized)
@ -528,22 +509,6 @@ with human-readable strings."
(font-lock-ensure) (font-lock-ensure)
(buffer-string)))) (buffer-string))))
(defun org-ql-view--font-lock-as-org (s)
"Return string S font-locked as in `org-mode'."
;; This works like `org-fontify-like-in-org-mode', but uses a single
;; buffer instead of a new one every time.
;; TODO(C): Submit these improvements upstream.
(let ((buffer (or (get-buffer " *org-ql-view--font-lock-as-org*")
(with-current-buffer (get-buffer-create " *org-ql-view--font-lock-as-org*")
(buffer-disable-undo)
(org-mode)
(current-buffer)))))
(with-current-buffer buffer
(insert s)
(font-lock-ensure)
(prog1 (buffer-string)
(erase-buffer)))))
(defun org-ql-view--buffer (&optional name) (defun org-ql-view--buffer (&optional name)
"Return `org-ql-view' buffer, creating it if necessary. "Return `org-ql-view' buffer, creating it if necessary.
If NAME is non-nil, return buffer by that name instead of using If NAME is non-nil, return buffer by that name instead of using
@ -661,7 +626,7 @@ purposes of compatibility with changes in Org 9.4."
(query (url-unhex-string query)) (query (url-unhex-string query))
(params (when params (url-parse-query-string params))) (params (when params (url-parse-query-string params)))
;; `url-parse-query-string' returns "improper" alists, which makes this awkward. ;; `url-parse-query-string' returns "improper" alists, which makes this awkward.
(sort (when-let* ((stored-string (car (alist-get "sort" params nil nil #'string=))) (sort (when-let* ((stored-string (alist-get "sort" params nil nil #'string=))
(read-value (read stored-string))) (read-value (read stored-string)))
;; Ensure the value is either a symbol or list of symbols (which excludes lambdas). ;; Ensure the value is either a symbol or list of symbols (which excludes lambdas).
(unless (or (symbolp read-value) (cl-every #'symbolp read-value)) (unless (or (symbolp read-value) (cl-every #'symbolp read-value))
@ -669,19 +634,17 @@ purposes of compatibility with changes in Org 9.4."
read-value)) read-value))
read-value)) read-value))
(org-super-agenda-allow-unsafe-groups nil) ; Disallow unsafe group selectors. (org-super-agenda-allow-unsafe-groups nil) ; Disallow unsafe group selectors.
(groups (--when-let (car (alist-get "super-groups" params nil nil #'string=)) (groups (--when-let (alist-get "super-groups" params nil nil #'string=)
(read it))) (read it)))
(title (--when-let (car (alist-get "title" params nil nil #'string=)) (title (--when-let (alist-get "title" params nil nil #'string=)
(read it))) (read it)))
(buffers-files (--if-let (car (alist-get "buffers-files" params nil nil #'string=)) (buffers-files (--if-let (alist-get "buffers-files" params nil nil #'string=)
(org-ql-view--expand-buffers-files (read it)) (org-ql-view--expand-buffers-files (read it))
(current-buffer)))) (current-buffer))))
(unless (or (bufferp buffers-files) (unless (or (bufferp buffers-files)
(stringp buffers-files) (stringp buffers-files)
(cl-every #'stringp buffers-files)) (cl-every #'stringp buffers-files))
(error "CAUTION: Link not opened because unsafe buffers-files parameter detected: %s" buffers-files)) (error "CAUTION: Link not opened because unsafe buffers-files parameter detected: %s" buffers-files))
(unless (or (stringp title) (null title))
(error "CAUTION: Link not opened because unsafe title parameter detected: %S" title))
(when (or (listp query) (when (or (listp query)
(string-match (rx bol (0+ space) "(") query)) (string-match (rx bol (0+ space) "(") query))
;; SAFETY: Query is in sexp form: ask for confirmation, because it could contain arbitrary code. ;; SAFETY: Query is in sexp form: ask for confirmation, because it could contain arbitrary code.
@ -914,11 +877,6 @@ return an empty string."
;; (which would also make it easier to do it independently of faces, etc). ;; (which would also make it easier to do it independently of faces, etc).
(title (--> (org-ql-view--add-faces element) (title (--> (org-ql-view--add-faces element)
(org-element-property :raw-value it))) (org-element-property :raw-value it)))
;; TODO(B): Needs refactoring. A function like `org-ql-view--add-faces'
;; should return a list of faces to be added.
(title-faces (get-text-property 0 'face title))
(title (org-ql-view--font-lock-as-org title))
(_ (add-face-text-property 0 (length title) title-faces t title))
(todo-keyword (-some--> (org-element-property :todo-keyword element) (todo-keyword (-some--> (org-element-property :todo-keyword element)
(org-ql-view--add-todo-face (org-ql-view--add-todo-face
(substring-no-properties it)))) (substring-no-properties it))))
@ -1056,9 +1014,7 @@ property."
(deadline-day-number (org-time-string-to-absolute (deadline-day-number (org-time-string-to-absolute
(org-element-timestamp-interpreter deadline-date 'ignore))) (org-element-timestamp-interpreter deadline-date 'ignore)))
(difference-days (- today-day-number deadline-day-number)) (difference-days (- today-day-number deadline-day-number))
(relative-due-date (org-add-props (relative-due-date (org-add-props (org-ql-view--format-relative-date difference-days) nil
(concat org-ql-view-relative-deadline-prefix
(org-ql-view--format-relative-date difference-days)) nil
'help-echo (org-element-property :raw-value deadline-date))) 'help-echo (org-element-property :raw-value deadline-date)))
;; FIXME: Unused for now: (todo-keyword (org-element-property :todo-keyword element)) ;; FIXME: Unused for now: (todo-keyword (org-element-property :todo-keyword element))
;; FIXME: Unused for now: (done-p (member todo-keyword org-done-keywords)) ;; FIXME: Unused for now: (done-p (member todo-keyword org-done-keywords))

View file

@ -1537,8 +1537,7 @@ COMPARATOR may be `<', `<=', `>', or `>='."
;; is "h:" while the user is typing. ;; is "h:" while the user is typing.
(list :regexp (rx bol (1+ "*") " ") (list :regexp (rx bol (1+ "*") " ")
:case-fold t)) :case-fold t))
((and `(,predicate-names ,comparator-or-num ,num) (`(,predicate-names ,comparator-or-num ,num)
(guard (numberp num)))
(let ((repeat (pcase comparator-or-num (let ((repeat (pcase comparator-or-num
('< `(repeat 1 ,(1- num) "*")) ('< `(repeat 1 ,(1- num) "*"))
('<= `(repeat 1 ,num "*")) ('<= `(repeat 1 ,num "*"))
@ -1547,8 +1546,7 @@ COMPARATOR may be `<', `<=', `>', or `>='."
((pred integerp) `(repeat ,comparator-or-num ,num "*"))))) ((pred integerp) `(repeat ,comparator-or-num ,num "*")))))
(list :regexp (rx-to-string `(seq bol ,repeat " ") t) (list :regexp (rx-to-string `(seq bol ,repeat " ") t)
:case-fold t))) :case-fold t)))
((and `(,predicate-names ,num) (`(,predicate-names ,num)
(guard (numberp num)))
(list :regexp (rx-to-string `(seq bol (repeat ,num "*") " ") t) (list :regexp (rx-to-string `(seq bol (repeat ,num "*") " ") t)
:case-fold t))) :case-fold t)))
;; NOTE: It might be necessary to take into account `org-odd-levels'; see docstring for ;; NOTE: It might be necessary to take into account `org-odd-levels'; see docstring for
@ -1626,15 +1624,11 @@ any link is found."
(or (null description) (or (null description)
(string-match-p description (match-string org-ql-link-description-group))))) (string-match-p description (match-string org-ql-link-description-group)))))
(_ (if (and description target) (_ (if (and description target)
(and (and (match-string 1) (and (string-match-p target (match-string 1))
(string-match-p target (match-string 1))) (string-match-p description (match-string org-ql-link-description-group)))
(and (match-string org-ql-link-description-group) (or (string-match-p description-or-target (match-string 1))
(string-match-p description (match-string org-ql-link-description-group)))) (string-match-p description-or-target
(or (and (match-string 1) (match-string org-ql-link-description-group)))))))))
(string-match-p description-or-target (match-string 1)))
(and (match-string org-ql-link-description-group)
(string-match-p description-or-target
(match-string org-ql-link-description-group))))))))))
(org-ql-defpred (rifle smart) (&rest strings) (org-ql-defpred (rifle smart) (&rest strings)
"Return non-nil if each of strings is found in the entry or its outline path. "Return non-nil if each of strings is found in the entry or its outline path.
@ -1808,62 +1802,34 @@ interpreted as nil or non-nil)."
;; predicate test for whether an entry has local ;; predicate test for whether an entry has local
;; properties when no arguments are given. ;; properties when no arguments are given.
(list 'property "")) (list 'property ""))
(`(,predicate-names ,property) (`(,predicate-names ,property ,value . ,plist)
;; Convert keyword property arguments to strings. Non-sexp ;; Convert keyword property arguments to strings. Non-sexp
;; queries result in keyword property arguments (because to do ;; queries result in keyword property arguments (because to do
;; otherwise would require ugly special-casing in the parsing). ;; otherwise would require ugly special-casing in the parsing).
(when (keywordp property) (when (keywordp property)
(setf property (substring (symbol-name property) 1))) (setf property (substring (symbol-name property) 1)))
(list 'property property)) (list 'property property value
(`(,predicate-names ,property . ,rest) :inherit (cond ((plist-member plist :inherit) (plist-get plist :inherit))
(pcase rest ((listp org-use-property-inheritance) ''selective)
(`(,value) (t org-use-property-inheritance)))))
;; Convert keyword property arguments to strings. Non-sexp
;; queries result in keyword property arguments (because to do
;; otherwise would require ugly special-casing in the parsing).
(when (keywordp property)
(setf property (substring (symbol-name property) 1)))
(list 'property property value))
((and `(,value . ,plist)
(guard (not (keywordp value))))
;; Convert keyword property arguments to strings. Non-sexp
;; queries result in keyword property arguments (because to do
;; otherwise would require ugly special-casing in the parsing).
(when (keywordp property)
(setf property (substring (symbol-name property) 1)))
(list 'property property value
:inherit (cond ((plist-member plist :inherit) (plist-get plist :inherit))
((listp org-use-property-inheritance) ''selective)
(t org-use-property-inheritance))))
((and plist (guard (keywordp (car rest))))
;; Convert keyword property arguments to strings. Non-sexp
;; queries result in keyword property arguments (because to do
;; otherwise would require ugly special-casing in the parsing).
(when (keywordp property)
(setf property (substring (symbol-name property) 1)))
(list 'property property nil
:inherit (cond ((plist-member plist :inherit) (plist-get plist :inherit))
((listp org-use-property-inheritance) ''selective)
(t org-use-property-inheritance)))))))
;; MAYBE: Should case folding be disabled for properties? What about values? ;; MAYBE: Should case folding be disabled for properties? What about values?
;; MAYBE: Support (property) without args. ;; MAYBE: Support (property) without args.
;; NOTE: When inheritance is enabled, the preamble can't be used, ;; NOTE: When inheritance is enabled, the preamble can't be used,
;; which will make the search slower. ;; which will make the search slower.
:preambles (((and `(,predicate-names ,property ,value) :preambles ((`(,predicate-names ,property ,value . ,(map :inherit))
(guard (atom value)))
;; We do NOT return nil, because the predicate still needs to be tested, ;; We do NOT return nil, because the predicate still needs to be tested,
;; because the regexp could match a string not inside a property drawer. ;; because the regexp could match a string not inside a property drawer.
(list :regexp (rx-to-string `(seq bol (0+ space) ":" ,property ":" (list :regexp (unless inherit
(1+ space) ,value (0+ space) eol)) (rx-to-string `(seq bol (0+ space) ":" ,property ":"
(1+ space) ,value (0+ space) eol)))
:query query)) :query query))
((and `(,predicate-names ,property ,value . ,plist) (`(,predicate-names ,property . ,(map :inherit))
(guard (keywordp (car plist)))) ;; We do NOT return nil, because the predicate still needs to be tested,
;; WE do NOT return nil, because the predicate still needs to be tested,
;; because the regexp could match a string not inside a property drawer. ;; because the regexp could match a string not inside a property drawer.
;; NOTE: The preamble only matches if there appears to be a value. ;; NOTE: The preamble only matches if there appears to be a value.
;; A line like ":ID: " without any other text does not match. ;; A line like ":ID: " without any other text does not match.
(list :regexp (unless (plist-get plist :inherit) (list :regexp (unless inherit
(rx-to-string `(seq bol (0+ space) ":" ,property ":" (1+ space) (rx-to-string `(seq bol (0+ space) ":" ,property ":" (1+ space)
(minimal-match (1+ not-newline)) eol))) (minimal-match (1+ not-newline)) eol)))
:query query))) :query query)))
@ -1875,7 +1841,7 @@ interpreted as nil or non-nil)."
;; Check that PROPERTY exists ;; Check that PROPERTY exists
(org-ql--value-at (org-ql--value-at
(point) (lambda () (point) (lambda ()
(org-entry-get (point) property inherit)))) (org-entry-get (point) property))))
(_ (_
;; Check that PROPERTY has VALUE. ;; Check that PROPERTY has VALUE.

View file

@ -74,8 +74,6 @@ Functions / Macros
Changelog Changelog
* 0.9-pre: 09-pre. * 0.9-pre: 09-pre.
* 0.8.10: 0810.
* 0.8.9: 089.
* 0.8.8: 088. * 0.8.8: 088.
* 0.8.7: 087. * 0.8.7: 087.
* 0.8.6: 086. * 0.8.6: 086.
@ -1049,8 +1047,6 @@ releases.
* Menu: * Menu:
* 0.9-pre: 09-pre. * 0.9-pre: 09-pre.
* 0.8.10: 0810.
* 0.8.9: 089.
* 0.8.8: 088. * 0.8.8: 088.
* 0.8.7: 087. * 0.8.7: 087.
* 0.8.6: 086. * 0.8.6: 086.
@ -1092,17 +1088,12 @@ releases.
* 0.1: 01. * 0.1: 01.
 
File: README.info, Node: 09-pre, Next: 0810, Up: Changelog File: README.info, Node: 09-pre, Next: 088, Up: Changelog
5.1 0.9-pre 5.1 0.9-pre
=========== ===========
*Additions* *Changes*
• Face org-ql-view-query, applied to view queries in header line.
• Face org-ql-view-title, applied to view titles in header line.
• Option org-ql-view-relative-deadline-prefix.
*Changes*
• Command org-ql-find respects narrowing of the current buffer by • Command org-ql-find respects narrowing of the current buffer by
default, allowing searching within the narrowed region. (Using one default, allowing searching within the narrowed region. (Using one
C-u argument widens the current buffer, and using two C-u C-u argument widens the current buffer, and using two C-u
@ -1110,9 +1101,11 @@ File: README.info, Node: 09-pre, Next: 0810, Up: Changelog
• Function org-ql-completing-read accepts a new NARROWP argument, • Function org-ql-completing-read accepts a new NARROWP argument,
which is passed to org-ql-select. which is passed to org-ql-select.
*Fixes* *Compatibility*
• Customization group for face org-ql-view-due-date. • Fix compilation error on Emacs 30. (#433
• Apply Org syntax font-locking to items in org-ql-view buffers. (https://github.com/alphapapa/org-ql/issues/433). Thanks to Akira
Komamura (https://github.com/akirak) and Stefan Monnier
(https://github.com/monnier).)
* Menu: * Menu:
@ -1127,51 +1120,9 @@ File: README.info, Node: helm-org-ql (1), Up: 09-pre
Tagged v0.6.2, fixing a compilation warning. Tagged v0.6.2, fixing a compilation warning.
 
File: README.info, Node: 0810, Next: 089, Prev: 09-pre, Up: Changelog File: README.info, Node: 088, Next: 087, Prev: 09-pre, Up: Changelog
5.2 0.8.10 5.2 0.8.8
==========
*Fixes*
• Command org-ql-refile uses the base buffer when refiling to an
indirect buffer. (#466
(https://github.com/alphapapa/org-ql/issues/466).)
• Predicate link could signal an error when searching text that is
mistakenly recognized as an Org link (e.g. Bash double-bracket
constructs in a source block). (Thanks to John Wiegley
(https://github.com/jwiegley) for reporting.)

File: README.info, Node: 089, Next: 088, Prev: 0810, Up: Changelog
5.3 0.8.9
=========
*Fixes*
• Predicate property when called with argument form (property
"PROPERTY-NAME" :inherit t). (#460
(https://github.com/alphapapa/org-ql/issues/460). Thanks to
Stewmath (https://github.com/Stewmath) for reporting.)
• Predicate levels preamble optimizer allows expressions in place
of the numeric argument. (See #460
(https://github.com/alphapapa/org-ql/issues/460). Thanks to
Stewmath (https://github.com/Stewmath) for reporting.)
• Reading of view settings from Org links in upcoming Emacs version.
(#461 (https://github.com/alphapapa/org-ql/issues/461). Thanks to
Ola Nilsson (https://github.com/snogge) for help debugging, and for
maintaining Buttercup
(https://github.com/jorgenschaefer/emacs-buttercup).)
*Compatibility*
• Fix compilation error on Emacs 30. (#433
(https://github.com/alphapapa/org-ql/issues/433). Thanks to Akira
Komamura (https://github.com/akirak) and Stefan Monnier
(https://github.com/monnier).)

File: README.info, Node: 088, Next: 087, Prev: 089, Up: Changelog
5.4 0.8.8
========= =========
*Fixes* *Fixes*
@ -1193,7 +1144,7 @@ File: README.info, Node: 088, Next: 087, Prev: 089, Up: Changelog
 
File: README.info, Node: 087, Next: 086, Prev: 088, Up: Changelog File: README.info, Node: 087, Next: 086, Prev: 088, Up: Changelog
5.5 0.8.7 5.3 0.8.7
========= =========
*Fixes* *Fixes*
@ -1221,7 +1172,7 @@ File: README.info, Node: 087, Next: 086, Prev: 088, Up: Changelog
 
File: README.info, Node: 086, Next: 085, Prev: 087, Up: Changelog File: README.info, Node: 086, Next: 085, Prev: 087, Up: Changelog
5.6 0.8.6 5.4 0.8.6
========= =========
*Fixes* *Fixes*
@ -1231,7 +1182,7 @@ File: README.info, Node: 086, Next: 085, Prev: 087, Up: Changelog
 
File: README.info, Node: 085, Next: 084, Prev: 086, Up: Changelog File: README.info, Node: 085, Next: 084, Prev: 086, Up: Changelog
5.7 0.8.5 5.5 0.8.5
========= =========
*Fixes* *Fixes*
@ -1248,7 +1199,7 @@ File: README.info, Node: 085, Next: 084, Prev: 086, Up: Changelog
 
File: README.info, Node: 084, Next: 083, Prev: 085, Up: Changelog File: README.info, Node: 084, Next: 083, Prev: 085, Up: Changelog
5.8 0.8.4 5.6 0.8.4
========= =========
*Fixes* *Fixes*
@ -1262,7 +1213,7 @@ File: README.info, Node: 084, Next: 083, Prev: 085, Up: Changelog
 
File: README.info, Node: 083, Next: 082, Prev: 084, Up: Changelog File: README.info, Node: 083, Next: 082, Prev: 084, Up: Changelog
5.9 0.8.3 5.7 0.8.3
========= =========
*Fixes* *Fixes*
@ -1275,8 +1226,8 @@ File: README.info, Node: 083, Next: 082, Prev: 084, Up: Changelog
 
File: README.info, Node: 082, Next: 081, Prev: 083, Up: Changelog File: README.info, Node: 082, Next: 081, Prev: 083, Up: Changelog
5.10 0.8.2 5.8 0.8.2
========== =========
*Fixes* *Fixes*
@ -1289,8 +1240,8 @@ File: README.info, Node: 082, Next: 081, Prev: 083, Up: Changelog
 
File: README.info, Node: 081, Next: 08, Prev: 082, Up: Changelog File: README.info, Node: 081, Next: 08, Prev: 082, Up: Changelog
5.11 0.8.1 5.9 0.8.1
========== =========
*Fixes* *Fixes*
@ -1304,7 +1255,7 @@ File: README.info, Node: 081, Next: 08, Prev: 082, Up: Changelog
 
File: README.info, Node: 08, Next: 074, Prev: 081, Up: Changelog File: README.info, Node: 08, Next: 074, Prev: 081, Up: Changelog
5.12 0.8 5.10 0.8
======== ========
*Additions* *Additions*
@ -1360,7 +1311,7 @@ File: README.info, Node: 08, Next: 074, Prev: 081, Up: Changelog
 
File: README.info, Node: 074, Next: 073, Prev: 08, Up: Changelog File: README.info, Node: 074, Next: 073, Prev: 08, Up: Changelog
5.13 0.7.4 5.11 0.7.4
========== ==========
*Fixes* *Fixes*
@ -1370,7 +1321,7 @@ File: README.info, Node: 074, Next: 073, Prev: 08, Up: Changelog
 
File: README.info, Node: 073, Next: 072, Prev: 074, Up: Changelog File: README.info, Node: 073, Next: 072, Prev: 074, Up: Changelog
5.14 0.7.3 5.12 0.7.3
========== ==========
*Fixes* *Fixes*
@ -1388,7 +1339,7 @@ File: README.info, Node: 073, Next: 072, Prev: 074, Up: Changelog
 
File: README.info, Node: 072, Next: 071, Prev: 073, Up: Changelog File: README.info, Node: 072, Next: 071, Prev: 073, Up: Changelog
5.15 0.7.2 5.13 0.7.2
========== ==========
*Fixes* *Fixes*
@ -1409,7 +1360,7 @@ File: README.info, Node: 072, Next: 071, Prev: 073, Up: Changelog
 
File: README.info, Node: 071, Next: 07, Prev: 072, Up: Changelog File: README.info, Node: 071, Next: 07, Prev: 072, Up: Changelog
5.16 0.7.1 5.14 0.7.1
========== ==========
*Fixes* *Fixes*
@ -1428,7 +1379,7 @@ File: README.info, Node: 071, Next: 07, Prev: 072, Up: Changelog
 
File: README.info, Node: 07, Next: 063, Prev: 071, Up: Changelog File: README.info, Node: 07, Next: 063, Prev: 071, Up: Changelog
5.17 0.7 5.15 0.7
======== ========
*Added* *Added*
@ -1487,7 +1438,7 @@ File: README.info, Node: 07, Next: 063, Prev: 071, Up: Changelog
 
File: README.info, Node: 063, Next: 062, Prev: 07, Up: Changelog File: README.info, Node: 063, Next: 062, Prev: 07, Up: Changelog
5.18 0.6.3 5.16 0.6.3
========== ==========
*Fixed* *Fixed*
@ -1503,7 +1454,7 @@ File: README.info, Node: 063, Next: 062, Prev: 07, Up: Changelog
 
File: README.info, Node: 062, Next: 061, Prev: 063, Up: Changelog File: README.info, Node: 062, Next: 061, Prev: 063, Up: Changelog
5.19 0.6.2 5.17 0.6.2
========== ==========
*Fixed* *Fixed*
@ -1514,7 +1465,7 @@ File: README.info, Node: 062, Next: 061, Prev: 063, Up: Changelog
 
File: README.info, Node: 061, Next: 06, Prev: 062, Up: Changelog File: README.info, Node: 061, Next: 06, Prev: 062, Up: Changelog
5.20 0.6.1 5.18 0.6.1
========== ==========
*Fixed* *Fixed*
@ -1532,7 +1483,7 @@ File: README.info, Node: 061, Next: 06, Prev: 062, Up: Changelog
 
File: README.info, Node: 06, Next: 052, Prev: 061, Up: Changelog File: README.info, Node: 06, Next: 052, Prev: 061, Up: Changelog
5.21 0.6 5.19 0.6
======== ========
*Added* *Added*
@ -1599,7 +1550,7 @@ File: README.info, Node: 06, Next: 052, Prev: 061, Up: Changelog
 
File: README.info, Node: 052, Next: 051, Prev: 06, Up: Changelog File: README.info, Node: 052, Next: 051, Prev: 06, Up: Changelog
5.22 0.5.2 5.20 0.5.2
========== ==========
*Fixed* *Fixed*
@ -1610,7 +1561,7 @@ File: README.info, Node: 052, Next: 051, Prev: 06, Up: Changelog
 
File: README.info, Node: 051, Next: 05, Prev: 052, Up: Changelog File: README.info, Node: 051, Next: 05, Prev: 052, Up: Changelog
5.23 0.5.1 5.21 0.5.1
========== ==========
*Fixed* *Fixed*
@ -1623,7 +1574,7 @@ File: README.info, Node: 051, Next: 05, Prev: 052, Up: Changelog
 
File: README.info, Node: 05, Next: 049, Prev: 051, Up: Changelog File: README.info, Node: 05, Next: 049, Prev: 051, Up: Changelog
5.24 0.5 5.22 0.5
======== ========
*Added* *Added*
@ -1664,7 +1615,7 @@ File: README.info, Node: 05, Next: 049, Prev: 051, Up: Changelog
 
File: README.info, Node: 049, Next: 048, Prev: 05, Up: Changelog File: README.info, Node: 049, Next: 048, Prev: 05, Up: Changelog
5.25 0.4.9 5.23 0.4.9
========== ==========
*Fixed* *Fixed*
@ -1675,7 +1626,7 @@ File: README.info, Node: 049, Next: 048, Prev: 05, Up: Changelog
 
File: README.info, Node: 048, Next: 047, Prev: 049, Up: Changelog File: README.info, Node: 048, Next: 047, Prev: 049, Up: Changelog
5.26 0.4.8 5.24 0.4.8
========== ==========
*Fixed* *Fixed*
@ -1687,7 +1638,7 @@ File: README.info, Node: 048, Next: 047, Prev: 049, Up: Changelog
 
File: README.info, Node: 047, Next: 046, Prev: 048, Up: Changelog File: README.info, Node: 047, Next: 046, Prev: 048, Up: Changelog
5.27 0.4.7 5.25 0.4.7
========== ==========
*Fixed* *Fixed*
@ -1700,7 +1651,7 @@ File: README.info, Node: 047, Next: 046, Prev: 048, Up: Changelog
 
File: README.info, Node: 046, Next: 045, Prev: 047, Up: Changelog File: README.info, Node: 046, Next: 045, Prev: 047, Up: Changelog
5.28 0.4.6 5.26 0.4.6
========== ==========
*Fixed* *Fixed*
@ -1713,7 +1664,7 @@ File: README.info, Node: 046, Next: 045, Prev: 047, Up: Changelog
 
File: README.info, Node: 045, Next: 044, Prev: 046, Up: Changelog File: README.info, Node: 045, Next: 044, Prev: 046, Up: Changelog
5.29 0.4.5 5.27 0.4.5
========== ==========
*Fixed* *Fixed*
@ -1725,7 +1676,7 @@ File: README.info, Node: 045, Next: 044, Prev: 046, Up: Changelog
 
File: README.info, Node: 044, Next: 043, Prev: 045, Up: Changelog File: README.info, Node: 044, Next: 043, Prev: 045, Up: Changelog
5.30 0.4.4 5.28 0.4.4
========== ==========
*Fixed* *Fixed*
@ -1737,7 +1688,7 @@ File: README.info, Node: 044, Next: 043, Prev: 045, Up: Changelog
 
File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog
5.31 0.4.3 5.29 0.4.3
========== ==========
*Fixed* *Fixed*
@ -1747,7 +1698,7 @@ File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog
 
File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog
5.32 0.4.2 5.30 0.4.2
========== ==========
*Fixed* *Fixed*
@ -1756,7 +1707,7 @@ File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog
 
File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog
5.33 0.4.1 5.31 0.4.1
========== ==========
*Fixed* *Fixed*
@ -1766,7 +1717,7 @@ File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog
 
File: README.info, Node: 04, Next: 032, Prev: 041, Up: Changelog File: README.info, Node: 04, Next: 032, Prev: 041, Up: Changelog
5.34 0.4 5.32 0.4
======== ========
_Note:_ The next release, 0.5, may include changes which will require _Note:_ The next release, 0.5, may include changes which will require
@ -1847,7 +1798,7 @@ automatically, as they will be pushed to the master branch when ready.
 
File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog
5.35 0.3.2 5.33 0.3.2
========== ==========
*Fixed* *Fixed*
@ -1860,7 +1811,7 @@ File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog
 
File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog
5.36 0.3.1 5.34 0.3.1
========== ==========
*Fixed* *Fixed*
@ -1870,7 +1821,7 @@ File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog
 
File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog
5.37 0.3 5.35 0.3
======== ========
*Added* *Added*
@ -1938,7 +1889,7 @@ File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog
 
File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog
5.38 0.2.3 5.36 0.2.3
========== ==========
*Fixed* *Fixed*
@ -1948,7 +1899,7 @@ File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog
 
File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog
5.39 0.2.2 5.37 0.2.2
========== ==========
*Fixed* *Fixed*
@ -1959,7 +1910,7 @@ File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog
 
File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog
5.40 0.2.1 5.38 0.2.1
========== ==========
*Fixed* *Fixed*
@ -1969,7 +1920,7 @@ File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog
 
File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog
5.41 0.2 5.39 0.2
======== ========
*Added* *Added*
@ -2052,7 +2003,7 @@ File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog
 
File: README.info, Node: 01, Prev: 02, Up: Changelog File: README.info, Node: 01, Prev: 02, Up: Changelog
5.42 0.1 5.40 0.1
======== ========
First tagged release. First tagged release.
@ -2137,90 +2088,88 @@ GPLv3
 
Tag Table: Tag Table:
Node: Top225 Node: Top225
Node: Contents2109 Node: Contents2079
Node: Screenshots2236 Node: Screenshots2206
Node: Installation2354 Node: Installation2324
Node: Quelpa2868 Node: Quelpa2838
Node: Helm support3396 Node: Helm support3366
Node: Usage3799 Node: Usage3769
Node: Commands4197 Node: Commands4167
Node: org-ql-find4662 Node: org-ql-find4632
Node: org-ql-open-link5570 Node: org-ql-open-link5540
Node: org-ql-refile6425 Node: org-ql-refile6395
Node: org-ql-search6753 Node: org-ql-search6723
Node: helm-org-ql8684 Node: helm-org-ql8654
Node: org-ql-view9062 Node: org-ql-view9032
Node: org-ql-view-sidebar9592 Node: org-ql-view-sidebar9562
Node: org-ql-view-recent-items9972 Node: org-ql-view-recent-items9942
Node: org-ql-sparse-tree10468 Node: org-ql-sparse-tree10438
Node: Queries11268 Node: Queries11238
Node: Non-sexp query syntax12385 Node: Non-sexp query syntax12355
Node: General predicates14144 Node: General predicates14114
Node: Ancestor/descendant predicates21069 Node: Ancestor/descendant predicates21039
Node: Date/time predicates22197 Node: Date/time predicates22167
Node: Functions / Macros25321 Node: Functions / Macros25291
Node: Agenda-like views25619 Node: Agenda-like views25589
Ref: Function org-ql-block25781 Ref: Function org-ql-block25751
Node: Listing / acting-on results27042 Node: Listing / acting-on results27012
Ref: Caching27250 Ref: Caching27220
Ref: Function org-ql-select28163 Ref: Function org-ql-select28133
Ref: Function org-ql-query30589 Ref: Function org-ql-query30559
Ref: Macro org-ql (deprecated)32363 Ref: Macro org-ql (deprecated)32333
Node: Custom predicates32678 Node: Custom predicates32648
Ref: Macro org-ql-defpred32902 Ref: Macro org-ql-defpred32872
Node: Dynamic block36343 Node: Dynamic block36313
Node: Links39067 Node: Links39037
Node: Tips39754 Node: Tips39724
Node: Changelog40078 Node: Changelog40048
Node: 09-pre41061 Node: 09-pre41001
Node: helm-org-ql (1)41987 Node: helm-org-ql (1)41785
Node: 081042128 Node: 08841926
Node: 08942657 Node: 08743005
Node: 08843797 Node: 08644233
Node: 08744873 Node: 08544467
Node: 08646101 Node: 08445123
Node: 08546335 Node: 08345575
Node: 08446991 Node: 08245916
Node: 08347443 Node: 08146309
Node: 08247784 Node: 0846730
Node: 08148179 Node: 07449456
Node: 0848602 Node: 07349681
Node: 07451328 Node: 07250415
Node: 07351553 Node: 07151336
Node: 07252287 Node: 0752147
Node: 07153208 Node: 06355013
Node: 0754019 Node: 06255546
Node: 06356885 Node: 06155853
Node: 06257418 Node: 0656423
Node: 06157725 Node: 05259479
Node: 0658295 Node: 05159781
Node: 05261351 Node: 0560206
Node: 05161653 Node: 04961737
Node: 0562078 Node: 04862019
Node: 04963609 Node: 04762368
Node: 04863891 Node: 04662777
Node: 04764240 Node: 04563185
Node: 04664649 Node: 04463546
Node: 04565057 Node: 04363905
Node: 04465418 Node: 04264108
Node: 04365777 Node: 04164269
Node: 04265980 Node: 0464516
Node: 04166141 Node: 03268617
Node: 0466388 Node: 03169020
Node: 03270489 Node: 0369217
Node: 03170892 Node: 02372517
Node: 0371089 Node: 02272751
Node: 02374389 Node: 02173031
Node: 02274623 Node: 0273236
Node: 02174903 Node: 0177314
Node: 0275108 Node: Development77415
Node: 0179186 Node: Copyright assignment77648
Node: Development79287 Node: Notes78238
Node: Copyright assignment79520 Node: Comparison with Org Agenda searches78402
Node: Notes80110 Node: org-sidebar79291
Node: Comparison with Org Agenda searches80274 Node: License79570
Node: org-sidebar81163
Node: License81442
 
End Tag Table End Tag Table

View file

@ -638,11 +638,6 @@ with keyword arg NOW in PLIST."
:to-equal (list :query t :to-equal (list :query t
:preamble (rx bol (repeat 2 4 "*") " ") :preamble (rx bol (repeat 2 4 "*") " ")
:preamble-case-fold t))) :preamble-case-fold t)))
(it "with an expression in level number's place"
(expect (org-ql--query-preamble '(level <= (string-to-number (property "PROPERTY"))))
:to-equal (list :query '(level <= (string-to-number (property "PROPERTY")))
:preamble nil
:preamble-case-fold t)))
(it "<" (it "<"
(expect (org-ql--query-preamble '(level < 3)) (expect (org-ql--query-preamble '(level < 3))
:to-equal (list :query t :to-equal (list :query t
@ -1344,15 +1339,7 @@ with keyword arg NOW in PLIST."
(org-ql-it "with a property and a value" (org-ql-it "with a property and a value"
(org-ql-expect ('(property "agenda-group" "plans")) (org-ql-expect ('(property "agenda-group" "plans"))
'("Take over the universe" "Write a symphony"))) '("Take over the universe" "Write a symphony"))))
(org-ql-it "with a property and \"nil :inherit t\""
(org-ql-expect ('(property "agenda-group" nil :inherit t))
'("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Spaceship lease" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Write a symphony")))
(org-ql-it "with a property and \":inherit t\""
(org-ql-expect ('(property "agenda-group" :inherit t))
'("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Spaceship lease" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Write a symphony"))))
(describe "(regexp)" (describe "(regexp)"
@ -1986,13 +1973,13 @@ with keyword arg NOW in PLIST."
(expression-link "[[org-ql-search:todo:?title%3D%28error%20%22UNSAFE%22%29]]")) (expression-link "[[org-ql-search:todo:?title%3D%28error%20%22UNSAFE%22%29]]"))
(it "Errors for a quoted lambda" (it "Errors for a quoted lambda"
(expect (open-link quoted-lambda-link) (expect (open-link quoted-lambda-link)
:to-throw 'error '("CAUTION: Link not opened because unsafe title parameter detected: (lambda (_ _) (error \"UNSAFE\"))"))) :to-throw 'wrong-type-argument '(characterp lambda)))
(it "Errors for an unquoted lambda" (it "Errors for an unquoted lambda"
(expect (open-link unquoted-lambda-link) (expect (open-link unquoted-lambda-link)
:to-throw 'error '("CAUTION: Link not opened because unsafe title parameter detected: (lambda (_ _) (error \"UNSAFE\"))"))) :to-throw 'wrong-type-argument '(characterp lambda)))
(it "Errors for an expression" (it "Errors for an expression"
(expect (open-link expression-link) (expect (open-link expression-link)
:to-throw 'error '("CAUTION: Link not opened because unsafe title parameter detected: (error \"UNSAFE\")")))) :to-throw 'wrong-type-argument '(characterp error))))
(describe "sort parameter" (describe "sort parameter"
:var ((quoted-lambda-link "[[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28error%20%22UNSAFE%22%29%29]]") :var ((quoted-lambda-link "[[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28error%20%22UNSAFE%22%29%29]]")
@ -2018,7 +2005,7 @@ with keyword arg NOW in PLIST."
(describe "View saving/loading" (describe "View saving/loading"
:var* ((temp-dir (make-temp-file "test-org-ql-" 'dir)) :var* ((temp-dir (make-temp-file "test-org-ql-" 'dir))
(temp-filenames (cl-loop for file in '("test1.org" "test2.org") (temp-filenames (cl-loop for file in '("test1.org" "test2.org")
collect (abbreviate-file-name (expand-file-name file temp-dir)))) collect (expand-file-name file temp-dir)))
(file-contents (with-temp-buffer (file-contents (with-temp-buffer
(insert "#+TITLE: Test data\n\n" (insert "#+TITLE: Test data\n\n"
"* TODO Heading 1\n" "* TODO Heading 1\n"
@ -2124,21 +2111,31 @@ with keyword arg NOW in PLIST."
(describe "Buffers/Files" (describe "Buffers/Files"
:var ((query '(and (todo "TODO") (regexp "heading"))) :var ((query '(and (todo "TODO") (regexp "heading")))
(one-filename (car temp-filenames))) (one-filename (car temp-filenames)))
(it "One filename matches" ;; NOTE: Inexplicably, on GitHub CI, the filenames are being
(expect (var-after-bookmark-set-and-jump 'org-ql-view-buffers-files one-filename query) ;; abbreviated (i.e. "/home/FOO" is replaced with "~/FOO");
:to-equal one-filename)) ;; I can only guess it's something to do with the way the
(it "A list of filenames matches" ;; Emacs instance is built in the Nix images we use there.
(expect (var-after-bookmark-set-and-jump 'org-ql-view-buffers-files temp-filenames query) ;; So we have to compare the filenames in abbreviated form.
:to-equal temp-filenames)) (cl-labels ((filenames-equal-p (a b)
;; NOTE: These actually bookmark the filenames backing the buffers. (seq-set-equal-p (mapcar #'abbreviate-file-name a)
(it "One buffer matches" (mapcar #'abbreviate-file-name b))))
(expect (var-after-bookmark-set-and-jump 'org-ql-view-buffers-files (it "One filename matches"
(find-file-noselect (car temp-filenames)) query) (should (equal (abbreviate-file-name
:to-equal one-filename)) (var-after-bookmark-set-and-jump 'org-ql-view-buffers-files one-filename query))
(it "A list of buffers matches" (abbreviate-file-name one-filename))))
(expect (var-after-bookmark-set-and-jump 'org-ql-view-buffers-files (it "A list of filenames matches"
(mapcar #'find-file-noselect temp-filenames) query) (should (filenames-equal-p (var-after-bookmark-set-and-jump 'org-ql-view-buffers-files temp-filenames query)
:to-equal temp-filenames))))) temp-filenames)))
;; NOTE: These actually bookmark the filenames backing the buffers.
(it "One buffer matches"
(should (equal (abbreviate-file-name
(var-after-bookmark-set-and-jump 'org-ql-view-buffers-files
(find-file-noselect (car temp-filenames)) query))
(abbreviate-file-name one-filename))))
(it "A list of buffers matches"
(should (filenames-equal-p (var-after-bookmark-set-and-jump 'org-ql-view-buffers-files
(mapcar #'find-file-noselect temp-filenames) query)
temp-filenames)))))))
(describe "Dynamic blocks" (describe "Dynamic blocks"
(describe "warn about sexp queries" (describe "warn about sexp queries"