Hi all,

I'd like to revisit the question of how #+CAPTION and #+NAME interact
with source block results during export, and propose a
header-argument-based solution.

The problem
-----------

In reproducible-research documents, source blocks frequently produce
tables (or figures) that need captions and cross-reference labels in
the exported output. The current behavior -- #+CAPTION before a
#+begin_src block applies to the source block, not its results --
means there is no clean way to caption a generated table.

Minimal example:

#+NAME: tab:summary
#+CAPTION: Summary statistics.
#+begin_src python :results value raw
return "| A | B |\n|---+---|\n| 1 | 2 |"
#+end_src

On LaTeX export, the table has no \caption{} or \label{}. The caption
attaches to the source block element, not the results.

Existing workarounds
--------------------

1. Place #+NAME: / #+CAPTION: directly above the #+RESULTS: block.
This works but is overwritten on every re-execution, making it
impractical for active documents.

2. Emit the #+NAME: / #+CAPTION: directives as part of the output
string itself (with :results raw). This is what John Kitchin
described in 2016 and what I currently do -- e.g. in Python:

display({"text/org": f"#+NAME: tab:foo\n#+CAPTION: My table.\n{org_table}"},
raw=True)

This works but couples the source language to org-mode export
internals. The code has to know it's running inside org-mode and
construct org directives as strings.

3. Use a :wrap function to inject attributes. Also works but requires
custom elisp per document.

Proposal
--------

Add optional header arguments that propagate to the results block on
execution:

#+begin_src python :results value raw :result-name tab:summary :result-caption 
Summary statistics.
return tabulate(df)
#+end_src

When org-babel inserts or updates results, it would prepend #+NAME:
and #+CAPTION: lines above the #+RESULTS: block, preserving them
across re-execution. This keeps the metadata with the source block
(where it's authored) while applying it to the results (where it's
needed for export).

An alternative would be to simply propagate the source block's own
#+NAME: / #+CAPTION: to the results when :exports results or :exports
both is set, since in those cases the user clearly intends the output
-- not the code -- to be the exported artifact.

Use case
--------

This comes up constantly in literate-programming and
reproducible-research workflows: org documents with dozens of
code-generated tables, each needing a caption and label for
cross-referencing. The current workarounds all break the abstraction
boundary between content and export machinery.

I'm aware this was discussed in 2013 (Nicolas Goaziou clarified the
current behavior as intentional for the new exporter), and again in
subsequent threads. I'm raising it again because the workarounds
remain awkward and the use case -- particularly with Jupyter kernels
via emacs-jupyter -- has only grown.

Happy to work on a patch if there's interest in either approach.

Best,
Peter Tittmann

Reply via email to