From cd95d10f05f1d770c17b6d70534578a11a0357d2 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 12 Nov 2020 04:55:43 -0600 Subject: [PATCH] Add: Dynamic block (property) column --- README.org | 27 +++++++++-------- notes.org | 33 ++++++++++++-------- org-ql-search.el | 31 +++++++++++++------ org-ql.info | 78 ++++++++++++++++++++++++++---------------------- 4 files changed, 99 insertions(+), 70 deletions(-) diff --git a/README.org b/README.org index 6fcfc92..8794c33 100644 --- a/README.org +++ b/README.org @@ -404,29 +404,30 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience 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~. - - Each column may also be specified as a list with the second element being a header string. For example, to abbreviate the priority column: ~(priority "P")~ ++ ~:columns~ A list of columns, including ~heading~, ~todo~, ~property~, ~priority~, ~deadline~, ~scheduled~. + - Each column may also be specified as a list with the second element being a header string. For example, to abbreviate the priority column: ~(priority "P")~. + - For certain columns, like =property=, arguments may be passed by specifying the column type itself as a list. For example, to display a column showing the values of a ~property~ named ~milestone~, with the header being abbreviated to ~M~: ~((property "milestone") "M")~. + ~: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: +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 (including the value of the =agenda-group= property with a custom header) 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 "P") deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M" - | Todo | P | 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 | + ,#+BEGIN: org-ql :query "todo: priority:A,B" :columns (todo (priority "P") ((property "agenda-group") "Group") deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M" + | Todo | P | Group | 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 | plans | 2017-07-15 00:00 | Take over the universe | + | TODO | B | | 2017-07-21 00:00 | Internet | + | TODO | A | bills | 2017-08-01 00:00 | Spaceship lease | + | TODO | A | | | Skype with president of Antarctica | + | TODO | B | | | Take over Mars | ,#+END: #+END_SRC diff --git a/notes.org b/notes.org index bbfa442..3718c69 100644 --- a/notes.org +++ b/notes.org @@ -24,12 +24,8 @@ | P | Keyword | Heading | |---+----------+--------------------------------------------------------------------| | A | UNDERWAY | [[Outline path predicate][Outline path predicate]] | -| B | UNDERWAY | [[Recursive queries][Recursive queries]] | -| B | UNDERWAY | [[Timeline view][Timeline view]] | | B | UNDERWAY | [["Node" caching]["Node" caching]] | -| B | UNDERWAY | [[Implement view with tabulated-list-mode or magit-section][Implement view with tabulated-list-mode or magit-section]] | | | UNDERWAY | [[Benchmarking tags searches without and with new group-tags support][Benchmarking tags searches without and with new group-tags support]] | -| | UNDERWAY | [[Add automated tests][Add automated tests]] | #+END: ** To-do @@ -48,6 +44,16 @@ | A | UNDERWAY | [[Outline path predicate][Outline path predicate]] | #+END: +** Milestones + +[[org-ql-search:todo%253A?super-groups=%2528%2528%253Aauto-property%2520%2522milestone%2522%2529%2529&sort=%2528priority%2529&title=%2522Milestones%2522][org-ql-search: Milestones]] + +#+BEGIN: org-ql :query "todo: property:milestone" :columns (((property "milestone") "M") (priority "P") todo heading) :sort (priority date) :take 7 +| M | P | Todo | Heading | +|-----+---+------+----------------------------| +| 0.6 | B | TODO | [[Save view to dynamic block][Save view to dynamic block]] | +#+END: + * [#A] Tasks :PROPERTIES: :TOC: :include descendants :depth 1 @@ -68,13 +74,9 @@ - [[#normalize-queries][Normalize queries]] - [[#update-view-screenshots][Update view screenshots]] - [[#org-agenda-skip-function][org-agenda-skip-function]] -- [[#test-caching][Test caching]] - [[#update-commentary][Update commentary]] - [[#outline-path-predicate][Outline path predicate]] -- [[#recursive-queries][Recursive queries]] -- [[#timeline-view][Timeline view]] - [[#node-caching]["Node" caching]] -- [[#implement-view-with-tabulated-list-mode-or-magit-section][Implement view with tabulated-list-mode or magit-section]] - [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] - [[#alternative-parsing-libraries][Alternative parsing libraries]] - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] @@ -82,7 +84,11 @@ - [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them {3/4}]] - [[#group-tag-support][Group tag support]] - [[#checking-links-for-unsafe-parameters][Checking links for unsafe parameters]] +- [[#recursive-queries][Recursive queries]] +- [[#timeline-view][Timeline view]] +- [[#implement-view-with-tabulated-list-mode-or-magit-section][Implement view with tabulated-list-mode or magit-section]] - [[#dynamic-blocks][Dynamic blocks]] +- [[#test-caching][Test caching]] - [[#helm-command][Helm command]] - [[#quickly-change-sortinggrouping-in-search-views][Quickly change sorting/grouping in search views]] - [[#byte-compile-lambdas][Byte-compile lambdas]] @@ -226,10 +232,6 @@ As discussed [[https://www.reddit.com/r/emacs/comments/cnrt2d/orgqlblock_integra I should benchmark it to see how much difference it makes, because all those ~fset~ calls on each heading isn't free. But if a macro were used to rewrite the built-in predicates to their full versions, all of that could be avoided... -** TODO [#C] Test caching - -See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. - ** TODO [#C] Update commentary ** UNDERWAY [#A] Outline path predicate @@ -1252,6 +1254,9 @@ Appears to be another implementation of magit-section-like expandable sections. ** PROJECT Dynamic blocks *** TODO [#B] Save view to dynamic block +:PROPERTIES: +:milestone: 0.6 +:END: [2020-11-12 Thu 03:23] A command to do this would be very helpful. @@ -1334,6 +1339,10 @@ For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this [2020-11-10 Tue 00:03] I think it's ready to merge now. +** PROJECT [#C] Test caching + +See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. + ** DONE [#A] Helm command In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. diff --git a/org-ql-search.el b/org-ql-search.el index 3abc468..2c4b213 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -247,10 +247,17 @@ Valid parameters include: form. :columns A list of columns, including `heading', `todo', - `priority', `deadline', `scheduled'. Each column may - also be specified as a list with the second element - being a header string. For example, to abbreviate - the priority column: (priority \"P\") + `property', `priority', `deadline', `scheduled'. + Each column may also be specified as a list with the + second element being a header string. For example, + to abbreviate the priority column: (priority \"P\"). + For certain columns, like `property', arguments may + be passed by specifying the column type itself as a + list. For example, to display a column showing the + values of a property named \"milestone\", with the + header being abbreviated to \"M\": + + ((property \"milestone\") \"M\"). :sort One or a list of Org QL sorting methods (see `org-ql-select'). @@ -287,7 +294,9 @@ For example, an org-ql dynamic block header could look like: (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))))))) + (ts-format ts-format (ts-parse-org-element it))))) + (cons 'property (lambda (element property &optional value) + (org-element-property (intern (concat ":" (upcase property))) element))))) (elements (org-ql-query :from (current-buffer) :where query :select '(org-element-headline-parser (line-end-position)) @@ -298,10 +307,14 @@ For example, an org-ql dynamic block header could look like: (integer (-take take elements))))) (cl-labels ((format-element (element) (string-join (cl-loop for column in columns - for fn = (cl-etypecase column - (symbol (alist-get column format-fns)) - (list (alist-get (car column) format-fns))) - collect (or (funcall fn element) "")) + collect (or (pcase-exhaustive column + ((pred symbolp) + (funcall (alist-get column format-fns) element)) + (`((,column . ,args) ,header) + (apply (alist-get column format-fns) element args)) + (`(,column ,header) + (funcall (alist-get column format-fns) element))) + "")) " | "))) ;; Table header (insert "| " (string-join (--map (pcase it diff --git a/org-ql.info b/org-ql.info index 3d86d66..9739c60 100644 --- a/org-ql.info +++ b/org-ql.info @@ -730,10 +730,15 @@ 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’. + ‘property’, ‘priority’, ‘deadline’, ‘scheduled’. • Each column may also be specified as a list with the second element being a header string. For example, to abbreviate the - priority column: ‘(priority "P")’ + priority column: ‘(priority "P")’. + • For certain columns, like property, arguments may be passed by + specifying the column type itself as a list. For example, to + display a column showing the values of a ‘property’ named + ‘milestone’, with the header being abbreviated to ‘M’: + ‘((property "milestone") "M")’. • ‘: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 @@ -746,18 +751,19 @@ 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: +with certain columns (including the value of the agenda-group property +with a custom header) and timestamp format: - #+BEGIN: org-ql :query "todo: priority:A,B" :columns (todo (priority "P") deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M" - | Todo | P | 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 | + #+BEGIN: org-ql :query "todo: priority:A,B" :columns (todo (priority "P") ((property "agenda-group") "Group") deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M" + | Todo | P | Group | 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 | plans | 2017-07-15 00:00 | Take over the universe | + | TODO | B | | 2017-07-21 00:00 | Internet | + | TODO | A | bills | 2017-08-01 00:00 | Spaceship lease | + | TODO | A | | | Skype with president of Antarctica | + | TODO | B | | | Take over Mars | #+END:  @@ -1289,29 +1295,29 @@ Node: Functions / Macros19755 Node: Agenda-like views20010 Node: Listing / acting-on results21415 Node: Dynamic block26017 -Node: Links28180 -Node: Tips28867 -Node: Changelog29185 -Node: 05-pre29824 -Node: 04631063 -Node: 04531466 -Node: 04431825 -Node: 04332182 -Node: 04232377 -Node: 04132536 -Node: 0432775 -Node: 03236706 -Node: 03137083 -Node: 0337280 -Node: 02340255 -Node: 02240483 -Node: 02140751 -Node: 0240950 -Node: 0144985 -Node: Notes45086 -Node: Comparison with Org Agenda searches45248 -Node: org-sidebar46120 -Node: License46399 +Node: Links28715 +Node: Tips29402 +Node: Changelog29720 +Node: 05-pre30359 +Node: 04631598 +Node: 04532001 +Node: 04432360 +Node: 04332717 +Node: 04232912 +Node: 04133071 +Node: 0433310 +Node: 03237241 +Node: 03137618 +Node: 0337815 +Node: 02340790 +Node: 02241018 +Node: 02141286 +Node: 0241485 +Node: 0145520 +Node: Notes45621 +Node: Comparison with Org Agenda searches45783 +Node: org-sidebar46655 +Node: License46934  End Tag Table