[O] finding a parent node
Hello All. What is the best way to iterate over ((great)*grand)?parent headlines of the current one (at point), that meets some criteria. --8---cut here---start-8--- * Projects I am working on. ** Project for Mondays *** tasks *** resources ** Project for the rest of the week *** tasks:TASKS: ^ -- (3) I'd like it to move here If I do this stuff I will rule the world. ^ - (2) or it may be here. TODO do this TODO do that I am trying. ^ -- (1) point is here TODO WAT? *** resources --8---cut here---end---8--- With my point somewher deep I'like to find the closest parent heading tagged :TASKS:. If that helps, I'd like to export the subtree of the heading I find by simply running the export function at any point of the subtree. Kind regards, -- Łukasz Stelmach Samsung RD Institute Poland Samsung Electronics
Re: [O] finding a parent node
l.stelm...@samsung.com (Łukasz Stelmach) writes: Hello, What is the best way to iterate over ((great)*grand)?parent headlines of the current one (at point), that meets some criteria. not an answer to your question, but rather a related question I wanted to post anyway, so I do it in this thread: simple-test.org: #+begin_src org * header 1 :PROPERTIES: :CUSTOM_ID: XYZ22 :END: * header 2 [2013-06-28 Fr 11:01] ** subheader 1 Some text ** subheader 2 More text and a table | label | col1 | col2 | |+--+--| | string | 3| 4| Text and a src-block #+begin_src emacs-lisp (+ 3 4) #+end_src #+end_src parse buffer: #+begin_src emacs-lisp (progn (goto-char (point-max)) (newline 2) (insert (format %s (with-current-buffer (find-file-noselect /path/to/simple-test.org) (setq tree (org-element-parse-buffer) ) #+end_src excerpts form parse-tree: #+begin_src emacs-lisp (org-data nil ;; first headline (headline (:raw-value header 1 :begin 1 :end55 :pre-blank0 :hiddenp outline :contents-begin 12 :contents-end 55 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 1 :footnote-section-p nil :archivedp nil :commentedp nil :quotedp nil :CUSTOM_ID XYZ22 :CATEGORY simple-test :title (header 1) :parent #0) (section (:begin 12 :end 55 :contents-begin 12 :contents-end 55 :post-blank 0 :parent #1) (property-drawer (:begin 12 :end 55 :hiddenp outline :contents-begin 27 :contents-end 47 :post-blank 0 :post-affiliated 12 :parent #2) (node-property (:key CUSTOM_ID :value XYZ22 :begin 27 :end 47 :post-blank 0 :parent #3) ;; second headline (headline (:raw-value header 2 :begin 55 :end 295 :pre-blank 0 :hiddenp outline :contents-begin 66 :contents-end 295 :level 1 :priority nil :tags nil :todo-keyword nil :todo-type nil :post-blank 0 :footnote-section-p nil :archivedp nil :commentedp nil :quotedp nil :CATEGORY simple-test :title (header 2) :parent #0) (section (:begin 66 :end 90 :contents-begin 66 :contents-end 90 :post-blank 0 :parent #1) (paragraph (:begin 66 :end 90 :contents-begin 66 :contents-end 90 :post-blank 0 :post-affiliated 66 :parent #2) (timestamp (:type inactive :raw-value [2013-06-28 Fr 11:01] :year-start 2013 :month-start 6 :day-start 28 :hour-start 11 :minute-start 1 :year-end 2013 :month-end 6 :day-end 28 :hour-end 11 :minute-end 1 :begin 68 :end 89 :post-blank 0 :parent #3)) )) ...) ) #+end_src now I can use `org-element-map' to access the elements and their attributes: #+begin_src emacs-lisp (insert (format \n\n%s (org-element-map tree 'timestamp '(lambda (X) (org-element-property :raw-value X) ;; = ([2013-06-28 Fr 11:01]) #+end_src this gives me the first timestamp element and its property list: #+begin_src emacs-lisp (setq stamp1 (org-element-map tree 'timestamp 'identity nil t)) #+end_src but for further processing I always struggle with the :parent attribute and the circularities in the list. I often would like to use just a sublist like this, with :parent being a Link or ID and not the parent object that refers to its parent object and so on ... #+begin_src emacs-lisp (timestamp (:type inactive :raw-value [2013-06-28 Fr 11:01] :year-start 2013 :month-start 6 :day-start 28 :hour-start 11 :minute-start 1 :year-end 2013 :month-end 6 :day-end 28 :hour-end 11 :minute-end 1 :begin 68 :end 89 :post-blank 0 :parent ID of or LINK to #3)) #+end_src I tried to use the NO-RECURSION arg of `org-element-map' for this, but often the parent is a headline or section, and then 'org-element-map' doesn't enter headlines or sections and returns nil, i.e. the timestamp is never found. Is there a way - using the parser/export framework toolbox - to avoid these circularities, i.e. to either ignore the :parent attribute or better replace the list object in it by something else that nevertheless identifies the parent unmistakenly? I know that with special bookkeeping while walking the tree one can deal with these circularities, maybe I'm just new to this stuff, but I feel they make the usual processing of such a nested list a bit complicated. -- cheers, Thorsten
Re: [O] finding a parent node
l.stelm...@samsung.com (Łukasz Stelmach) writes: Hello Lukasz, assume my simple-test.org with a :TASK: tag: #+begin_src org * header 1 :PROPERTIES: :CUSTOM_ID: XYZ22 :END: * header 2 :TASK: [2013-06-28 Fr 11:01] ** subheader 1 Some text ** subheader 2 More text and a table | label | col1 | col2 | |+--+--| | string | 3| 4| Text and a src-block #+begin_src emacs-lisp (+ 3 4) #+end_src #+end_src With my point somewher deep I'like to find the closest parent heading tagged :TASKS:. Lets move point to the source-block and get `org-element-context': #+begin_src emacs-lisp (with-current-buffer (find-file /path/to/simple-test.org) (goto-char (point-min)) (org-babel-next-src-block) (message %s (point)) (format %s (org-element-context))) #+end_src #+begin_quote (src-block (:language emacs-lisp :switches nil :parameters nil :begin 319 :end 362 :number-lines nil :preserve-indent nil :retain-labels t :use-labels t :label-fmt nil :hiddenp nil :value (+ 3 4) :post-blank 0 :post-affiliated 319 :parent nil)) #+end_quote too bad, does not work in isolated use, :parent is nil. Othewise one could get the parent(s) and check for the :TASK: tag. So the only way to find this headline I know of would be: #+begin_src emacs-lisp (with-current-buffer (find-file-noselect /path/to/simple-test.org) (let ((tree (org-element-parse-buffer))) (org-element-map tree 'headline (lambda (hl) (and (member TASK (org-element-property :tags hl)) (list (org-element-property :begin hl) (org-element-property :end hl))) #+end_src returns ,--- | ((55 362)) `--- so you could at least find out if (point) is inside a headline with a :TASK: tag, then get this headline and use its attribute list to move to some place inside of it. But I'm sure Nicolas can give you a much better solution (I would be interested in that solution too). -- cheers, Thorsten
Re: [O] finding a parent node
It was 2013-07-02 wto 13:06, when Thorsten Jolitz wrote: l.stelm...@samsung.com (Łukasz Stelmach) writes: Hello Lukasz, assume my simple-test.org with a :TASK: tag: #+begin_src org * header 1 :PROPERTIES: :CUSTOM_ID: XYZ22 :END: * header 2 :TASK: [2013-06-28 Fr 11:01] ** subheader 1 Some text ** subheader 2 More text and a table | label | col1 | col2 | |+--+--| | string | 3| 4| Text and a src-block #+begin_src emacs-lisp (+ 3 4) #+end_src #+end_src With my point somewher deep I'like to find the closest parent heading tagged :TASKS:. Lets move point to the source-block and get `org-element-context': #+begin_src emacs-lisp (with-current-buffer (find-file /path/to/simple-test.org) (goto-char (point-min)) (org-babel-next-src-block) (message %s (point)) (format %s (org-element-context))) #+end_src #+begin_quote (src-block (:language emacs-lisp :switches nil :parameters nil :begin 319 :end 362 :number-lines nil :preserve-indent nil :retain-labels t :use-labels t :label-fmt nil :hiddenp nil :value (+ 3 4) :post-blank 0 :post-affiliated 319 :parent nil)) #+end_quote too bad, does not work in isolated use, :parent is nil. Othewise one could get the parent(s) and check for the :TASK: tag. So the only way to find this headline I know of would be: #+begin_src emacs-lisp (with-current-buffer (find-file-noselect /path/to/simple-test.org) (let ((tree (org-element-parse-buffer))) (org-element-map tree 'headline (lambda (hl) (and (member TASK (org-element-property :tags hl)) (list (org-element-property :begin hl) (org-element-property :end hl))) #+end_src returns ,--- | ((55 362)) `--- so you could at least find out if (point) is inside a headline with a :TASK: tag, then get this headline and use its attribute list to move to some place inside of it. But I'm sure Nicolas can give you a much better solution (I would be interested in that solution too). This might be enough for me as I get the tree in the exporting code. However, this way is far from efficient. If only there was a way to find the current element in the tree. I am not sure yet, but a sequence of org-back-to-heading and re-search-backward inside a save-excursion may be the easiest way to place the point where I want it. Any other thoughts? -- Łukasz Stelmach Samsung RD Institute Poland Samsung Electronics
Re: [O] finding a parent node
l.stelm...@samsung.com (Łukasz Stelmach) writes: It was 2013-07-02 wto 13:06, when Thorsten Jolitz wrote: l.stelm...@samsung.com (Łukasz Stelmach) writes: This might be enough for me as I get the tree in the exporting code. However, this way is far from efficient. If only there was a way to find the current element in the tree. I am not sure yet, but a sequence of org-back-to-heading and re-search-backward inside a save-excursion may be the easiest way to place the point where I want it. Any other thoughts? #+begin_src emacs-lisp (defun tj/export-enclosing-header (tag backend) Export enclosing header with TAG member of tags. (save-excursion (unless (org-on-heading-p) (outline-previous-heading)) (while (not (member tag (org-get-tags))) (outline-up-heading 1)) (org-export-as backend 'SUBTREEP))) #+end_src then doing (with point e.g. at the src-block) ,-- | M-: (tj/export-enclosing-header TASK 'html) `-- works in my sample org file. Not sure if this what you are looking for -- cheers, Thorsten