0

This problem is so convoluted that maybe I should call it a puzzle...


On the Unix shell command line, I can convert TSV (tab-separated-values) input to org-mode table format with this perl one-liner:

perl -lpe 's/(?:^|$|\t)/|/g'

So, for example, I can write something like

<<<pipeline producing TSV rows>>> | perl -lpe 's/(?:^|$|\t)/|/g' > mytable.org

The contents of mytable.org would be a valid org-mode table, but it would not be nicely formatted.

For example, if <<<pipeline producing TSV rows>>> produced the following

1   ABCDEFG
234567  HIJKLMNO
890123  P

...the contents of mytable.org would be

|1|ABCDEFG|
|234567|HIJKLMNO|
|890123|P|

To format it nicely, I could

  1. open mytable.org with Emacs;
  2. set the major mode to org-mode (if it doesn't happen by default);
  3. hit C-c C-c, aka org-ctrl-c-ctrl-c-hook, which has the effect of reformatting the table so that the delimiters line up; and
  4. save the file;

...after which the contents of mytable.org would look like this

|      1 | ABCDEFG  |
| 234567 | HIJKLMNO |
| 890123 | P        |

My question is, how can I perform this reformating operation from the command line, without having to start an interactive Emacs session?

More specifically, is there a way to implement a pipeline component, that uses Emacs, and that I can insert right before the output redirection > mytable.org, like this

<<<pipeline producing TSV rows>>> | perl -lpe 's/(?:^|$|\t)/|/g' \
    | format-org-table > mytable.org

...that it would achieve the same final form of mytable.org as shown earlier? The goal here is to avoid the need to "manually" open mytable.org with Emacs, then hit C-c C-c, etc.

1
  • Take a look at using Emacs in noninteractive batch mode.
    – Dan
    Nov 18, 2018 at 18:58

1 Answer 1

1

You can try the following:

;;; csv-to-org-table.el --- Convert CSV to Org table  -*- lexical-binding: t; -*-

;;; Commentary:

;; Example:
;; 
;; ~ $ echo "a\tb\n1\t2" | emacs --batch -l csv-to-org-table.el
;; | a | b |
;; | 1 | 2 |

;;; Code:

(insert-file-contents "/dev/stdin")

(if (zerop (buffer-size))
    (kill-emacs)
  (require 'org)
  (org-table-convert-region (point-min) (point-max))
  (princ (buffer-string)))

;;; csv-to-org-table.el ends here

If you prefer format-org-table to emacs --batch -l csv-to-org-table.el, you can create an Emacs Lisp script or shell alias/function.


However, it is better to use a proper programming language and implement org-table-convert-region from scratch, I don't think it will be difficult.

2
  • Thank you! Out of curiosity, is there a problem with replacing the (if (zerop (buffer-size)) ... with (unless (zerop (buffer-size)) ..., getting rid of the (kill-emacs), and putting the remaining expressions in a (progn ...)?
    – kjo
    Nov 19, 2018 at 22:46
  • 1
    @kjo No problem. It is actually better. The above code is ported from github.com/xuchunyang/emacs.d/blob/master/bin/csv-to-org-table, somehow (kill-emacs) is used.
    – xuchunyang
    Nov 20, 2018 at 2:56

Your Answer

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

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