From mboxrd@z Thu Jan 1 00:00:00 1970 From: Thorsten Jolitz Subject: Re: org-export: how to copy the parsed tree? Date: Sat, 01 Mar 2014 11:21:37 +0100 Message-ID: <878usu43ta.fsf@gmail.com> References: <87wqgeemto.fsf@gmail.com> <87r46m489o.fsf@gmail.com> Mime-Version: 1.0 Content-Type: text/plain Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:54486) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WJh2P-0003C4-E1 for emacs-orgmode@gnu.org; Sat, 01 Mar 2014 05:21:04 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WJh2G-00078h-Hx for emacs-orgmode@gnu.org; Sat, 01 Mar 2014 05:20:57 -0500 Received: from plane.gmane.org ([80.91.229.3]:50754) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WJh2G-000787-7p for emacs-orgmode@gnu.org; Sat, 01 Mar 2014 05:20:48 -0500 Received: from list by plane.gmane.org with local (Exim 4.69) (envelope-from ) id 1WJh2E-0004Sk-Kp for emacs-orgmode@gnu.org; Sat, 01 Mar 2014 11:20:46 +0100 Received: from e178063227.adsl.alicedsl.de ([85.178.63.227]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sat, 01 Mar 2014 11:20:46 +0100 Received: from tjolitz by e178063227.adsl.alicedsl.de with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sat, 01 Mar 2014 11:20:46 +0100 List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: emacs-orgmode@gnu.org Thorsten Jolitz writes: > Vitalie Spinu writes: > >> Is there an easy way to copy org sub-tree in :filter-parse-tree? >> >> The structure of the parsed tree is somewhat complicated with recursive >> references to parents in multiple places. So, copy-tree infloops. > > You will get a better answer most likely, but with (org-no-properties > contents) you can get the original Org-syntax of a parse-tree element, > e.g. applied to all sections (untested): > > ,---------------------------------------------------------------- > | (defun org-myexp-section (section contents info) > | "Transcode SECTION element into myexp syntax. > | CONTENTS is its contents, as a string or nil. INFO is ignored." > | (if (and contents (stringp contents) (> (length contents) 0)) > | (format "%S" > | (org-no-properties contents)) > | "")) > `---------------------------------------------------------------- I probably misunderstood your question. I don't know if there is an easy way to copy a subtree, but I do know about the problems with the recursive references, so I found a way to replace them with simple numeric :org-elem-id and :parent-id attributes: ,-------------------------------------------- | :filters-alist '((:filter-parse-tree | . org-myexp-filter-parse-tree-function) `-------------------------------------------- #+begin_src emacs-lisp (defun org-myexp-filter-parse-tree-function (tree backend info) "Filter complete parsed TREE ignoring BACKEND and INFO." ;; optional (org-myexp-add-children (org-myexp-add-parent-ids (org-myexp-add-ids tree backend info) backend info) backend info)) (defun org-myexp-add-ids (tree backend info) "Add ':org-elem-id' property to each element of parse TREE." (let ((counter 1) (structure 1)) (org-element-map tree myexp-default-map-types (lambda (--elem) (org-element-put-property --elem :org-elem-id counter) (setq counter (1+ counter)) (and (eq (org-element-type --elem) 'plain-list) (org-element-put-property --elem :structure-id structure) (setq structure (1+ structure)))))) tree) (defun org-myexp--collect-children (tree) "Return alist with '(org-elem-id . parent-id)' pairs. The data is collected from parse TREE." (let (child-lst) (org-element-map tree 'headline (lambda (--headline) (push (cons (org-element-property :org-elem-id --headline) (org-element-property :parent-id --headline)) child-lst))) child-lst)) ;; optional (defun org-myexp-add-children (tree backend info) "Add `:children' property to each headline in parse TREE. Assumes that all headlines are tagged with an `:org-elem-id' property and that the circular-list read-syntax of the `:parent' attribute has been replaced with simple integer values (the :org-elem-id of the elements parent)." (let ((pairs (org-myexp--collect-children tree))) (org-element-map tree 'headline (lambda (--elem) (org-element-put-property --elem :children (reverse (delq nil (mapcar (lambda (--pair) (and (eq (cdr --pair) (org-element-property :org-elem-id --elem)) (car --pair))) pairs))))))) tree) (defun org-myexp-add-parent-ids (tree backend info) "Add `:parent-id' and `:parent-structure-id' to parse-tree TREE." (org-element-map tree myexp-all-map-types (lambda (--elem) (let ((par (org-element-property :parent --elem))) (and (eq (org-element-type --elem) 'item) (eq (org-element-type par) 'plain-list) (org-element-put-property --elem :parent-structure-id (org-element-property :structure-id par))) (org-element-put-property --elem :parent-id (if (eq (org-element-type par) 'org-data) 0 (org-element-property :org-elem-id par))))) nil nil nil 'WITH-AFFILIATED) tree) #+end_src Then in the transcode functions I build the parse-tree again without the circular :parent attribut, but with the information contained in it now contained in :org-elem-id and :parent-id: #+begin_src emacs-lisp (defun org-myexp-headline (headline contents info) "Transcode HEADLINE element into myexp syntax. CONTENTS is its contents, as a string or nil. INFO is ignored." (let ((props org-myexp-node-properties)) (setq org-myexp-node-properties nil) (format "(headline %S %s) " (list 'org-elem-id (org-element-property :org-elem-id headline) 'parent-id (org-element-property :parent-id headline) [...]) (org-no-properties contents)))) #+end_src Not really an easy way, and I needed it for a very special purpose so it might not fit your needs. However, this can be used to convert the circular parse-tree to a non-circular nested list that all the usual list processing functions can digest. But I must say that I simply transformed all the SECTIONS to Org-syntax (with no circular refs at all), so I ended up with only a handful transcode functions. Doing the above on the whole parse-tree with all its circular references might be a tedious exercise ... -- cheers, Thorsten