views:

180

answers:

1

I would like to export from Org-Mode tables to s-expressions.

| first  | second | thrid  |
|--------+--------+--------|
| value1 | value2 | value3 |
| value4 | value5 | value6 |

Would turn into:

((:FIRST "value1" :SECOND "value2" :THIRD "value3")
 (:FIRST "value4" :SECOND "value5" :THIRD "value6"))

I plan on writing such a setup if it doesn't exist yet but figured I'd tap into the stackoverflow before I start reinventing the wheel.

+2  A: 

This does the trick. It has minimal error checking.

The interface to use is either the programmatic interface:

(org-table-to-sexp <location-of-beginning-of-table> <location-of-end-of-table>)

In which case it'll return the sexp you requested.

If you wanted an interactive usage, you can call the following command to operate on the table in the region. So, set the mark at the beginning of the table, move to the end, and type:

M-x insert-org-table-to-sexp

That will insert the desired sexp immediately after the table in the current buffer.

Here is the code:

(defun org-table-to-sexp-parse-line ()
  "Helper, returns the current line as a list of strings"
  (save-excursion
    (save-match-data
      (let ((result nil)
            (end-of-line (save-excursion (end-of-line) (point))))
        (beginning-of-line)
        (while (re-search-forward "\\([^|]*\\)|" end-of-line t)
          (let ((match (mapconcat 'identity (split-string (match-string-no-properties 1)) " ")))
            (if (< 0 (length match))
                ;; really want to strip spaces from front and back
                (push match result))))
        (reverse result)))))

(require 'cl)
(defun org-table-to-sexp (b e)
  "Parse an org-mode table to sexp"
  (save-excursion
    (save-match-data
      (goto-char b)
      (let ((headers (mapcar
                      (lambda (str)
                        (make-symbol (concat ":" (upcase str))))
                      (org-table-to-sexp-parse-line)))
            (sexp nil))
        (forward-line 1)                ;skip |--+--+--| line
        (while (< (point) e)
          (forward-line 1)
          (let ((line-result nil))
            (mapcar* (lambda (h e)
                       (push h line-result)
                       (push e line-result))
                     headers
                     (org-table-to-sexp-parse-line))
            (if line-result
                (push (reverse line-result)
                      sexp))))
        sexp))))

(defun insert-org-table-to-sexp (b e)
  "Convert the table specified by the region and insert the sexp after the table"
  (interactive "r")
  (goto-char (max b e))
  (print (org-table-to-sexp b e) (current-buffer)))
Trey Jackson
I am not sure how I would use that function. I added it to my .emacs eval'd it but I don't get how I'd use it.If you could expand on how to use that, I would really appreciate it.
Chris McDonald
@Chris I added an interactive command which you can just type. I think the larger question is: how do you want to use it?
Trey Jackson