org-ql/examples.org
2020-01-04 21:35:17 -08:00

238 lines
8.6 KiB
Org Mode

#+TITLE: org-ql examples
* Contents
:PROPERTIES:
:TOC: this
:END:
- [[#agenda-like-view][Agenda-like view]]
- [[#entries-from-the-past-week][Entries from the past week]]
- [[#find-entries-matching-a-certain-custom_id][Find entries matching a certain CUSTOM_ID]]
- [[#listing-bills-coming-due][Listing bills coming due]]
- [[#music-database][Music database]]
- [[#return-org-elements][Return Org elements]]
- [[#set-tags-on-certain-entries][Set tags on certain entries]]
- [[#show-entries-with-recent-timestamps][Show entries with recent timestamps]]
- [[#stuck-projects-block-agenda][Stuck projects block agenda]]
* Agenda-like view
Show an agenda-like view, similar to a "traditional" Org Agenda with Log Mode turned on.
#+BEGIN_SRC elisp
(org-ql-search (org-agenda-files)
'(or (and (not (done))
(or (habit)
(deadline auto)
(scheduled :to today)
(ts-active :on today)))
(closed :on today))
:sort '(date priority todo))
#+END_SRC
Another example, showing grouping with [[https://github.com/alphapapa/org-super-agenda][org-super-agenda]]:
#+BEGIN_SRC elisp
(org-ql-search "~/src/emacs/org-super-agenda/test/test.org"
'(and (or (ts-active :on today)
(deadline auto)
(scheduled :to today))
(not (done)))
:title "My Agenda View"
;; The `org-super-agenda-groups' setting is used automatically when set, or it
;; may be overriden by specifying it here:
:super-groups '((:name "Bills"
:tag "bills")
(:todo ("SOMEDAY" "TO-READ" "CHECK" "TO-WATCH" "WATCHING")
:order 7)
(:name "Personal"
:habit t
:tag "personal"
:order 3)
(:todo "WAITING"
:order 6)
(:priority "A" :order 1)
(:priority "B" :order 2)
(:priority "C" :order 2)))
#+END_SRC
Which displays this buffer:
[[images/screenshot.png]]
* Entries from the past week
Show entries that have any timestamp within the past week. Group by date using =org-super-agenda= with the =:auto-ts= group.
#+BEGIN_SRC elisp
(org-ql-search (org-agenda-files)
'(ts :from -7 :to today)
:title "Recent Items"
:sort '(date priority todo)
:super-groups '((:auto-ts t)))
#+END_SRC
* Find entries matching a certain =CUSTOM_ID=
Since queries can contain both built-in =org-ql= predicate expressions and arbitrary expressions, they can be combined in useful ways. This example uses the built-in =property= predicate to quickly locate entries that have the =CUSTOM_ID= property set, and then compares the value of that property to the string =issue=.
#+BEGIN_SRC elisp
(org-ql-query
:select #'org-get-heading
:from "~/org/tickets.org"
:where '(and (property "CUSTOM_ID")
(string-match "issue" (org-entry-get (point) "CUSTOM_ID"))))
#+END_SRC
Using the =property= predicate as the first clause of the two clauses joined with =and= allows =org-ql= to optimize the query by searching through the buffer directly to entries that set the =CUSTOM_ID= property, which is much faster than testing every entry in a buffer. Also, If the query were only the =string-match= call, it would signal an error on entries that didn't have the property set, because =org-entry-get= would return nil.
* Listing bills coming due
This uses the example in the readme file, but maps across the elements returned by ~org-ql~ to present a simple list of titles and deadlines.
#+BEGIN_SRC elisp
(org-ql-query
:select '(list (substring-no-properties (org-get-heading t t))
(org-entry-get (point) "DEADLINE"))
:from (org-agenda-files)
:where '(and (not (done))
(tags "bills")
(deadline auto))
:order-by 'deadline)
;;=> (("Electric bill" "<2018-08-23 Thu +1m>")
;; ("Rent" "<2018-09-01 Sat +1m>"))
#+END_SRC
This could also be put in a script, which could use desktop notifications to remind of bills coming due: [[examples/org-bills-due.el][org-bills-due.el]].
* Music database
If you kept a database of music in an Org file, you could run a query like this to find tracks composed by Chopin that do not have their key recorded in the database.
#+BEGIN_SRC elisp
(org-ql-search "~/org/music.org"
'(and (property "genre" "classical")
(property "composer" "Chopin")
(not (property "key"))))
#+END_SRC
* Return Org elements
Return a list of Org entry elements in the file =~/org/main.org= which have the =SOMEDAY= to-do keyword, are tagged =Emacs=, and have priority B or higher. =org-ql= is the macro version of =org-ql-select=; it does not require quoting the query sexp.
#+BEGIN_SRC elisp
(org-ql "~/org/main.org"
(and (todo "SOMEDAY")
(tags "Emacs")
(priority >= "B")))
;;=> ((headline (:raw-value "org-board" :begin 1220270 :end 1220403 ...)) ...)
#+END_SRC
* Set tags on certain entries
Set the tag =Emacs= on every entry in the inbox file that mentions =Emacs=. The bare-string query ="Emacs"= is equivalent to ~(regexp "Emacs")~.
#+BEGIN_SRC elisp
(org-ql-select "~/org/inbox.org"
"Emacs"
:action '(org-toggle-tag "Emacs" 'on))
#+END_SRC
* Show entries with recent timestamps
You can also access these views with the command ~org-ql-view~.
#+BEGIN_SRC elisp
;; Show entries with any timestamp from last 7 days:
(org-ql-view-recent-items 7)
;; Show entries clocked in last 30 days:
(org-ql-view-recent-items 30 'clocked)
;; Show entries closed in last 30 days:
(org-ql-view-recent-items 30 'closed)
#+END_SRC
* Stuck projects block agenda
Reddit user =emptymatrix= [[https://www.reddit.com/r/emacs/comments/cnrt2d/orgqlblock_integrates_orgql_into_org_agenda/ewtqez8/][shared]] this example of replacing a traditional =org-stuck-projects= view like:
#+BEGIN_SRC elisp
(setq org-stuck-projects
'("+@project/-DONE" ("NEXT") nil "SCHEDULED:"))
#+END_SRC
With this =org-ql-block= agenda view, like:
#+BEGIN_SRC elisp
(setq org-agenda-custom-commands
'(("s" "Stuck Projects"
((org-ql-block '(and (tags "@project")
(not (done))
(not (descendants (todo "NEXT")))
(not (descendants (scheduled))))
((org-ql-block-header "Stuck Projects")))))))
#+END_SRC
* Exporting timetable to icalendar format
Exporting all available appointments to icalendar format for further upload. More insight [[https://www.reddit.com/r/orgmode/comments/e8q0iw/question_display_duration_as_block_in_the_agenda/][here]].
Saving org-ql search:
#+begin_src emacs-lisp
(let ((file "~/org/export/timetable.org")
(buffer-name "*org-ql-view-exporting*"))
(org-ql-search
(org-agenda-files)
'(and (not (done))
;; Only active time stamps
(ts-active)
;; Only appointments (i.e. with hour\time specification)
(regexp org-scheduled-time-hour-regexp))
:super-groups '((:auto-ts t))
:buffer buffer-name)
(org-agenda-write file nil t buffer-name))
#+end_src
Converting org-mode file to icalendar file:
#+begin_src emacs-lisp
(let (;; With alarm on event start
(org-icalendar-alarm-time 1)
;; Export tags
(org-icalendar-categories (quote (local-tags category)))
;; Don't include body to ICS event
(org-icalendar-include-body nil)
;; Use all headins avaialable
(org-icalendar-use-deadline (quote (event-if-not-todo event-if-todo todo-start)))
(org-icalendar-use-scheduled (quote (event-if-not-todo event-if-todo todo-start)))
(org-icalendar-with-timestamps nil)
;; Item duration for headlines without duration
(org-agenda-default-appointment-duration 0))
(find-file "~/org/export/timetable.org")
(org-icalendar-export-to-ics))
#+end_src
* Get all in progress tasks for [[https://github.com/ahungry/org-jira][org-jira]] users
For best results, inject it to bigger agenda view for your work items.
#+begin_src emacs-lisp
(org-ql-search
(org-agenda-files)
'(and (tags "work")
(and (property "assignee" "your-jira-username")
(todo "PROG")))
:super-groups
'((:name "In progress" :order 1 :todo "PROG")))
#+end_src
* COMMENT Code :noexport:
:PROPERTIES:
:TOC: ignore
:END:
** File-local variables
# Local Variables:
# eval: (require 'org-make-toc)
# before-save-hook: org-make-toc
# End: