2

If a code-block that is supposed to produce a table return nil, then nothing at all is inserted, as demonstrated by the second example below.

#+begin_src emacs-lisp :results table
  '(("foo" "bar"))
#+end_src
#+RESULTS:
| foo | bar |

#+begin_src emacs-lisp :results table
  nil
#+end_src
#+RESULTS:

I would like to keep it that way, but also use post-processing to add a header to all non-empty tables (and only those).

Unfortunately post-processing changes how nil (i.e., the empty table) is handled:

#+name: addheader
#+header: :var rows="" :var header=""
#+begin_src elisp :hlines yes
  (and rows `(("Key" "Value") hline ,@rows))
#+end_src

#+header: :post addheader(*this*,'("Key" "Value"))
#+begin_src emacs-lisp :results table
  '(("foo" "bar"))
#+end_src
#+RESULTS:
| Key | Value |
|-----+-------|
| foo | bar   |

#+header: :post addheader(*this*,'("Key" "Value"))
#+begin_src emacs-lisp :results table
  nil
#+end_src
#+RESULTS:
: nil

Can I somehow prevent this result:

#+RESULTS:
: nil

and get back just:

#+RESULTS:

2 Answers 2

1

The simplest solution would be to write an elisp function that adds the table header and to wrap the code in the source blocks with this function.

It may be that this is not possible, because the Elisp blocks in your question are just replacements for blocks in other programming languages.

In that case we need to take a closer look at the cause of the result output : nil:

The :post header argument is evaluated by org-babel-ref-resolve close to the end of org-babel-execute-src-block.

The problem is that org-babel-ref-resolve returns the string "nil" instead of the symbol nil. That result is printed as : nil rather than dismissing it.

This is caused by the final lines of org-babel-ref-resolve:

(defun org-babel-ref-resolve (ref)
...
         (cond
          ((symbolp result) (format "%S" result))
          ((and index (listp result))
           (org-babel-ref-index-list index result))
          (t result)))))))))

I wonder whether the formatting of symbols as string is really appropriate there.
Maybe, one should remove that format-line at all:

(defun org-babel-ref-resolve (ref)
...
         (cond
          ((and index (listp result))
           (org-babel-ref-index-list index result))
          (t result)))))))))

(BTW: The cond could be replaced by an if in this case.)

If you are not so adventurous you could only keep the symbol nil and transform other symbols to strings:

(defun org-babel-ref-resolve (ref)
...
         (cond
          ((and result (symbolp result)) (format "%S" result))
          ((and index (listp result))
           (org-babel-ref-index-list index result))
          (t result)))))))))

If you do not want to tinker with the source code directly,
you can use the following code in your init file.

It is a bit like advising a function, but one can replace specific syntactic expressions within function definitions, such as (symbolp return), with other expressions, such as (and return (symbolp return)).

(require 'ob-ref)

(defun lispTZA-replace-in-fundef (fun from to)
  "Replace sexp FROM with sexp TO in function definition of symbol FUN.
Note, that the source file for FUN must be available.

Return the modified symbol-function."
  (condition-case err
      (let* ((pos (find-function-noselect fun t))
             (buf (car pos))
             (pt (cdr pos)))
        (with-current-buffer buf
          (save-excursion
            (goto-char pt)
            (eval (read buf) t))))
    (error nil))
  (when (setq fun (and (symbolp fun) (symbol-function fun)))
    (let (transform-tree)
      (setq transform-tree
        (lambda (tree)
          (cond
           ((equal tree from)
        to)
           ((consp tree)
        (cons ;; This does a copy for us.
         (funcall transform-tree (car tree))
         (funcall transform-tree (cdr tree))))
           (t
        tree))))
      (funcall transform-tree fun))))

;; For reloading the init file:
(advice-remove 'org-babel-ref-resolve #'ad-org-babel-ref-resolve)

(defalias 'ad-org-babel-ref-resolve
  (lispTZA-replace-in-fundef
   'org-babel-ref-resolve
   '(symbolp result) '(and result (symbolp result)))
  "Replacement for `org-babel-ref-resolve' not turning a nil result into a string.")

(advice-add 'org-babel-ref-resolve :override #'ad-org-babel-ref-resolve)

Tested with Org-version 9.3.7.

4
  • 1
    Thanks for identifying the code that causes this. I was hoping I was just holding it wrong and that by, say, using the correct header arguments I could get the behavior I desire. Your suggested "simplest solution" is what I have been using the last few years. I have identified the commit that made this change: 51a628bc5efc20231ac4ffad3053a12be81c9a75. Hoped it was a recent change, but its from 2009. I might experiment with this at some point and suggest a change on the mailing list.
    – tarsius
    May 17, 2022 at 21:31
  • @tarsius Nice that you found the commit github.com/bzg/org-mode/commit/…. Do you have any idea why they introduced (format "%S" result)? Maybe, a real solution is more complicated than my simple hack.
    – Tobias
    May 17, 2022 at 21:56
  • To make some test work it seems. I.e., not really by thinking about it deeply. I'm gonna suggest on the mailing list that at least handling of nil/empty-list should be changed.
    – tarsius
    May 21, 2022 at 9:53
  • I've finally reported this and my fix got merged: list.orgmode.org/87y1tu90vz.fsf@localhost/T/….
    – tarsius
    Oct 7, 2022 at 18:57
1

In the next Org release (9.6) this will work as outlined in the question. My fix was merged: https://list.orgmode.org/87y1tu90vz.fsf@localhost/T/#m9a13f22f6b53c090b7721787ad99344f4bdb7b01.

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.