Org tables in comments and docstrings: in Emacs Lisp and Bash

I recently wanted to add an Org table as a comment to a Bash file. But how?

Well, the first thing would be to enable it. As it happens, there's a minor-mode called orgtbl-mode. Here's one way to turn it on for prog-mode and derived:

(use-package org-table
  :after org
  :hook (prog-mode . orgtbl-mode))

I was already using this in Emacs Lisp files, in three different ways.

Emacs Lisp

The first way was as regular comments. I avoid that, because you can't really edit the table when commented. So you need to first finish your table uncommented; and then you comment it, so it'll look like this:

;;   Types of flanges we used:
;;
;; |          | Size | Weight |
;; |----------+------+--------|
;; | Flange 1 |   10 |     70 |
;; | Flange 2 |    5 |     42 |

The second way was inside docstrings. This is straightforward:

(defun flanges-foo (flange)
  "Convert a flange into a FOO.
This will only work with defrobnicated flanges, such as:

  |          | Size | Weight |
  |----------+------+--------|
  | Flange 1 |   10 |     70 |
  | Flange 2 |    5 |     42 |"
  (flanges--convert-foo flange))

One detail: Emacs Manual frowns upon leaving trailing empty lines in docstrings. If the docstring ends with the Org table, the double quote should come immediately after it. If you then try to edit the table after that, or simply press RET before it, the quote will become a new column, which is not what you want.

So with point before the quote, run M-x open-line RET.
Or just C-o, which is probably what that's bound to.
Then edit the table. Then close it again.

The third way was inside "description macros" — something that I invented, and often use in my packages, as "supra-defun docstrings", so to speak, or docstrings for your elisp headings:

(xht--describe
  "These are functions to convert flanges to hash tables — because why not?

They have been tested with these types of flanges:

  |          | Size | Weight |
  |----------+------+--------|
  | Flange 1 |   10 |     70 |
  | Flange 2 |    5 |     42 |

Note that flanges should always be properly defrobnicated."

So that's Emacs Lisp. What about Bash?

Bash

I've found two ways to use Org tables in Bash.

The first way was as regular comments. As with Emacs Lisp, I avoid that, because you can't really edit the table when commented. So likewise, you need to first finish your table uncommented; then you comment it, and it'll look like this:

#   Types of flanges we used:
#
# |          | Size | Weight |
# |----------+------+--------|
# | Flange 1 |   10 |     70 |
# | Flange 2 |    5 |     42 |

The second way is much better. As with Emacs Lisp, we put it inside a string. The differences are:

  • Bash doesn't have docstrings — nothing that belongs to a function as just documentation and accessible as such.
  • Strings in Bash can be built with either double or single quotes.
  • A string by itself will be executed — which, at best, will throw an error.

An error? Yes:

"This is a test"
'This is also a test'
bash: line 1: This is a test: command not found
bash: line 2: This is also a test: command not found

So how do we get around that?

Answer: with the null command — namely, :.

The table must not share lines with a quotation mark, or these lines won't be editable as table.

The choice of quoting depends on whether other quotes show up in the string, and on your personal preferences.

Here's one with title:

#1

: "Types of flanges we used:

 |          | Size | Weight |
 |----------+------+--------|
 | Flange 1 |   10 |     70 |
 | Flange 2 |    5 |     42 |
"

And some without title:

#2

: '
  |          | Size | Weight |
  |----------+------+--------|
  | Flange 1 |   10 |     70 |
  | Flange 2 |    5 |     42 |
'

#3

: '
|          | Size | Weight |
|----------+------+--------|
| Flange 1 |   10 |     70 |
| Flange 2 |    5 |     42 |
'

#4

:                          '
|          | Size | Weight |
|----------+------+--------|
| Flange 1 |   10 |     70 |
| Flange 2 |    5 |     42 |
'

What if your string uses both types of quotes?

Then you make it a Here Document:

#5

: <<_
Last week's flanges:

|            | kg |
|------------+----|
| Flange "x" | 42 |
| Flange "y" | 17 |
_

You can always do that, actually, even without Org tables.

But guess what? It seems that, unlike a normal string, a Here Document by itself does not return error. Nor does a Here String:

# Error here ('A foo: command not found'):
"A foo"

# But no error here:
<<<"A foo"

# And no error here:
<<EOF
A foo
EOF

This means that the : wouldn't be strictly needed:

#6

<<_
Last week's flanges:

|            | kg |
|------------+----|
| Flange "x" | 42 |
| Flange "y" | 17 |
_

All Org table examples above execute with no output and no error.

Nevertheless, this last one gets a warning from ShellCheck. You could ignore it, but the no-error behavior may not be by design, and some Bash developer may decide to change that in the future — breaking all your past scripts with Here Docs now trying to execute the strings...

So #5 is probably best: the conservative extra : is barely perceptible, and it was designed to ignore whatever is in front of it.

And you know what: we could have docstrings for Bash, after all.

📆 2025-11-08