Xah Lee, 2008-04, 2009-11-06
This page shows a example of writing a emacs lisp function that turns the current block of text into a HTML table. If you don't know elisp, first take a look at Emacs Lisp Basics.
I want to write a function, such that, when called, the current block of text the cursor is on, becomes a HTML table. Suppose the block of text is this:
a b c 1 2 3 this and that
after pressing a button, it should become:
<table border="1" cellpadding="5" cellspacing="0"> <tr><td>a</td><td>b</td><td>c</td></tr> <tr><td>1</td><td>2</td><td>3</td></tr> <tr><td>this</td><td>and</td><td>that</td></tr> </table>
and is rendered in browser like this:
| a | b | c |
| 1 | 2 | 3 |
| this | and | that |
The problem will have 3 major steps:
First, we do step 2. We write a function that takes 2 argument: a text block as string, and a separator as string, and return htmlized version of the text block.
This may sound complicated, but it is easily done by replacing the separator in the text block by “</td><td>, and wrap each line by “<tr><td>” and “</td></tr>”, then wrap a “<table>” and “</table>” around the whole block.
The primary function we'll use for this is “replace-regexp-in-string”. Here's the code:
(defun make-html-table-string (textblock delim) "Transform the string TEXTBLOCK into a HTML marked up table. “\n” is used as delimiter of rows. The argument DELIM is a char used as the delimiter for columns. See the parent function `make-html-table'." (setq textblock (replace-regexp-in-string delim "</td><td>" textblock)) (setq textblock (replace-regexp-in-string "\n" "</td></tr>\n<tr><td>" textblock)) (setq textblock (substring textblock 0 -8)) ; delete the beginning “<tr><td>” in last line (concat "<table class=\"nrm\">\n<tr><td>" textblock "</table>") )
To test this code, we can call it like this:
(make-html-table-string "1 2 3\na b c\n" " ")
All we have to do know, is to grab the current text block, then feed it into make-html-table-string, then insert the result.
Grabbing a block of text is done by knowing the position of occurrences of a consecutive end of line characters (represented by "\n" in emacs), before and after the current cursor position. Such a unit of text is called “paragraph” in emacs, and the function “thing-at-point” will do this for us.
; set mytext to be the current paragraph (setq mytext (thing-at-point 'paragraph)) ; gets the beginning and ending positions of the paragraph ; as a cons cell (cons p1 p2) ; set it to var bnds (setq bnds (bounds-of-thing-at-point 'paragraph))
With this function, our job becomes very simple. Here's the code:
(defun make-html-table (sep) "Transform the current paragraph into a HTML table. The “current paragraph” is defined as having empty lines before and after the block of text the cursor is on. For example: a*b*c 1*2*3 this*and*that with “*” as separator, becomes <table class=\"nrm\"> <tr><td>a</td><td>b</td><td>c</td></tr> <tr><td>1</td><td>2</td><td>3</td></tr> <tr><td>this</td><td>and</td><td>that</td></tr> </table>" (interactive "sEnter string pattern for column separation:") (let (bds p1 p2 myStr) (setq bds (bounds-of-thing-at-point 'paragraph)) (setq p1 (+ (car bds) 1)) (setq p2 (cdr bds)) (setq myStr (buffer-substring-no-properties p1 p2)) (delete-region p1 p2) (insert (make-html-table-string myStr sep) "\n") ))
One thing to note here is the code contained this line: “(interactive "sEnter string pattern for column separation:")”. What this line does, is that it will ask user to input a text pattern to be taken as the table column separator. The text the user enter will become the value of the parameter “sep” in the code. The first character “s”, in string of the argument of “interactive”, is to tell emacs that whatever the user entered should be t as a string datatype. (as opposed to, for example, a number)
In general, here's a simplified description on how to use “interactive”.
(info "(elisp) Defining Commands")
Emacs rules!
The above is a simple method to turn a text blog into a HTML table. Once you have the table as html code, you can not easily add or delete row or columns. Emacs 22 comes with a table.el by Takaaki Ota that makes table editing a little easier. See: Working With Tables In Emacs.