Emacs Asked by Omar113 on September 2, 2021
I am bad at elisp. I am trying to return to follow the idea of just getting everything from the orgfile, then pass it to R code to do easier analysis for me.
This works to generate only tags table
#+name: orgtable
#+begin_src emacs-lisp
(let (orgtable)
(org-map-entries
(lambda ()
(dolist (tag (org-get-tags))
(push (list tag) orgtable))))
orgtable)
#+end_src
#+begin_src R :var orgtable=orgtable
table(orgtable)
#+end_src
The above snippet works good. But I am trying to make a full table of the following columns
* TODO Task 1 :tag1:
deadline:1-9-2021
* Waiting Task2
** DONE subtask :tag2:
::LOGBOOK::
completed: 7-7-2020
clock: start time- endtime => 2hours
#+begin_src
;;some script
#+End_src
#+ results
todo:task name:tags: schedule:deadline: clock: completed:
-----------------------------------------------------------------------
todo: task1 : tag1: :1-9-2021: :
waiting: task2: : : : :
done: subtask : tag2: : : 2hrs: 7-7-2020
I just don’t know how to nest all of that in elisp code something like:
#+begin_src emacs-lisp
(let (orgtable)
(org-map-entries
(lambda ()
(dolist (tag '((org-get-tags)
(org-get-todo-state)
(org-get-property-block)
))
(push (list tag) orgtable))))
orgtable)
#+end_src
This just fails and not evaluated. Also it would be nice if I can extract every property on it’s own column.
Here's an example Org file (based on what you provided but fixed up for syntax etc). It does not contain everything you want, but it does most of it - if I find time, I might come back for the rest:
#+TODO: TODO WAITING | DONE
#+STARTUP: logdrawer logdone
* TODO Task 1 :tag1:tag2:
DEADLINE: <2020-07-21 Tue>
* WAITING Task2
SCHEDULED: <2020-07-21 Tue>
** DONE subtask :tag2:tag3:
CLOSED: [2020-07-21 Tue 15:50]
:LOGBOOK:
CLOCK: [2020-07-21 Tue 15:47]--[2020-07-21 Tue 15:49] => 0:02
:END:
* COMMENT Code
#+name: tags
#+begin_src emacs-lisp
(defun entry-get (prop)
(or (org-entry-get (point) prop) ""))
(defun ndk/entries-table ()
(interactive)
(let ((tbl '(hline ("Name" "TODO" "Tags" "Scheduled" "Deadline" "Clock" "Closed"))))
(org-clock-sum)
(org-map-entries
(lambda ()
(push (list (entry-get "ITEM")
(entry-get "TODO")
(entry-get "TAGS")
(entry-get "SCHEDULED")
(entry-get "DEADLINE")
(entry-get "CLOCKSUM")
(entry-get "CLOSED"))
tbl))
t
'file
'comment)
(reverse tbl)))
(ndk/entries-table)
#+end_src
#+RESULTS: tags
| Name | TODO | Tags | Scheduled | Deadline | Clock | Closed |
|---------+---------+-------------+------------------+------------------+-------+------------------------|
| Task 1 | TODO | :tag1:tag2: | | <2020-07-21 Tue> | | |
| Task2 | WAITING | | <2020-07-21 Tue> | | 0:02 | |
| subtask | DONE | :tag2:tag3: | | | 0:02 | [2020-07-21 Tue 15:50] |
Some notes:
#+TODO:
setting, defining the TODO
states, to make the file self-contained.LOGBOOK
stuff yet: that needs fixing up, both in the file and in the code.Code
section as a COMMENT
and I make sure in the code to skip COMMENT
ed sections from processing.org-map-entries
is limited to the current file and is instructed to skip COMMENT
sections.nil
because that's what org-entry-get
returns. We can replace those calls with (or (org-entry-get (point) "....") "")
to make it return an empty string instead.EDIT: Added the following changes:
org-clock-sum
in the buffer before you try to retrieve the CLOCKSUM property, so I added a call to it.org-entry-get
to deal with the "nil vs empty string" problem above.ndk/entries-table
and added a call to it in the source block to produce the table.I believe this completes everything you asked for in the original question.
For the question in your comment, there are a couple of ways of dealing with it: probably the easiest is to leave everything as is, but change the ndk/entries-table function to take an argument, either a filename or a buffer. We then do everything in that buffer (but still produce the output in *this* buffer). Here's an implementation (for the whole file: you can't pick just a headline with this version, but I probably won't be able to do that any time soon - the implementation could be something like this though: make the headline a second optional argument, search in the chosen buffer for the desired headline, make sure you are in the right place, then call
org-map-enrieswith a
treeargument instead of a
fileargument
org-map-entries` is nothing if not flexible ;-) ):
#+name: tags
#+begin_src emacs-lisp
(defun entry-get (prop)
(or (org-entry-get (point) prop) ""))
(defun ndk/entries-table (&optional file-or-buffer)
(interactive)
(cond
((null file-or-buffer)
;; just use the current buffer
)
((bufferp file-or-buffer)
(set-buffer file-or-buffer))
(t
(set-buffer (find-file-noselect file-or-buffer))))
(let ((tbl '(hline ("Name" "TODO" "Tags" "Scheduled" "Deadline" "Clock" "Closed"))))
(org-clock-sum)
(org-map-entries
(lambda ()
(push (list (entry-get "ITEM")
(entry-get "TODO")
(entry-get "TAGS")
(entry-get "SCHEDULED")
(entry-get "DEADLINE")
(entry-get "CLOCKSUM")
(entry-get "CLOSED"))
tbl))
t
'file
'comment)
(reverse tbl)))
(ndk/entries-table "./bar.org")
#+end_src
#+RESULTS: tags
| Name | TODO | Tags | Scheduled | Deadline | Clock | Closed |
|-------------------+------+-------------+------------------+------------------+-------+------------------------|
| Task bar1 | TODO | :tag1:tag2: | | <2020-07-21 Tue> | | |
| WAITING Task bar2 | | | <2020-07-21 Tue> | | 0:02 | |
| subtask bar | DONE | :tag2:tag3: | | | 0:02 | [2020-07-21 Tue 15:50] |
BTW bar.org
is more or less a copy of the original file with the titles changed, and no code included.
Correct answer by NickD on September 2, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP