Add: Dynamic block

This commit is contained in:
Adam Porter 2020-11-09 23:50:34 -06:00
parent 2c466ebdcd
commit c0ded3ded3
4 changed files with 202 additions and 51 deletions

View file

@ -68,6 +68,7 @@ Installing with [[https://framagit.org/steckerhalter/quelpa][Quelpa]] is easy:
- [[#ancestordescendant-predicates][Ancestor/descendant predicates]] - [[#ancestordescendant-predicates][Ancestor/descendant predicates]]
- [[#datetime-predicates][Date/time predicates]] - [[#datetime-predicates][Date/time predicates]]
- [[#functions--macros][Functions / Macros]] - [[#functions--macros][Functions / Macros]]
- [[#dynamic-block][Dynamic block]]
- [[#tips][Tips]] - [[#tips][Tips]]
:END: :END:
@ -396,6 +397,36 @@ Examples:
Expands into a call to ~org-ql-select~ with the same arguments. For convenience, arguments should be unquoted. Expands into a call to ~org-ql-select~ with the same arguments. For convenience, arguments should be unquoted.
** Dynamic block
Org QL provides a dynamic block that lists entries in the current document matching a query. In the header, these parameters are supported:
+ ~:query~: An Org QL query expression in either sexp or non-sexp form.
+ ~:columns~ A list of columns, including ~heading~, ~todo~, ~priority~, ~deadline~, ~scheduled~.
+ ~:sort~ One or a list of Org QL sorting methods (see ~org-ql-select~).
+ ~:take~ Optionally take a number of results from the front (a positive number) or the end (a negative number) of the results.
+ ~:ts-format~ Optional format string used to format timestamp-based columns.
The heading column is formatted as a link to the heading (not shown in the following example).
For example, this dynamic block shows the first seven headings that are to-do items with priority A or B, sorted by deadline then priority, with certain columns and timestamp format:
# NOTE: These results are edited manually because the Org links don't display well in the Info manual.
#+BEGIN_SRC org
,#+BEGIN: org-ql :query "todo: priority:A,B" :columns (todo priority deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M"
| Todo | Priority | Deadline | Heading |
|------+----------+------------------+---------------------------------------|
| TODO | A | 2017-07-07 00:00 | Take over the world |
| TODO | B | 2017-07-10 00:00 | Renew membership in supervillain club |
| TODO | A | 2017-07-15 00:00 | Take over the universe |
| TODO | B | 2017-07-21 00:00 | Internet |
| TODO | A | 2017-08-01 00:00 | Spaceship lease |
| TODO | A | | Skype with president of Antarctica |
| TODO | B | | Take over Mars |
,#+END:
#+END_SRC
** Tips ** Tips
+ Org QL View buffers can be bookmarked with Emacs bookmark commands, e.g. =C-x r m=. This also integrates with [[https://github.com/alphapapa/org-sidebar][org-sidebar]] and [[https://github.com/alphapapa/burly.el][Burly]]. + Org QL View buffers can be bookmarked with Emacs bookmark commands, e.g. =C-x r m=. This also integrates with [[https://github.com/alphapapa/org-sidebar][org-sidebar]] and [[https://github.com/alphapapa/burly.el][Burly]].
@ -413,6 +444,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience
+ 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. + Predicate =link=, which matches descriptions and targets in Org links.
+ Emacs bookmark support: Org QL View buffers can be bookmarked with, e.g. =C-x r m= and shown with, e.g. =C-x r b=. (This also enables view restoration with [[https://github.com/alphapapa/burly.el][Burly]].) + Emacs bookmark support: Org QL View buffers can be bookmarked with, e.g. =C-x r m= and shown with, e.g. =C-x r b=. (This also enables view restoration with [[https://github.com/alphapapa/burly.el][Burly]].)
+ Dynamic block support.
+ Mascot. + Mascot.
*Changed* *Changed*

View file

@ -16,7 +16,7 @@
* [#A] Overview * [#A] Overview
#+BEGIN: org-ql :query (todo "UNDERWAY") :format (priority todo heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" #+BEGIN: org-ql :query (todo "UNDERWAY") :columns (priority todo heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M"
| Priority | Todo | Heading | | Priority | Todo | Heading |
|----------+----------+--------------------------------------------------------------------| |----------+----------+--------------------------------------------------------------------|
| A | UNDERWAY | [[Dynamic blocks][Dynamic blocks]] | | A | UNDERWAY | [[Dynamic blocks][Dynamic blocks]] |
@ -206,7 +206,7 @@ For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this
#+BEGIN_SRC elisp #+BEGIN_SRC elisp
(cl-defun org-dblock-write:org-ql (params) (cl-defun org-dblock-write:org-ql (params)
"FIXME: Docstring" "FIXME: Docstring"
(pcase-let* (((map :query :format :sort :ts-format) params) (pcase-let* (((map :query :columns :sort :ts-format) params)
(format-fns (list (cons 'heading (lambda (element) (format-fns (list (cons 'heading (lambda (element)
(org-make-link-string (org-element-property :raw-value element) (org-make-link-string (org-element-property :raw-value element)
(org-element-property :raw-value element)))) (org-element-property :raw-value element))))
@ -230,11 +230,11 @@ For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this
:select '(org-element-headline-parser (line-end-position)) :select '(org-element-headline-parser (line-end-position))
:order-by sort))) :order-by sort)))
(cl-labels ((format-element (cl-labels ((format-element
(element) (string-join (cl-loop for prop in format (element) (string-join (cl-loop for column in columns
for fn = (alist-get prop format-fns) for fn = (alist-get column format-fns)
collect (funcall fn element)) collect (funcall fn element))
" | "))) " | ")))
(insert "| " (string-join (--map (capitalize (symbol-name it)) format) " | ") " |" "\n") (insert "| " (string-join (--map (capitalize (symbol-name it)) columns) " | ") " |" "\n")
(insert "|- \n") (insert "|- \n")
(dolist (element elements) (dolist (element elements)
(insert "| " (format-element element) " |" "\n")) (insert "| " (format-element element) " |" "\n"))

View file

@ -232,6 +232,81 @@ automatically from the query."
;;;###autoload ;;;###autoload
(defalias 'org-ql-block 'org-ql-search-block) (defalias 'org-ql-block 'org-ql-search-block)
;;;; Dynamic blocks
;; This section implements support for Org dynamic blocks. See Info node `(org)Dynamic blocks'.
(require 'org-table)
(cl-defun org-dblock-write:org-ql (params)
"Insert content for org-ql dynamic block at point according to PARAMS.
Valid parameters include:
:query An Org QL query expression in either sexp or non-sexp form.
:columns A list of columns, including `heading', `todo',
`priority', `deadline', `scheduled'.
:sort One or a list of Org QL sorting methods (see `org-ql-select').
:take Optionally take a number of results from the front (a
positive number) or the end (a negative number) of the results.
:ts-format Optional format string used to format timestamp-based columns.
For example, an org-ql dynamic block header could look like:
#+BEGIN: org-ql :query (todo \"UNDERWAY\") :columns (priority todo heading) :sort (priority date) :ts-format \"%Y-%m-%d %H:%M\""
(pcase-let* (((map :query :columns :sort :ts-format :take) params)
(query (cl-etypecase query
(string (org-ql--plain-query query))
(t query)))
(columns (or columns '(heading todo priority)))
;; MAYBE: Custom column functions.
(format-fns
;; NOTE: Backquoting this alist prevents the lambdas from seeing
;; the variable `ts-format', so we use `list' and `cons'.
(list (cons 'heading (lambda (element)
(org-make-link-string (org-element-property :raw-value element)
(org-element-property :raw-value element))))
(cons 'todo (lambda (element)
(org-element-property :todo-keyword element)))
(cons 'priority (lambda (element)
(--when-let (org-element-property :priority element)
(char-to-string it))))
(cons 'deadline (lambda (element)
(--when-let (org-element-property :deadline element)
(ts-format ts-format (ts-parse-org-element it)))))
(cons 'scheduled (lambda (element)
(--when-let (org-element-property :scheduled element)
(ts-format ts-format (ts-parse-org-element it)))))))
(elements (org-ql-query :from (current-buffer)
:where query
:select '(org-element-headline-parser (line-end-position))
:order-by sort)))
(when take
(setf elements (cl-etypecase take
((and integer (satisfies minusp)) (-take-last (abs take) elements))
(integer (-take take elements)))))
(cl-labels ((format-element
(element) (string-join (cl-loop for column in columns
for fn = (alist-get column format-fns)
collect (or (funcall fn element) ""))
" | ")))
;; Insert table header.
(insert "| " (string-join (--map (capitalize (symbol-name it))
columns)
" | ")
" |" "\n")
;; Separator line.
(insert "|- \n")
;; Elements.
(dolist (element elements)
(insert "| " (format-element element) " |" "\n"))
;; Delete final newline and align table.
(delete-char -1)
(org-table-align))))
;;;; Functions ;;;; Functions
(cl-defun org-ql-search-directories-files (&key (directories (list org-directory)) (cl-defun org-ql-search-directories-files (&key (directories (list org-directory))

View file

@ -35,6 +35,7 @@ Usage
* Commands:: * Commands::
* Queries:: * Queries::
* Functions / Macros:: * Functions / Macros::
* Dynamic block::
* Tips:: * Tips::
Commands Commands
@ -154,7 +155,7 @@ File: README.info, Node: Usage, Next: Changelog, Prev: Installation, Up: Top
******* *******
• • • •
• • • • • • • • • • • •
Feedback on these APIs is welcome. Eventually, after being tested Feedback on these APIs is welcome. Eventually, after being tested
and polished, they will be considered stable. and polished, they will be considered stable.
@ -165,6 +166,7 @@ and polished, they will be considered stable.
* Commands:: * Commands::
* Queries:: * Queries::
* Functions / Macros:: * Functions / Macros::
* Dynamic block::
* Tips:: * Tips::
 
@ -544,7 +546,7 @@ number of days. The number can be negative to invert the direction.
scheduled at any time. scheduled at any time.
 
File: README.info, Node: Functions / Macros, Next: Tips, Prev: Queries, Up: Usage File: README.info, Node: Functions / Macros, Next: Dynamic block, Prev: Queries, Up: Usage
4.3 Functions / Macros 4.3 Functions / Macros
====================== ======================
@ -711,9 +713,49 @@ File: README.info, Node: Listing / acting-on results, Prev: Agenda-like views,
For convenience, arguments should be unquoted. For convenience, arguments should be unquoted.
 
File: README.info, Node: Tips, Prev: Functions / Macros, Up: Usage File: README.info, Node: Dynamic block, Next: Tips, Prev: Functions / Macros, Up: Usage
4.4 Tips 4.4 Dynamic block
=================
Org QL provides a dynamic block that lists entries in the current
document matching a query. In the header, these parameters are
supported:
:query: An Org QL query expression in either sexp or non-sexp
form.
:columns A list of columns, including heading, todo,
priority, deadline, scheduled.
:sort One or a list of Org QL sorting methods (see
org-ql-select).
:take Optionally take a number of results from the front (a
positive number) or the end (a negative number) of the results.
:ts-format Optional format string used to format timestamp-based
columns.
The heading column is formatted as a link to the heading (not shown
in the following example).
For example, this dynamic block shows the first seven headings that
are to-do items with priority A or B, sorted by deadline then priority,
with certain columns and timestamp format:
#+BEGIN: org-ql :query "todo: priority:A,B" :columns (todo priority deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M"
| Todo | Priority | Deadline | Heading |
|------+----------+------------------+---------------------------------------|
| TODO | A | 2017-07-07 00:00 | Take over the world |
| TODO | B | 2017-07-10 00:00 | Renew membership in supervillain club |
| TODO | A | 2017-07-15 00:00 | Take over the universe |
| TODO | B | 2017-07-21 00:00 | Internet |
| TODO | A | 2017-08-01 00:00 | Spaceship lease |
| TODO | A | | Skype with president of Antarctica |
| TODO | B | | Take over Mars |
#+END:

File: README.info, Node: Tips, Prev: Dynamic block, Up: Usage
4.5 Tips
======== ========
• Org QL View buffers can be bookmarked with Emacs bookmark commands, • Org QL View buffers can be bookmarked with Emacs bookmark commands,
@ -767,6 +809,7 @@ File: README.info, Node: 05-pre, Next: 046, Up: Changelog
e.g. C-x r m and shown with, e.g. C-x r b. (This also enables e.g. C-x r m and shown with, e.g. C-x r b. (This also enables
view restoration with Burly view restoration with Burly
(https://github.com/alphapapa/burly.el).) (https://github.com/alphapapa/burly.el).)
• Dynamic block support.
• Mascot. • Mascot.
*Changed* *Changed*
@ -1188,48 +1231,49 @@ GPLv3
 
Tag Table: Tag Table:
Node: Top225 Node: Top225
Node: Contents1521 Node: Contents1539
Node: Screenshots1644 Node: Screenshots1662
Node: Installation1762 Node: Installation1780
Node: Quelpa2400 Node: Quelpa2418
Node: Usage2843 Node: Usage2861
Node: Commands3205 Node: Commands3245
Node: org-ql-search3678 Node: org-ql-search3718
Node: helm-org-ql5392 Node: helm-org-ql5432
Node: org-ql-view5804 Node: org-ql-view5844
Node: org-ql-view-sidebar6304 Node: org-ql-view-sidebar6344
Node: org-ql-view-recent-items6660 Node: org-ql-view-recent-items6700
Node: org-ql-sparse-tree7144 Node: org-ql-sparse-tree7184
Node: Queries7944 Node: Queries7984
Node: Non-sexp query syntax8852 Node: Non-sexp query syntax8892
Node: General predicates10559 Node: General predicates10599
Node: Ancestor/descendant predicates15774 Node: Ancestor/descendant predicates15814
Node: Date/time predicates16902 Node: Date/time predicates16942
Node: Functions / Macros19557 Node: Functions / Macros19597
Node: Agenda-like views19803 Node: Agenda-like views19852
Node: Listing / acting-on results21208 Node: Listing / acting-on results21257
Node: Tips25810 Node: Dynamic block25859
Node: Changelog26141 Node: Tips27885
Node: 05-pre26780 Node: Changelog28211
Node: 04627626 Node: 05-pre28850
Node: 04528029 Node: 04629726
Node: 04428388 Node: 04530129
Node: 04328745 Node: 04430488
Node: 04228940 Node: 04330845
Node: 04129099 Node: 04231040
Node: 0429338 Node: 04131199
Node: 03233269 Node: 0431438
Node: 03133646 Node: 03235369
Node: 0333843 Node: 03135746
Node: 02336818 Node: 0335943
Node: 02237046 Node: 02338918
Node: 02137314 Node: 02239146
Node: 0237513 Node: 02139414
Node: 0141548 Node: 0239613
Node: Notes41649 Node: 0143648
Node: Comparison with Org Agenda searches41811 Node: Notes43749
Node: org-sidebar42683 Node: Comparison with Org Agenda searches43911
Node: License42962 Node: org-sidebar44783
Node: License45062
 
End Tag Table End Tag Table