0

I've been trying to get the content of the paragraph element unsuccessfully using org-element-contents, is there something I am missing here?

I have a org document as follows:

* world
** China
*** Music
About music
*** Dance
About dance
** Japan
*** Technology
About technology
*** Movies
About movies

The elisp code lives in the same document(sorry, :( I haven't spent proper time learning elisp yet!):

#+BEGIN_SRC emacs-lisp :exports results :results none
; https://emacs.stackexchange.com/questions/53359/org-mode-headings-to-org-table
(defun goto-header()
  (org-back-to-heading)
  (org-end-of-meta-data t)
  )

(defun create_table ()
  (let
      ((rows))
    (org-map-entries
     (lambda ()
       (let*
           ((el (org-element-at-point)))
         (let* (
                (title (org-element-property :title el))
                )
           (forward-line)
           (setq desc (org-element-contents (org-element-at-point)))
           (previous-line)
           (push (list title desc) rows))))
     "LEVEL=3"
     'tree)
    (setq rows (nreverse rows))
    (setq rows (append (list '(title topic) 'hline) rows))
    (goto-header)
    (insert (concat (orgtbl-to-orgtbl rows nil) "\n"))
    )
  )

(defun create_tables ()
  (org-map-entries #'create_table "LEVEL=2")
  )

(create_tables)
#+END_SRC

It makes the following change to the document:

* world
** China
| title   | topic |
|---------+-------|
| Music   | nil   |
| (Dance) | nil   |
*** Music
About music
*** Dance
About dance
** Japan
| title      | topic |
|------------+-------|
| Technology | nil   |
| (Movies)   | nil   |
*** Technology
About technology
*** Movies
About movies

So the next two things I want is to the paragraph text to be in the topic column and and then to remove the headings. But currently I am struggling to get the contents of the paragraph. What am I missing here?

The usecase for this is I am trying to export my elfeed-org config into nice HTML tables.

1

2 Answers 2

4

Normally an element is a list of the form (TYPE PROPS CONTENTS), but CONTENTS is almost never useful for the purposes of the org-element library, so org-element-at-point leaves it out. Its doc string says:

...
Return value is a list like (TYPE PROPS) where TYPE is the type
of the element and PROPS a plist of properties associated to the
element.
...

Unfortunately, the missing CONTENTS part is exactly what org-element-contents is looking for, hence the nil return value.

But the contents are implicitly specified in the PROPS that org-element-at-point returns: there are two properties :contents-begin and :contents-end that specify the buffer positions of the beginning and the end of the contents, so you can get the contents from those two with buffer-substring (or more likely, buffer-substring-no-properties - you probably don't care about any string properties). To get the values of the properties themselves, you can use org-element-property.

Putting all these things together, you can write your own function to get the contents:

(defun my/org-element-contents (element)
   "Get the contents of the partially specified 'element'
that only consists of '(TYPE PROPS)'."
   (let ((beg (org-element-property :contents-begin element))
         (end (org-element-property :contents-end element)))
     (buffer-substring-no-properties beg end)))

and using (my/org-element-contents (org-element-at-point)) instead of (org-element-contents (org-element-at-point)). You may have to manipulate the string a bit (e.g. to delete newlines) in order to add it to the table.

1
  • 1
    Thanks! this was an extremely helpful explanation. Managed to get what I wanted! :)
    – Hrishikesh
    Commented Jul 12, 2022 at 2:25
0
  1. Create a new file input.org with following content
* world

** China

*** Music

About music

Labore non esse labore exercitation

*** Dance

About dance

Nisi sint incididunt enim

** Japan

*** Technology

About technology

Cillum duis ea magna sint elit, sunt

*** Movies

About movies

Excepteur anim consequat aliqua reprehenderit excepteur

  1. Copy the following snippet to *scratch* buffer, and do M-x eval-buffer
(require 'org)
(require 'dash)

(defun lisp-table-to-org-table (lisp-table)
  (->> lisp-table
       (--map (cons "" it))
       (--tree-map
        (->> it
             substring-no-properties
             (replace-regexp-in-string "\n+" " ")
             org-trim))
       (--map (->> it
                   (-interpose "|")
                   (apply #'concat)))
       (-interpose "\n")
       (apply #'concat)
       list
       (--map (with-temp-buffer
                (org-mode)
                (save-excursion
                  (insert it))
                (org-table-align)
                (buffer-substring-no-properties (point-min) (point-max))))
       car))

(defun my-transform ()
  (interactive)
  (->>
   (org-element-map (org-element-parse-buffer) 'headline
     (lambda (h)
       (when (= (org-export-get-relative-level h nil) 2)
         (list :start (org-element-property :contents-begin h)
               :end (org-element-property :contents-end h)
               :table (-> h
                          org-element-contents
                          (org-element-map 'headline
                              (lambda (h)
                                (list (substring-no-properties
                                       (org-element-interpret-data
                                        (org-element-property :title h)))
                                      (org-element-interpret-data
                                       (org-element-contents h))))
                            nil nil 'headline)
                          lisp-table-to-org-table)))))
   reverse
   (--map
    (progn
      (goto-char (plist-get it :start))
      (delete-region (plist-get it :start)
                     (plist-get it :end))
      (insert (plist-get it :table))))))


  1. C-x C-f input.org
  2. Do M-x my-transform RET
  3. You will see this
* world

** China

| Music | About music Labore non esse labore exercitation |
| Dance | About dance Nisi sint incididunt enim           |

** Japan

| Technology | About technology Cillum duis ea magna sint elit, sunt                |
| Movies     | About movies Excepteur anim consequat aliqua reprehenderit excepteur |


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.